![]() |
|
#16
|
|||
|
|||
|
Quote:
1. The case of duplicates in column H in NDS_SHEET In NSD_SHEET H24 = H25 = DemoData_0000015_Import.zip You didn't write how to search, so I did this: When the code finds H24 = "DemoData_0000015_Import.zip" in B229 in REF_SHEET, it no longer searches for H25 in REF_SHEET (that's why I use dictionary DIC) So how do you want it now? Should there be 2 results (for H24 and H25)? <#266912.1><line 24> <#266912.1><line 25> ??? Or maybe something else? If you don't say anything, I won't know anything. 2. The issue of duplicates in column B in REF_SHEET. For example, let's say that "DemoData_0000015_Import.zip" occurs 3 times in column B of REF_SHEET - in B299, B367 and B489. How many results should there be? At the moment, the code will find "DemoData_0000015_Import.zip" in B299 and stop searching, it will not search any further to find in B367 and B489 (Exit For in If pos Then … End If). So what do you want now? The code should search further to B367 and B489? 3. Are we looking for "File Name" from column H of sheet NDS_SHEET in column B of sheet REF_SHEET, or vice versa: will we find for each "File Path" from column B of sheet REF_SHEET its "companion" in column H of sheet NDS_SHEET? 4. Or maybe something else that I don't know about? If you don't say anything, I won't know anything. |
|
#17
|
|||
|
|||
|
Quote:
Batman, I understand your frustration. As I tried to explain at the very start, it is a complicated process. Complicated and difficult to explain. The REF_SHEET can contain hundreds of thousands of records. The one I am testing with has 440,000. The NDS_SHEET can have tens of thousands, but for testing I have only 21. The code I provided in modMain launches a userform interface. With that interface you can create all of the possible outcomes. It works. I am just looking for something that might work faster. DemoData_0000015_Import.zip You didn't write how to search, so I did this: When the code finds H24 = "DemoData_0000015_Import.zip" in B229 in REF_SHEET, it no longer searches for H25 in REF_SHEET (that's why I use dictionary DIC) So how do you want it now? Should there be 2 results (for H24 and H25)? <#266912.1><line 24> <#266912.1><line 25> ??? Or maybe something else? If you don't say anything, I won't know anything. That depends on if you select "First Match Only" or "Duplicate Reference Row" in the first case then there should be only one record in the Overlay for #266912.1" in the second case there should be two records. 2. The issue of duplicates in column B in REF_SHEET. For example, let's say that "DemoData_0000015_Import.zip" occurs 3 times in column B of REF_SHEET - in B299, B367 and B489. How many results should there be? At the moment, the code will find "DemoData_0000015_Import.zip" in B299 and stop searching, it will not search any further to find in B367 and B489 (Exit For in If pos Then End If). So what do you want now? The code should search further to B367 and B489? Yes. Every record of the REF_SHEET that might have a match in the NDS_SHEET must be processed. That was my initial approach. Loop through every REF_SHEET record ... with my actual data this was taking about a minute. I changed that initial approach to first loop through the smaller NDS_SHEET to find and create a collection of REF_SHEET Rows that "DO" have a match. I then looped through the Rows in that collection. With the actual data the process now takes about 12 seconds. The options for the REF_SHEET records are: If No Match Found in NDS_SHEET 1. Discard (don't include) RS_SHEET REF/Control# records in Overlay 2. Copy control ID from RS_SHEET as new record in Overlay 3. Cancel processing - don't create overlay 3. Are we looking for "File Name" from column H of sheet NDS_SHEET in column B of sheet REF_SHEET. Yes. NDS_SHEET column 8 list single file name e.g., Test.png. REF_SHEET column 2 can list single or mulitple files names e.g., Testing.png//Test.png//This is a test.png. If InStr(REF_SHEET(2),NDS_SHEET(8)> 0 Then If First Match Option Record and get out Else Record either as new row, or delimited data in existing row. End If ... will we find for each "File Path" from column B of sheet REF_SHEET its "companion" in column H of sheet NDS_SHEET? It is not really a file path. It can be a single file name or multiple files name delimited with // / or \. No. There are three options if a "companion" is not found in the NDS_SHEET. All the looping takes time. As I've said, I've gotten down to 12 seconds with the 440,000 REF_SHEET I have. I like your thought process and its possible it might shave off a a few seconds. I thought a power query might get it done in the blink of and eye?? Thank you. |
|
#18
|
|||
|
|||
|
Quote:
Quote:
1. Change to Code:
ReDim result(1 To UBound(find_data, 1), 1 To 9) That's all |
|
#19
|
|||
|
|||
|
At the moment we are taking all duplicates in REF_SHEET.
Still the matter of duplicates in column H in NDS_SHEET. At the moment H24 = H25 = DemoData_0000015_Import.zip. The code only takes H24 ("First Match Only"?) so we add to DIC key = filename = "DemoData_0000015_Import.zip", item = i = 24 (row number where "DemoData_0000015_Import.zip" occurs). If you want 2 results: <#266912.1><line 24> <#266912.1><line 25> you need to add 2 items to DIC: key = "DemoData_0000015_Import.zip", item = 24 key = "DemoData_0000015_Import.zip", item = 25 In total we take all duplicates in REF_SHEET and all duplicates in H in NDS_SHEET: #266912.1 <line 24 in NDS_SHEET> #266912.1 <line 25 in NDS_SHEET> #77777.1 <line 24 in NDS_SHEET> #77777.1 <line 25 in NDS_SHEET> #77777.2 <line 24 in NDS_SHEET> #77777.2 <line 25 in NDS_SHEET> So 6 results (3*2) for "DemoData_0000015_Import.zip": 3 duplicates in REF_SHEET and 2 duplicates in NDS_SHEET Code for this case: Code:
Option Explicit
Sub demo()
Dim lastRow As Long, pos As Long, i As Long, j As Long, k As Long, count As Long, curr_row As Long, filename As String, key, item, data(), find_data(), result(), dic As Object
With Worksheets("OVERLAY")
' cleaning old results
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow > 1 Then .Range("A2").Resize(lastRow - 1, 9).ClearContents
End With
With Worksheets("NDS_SHEET")
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow = 4 Then Exit Sub ' there is no data in NDS_SHEET
data = .Range("A5").Resize(lastRow - 4, 8).value ' A:H to data
End With
With Worksheets("REF_SHEET")
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow = 1 Then Exit Sub ' there is no data in REF_SHEET
find_data = .Range("A2").Resize(lastRow - 1, 2).value
End With
Set dic = CreateObject("Scripting.Dictionary")
dic.CompareMode = vbTextCompare
For i = 1 To UBound(data, 1)
filename = data(i, 8) ' column 8 sheet NDS_SHEET
If Not dic.Exists(filename) Then
ReDim item(1 To 1)
' first duplicate row number
item(1) = i
dic.Add filename, item
Else
item = dic.item(filename)
ReDim Preserve item(1 To UBound(item) + 1)
' next duplicate row number
item(UBound(item)) = i
dic.item(filename) = item
End If
Next i
' in case of and duplicates in NDS_SHEET and duplicates in REF_SHEET the result array is the largest
ReDim result(1 To UBound(find_data, 1) * UBound(data, 1), 1 To 9)
For Each key In dic.keys
item = dic.item(key) ' array of duplicate row numbers in column H sheet NDS_SHEET
For i = 1 To UBound(find_data, 1)
pos = InStr(1, find_data(i, 2), key, vbTextCompare)
If pos Then
For k = 1 To UBound(item)
count = count + 1
result(count, 1) = find_data(i, 1)
curr_row = item(k) ' line number in data() with given filename
For j = 1 To 8
result(count, j + 1) = data(curr_row, j)
Next j
Next k
End If
Next i
Next key
If count Then Worksheets("OVERLAY").Range("A2").Resize(count, 9).value = result
Set dic = Nothing
End Sub
|
|
#20
|
|||
|
|||
|
Batman,
Batman, I have been off tinkering with the code you sent before this last. Yes, it was returning all the FirstMatch rows (or 9 rows with the our test file) (or 39 rows with my larger test file) As you have already discovered, to return FirstMatch and duplicate rows then you must cycle every NDS file name for every REF file name(s). The MyDemo() below was what I have come up with and was testing before your last post. The Sub YourLastModified() below is your last with a modification to either FirstMatch or Duplicate. Both return 9 rows with FirstMatch option on and 12 rows with FirstMatch option off. You are light years ahead of me with using the Scripting.Dictionary (My hat is off to you). The time difference with our small sample test file is insignificant. With the larger file 440,000 REF_SHEET rows. Your method is about 0.4 seconds faster. However either method is about 4 seconds faster than what I currently have coded in the userform. The only advantage with Sub MyDemo() is that the arrangement of the REF/Control# in the Overlay match those in the REF. That can easily be fixed. So no, worries. Now, there is much more “mud” in the mix, so my next step is to see if I can accommodate the other Dup row options (I think I can). Another chap is off looking at using PowerQuery, to achieve the desired result. Will just have to wait as see what he comes up with. In any case this has been a tremendous learning experience for me and I thank you very much for for your time and interest. Code:
Option Explicit
Sub MyDemo()
Dim lastRow As Long, pos As Long, i As Long, j As Long, count As Long, curr_row As Long, filename As String, key, item, data(), find_data(), result(), dic As Object
Dim arrItems
Dim lngIndex As Long
Dim bMatchFirst As Boolean
Dim Start
Start = Timer
bMatchFirst = False
With Worksheets("OVERLAY")
'cleaning old results
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow > 1 Then .Range("A2").Resize(lastRow - 1, 9).ClearContents
End With
With Worksheets("NDS_SHEET")
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow = 4 Then Exit Sub ' there is no data in NDS_SHEET
data = .Range("A5").Resize(lastRow - 4, 8).value ' A:H to data
End With
With Worksheets("REF_SHEET")
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow = 1 Then Exit Sub ' there is no data in REF_SHEET
find_data = .Range("A2").Resize(lastRow - 1, 2).value
End With
Set dic = CreateObject("Scripting.Dictionary")
dic.CompareMode = vbTextCompare
For i = 1 To UBound(data, 1)
filename = data(i, 8) ' column 8 sheet NDS_SHEET
'we only take the first occurrence of a given filename
'If Not dic.Exists(filename) Then dic.Add filename, i
'No. We take "ALL" filesnames.
dic.Add i, filename
Next i
arrItems = dic.Items
ReDim result(1 To UBound(find_data, 1), 1 To 9)
For i = 1 To UBound(find_data, 1)
For lngIndex = 0 To UBound(arrItems)
'For Each key In dic.Keys
'pos = InStr(1, find_data(i, 2), key, vbTextCompare)
pos = InStr(1, find_data(i, 2), arrItems(lngIndex), vbTextCompare)
If pos Then
count = count + 1
result(count, 1) = find_data(i, 1)
'curr_row = dic.Keys(i).Value ' line number in data() with given filename
curr_row = lngIndex + 1 'dic.Items(lngIndex).Value
For j = 1 To 8
result(count, j + 1) = data(curr_row, j)
Next j
If bMatchFirst Then Exit For
End If
Next lngIndex
Next i
If count Then Worksheets("OVERLAY").Range("A2").Resize(count, 9).value = result
Set dic = Nothing
MsgBox Timer - Start
End Sub
Sub YourLastModified()
Dim Start
Start = Timer
Dim lastRow As Long, pos As Long, i As Long, j As Long, k As Long, count As Long, curr_row As Long, filename As String, key, item, data(), find_data(), result(), dic As Object
Dim bFirstMatch As Boolean
bFirstMatch = False
With Worksheets("OVERLAY")
' cleaning old results
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow > 1 Then .Range("A2").Resize(lastRow - 1, 9).ClearContents
End With
With Worksheets("NDS_SHEET")
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow = 4 Then Exit Sub ' there is no data in NDS_SHEET
data = .Range("A5").Resize(lastRow - 4, 8).value ' A:H to data
End With
With Worksheets("REF_SHEET")
lastRow = .Cells(Rows.count, "A").End(xlUp).Row
If lastRow = 1 Then Exit Sub ' there is no data in REF_SHEET
find_data = .Range("A2").Resize(lastRow - 1, 2).value
End With
Set dic = CreateObject("Scripting.Dictionary")
dic.CompareMode = vbTextCompare
For i = 1 To UBound(data, 1)
filename = data(i, 8) ' column 8 sheet NDS_SHEET
If Not dic.Exists(filename) Then
ReDim item(1 To 1)
' first duplicate row number
item(1) = i
dic.Add filename, item
Else
item = dic.item(filename)
ReDim Preserve item(1 To UBound(item) + 1)
' next duplicate row number
item(UBound(item)) = i
dic.item(filename) = item
End If
Next i
' in case of and duplicates in NDS_SHEET and duplicates in REF_SHEET the result array is the largest
ReDim result(1 To UBound(find_data, 1) * UBound(data, 1), 1 To 9)
For Each key In dic.Keys
item = dic.item(key) ' array of duplicate row numbers in column H sheet NDS_SHEET
For i = 1 To UBound(find_data, 1)
pos = InStr(1, find_data(i, 2), key, vbTextCompare)
If pos Then
For k = 1 To UBound(item)
'If k > 1 Then MsgBox item(k)
count = count + 1
result(count, 1) = find_data(i, 1)
curr_row = item(k) ' line number in data() with given filename
For j = 1 To 8
result(count, j + 1) = data(curr_row, j)
Next j
If bFirstMatch Then Exit For
Next k
End If
Next i
Next key
If count Then Worksheets("OVERLAY").Range("A2").Resize(count, 9).value = result
Set dic = Nothing
MsgBox Timer - Start
End Sub
|
|
#21
|
|||
|
|||
|
|
|
#22
|
|||
|
|||
|
Well not solved. Moved along certainly. Want to leave the thread open in case someone else offers a different approach.
|
|
#23
|
|||
|
|||
|
Batman, After working with this code a bit more, I am going to mark this thread solved. I found that I didn't really need to use a dictionary at all and I believe the real efficiency gain was writing data to the arrays vice directly in the worksheet. The following code does 95% on what I need and with a 440,000 row REF sheet, it does it in under 9 seconds. That is a big improvement and I think with a little more work I can call the cannon ball fully polished. If someone comes along in this tread or the crosspost with a PowerQuery solution, I'll be eager to look at it but you have been a tremendous help. Thank you again!! Code:
Option Explicit
Sub MyModified()
Dim oOS As Worksheet
Dim strColHeadings As String
Dim varNDS_Data(), varREF_Data(), varOverlay_Data()
Dim lngST As Long, lngIndex As Long, lngFldIndex As Long, lngItemIndex As Long, lngRecordIndex As Long, lngNDSRowIndex As Long
Dim lngOSRow As Long, lngOSCol As Long
Dim strFileName As String
Dim bMatched As Boolean, bNoMatch As Boolean, bNoREFMatchCanx As Boolean, bNoREFMatchCopyID As Boolean, bFirstMatch As Boolean
Dim bDupRow As Boolean, bConcatenateDupSC As Boolean, bConcatenateDupLF As Boolean, bNoMultiMatches As Boolean
Dim bDelim As Boolean, strDelimiter As String
lngST = Timer
strColHeadings = "REF/Contol#|Ser. Nb|Document Type|Document Date|Classification|Title|Description|Has Attachments|File Name"
bMatched = False
'NDS_Options Note: Only one on the next line shoul be true
bFirstMatch = True: bDupRow = False: bConcatenateDupSC = False: bConcatenateDupLF = False: bNoMultiMatches = False
'REF_Options Note: Normally both on next line are Fallse. Only one on the next line can be true
bNoREFMatchCopyID = False: bNoREFMatchCanx = False
strDelimiter = ";": If bConcatenateDupLF = True Then strDelimiter = vbCrLf
On Error Resume Next
Set oOS = Worksheets("OVERLAY")
If Err.Number = 0 Then
Application.DisplayAlerts = False
oOS.Delete
Application.DisplayAlerts = True
End If
On Error GoTo 0
Set oOS = Worksheets.Add
oOS.Name = "OVERLAY"
DoEvents
With Worksheets("NDS_SHEET")
lngIndex = .Cells(Rows.count, "A").End(xlUp).Row
If lngIndex = 4 Then Exit Sub 'There is no data in NDS_SHEET
varNDS_Data = .Range("A5").Resize(lngIndex - 4, 8).Value
End With
With Worksheets("REF_SHEET")
lngIndex = .Cells(Rows.count, "A").End(xlUp).Row
If lngIndex = 1 Then Exit Sub 'There is no data in REF_SHEET
varREF_Data = .Range("A2").Resize(lngIndex - 1, 2).Value
End With
ReDim varOverlay_Data(1 To UBound(varREF_Data, 1), 1 To 9)
For lngIndex = 1 To UBound(varREF_Data, 1)
bNoMatch = True
bMatched = False
For lngItemIndex = 1 To UBound(varNDS_Data, 1)
If InStr(1, varREF_Data(lngIndex, 2), varNDS_Data(lngItemIndex, 8), vbTextCompare) > 0 Then
bNoMatch = False
If Not bMatched Then
lngRecordIndex = lngRecordIndex + 1
varOverlay_Data(lngRecordIndex, 1) = varREF_Data(lngIndex, 1)
lngNDSRowIndex = lngItemIndex + 1
For lngFldIndex = 1 To 8
varOverlay_Data(lngRecordIndex, lngFldIndex + 1) = varNDS_Data(lngNDSRowIndex, lngFldIndex)
Next lngFldIndex
If bFirstMatch Then Exit For
bMatched = True
Else
If Not bNoMultiMatches Then
If bDupRow Then
lngRecordIndex = lngRecordIndex + 1
varOverlay_Data(lngRecordIndex, 1) = varREF_Data(lngIndex, 1)
lngNDSRowIndex = lngItemIndex + 1
For lngFldIndex = 1 To 8
varOverlay_Data(lngRecordIndex, lngFldIndex + 1) = varNDS_Data(lngNDSRowIndex, lngFldIndex)
Next lngFldIndex
Else
For lngFldIndex = 1 To 8
varOverlay_Data(lngRecordIndex, lngFldIndex + 1) = varOverlay_Data(lngRecordIndex, lngFldIndex + 1) & strDelimiter & varNDS_Data(lngNDSRowIndex, lngFldIndex)
Next lngFldIndex
End If
Else
MsgBox "Overlay function canceled due to multiple match on REF_SHEET row: " & lngIndex + 1
GoTo lbl_Exit
End If
End If
End If
Next lngItemIndex
Select Case True
Case bNoREFMatchCopyID And bNoMatch
lngRecordIndex = lngRecordIndex + 1
'varOverlay_Data(lngRecordIndex, 1) = varREF_Data(lngIndex, 1)
Case bNoREFMatchCanx And bNoMatch
MsgBox "Overlay function canceled due to no NDS match for REF_SHEET row: " & lngIndex
Exit For
End Select
Next lngIndex
If lngRecordIndex Then oOS.Range("A2").Resize(lngRecordIndex, 9).Value = varOverlay_Data
With oOS
.Range("A1").Resize(1, 9).Value = Split(strColHeadings, "|")
DoEvents
.Rows(1).Font.Bold = True
.Rows(1).AutoFilter
.Rows(1).Select
.Application.ActiveWindow.SplitColumn = 1
.Application.ActiveWindow.SplitRow = 1
.Application.ActiveWindow.FreezePanes = True
DoEvents
With .UsedRange
.WrapText = False
.EntireColumn.AutoFit
If .ColumnWidth > 60 Then .ColumnWidth = 60
End With
DoEvents
lngOSRow = 2
Do While Len(.Cells(lngOSRow, 2).Value) > 0
lngOSCol = 2
Do While Len(.Cells(1, lngOSCol).Value) > 0
.Cells(lngOSRow, lngOSCol).FormulaR1C1 = .Cells(lngOSRow, lngOSCol).Value
lngOSCol = lngOSCol + 1
Loop
lngOSRow = lngOSRow + 1
Loop
.UsedRange.Columns.AutoFit
.UsedRange.Rows.AutoFit
DoEvents
If bDupRow Then
With .Columns(1)
.FormatConditions.AddUniqueValues
.FormatConditions(.FormatConditions.count).SetFirstPriority
With .FormatConditions(1)
.DupeUnique = xlDuplicate
.Font.Color = -16383844
.Font.TintAndShade = 0
.Interior.PatternColorIndex = xlAutomatic
.Interior.Color = 13551615
.Interior.TintAndShade = 0
.StopIfTrue = False
End With
End With
End If
End With
MsgBox Timer - lngST
lbl_Exit:
Set oOS = Nothing
Exit Sub
lbl_Canx:
Application.DisplayAlerts = False
oOS.Delete
Application.DisplayAlerts = True
GoTo lbl_Exit
End Sub
|
|
#24
|
|||
|
|||
|
Quote:
1. Yes, when there is a lot of data, reading/writing to the sheet should not be done cell by cell. Data should be read once into tables, something should be done on this data and once put into the sheet. And a dictionary can be useful. Note that at the beginning I did not know much about what you intended to do, you did not say anything about the data. At the beginning I did not know whether you were taking duplicates in H in the NDS_SHEET sheet but I assumed that I was not taking duplicates. So I am taking only the first one and will not check the next ones. I did not know anything about the data but it is possible that there are e.g. 10 duplicates of "DemoData_0000015_Import.zip". Of course, you can not use the dictionary, but each time you have to assess whether it is better to use the dictionary or not. Let's assume that there are 10 rows in NDS_SHEET and each one contains "DemoData_0000015_Import.zip" and in REF_SHEET 1000 rows and only 1 row contains "DemoData_0000015_Import.zip". There is only 1 result. DIC contains only 1 key and in the worst case, when "DemoData_0000015_Import.zip" is in the last row of REF_SHEET, the code executes 1000 FOR loops (1000 INSTR). If the dictionary is not used, then in the worst case after executing 999*10 = 9990 FOR loops (999 external * 10 internal) - 9990 times of INSTR execution the code will not find a match yet. Only with lngIndex = 1000 and lngItemIndex = 1 will it find a match. 2. I don't understand this Code:
lngNDSRowIndex = lngItemIndex + 1 varOverlay_Data(lngRecordIndex, lngFldIndex + 1) = varNDS_Data(lngNDSRowIndex, lngFldIndex) Code:
lngNDSRowIndex = lngItemIndex varOverlay_Data(lngRecordIndex, lngFldIndex + 1) = varNDS_Data(lngNDSRowIndex, lngFldIndex) Code:
varOverlay_Data(lngRecordIndex, lngFldIndex + 1) = varNDS_Data(lngItemIndex, lngFldIndex) |
|
#25
|
|||
|
|||
|
Batman,
Just headed out for a short leisure trip. Haven't fully digested your comments and I will have to look it over closely but I think you are correct about 2. Thank you. |
|
#26
|
|||
|
|||
|
Quote:
1. REF_SHEET has 1000 rows - the first 999 rows contain e.g. "DemoData_A000001.zip", "DemoData_A000002.zip", ..., "DemoData_A000999.zip" - the last row contains "DemoData_0000015_Import.zip" 2. NDS_SHEET has 10 rows, each containing "DemoData_0000015_Import.zip" Therefore, there is only 1 result: <REF/Contol# from the last row of REF>< 8 columns from the first row of NDS> A. from DIC - 10 FOR loops to add key = "DemoData_0000015_Import.zip", item = 1 - 999 FOR loops and the code will not find "DemoData_0000015_Import.zip" (the only key with DIC). Only loop 1000 will find "DemoData_0000015_Import.zip" on the last line of REF. In total INSTR is executed 1000 times + 10 times "If Not dic.Exists(filename) Then dic.Add filename, and" B. Without DIC For lngIndex = 1 to 999 and lngItemIndex = 1 to 10 the code executes 999*10 = 9990 times INSTR, and will not find a match. Only with lngIndex = 1000 and lngItemIndex = 1 will it find a match. In total the code executes INSTR 9990 + 1 = 9991 times. |
|
#27
|
|||
|
|||
|
Batman,
Yes, you were correct. You seem to have a very good handle on dictionary. Perhaps you can explain why this code errors: Code:
Sub Test()
Dim oDic As Object, oKey
Dim varVals
Dim lngIndex As Long
varVals = Split("APPLES,Apples,Pears,Pears,PEARS,pears,Blueberries,APPLES", ",")
Set oDic = CreateObject("Scripting.Dictionary")
oDic.CompareMode = 1
For lngIndex = 0 To UBound(varVals)
If oDic.Exists(varVals(lngIndex)) Then
oDic.Item(varVals(lngIndex)) = oDic.Item(varVals(lngIndex)) + 1
Else
oDic.Add varVals(lngIndex), 1
End If
Next
For Each oKey In oDic.Keys
MsgBox oKey & " count = " & oDic.Item(oKey)
Next oKey
'Why can't set oKey to a spefic key index e.g.:
oKey = oDic.Keys(1).Value 'Errors here
MsgBox oKey & " count = " & oDic.Item(oKey)
lbl_Exit:
Exit Sub
End Sub
|
|
#28
|
|||
|
|||
|
1. oKey = oDic.Keys(1).Value
oDic.Add varVals(lngIndex), 1 => Key = varVals(lngIndex) = STRING Even if oDic.Keys returns key, key is not an object so it cannot have a property, and it certainly cannot have a VALUE property 2. oKey = oDic.Keys(1) still causes an error. Why? Take a test and change to menu Tools -> References -> select "Microsoft Scripting Runtime" Code:
Subtest2()
Dim oDic As Scripting.Dictionary, oKey
Dim varVals
Dim lngIndex As Long
varVals = Split("APPLES,Apples,Pears,Pears,PEARS,pears,Blueberries,APPLES", ",")
Set oDic = New Scripting.Dictionary
oDic.CompareMode = 1
For lngIndex = 0 To UBound(varVals)
If oDic.Exists(varVals(lngIndex)) Then
oDic.Item(varVals(lngIndex)) = oDic.Item(varVals(lngIndex)) + 1
Else
oDic.Add varVals(lngIndex), 1
EndIf
Next
For Each oKey In oDic.Keys
MsgBox oKey & " count = " & oDic.Item(oKey)
Next oKey
oKey = oDic.Keys(1)
MsgBox oKey & " count = " & oDic.Item(oKey)
lbl_Exit:
Exit Sub
End Sub
--------------- A. My explanation: VBA is a scripting language, interpreted, not compiled. In my code, thanks to adding a reference and "early binding", the interpreter already "at the beginning" knows that Keys is a method - a function without a parameter that returns an array, so (1) means the first element of this array. In your code, because of "late binding", the interpreter does not know whether Keys is a method or properties. It's probably looking for a Keys function with one parameter, and there isn't one. -------------------------------- With "late binding" (your code) you have 2 ways: 1. Code:
Dim arrKey arrKey = oDic.Keys ' the interpreter looks for method Keys without a parameter, and it will definitely find oKey = arrKey(1) ' Keys returns an array, so arrKey is an array and arrKey(1) is the array element at index 1 Code:
oKey = oDic.Keys()(1) ' oDic.Keys() means method without a parameter, and returns an array, so (1) is the array element at index 1 MsgBox oKey & " count = " & oDic.Item(oKey) |
|
#29
|
|||
|
|||
|
Yes. That all makes sense. There is one final piece to the larger project you have been involved with. I will post it later this evening to see if you have an idea. Thank you.
|
|
#30
|
|||
|
|||
|
I'd use:
Code:
Sub M_snb()
sn = Sheet1.Range("H2:H23")
sp = [transpose(ref_sheet!B2:B17)]
For j = 1 To UBound(sn)
c00 = c00 & vbLf & Join(Filter(sp, sn(j, 1)), vbLf)
Next
y = UBound(Filter(Split(c00, vbLf), ".")) + 1
MsgBox Join(Filter(Split(c00, vbLf), "."), vbLf), , y
End Sub
|
|
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| How to Remove the subtotal columns in a sheet | Marcia | Excel | 3 | 12-01-2023 05:48 AM |
Relating cells in a row in one sheet to cells in columns on another sheet.
|
mbesspiata3 | Excel | 2 | 01-06-2017 05:42 AM |
Create a New Sheet from Existing Sheet with Specific Columns
|
malam | Excel Programming | 1 | 10-17-2014 10:01 PM |
From an XL sheet ,how to keep the group of columns which match with other XL sheet
|
Zubairkhan | Excel | 2 | 03-04-2014 10:57 PM |
| Removing columns within sheet | shabbaranks | Excel | 2 | 09-11-2012 05:03 AM |