So I have this Excel workbook which basically is supposed to be a data sheet for work clothes for each employee. What I want is to have one sheet for each person (first name and last name), then one sheet for each clothing available.
Then one sheet to merge it all together. But, this would involve a repeat of each name as many times as there are unique cloth types. Hard to explain, but I've got a workbook available for download here: http://www.mediafire.com/?dxurbdjq340su6j
Sheet2(Users) contains a simple list of each unique user. Sheet3(Articles) contains a list of each unique clothing article. And then finally we have the first Sheet(Summary) which contains a merged list of it all. Based on this Summary sheet, I'm gonna create a pivot ta开发者_运维技巧ble later. But first I need the functionality here to be dynamic. Whenever a new user or clothing is added or deleted, I only want to do this in Sheet2 or Sheet3. Whatever is in Sheet1 should collect the data dynamically.
Any idea? Would I have to create a macro to do this?
Edit: Ok, so I've created a module with two public Dictionaries. Here's the code I've got so far:
ThisWorkbook
Private Sub Workbook_Open()
' Create dictionaries
Set dictName = New Dictionary
Set dictClothItems = New Dictionary
' Collect data
collectDictName
collectDictClothItems
End Sub
Module1:
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" & 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" & Rows.Count).End(xlUp))
For Each strClothName In rngName
dictClothItems.Add strClothName, ""
Next
End With
End Sub
So, here I collect the data and store these in an array. I wasn't sure how to collect the data from the range, so I used For Each strName In rngName
. Looks like it collects other data that I really don't need as well. Can probably fix that up by creating a string variable and assigning the value I'm after to that. And then adding that string to the Dictionary. Anyways, now that the data's collected, I need to compare and add it to the actual Summary sheet now. Any idea on where to begin?
Question rephrasing
So basically, what you want is:
Each time you add a new value on either Sheet2 (Users) or Sheet3 (Clothes), you want Excel to dynamically add on Sheet1 (Summary) a new row for each value on the other Sheet (Users or Clothes depending on the one that was changed)
Btw, where does the amount come from?
Answer
Yet, to answer your question, the easiest way is to do it with VBA so it will be dynamic.
Here is what you can do:
- add en event
Worksheet_Change()
on both Sheet2 and Sheet3 (see on Chip Pearson website how to do it) - this procedure will watch every change on these sheets. Every time a user add a value, you should
loop over the other Sheetget the value from the other sheet and populate an array (Clothes or User depending on the value) - IMHO, the easiest way to consolidate the data is to
createloop over your created array (or use a dictionary)and append every new row to your array - eventually, you can add the array in your
Summary
sheet
Don't hesitate to ask for some more information if you need or ask a new question with what you've tried if you are still stuck.
[EDIT 2] Here is a full working solution for articles (easily adaptable for users)
Code on Sheet3 (Articles)
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" & Rows.Count).End(xlUp).Row + 1
.Range("A" & iLastrow & ":D" & iLastrow + UBound(vNames) - 1).Value = aSum
End With
End Sub
Code in a module
Option Explicit
Public vNames As Variant
Public vClothes As Variant
Public Sub collectNames()
With ThisWorkbook.Sheets(2)
vNames = .Range("A2", .Range("A" & Rows.Count).End(xlUp))
End With
End Sub
Public Sub collectClothItems()
With ThisWorkbook.Sheets(3)
vClothes = .Range("A2", .Range("B" & Rows.Count).End(xlUp))
End With
End Sub
I didn't use dictionaries (maybe @Issun may have an idea here, he is a dict-expert) but arrays because it was easier to map to the sheet ranges.
精彩评论