#excel #vba #excel-2007
#excel #vba #excel-2007
Вопрос:
Итак, у меня есть эта книга Excel, которая в основном должна быть таблицей данных для рабочей одежды для каждого сотрудника. Я хочу, чтобы у каждого человека было по одному листу (имя и фамилия), затем по одному листу для каждой доступной одежды.
Затем один лист, чтобы объединить все это вместе. Но это потребовало бы повторения каждого имени столько раз, сколько существует уникальных типов ткани. Сложно объяснить, но у меня есть рабочая книга, доступная для скачивания здесь: http://www.mediafire.com/?dxurbdjq340su6j
Лист2 (Пользователи) содержит простой список каждого уникального пользователя. Лист3 (Статьи) содержит список каждой уникальной статьи одежды. И, наконец, у нас есть первый лист (сводка), который содержит объединенный список всего этого. На основе этого сводного листа я позже создам сводную таблицу. Но сначала мне нужно, чтобы функциональность здесь была динамической. Всякий раз, когда добавляется или удаляется новый пользователь или одежда, я хочу делать это только в Sheet2 или Sheet3. Все, что находится на листе 1, должно собирать данные динамически.
Есть идеи? Должен ли я создавать макрос для этого?
Редактировать: Хорошо, итак, я создал модуль с двумя общедоступными словарями. Вот код, который у меня есть до сих пор:
Эта рабочая тетрадь
Private Sub Workbook_Open()
' Create dictionaries
Set dictName = New Dictionary
Set dictClothItems = New Dictionary
' Collect data
collectDictName
collectDictClothItems
End Sub
Модуль1:
Public dictName As Dictionary
Public dictClothItems As Dictionary
Public Sub collectDictName()
Dim v As Variant
Dim rngName As Range
' Add values
With ThisWorkbook.Sheets(2)
Set rngName = .Range("A2", .Range("A" amp; Rows.Count).End(xlUp))
For Each strName In rngName
dictName.Add strName, ""
Next
End With
End Sub
Public Sub collectDictClothItems()
Dim v As Variant
Dim rngName As Range
' Add values
With ThisWorkbook.Sheets(3)
Set rngName = .Range("A2", .Range("A" amp; Rows.Count).End(xlUp))
For Each strClothName In rngName
dictClothItems.Add strClothName, ""
Next
End With
End Sub
Итак, здесь я собираю данные и сохраняю их в массиве. Я не был уверен, как собирать данные из диапазона, поэтому я использовал For Each strName In rngName
. Похоже, он собирает другие данные, которые мне действительно не нужны. Вероятно, это можно исправить, создав строковую переменную и присвоив ей значение, которое мне нужно. А затем добавление этой строки в словарь. В любом случае, теперь, когда данные собраны, мне нужно сравнить и добавить их в фактический сводный лист. Есть идеи, с чего начать?
Ответ №1:
Перефразирование вопроса
Итак, по сути, то, что вы хотите, это:
Каждый раз, когда вы добавляете новое значение на листе 2 (пользователи) или листе 3 (одежда), вы хотите, чтобы Excel динамически добавлял на листе 1 (Сводка) новую строку для каждого значения на другом листе (пользователи или Одежда в зависимости от того, что было изменено)
Кстати, откуда берется сумма?
Ответ
Тем не менее, чтобы ответить на ваш вопрос, самый простой способ — сделать это с помощью VBA, чтобы он был динамичным.
Вот что вы можете сделать:
- добавьте событие en
Worksheet_Change()
как на Лист2, так и на Лист3 (см. На веб-сайте Chip Pearson, как это сделать) - эта процедура будет отслеживать каждое изменение на этих листах. Каждый раз, когда пользователь добавляет значение, вы должны
перебирать другой лист, получать значение с другого листа и заполнять массив (одежда или пользователь в зависимости от значения) - ИМХО, самый простой способ объединить данные —
создатьцикл над созданным вами массивом (или использовать словарь)и добавлять каждую новую строку в ваш массив - в конце концов, вы можете добавить массив в свой
Summary
лист
Не стесняйтесь запрашивать дополнительную информацию, если вам нужно, или задать новый вопрос о том, что вы пробовали, если вы все еще застряли.
[ПРАВКА 2] Вот полное рабочее решение для статей (легко адаптируемое для пользователей)
Код на листе 3 (Статьи)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim aSum() As String
Dim sArticle As String, sPrice As Long
Dim i As Integer, iLastrow As Integer
If Intersect(Range("A:B"), Target) Is Nothing Then Exit Sub
'if no price, exit sub
If Not Intersect(Range("A:A"), Target) Is Nothing Then
If Target.Offset(0, 1).Value = Empty Then Exit Sub
sArticle = Target.Value
sPrice = CLng(Target.Offset(0, 1).Value)
End If
'if no name, exit sub
If Not Intersect(Range("B:B"), Target) Is Nothing Then
If Target.Offset(0, -1).Value = Empty Then Exit Sub
sArticle = Target.Offset(0, -1).Value
sPrice = CLng(Target.Value)
End If
'get the names in an array
collectNames
'store the data in a new array so to map these values in the end
ReDim aSum(UBound(vNames) - 1, 3)
For i = 0 To UBound(vNames) - 1
aSum(i, 0) = vNames(i 1, 1)
aSum(i, 1) = sArticle
aSum(i, 3) = sPrice
Next
'store the data back to the Summary sheet
With ThisWorkbook.Sheets("Summary")
iLastrow = .Range("A" amp; Rows.Count).End(xlUp).Row 1
.Range("A" amp; iLastrow amp; ":D" amp; iLastrow UBound(vNames) - 1).Value = aSum
End With
End Sub
Код в модуле
Option Explicit
Public vNames As Variant
Public vClothes As Variant
Public Sub collectNames()
With ThisWorkbook.Sheets(2)
vNames = .Range("A2", .Range("A" amp; Rows.Count).End(xlUp))
End With
End Sub
Public Sub collectClothItems()
With ThisWorkbook.Sheets(3)
vClothes = .Range("A2", .Range("B" amp; Rows.Count).End(xlUp))
End With
End Sub
Я не использовал словари (возможно, у @Issun может быть идея здесь, он эксперт по dict), но массивы, потому что их было проще сопоставить с диапазонами листов.
Комментарии:
1. У вас есть идея! 🙂 Я хочу, чтобы сводный лист обновлялся новыми значениями, а также удалял или добавлял строки, если что-либо добавлено или удалено из листов 2 и 3. Сумма не берется ниоткуда. Вот где мы вручную вводим и добавляем нужную нам сумму :). Считаете ли вы, что Worksheet_Change необходим? Это, вероятно, было бы быстрее, я думаю. Мне нужно будет попробовать несколько вещей 🙂 Кстати, есть ли у вас какие-нибудь умные идеи о том, как структурировать нужные мне функции в VBA? Возможно, я могу объединить формулы Excel? Единственное, что я знаю, как это сделать, это просмотреть каждую ячейку, проверить значение, перейти к следующему.
2. с помощью формулы вы могли
VLOOKUP
бы получить некоторую информацию, но поскольку вы собираетесь расширять массив (я отредактирую свой ответ, вам не придется перебирать ячейки, а только массив), я не думаю, что это действительно того стоит.3. Взгляните на мой обновленный первый пост. Теперь мне удалось собрать некоторые данные. Но на самом деле сравнение данных, поиск дубликатов и упорядочивание данных. Есть идеи, куда идти дальше?
4. Я обновил свой пост рабочим решением. Я использовал массивы вместо dict, потому что это было проще сопоставить с / с диапазонами листов и легче перебирать. Недостатком является то, что он не проверяет наличие дубликатов.
5. Вау, код довольно прост для чтения и понимания 🙂 Я буду использовать это и немного изменю код, чтобы убедиться, что нет никаких ошибок 🙂 Я обновлю код, когда закончу! 🙂