1

Here is my data:

Data

There are blocks of data on the same sheet, column F will always have the "Controller Firmware Version" at some point and the version will always be one cell below it, as well as D containing the charger serial number two to the left of it.

My desired outcome is a list box compiling all the PK### with their respective firmware versions:

PK### LP2.28
PK### LP#.##
...

Sub Check_Firmware()
    Dim S1$, Firmware As Range, x As Range, ws As Worksheet

    ws = Worksheet(Sheet1)
    Search = "Controller Firmware Version"

    With ws

    Set Firmware = Range("F:F" & Cells(Rows.Count, "F").End(xlUp).Row)
    For Each x In Firmware
        If x.Value2 = "Search" Then
            S1 = S1 & " " & worksheet.function(offset(x.Address(0, 0),1,0)
        End If
    Next

      'How to offset and copy the LP2.28 and compile the results?

End Sub
4
  • 1
    In your code x.Value2 = "Search" the "Search" is not the variable Search so you should remove the quotes " " here to use the variable Search = "Controller Firmware Version" Commented Sep 13, 2018 at 13:07
  • 3
    x.Value2 = "Search" You are looking for the string "Search", not for the string contained in the variable Search. Use x.Value2 = Search. A better way could be to use .Find. You can use x.Offset(1,0).Value2 and x.Offset(1,-2).Value2 to access your data. Commented Sep 13, 2018 at 13:08
  • @PEH Good catches, thank you. Commented Sep 13, 2018 at 13:37
  • @Vincent G Good catches, thank you. Commented Sep 13, 2018 at 13:37

2 Answers 2

4

Use Option Explicit. It is really a must and it helps you fix about 1 error per line of code.

This is an example:

Option Explicit

Sub TestMe()

    Dim S1 As String, search As String, Firmware As Range
    Dim x As Range, ws As Worksheet

    Set ws = Worksheets("Sheet1")
    search = "Controller Firmware Version"

    With ws
        Set Firmware = .Range("F1:F" & .Cells(.Rows.Count, "F").End(xlUp).Row)
        For Each x In Firmware
            If x.Value2 = search Then
                S1 = S1 & " " & x.Offset(1, -2)
                S1 = S1 & " " & x.Offset(1, 0)
                S1 = S1 & vbCrLf
            End If
        Next
    End With

    Debug.Print S1

End Sub

Changes:

  • declared search variable;
  • Worksheets instead of Worksheet;
  • . is added before .Range("F1:F"..., thus the With ws is actually useful;
  • Range("F:F") would return the whole column. To take a specific number of cell, .Range("F1:F & numberOfCells) is needed. .Range("F:F5") would be an error;
  • x.Offset() is the function, needed to get the relative value of a range object;
  • when a worksheet object is assigned, it is done with the word set - Set ws = Worksheets("Sheet1")
Sign up to request clarification or add additional context in comments.

3 Comments

might want to offset -2 columns.
and offset one row too
@vitaya thank you for showing me the option explicit
1

Can be done like this

Option Explicit

Sub Check_Firmware()
    Dim ArrPK() As String, SearchString As String 'Declare ArrPk as string array 
    Dim Firmware As Range, aCell As Range
    Dim ws As Worksheet
    Dim PkCounter As Long
    Dim LstBox As msforms.ListBox

    Set ws = ThisWorkbook.Sheets("Sheet1")        
    SearchString = "Controller Firmware Version"
    Set LstBox = UserForm1.ListBox1
    
    PkCounter = 1
    
    With ws
         'set range that will be source for searching 
        Set Firmware = .Range("F1:F" & .Cells(.Rows.Count, "F").End(xlUp).Row)                          
       
        For Each aCell In Firmware 'loop each cell of desired range 
            If aCell.Value2 = SearchString Then 'if match found 
                ReDim Preserve ArrPK(1 To 2, 1 To PkCounter) 'redimension array.
                ArrPK(1, PkCounter) = aCell.Offset(1, 0) 'firmware
                ArrPK(2, PkCounter) = aCell.Offset(1, -2) 'serial no
                PkCounter = PkCounter + 1 'increase counter for next match found 
            End If
        Next
    End With
    
    With LstBox
        .Clear
        .ColumnCount = 2
        .Width = 105
        .ColumnWidths = "50;50"
        For PkCounter = LBound(ArrPK(), 2) To UBound(ArrPK(), 2)
            .AddItem 'add new item to listbox 
              'put values to newly added row 
            .List(PkCounter - 1, 0) = ArrPK(1, PkCounter) 'new row/column 0 
            'PkCounter - 1 because listbox is counted from 0 
            .List(PkCounter - 1, 1) = ArrPK(2, PkCounter)'new row/column 1 
        Next PkCounter
    End With
    
    UserForm1.Show

End Sub

EDIT:

ReDim Preserve ArrPK(1 To 2, 1 To PkCounter)

This sets new dimensions for array
So now you have 2 dimension array.

Preserve means that all values that are already in array will stay there

1 To 2 and 1 to PkCounter are new dimensions for array. When you find more matches then PkCounter grows and so do array.

Put a Breakpoint on With LstBox open "Locals" window. You'll see your ArrPK array there, and you'll be able to check what's inside of it.

You can read more about arrays on the web.

1 Comment

Exactly what I wanted, beautiful - thank you. Can you add a few comments about the ArrPK function and specifically the ArrPK(1 To 2 ...) what the "1 To 2" is referencing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.