Run Dictionary Script & Find based on multiple criteria

Lil Stinker

Board Regular
Joined
Feb 16, 2022
Messages
143
Office Version
  1. 2019
Platform
  1. Windows
@DanteAmor Hello again!

Since I only understand basic VBA, I need help figuring out how to update my Inventory sheet with returns based on a few different criteria. Here is the code you provided for locating and updating the serial numbers in inventory when items were going out.
VBA Code:
Sub out_serial_number()
  Dim sh1 As Worksheet, sh2 As Worksheet
  Dim a As Variant, b As Variant, c As Variant
  Dim dic As Object, rng As Range
  Dim i&, j&, wRow&
  Dim dt As Date, lo As String, cad As String
  Dim f As Range
  
  Set sh1 = Sheets("Sheet1")
  Set sh2 = Sheets("Sheet2")
  Set dic = CreateObject("Scripting.Dictionary")
  If sh1.AutoFilterMode Then sh1.AutoFilterMode = False
  If sh2.AutoFilterMode Then sh2.AutoFilterMode = False
  sh1.Cells.EntireRow.Hidden = False
  sh2.Cells.EntireRow.Hidden = False
  
  Set f = sh1.Range("B:B").Find("SERIAL NUMBERS", , xlValues, xlWhole, xlByRows, xlPrevious, False)
  a = sh1.Range("B11:O" & f.Row - 1).Value
  b = sh2.Range("B2:B" & sh2.Range("B" & Rows.Count).End(3).Row).Value
  c = sh2.Range("E2:G" & sh2.Range("B" & Rows.Count).End(3).Row).Value
  Set rng = sh2.Range("F1")
  
  dt = sh1.Range("A1").Value
  lo = sh1.Range("H1").Value
  
  For i = 1 To UBound(b, 1)
    dic(b(i, 1)) = i
  Next
  
  For i = 1 To UBound(a, 1)
    For j = 1 To UBound(a, 2)
      If a(i, j) <> "" Then
        If dic.exists(a(i, j)) Then
          wRow = dic(a(i, j))
          c(wRow, 1) = "Out"
          c(wRow, 2) = lo
          c(wRow, 3) = dt
          Set rng = Union(rng, sh2.Range("F" & wRow + 1))
        Else
          cad = cad & a(i, j) & vbCr
        End If
      End If
    Next
  Next
  
  sh2.Range("E2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
  rng.Font.Bold = True
  sh2.Range("F1").Font.Bold = False
  If cad <> "" Then
    MsgBox cad, , "Serial number was not found in inventory"
  End If
End Sub
Now, however, I need to mark the items "IN" but the process is a bit different. Not only does it need to find the matching serial number on the Inventory sheet, but it also needs to match the status based on the codes entered into a corresponding range on Sheet1. Based on my post from yesterday, Populate range based on match found between Userform & another range, I need to find the matching serial number and if the corresponding code range has a "Y", mark it "IN" on the Inventory sheet. If it has an "R", mark it as "DMG" on Inventory and for all entries, include the date of return on the Inventory sheet (or Sheet2).

It should look something like this:
Book1.xlsm
ABCDEFGHZAAABACADAEAFAG
12/3/2023Date Out2/13/2023Date InLocationOC Carnival Event
2SERIAL NUMBERSApplesSerial Codes
3011401642644476471649455106YRGYY
4016401742754480471749485107RDyRY
Sheet1

Book1.xlsm
ABCDEFGH
1Item IDSerialNumberItemDescriptionStatusLocationDateOutReturnDate
21011ApplesRed DeliciousINWarehouse2/13/2023
32016ApplesGranny SmithDMGRepair2/6/2023
434016ApplesGranny SmithDMGRepair2/13/2023
544264ApplesRed DeliciousOUTOC Carnival Event2/3/2023
654476OrangesNavalOUTOC Carnival Event2/3/2023
764945ApplesGranny SmithINWarehouse2/13/2023
875106PearsBoschINWarehouse2/13/2023
984716PearsBoschINWarehouse2/6/2023
1094017OrangesNavalINWarehouse2/13/2023
Inventory
 

Excel Facts

Why does 9 mean SUM in SUBTOTAL?
It is because Sum is the 9th alphabetically in Average, Count, CountA, Max, Min, Product, StDev.S, StDev.P, Sum, VAR.S, VAR.P.
Assumptions:
1. As I recall, the serial numbers started on row 11 from B to O.
But you can adjust it in this line:
a = sh1.Range("B11:AN" & f.Row - 1).Value 'Fit the starting row number of the serial numbers

2. It also adjusts the date and location:
dt_in = sh1.Range("D9").Value 'Fit the cell of the date in
lo = sh1.Range("H9").Value 'Fit the cell of the location

3. I also remember that you had the text "SERIAL NUMBERS" at the end of the data in column B.

4. If it doesn't have "Y" and it doesn't have "R" then the status will be empty.

5. Now you will have 2 macros one macro for OUT and now this macro for IN.

VBA Code:
Sub IN_serial_number()
  Dim sh1 As Worksheet, sh2 As Worksheet
  Dim a As Variant, b As Variant, c As Variant
  Dim dic As Object, rng As Range
  Dim i&, j&, wRow&
  Dim dt_in As Date, lo As String, cad As String, sCod As String
  Dim f As Range
  
  Set sh1 = Sheets("Sheet1")
  Set sh2 = Sheets("Inventory")
  Set dic = CreateObject("Scripting.Dictionary")
  If sh1.AutoFilterMode Then sh1.AutoFilterMode = False
  If sh2.AutoFilterMode Then sh2.AutoFilterMode = False
  sh1.Cells.EntireRow.Hidden = False
  sh2.Cells.EntireRow.Hidden = False
  
  Set f = sh1.Range("B:B").Find("SERIAL NUMBERS", , xlValues, xlWhole, xlByRows, xlPrevious, False)
  
  a = sh1.Range("B11:AN" & f.Row - 1).Value    'Fit the starting row number of the serial numbers
  dt_in = sh1.Range("D9").Value               'Fit the cell of the date in
  lo = sh1.Range("H9").Value                  'Fit the cell of the location
  
  b = sh2.Range("B2:B" & sh2.Range("B" & Rows.Count).End(3).Row).Value
  c = sh2.Range("E2:H" & sh2.Range("B" & Rows.Count).End(3).Row).Value
  Set rng = sh2.Range("F1")
  For i = 1 To UBound(b, 1)
    dic(b(i, 1)) = i
  Next
  
  For i = 1 To UBound(a, 1)
    For j = 1 To 14             'from column B to column O
      If a(i, j) <> "" Then
        If dic.exists(a(i, j)) Then
          wRow = dic(a(i, j))
          sCod = ""
          Select Case a(i, j + 25)
            Case "Y": sCod = "IN"
            Case "R": sCod = "DMG"
          End Select
          c(wRow, 1) = sCod
          c(wRow, 2) = lo
          c(wRow, 4) = dt_in
          Set rng = Union(rng, sh2.Range("F" & wRow + 1))
        Else
          cad = cad & a(i, j) & vbCr
        End If
      End If
    Next
  Next
  
  sh2.Range("E2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
  rng.Font.Bold = True
  sh2.Range("F1").Font.Bold = False
  If cad <> "" Then
    MsgBox cad, , "Serial number was not found in inventory"
  End If
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Cordially
Dante Amor
--------------​
 
Upvote 0
I'm getting inconsistent results with this on both my test workbook and actual workbook. Honestly, I'm completely baffled. Now it seems that neither the original working code for marking items Out is running correctly in my test workbook either. It appears to only recognize serial numbers starting with zero or letters in them when running the Out code. The cad msgbox comes up "not finding" every serial number that is just a number with no starting zero or letter. As a result, it only marks the found numbers Out on the Inventory sheet.

When running the In code, the results are inconsistent. It seems to find all of the serial numbers despite the cad msgbox coming up with the identical numbers not found. However, only one number was marked DMG even though I have a few marked "R" which should signify DMG. And only a handful of results populated with the Return Date.

I've tried changing the formatting on both sheets to General and Text but the results are the same. Perhaps my initial test sample didn't include serial numbers with letters and starting zeros? I've posted a new sample below to demonstrate the modified ranges in the code.

I did make some minor modifications to both macros but, as I mentioned in the previous post, the Out macro was working just fine even with my modifications. Please tell me if I screwed something up.
Out:
VBA Code:
  Dim sh1 As Worksheet, sh2 As Worksheet
  Dim a As Variant, b As Variant, c As Variant
  Dim dic As Object, rng As Range, f As Range
  Dim i&, j&, wRow&
  Dim dt As Date, dtN As Date, lo As String, cad As String
  Dim count As Long, benchmark As Double
  
  Set sh1 = Sheets("Sheet1")
  Set sh2 = Sheets("Inventory")
  Set dic = CreateObject("Scripting.Dictionary")
'    If sh2.AutoFilterMode Then sh2.AutoFilterMode = False  <--turned off auto filter altogether so no longer needed
'  sh1.Cells.EntireRow.Hidden = False
  Set f = sh1.Range("B:B").Find("SERIAL NUMBERS", , xlValues, xlWhole, xlByRows, xlPrevious, False)
  a = sh1.Range("B3:S" & f.Row - 1).Value
  b = sh2.Range("B2:B" & sh2.Range("B" & Rows.count).End(3).Row).Value
  c = sh2.Range("E2:H" & sh2.Range("B" & Rows.count).End(3).Row).Value
  Set rng = sh2.Range("F1")
  
  dt = sh1.Range("A1").Value
  lo = sh1.Range("H1").Value
  
  For i = 1 To UBound(b, 1)
    dic(b(i, 1)) = i
  Next
  
  For i = 1 To UBound(a, 1)
    For j = 1 To UBound(a, 2)
      If a(i, j) <> "" Then
        If dic.exists(a(i, j)) Then
          wRow = dic(a(i, j))
          c(wRow, 1) = "OUT"
          c(wRow, 2) = lo
          c(wRow, 3) = dt
          Set rng = Union(rng, sh2.Range("F" & wRow + 1))
        Else
          cad = cad & a(i, j) & vbCr
        End If
      End If
    Next
  Next
  
  sh2.Range("E2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
  rng.Font.Bold = True
  sh2.Range("F1").Font.Bold = False
  If cad <> "" Then
    MsgBox cad, , "Serial number not found in inventory"
  End If

End Sub

In:
VBA Code:
Sub IN_serial_number2()
  Dim sh1 As Worksheet, sh2 As Worksheet
  Dim a As Variant, b As Variant, c As Variant
  Dim dic As Object, rng As Range
  Dim i&, j&, wRow&
  Dim dt_in As Date, lo As String, cad As String, sCod As String
  Dim f As Range
  
  Set sh1 = Sheets("Sheet1")
  Set sh2 = Sheets("Inventory")
  Set dic = CreateObject("Scripting.Dictionary")
  
  Set f = sh1.Range("B:B").Find("SERIAL NUMBERS", , xlValues, xlWhole, xlByRows, xlPrevious, False)
  
  a = sh1.Range("B3:AR" & f.Row - 1).Value    'Fit the starting row number of the serial numbers
  dt_in = sh1.Range("D1").Value               'Fit the cell of the date in
  lo = "Warehouse"                  'Fit the cell of the location
  b = sh2.Range("B2:B" & sh2.Range("B" & Rows.count).End(3).Row).Value
  c = sh2.Range("E2:H" & sh2.Range("B" & Rows.count).End(3).Row).Value
  Set rng = sh2.Range("F1")
  For i = 1 To UBound(b, 1)
    dic(b(i, 1)) = i
  Next
  
  For i = 1 To UBound(a, 1)
    For j = 1 To 18             'from column B to column S
      If a(i, j) <> "" Then
        If dic.exists(a(i, j)) Then
          wRow = dic(a(i, j))
          sCod = ""
          Select Case a(i, j + 25)
            Case "Y": sCod = "IN"
            Case "R": sCod = "DMG"
          End Select
          c(wRow, 1) = sCod
          c(wRow, 2) = lo
          c(wRow, 3) = ""   '<--added to clear date out field
          c(wRow, 4) = dt_in
          Set rng = Union(rng, sh2.Range("F" & wRow + 1))
        Else
          cad = cad & a(i, j) & vbCr
        End If
      End If
    Next
  Next
  
  sh2.Range("E2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
  rng.Font.Bold = False
  sh2.Range("F1").Font.Bold = True
  If cad <> "" Then
    MsgBox cad, , "Serial number was not found in inventory"
  End If
End Sub

Book1.xlsm
ABCDEFGHIJKLMNOPQRSTZAAABACADAEAFAGAHAIAJAKALAMANAOAPAQAR
12/3/2023Date Out2/13/2023Date InLocationOC Carnival Event
2SERIAL NUMBERSApplesOrangesPearsSerial Codes
30114016426444764716494551065318553757275943640765486721MB0069569MB211A322YRGYYYRRGGYYYYR
40164017427544804717494851075320554057315945640865536722MB0079570MB212A348RDyRYYYRYY
5
6
7
8
9SERIAL NUMBERSApplesOrangesPears
Sheet1


4. If it doesn't have "Y" and it doesn't have "R" then the status will be empty.
Apologies, I neglected to mention in the Serial Code section, if the cell is blank or has "G" or "RD", nothing should change on the Inventory sheet as it refers to either the item not coming in yet or was returned previously in either a "Y" or "R" state.

Other notes, I turned off the AutoFilter on the Inventory sheet manually so it doesn't need to be part of the macro. And I added in [ c(wRow, 3) = "" ] to clear the Date Out field if the number is being marked IN.
 
Upvote 0
Try the following:

VBA Code:
Sub OUT_serial_number2()
  Dim sh1 As Worksheet, sh2 As Worksheet
  Dim a As Variant, b As Variant, c As Variant
  Dim dic As Object, rng As Range, f As Range
  Dim i&, j&, wRow&
  Dim dt As Date, lo As String, cad As String, snum As String
 
  Set sh1 = Sheets("Sheet1")
  Set sh2 = Sheets("Inventory")
  Set dic = CreateObject("Scripting.Dictionary")
  Set f = sh1.Range("B:B").Find("SERIAL NUMBERS", , xlValues, xlWhole, xlByRows, xlPrevious, False)
  a = sh1.Range("B3:S" & f.Row - 1).Value
  b = sh2.Range("B2:B" & sh2.Range("B" & Rows.count).End(3).Row).Value
  c = sh2.Range("E2:H" & sh2.Range("B" & Rows.count).End(3).Row).Value
  Set rng = sh2.Range("F1")
 
  dt = sh1.Range("A1").Value
  lo = sh1.Range("H1").Value
 
  For i = 1 To UBound(b, 1)
    dic(Format(b(i, 1), "@")) = i
  Next
 
  For i = 1 To UBound(a, 1)
    For j = 1 To UBound(a, 2)
      If a(i, j) <> "" Then
        snum = Format(a(i, j), "@")
        If dic.exists(snum) Then
          wRow = dic(snum)
          c(wRow, 1) = "OUT"
          c(wRow, 2) = lo
          c(wRow, 3) = dt
          Set rng = Union(rng, sh2.Range("F" & wRow + 1))
        Else
          cad = cad & a(i, j) & vbCr
        End If
      End If
    Next
  Next
 
  sh2.Range("E2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
  rng.Font.Bold = True
  sh2.Range("F1").Font.Bold = False
  If cad <> "" Then
    MsgBox cad, , "Serial number not found in inventory"
  End If
End Sub

------------------​

VBA Code:
Sub IN_serial_number2()
  Dim sh1 As Worksheet, sh2 As Worksheet
  Dim a As Variant, b As Variant, c As Variant
  Dim dic As Object, rng As Range, f As Range
  Dim i&, j&, wRow&
  Dim dt_in As Date, lo As String, cad As String, sCod As String, snum As String
 
  Set sh1 = Sheets("Sheet1")
  Set sh2 = Sheets("Inventory")
  Set dic = CreateObject("Scripting.Dictionary")
 
  Set f = sh1.Range("B:B").Find("SERIAL NUMBERS", , xlValues, xlWhole, xlByRows, xlPrevious, False)
 
  a = sh1.Range("B3:AR" & f.Row - 1).Value    'Fit the starting row number of the serial numbers
  dt_in = sh1.Range("D1").Value               'Fit the cell of the date in
  lo = "Warehouse"                  'Fit the cell of the location
  b = sh2.Range("B2:B" & sh2.Range("B" & Rows.count).End(3).Row).Value
  c = sh2.Range("E2:H" & sh2.Range("B" & Rows.count).End(3).Row).Value
  Set rng = sh2.Range("F1")
  For i = 1 To UBound(b, 1)
    dic(Format(b(i, 1), "@")) = i
  Next
 
  For i = 1 To UBound(a, 1)
    For j = 1 To 18             'from column B to column S
      If a(i, j) <> "" Then
        snum = Format(a(i, j), "@")
        If dic.exists(snum) Then
          wRow = dic(snum)
          sCod = ""
          Select Case a(i, j + 25)
            Case "Y": sCod = "IN"
            Case "R": sCod = "DMG"
          End Select
          If sCod <> "" Then
            c(wRow, 1) = sCod
            c(wRow, 2) = lo
            c(wRow, 3) = ""   '<--added to clear date out field
            c(wRow, 4) = dt_in
            Set rng = Union(rng, sh2.Range("F" & wRow + 1))
          End If
        Else
          cad = cad & a(i, j) & vbCr
        End If
      End If
    Next
  Next
 
  sh2.Range("E2").Resize(UBound(c, 1), UBound(c, 2)).Value = c
  rng.Font.Bold = False
  sh2.Range("F1").Font.Bold = True
  If cad <> "" Then
    MsgBox cad, , "Serial number was not found in inventory"
  End If
End Sub

--------------
I hope to hear from you soon.
Respectfully
Dante Amor
--------------​
"Patience is bitter, but its fruit is sweet"
"La paciencia es amarga, pero sus frutos son dulces"
"La patience est amère, mais son fruit est doux"

- Jean Jacques Rousseau -​
 
Upvote 0
Solution
So I think we're solid on the OUT macro. It ran great both on the test and actual workbook, no issues. As for the IN macro, it runs great on the test but nothing is happening in the actual book. The Inventory worksheet is not getting updated at all.

Can you tell me what the 25 in this line represents?
Select Case a(i, j + 25)
If it's a column count or something spacial, it could be where the issue stems from. My actual workbook has 25 columns with helper information in between the Serial Number range and the Serial Code range whereas the test book only had a few blank columns in between. Other than that, I can't think of what else would be causing the problem. I'm not getting any errors, just no results.

Thank you again 🙏
 
Upvote 0
Assumptions:
Could you put the real example, that is, your real file, so I wouldn't have to be assuming things.

Share your file. In the file you tell me with which values you have problems.
You could upload a copy of your file to a free site such www.dropbox.com or google drive. Once you do that, mark it for 'Sharing' and you will be given a link to the file that you can post here. If the workbook contains confidential information, you could replace it with generic data.

---------------------​


Can you tell me what the 25 in this line represents?

1687830598833.png
 
Upvote 0
I can't share the workbook because it's proprietary. However, now that I know what that 25 was referring to, I was able to make the correction and now it is running perfectly! It was all my fault from the start, I had forgotten about some of the columns in the actual workbook because they were hidden. Otherwise, my test book was nearly exact. Apologies for the inconvenience but we are good now.

One last question, since Dictionary stores the values in memory each time it is run, does it increase the file size? I just noticed my file size increased to over a MB since last week without adding any significant elements. Just wondering if this would be a part of the reason.
 
Upvote 0
since Dictionary stores the values in memory each time it is run, does it increase the file size?
No.

Check if you have unused cells in your sheet, that is, maybe cells with blank spaces.
Press Control + End to go to the bottom of the sheet, delete the rows and columns that appear to have no data.
 
Upvote 0

Forum statistics

Threads
1,215,071
Messages
6,122,964
Members
449,094
Latest member
Anshu121

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top