everyone. I appreciate the people that helped me a few days back. I can say that there has been a bit of progress, but it's pretty much not done yet.
I'm trying to compare the Primary Store (Column C) and Secondary Store (Column E) combinations under the same Buyer (Column G). If the Buyer has more than 1 combination of stores, the filter will not be applied to them and will give me an error instead. Somebody helped me through this (Thank you, Michał Turczyn!), but I am stuck at yet another wall.
I wanted to confirm if the VBA 'Dictionary' works in storing data that are in other languages? All of the data within the cell are either numerical or in Japanese.
The Dictionary keys are ending up as 'Empty' on my side. May I have some help or even suggestions? When I get the debug window, it highlights the [If DICT(SELECTED_ENDUSER).Count > 1 Then]. I'm at my wits end.
Dim WS As Worksheet
Dim LAST_ROW As Long
Dim DICT As Object
Dim ENDUSER As String
Dim i As Long
Dim KEY As Variant
Dim UNIQUE_PAIR As String
Dim PAIRS_DICT As Object
Dim SELECTED_ENDUSER As String
Dim FILTERED_ENDUSER As Boolean
Set WS = ThisWorkbook.ActiveSheet
LAST_ROW = WS.Cells(WS.Rows.Count, "G").End(xlUp).Row
Set DICT = CreateObject("Scripting.Dictionary")
Set DICT = New Dictionary
For i = 3 To LAST_ROW
ENDUSER = Trim(WS.Cells(i, "G").Value)
If ENDUSER <> "" Then
UNIQUE_PAIR = WS.Cells(i, "C").Value & "|" & WS.Cells(i, "E").Value
If Not DICT.Exists(ENDUSER) Then
Set PAIRS_DICT = CreateObject("Scripting.Dictionary")
DICT.Add ENDUSER, PAIRS_DICT
End If
DICT(ENDUSER)(UNIQUE_PAIR) = 1
End If
Next i
SELECTED_ENDUSER = Cells(AROW, 7).Value
FILTERED_ENDUSER = DICT.Exists(SELECTED_ENDUSER)
If Not FILTERED_ENDUSER Then
MsgBox "エンドユーザー「" & SELECTED_ENDUSER & "」はいませんでした。"
Exit Sub
End If
If DICT(SELECTED_ENDUSER).Count > 1 Then
MsgBox "コンフリ有りエンドユーザー様です。", vbCritical
Exit Sub
End If
If WS.AutoFilterMode Then WS.AutoFilter.ShowAllData
WS.Range("A1").AutoFilter Field:=7, Criteria1:=SELECTED_ENDUSER
MsgBox "エンドユーザー:" & SELECTED_ENDUSER & "。"
Application.ScreenUpdating = True
End Sub
In Excel VBA, a Dictionary
is an object that stores data as key-value pairs, allowing fast lookup and grouping - it works with all objects, not just "words" so it should not be confused with every day meaning of this word and it can certainly be used to for Japanese.
Set DICT = CreateObject("Scripting.Dictionary")
Set DICT = New Dictionary
You don't need both, Set DICT = CreateObject("Scripting.Dictionary")
is enough.
VBA Dictionary can handle Unicode, including Japanese characters. However, issues can arise if:
Make sure to clean your inputs - ENDUSER = Trim(CStr(WS.Cells(i, "G").Value))
and
SELECTED_ENDUSER = Trim(CStr(Cells(AROW, 7).Value))
My suggestion:
Sub FilterByStoreCombination()
Dim wsActive As Worksheet
Dim lastRow As Long
Dim buyerStoreMap As Object
Dim buyerName As String
Dim rowIndex As Long
Dim storePairKey As String
Dim storePairDict As Object
Dim selectedBuyer As String
Dim isBuyerFound As Boolean
Dim activeRow As Long
' Initialize worksheet and dictionary
Set wsActive = ThisWorkbook.ActiveSheet
lastRow = wsActive.Cells(wsActive.Rows.Count, "G").End(xlUp).Row
Set buyerStoreMap = CreateObject("Scripting.Dictionary")
' Build dictionary of buyers and their unique store combinations
For rowIndex = 3 To lastRow
buyerName = Trim(CStr(wsActive.Cells(rowIndex, "G").Value))
If buyerName <> "" Then
storePairKey = Trim(CStr(wsActive.Cells(rowIndex, "C").Value)) & "|" & Trim(CStr(wsActive.Cells(rowIndex, "E").Value))
If Not buyerStoreMap.Exists(buyerName) Then
Set storePairDict = CreateObject("Scripting.Dictionary")
buyerStoreMap.Add buyerName, storePairDict
End If
buyerStoreMap(buyerName)(storePairKey) = 1
End If
Next rowIndex
' Get selected buyer from the active row
activeRow = ActiveCell.Row
selectedBuyer = Trim(CStr(wsActive.Cells(activeRow, 7).Value))
isBuyerFound = buyerStoreMap.Exists(selectedBuyer)
If Not isBuyerFound Then
MsgBox "The selected buyer '" & selectedBuyer & "' was not found.", vbExclamation
Exit Sub
End If
' Check for multiple store combinations
If buyerStoreMap(selectedBuyer).Count > 1 Then
MsgBox "This buyer has conflicting store combinations.", vbCritical
Exit Sub
End If
' Apply filter to show only the selected buyer
If wsActive.AutoFilterMode Then wsActive.AutoFilter.ShowAllData
wsActive.Range("A1").AutoFilter Field:=7, Criteria1:=selectedBuyer
MsgBox "Buyer: " & selectedBuyer & " has been filtered.", vbInformation
Application.ScreenUpdating = True
End Sub
Edit, the code works with my test inputs being as per the below table.
A | B | C | D | E | F | G |
---|---|---|---|---|---|---|
Store Omega | Outlet A | Buyer002 | ||||
Store Alpha | Outlet E | Buyer003 | ||||
Store Beta | Outlet E | Buyer001 | ||||
Store Delta | Outlet B | Buyer001 | ||||
Store Gamma | Outlet C | Buyer005 | ||||
Store Alpha | Outlet C | Buyer004 | ||||
Store Alpha | Outlet E | Buyer003 | ||||
Store Delta | Outlet A | Buyer002 | ||||
Store Gamma | Outlet D | Buyer004 | ||||
Store Gamma | Outlet D | Buyer005 | ||||
Store Gamma | Outlet C | Buyer001 | ||||
Store Alpha | Outlet E | Buyer003 | ||||
Store Alpha | Outlet E | Buyer003 | ||||
Store Beta | Outlet D | Buyer002 | ||||
Store Alpha | Outlet E | Buyer003 | ||||
Store Delta | Outlet C | Buyer002 | ||||
Store Gamma | Outlet D | Buyer001 | ||||
Store Alpha | Outlet B | Buyer004 | ||||
Store Omega | Outlet D | Buyer004 |
Working screenshots: