简体   繁体   中英

Excel VBA - Match Function gives error in loop

I am an amateur excel vba coder. I am trying to figure out why does match function gives an error "1004, Unable to get the match property of the worksheetfunction" to me when it runs the third time in the loop.

My code is:

Sub com_emp()
'Defining variables
Application.Run "set_var"
c_row_now = db_r_datastart
row_now = ce_r_datastart

Do While cy.Cells(c_row_now, db_c_ident) <> ""
On Error GoTo skip_emp 'In case employee is not found in historical, error redirect

    h_row_now = Application.WorksheetFunction.Match(cy.Cells(c_row_now, db_c_ident), hy.Columns(db_c_ident), 0)

    If h_row_now > 0 And hy.Cells(h_row_now, db_c_englev) <> "" Then 'If person is found and also has engagement level

        ce.Cells(row_now, ce_c_ident) = cy.Cells(c_row_now, db_c_ident)
        ce.Cells(row_now, ce_c_his_englev) = hy.Cells(h_row_now, db_c_englev)
        ce.Cells(row_now, ce_c_his_eng) = hy.Cells(h_row_now, db_c_eng)
        ce.Cells(row_now, ce_c_cur_englev) = cy.Cells(c_row_now, db_c_englev)
        ce.Cells(row_now, ce_c_cur_eng) = cy.Cells(c_row_now, db_c_eng)
        ce.Cells(row_now, ce_c_lev1) = cy.Cells(c_row_now, db_c_lev1)
        ce.Cells(row_now, ce_c_lev2) = cy.Cells(c_row_now, db_c_lev2)
        ce.Cells(row_now, ce_c_lev3) = cy.Cells(c_row_now, db_c_lev3)
        ce.Cells(row_now, ce_c_lev4) = cy.Cells(c_row_now, db_c_lev4)
        ce.Cells(row_now, ce_c_lev5) = cy.Cells(c_row_now, db_c_lev5)

        row_now = row_now + 1
    End If


skip_emp:
c_row_now = c_row_now + 1
Loop

End Sub

The function that I am calling sets some global variables which are being used by other macros.

'''''DECLARATIONS'''''
'Current and Historical Year Sheet
Public db_c_ident As Integer
Public db_c_say1 As Integer
Public db_c_say2 As Integer
Public db_c_stay1 As Integer
Public db_c_stay2 As Integer
Public db_c_strive1 As Integer
Public db_c_strive2 As Integer
Public db_c_lev1 As Integer
Public db_c_lev2 As Integer
Public db_c_lev3 As Integer
Public db_c_lev4 As Integer
Public db_c_lev5 As Integer
Public db_c_avg As Integer
Public db_c_englev As Integer
Public db_c_eng As Integer

'Common Employees
Public ce_r_datastart As Integer
Public ce_c_ident As Integer
Public ce_c_his_englev As Integer
Public ce_c_his_eng As Integer
Public ce_c_cur_englev As Integer
Public ce_c_cur_eng As Integer
Public ce_c_lev1 As Integer
Public ce_c_lev2 As Integer
Public ce_c_lev3 As Integer
Public ce_c_lev4 As Integer
Public ce_c_lev5 As Integer

'Workbook, Sheets and other stuff
Public cy As Worksheet
Public hy As Worksheet
Public ce As Worksheet
Public bck As Worksheet



'Variables
Public db_r_datastart As Long
Public row_now As Long
Public h_row_now As Long
Public c_row_now As Long

''''Global Value Pick'''''
Private Sub set_var()

'Workbook, Sheets and other stuff
Set cy = ThisWorkbook.Worksheets("Current Year")
Set hy = ThisWorkbook.Worksheets("Historical Year")
Set ce = ThisWorkbook.Worksheets("Common")
Set bck = ThisWorkbook.Worksheets("Backend")

'Current and Historical Year Sheet
db_r_datastart = bck.Cells(4, 3)
db_c_ident = bck.Cells(5, 3)
db_c_say1 = bck.Cells(6, 3)
db_c_say2 = bck.Cells(7, 3)
db_c_stay1 = bck.Cells(8, 3)
db_c_stay2 = bck.Cells(9, 3)
db_c_strive1 = bck.Cells(10, 3)
db_c_strive2 = bck.Cells(11, 3)
db_c_lev1 = bck.Cells(12, 3)
db_c_lev2 = bck.Cells(13, 3)
db_c_lev3 = bck.Cells(14, 3)
db_c_lev4 = bck.Cells(15, 3)
db_c_lev5 = bck.Cells(16, 3)
db_c_avg = bck.Cells(17, 3)
db_c_englev = bck.Cells(18, 3)
db_c_eng = bck.Cells(19, 3)

'Common Employees
ce_r_datastart = bck.Cells(31, 3)
ce_c_ident = bck.Cells(32, 3)
ce_c_his_englev = bck.Cells(33, 3)
ce_c_his_eng = bck.Cells(34, 3)
ce_c_cur_englev = bck.Cells(35, 3)
ce_c_cur_eng = bck.Cells(36, 3)
ce_c_lev1 = bck.Cells(37, 3)
ce_c_lev2 = bck.Cells(38, 3)
ce_c_lev3 = bck.Cells(39, 3)
ce_c_lev4 = bck.Cells(40, 3)
ce_c_lev5 = bck.Cells(41, 3)


End Sub

I am aware my code might not be the most efficient as I am just learning, so any recommendations would be appreciated.

If you are going to use On Error statements, you need to make sure you handle the errors correctly. The code should look something like:

Sub com_emp()
    '...

    Do While cy.Cells(c_row_now, db_c_ident) <> ""
        On Error GoTo myErrHandler 'In case employee is not found in historical, error redirect

        h_row_now = Application.WorksheetFunction.Match(cy.Cells(c_row_now, db_c_ident), hy.Columns(db_c_ident), 0)
        '...

skip_emp:
        c_row_now = c_row_now + 1
    Loop
    Exit Sub

myErrHandler:
    Resume skip_emp ' Finish error handling mode, resume normal mode
End Sub

However, it would be better to handle errors yourself whenever you can:

Sub com_emp()
    Dim h_row_now As Variant ' to allow it to accept an error value
                             ' Note: This declaration will "shadow" the public-scoped one
                             ' but it looks like you are just using it here as a
                             ' temporary variable anyway
    'Defining variables
    'Application.Run "set_var"  ' Shouldn't need to "Run" the other sub.
    set_var                     ' Just invoke it.
    c_row_now = db_r_datastart
    row_now = ce_r_datastart

    Do While cy.Cells(c_row_now, db_c_ident) <> ""

        h_row_now = Application.Match(cy.Cells(c_row_now, db_c_ident), hy.Columns(db_c_ident), 0)
        If Not IsError(h_row_now) Then ' only process if a match was found

            If hy.Cells(h_row_now, db_c_englev) <> "" Then 'If person is found and also has engagement level

                ce.Cells(row_now, ce_c_ident) = cy.Cells(c_row_now, db_c_ident)
                ce.Cells(row_now, ce_c_his_englev) = hy.Cells(h_row_now, db_c_englev)
                ce.Cells(row_now, ce_c_his_eng) = hy.Cells(h_row_now, db_c_eng)
                ce.Cells(row_now, ce_c_cur_englev) = cy.Cells(c_row_now, db_c_englev)
                ce.Cells(row_now, ce_c_cur_eng) = cy.Cells(c_row_now, db_c_eng)
                ce.Cells(row_now, ce_c_lev1) = cy.Cells(c_row_now, db_c_lev1)
                ce.Cells(row_now, ce_c_lev2) = cy.Cells(c_row_now, db_c_lev2)
                ce.Cells(row_now, ce_c_lev3) = cy.Cells(c_row_now, db_c_lev3)
                ce.Cells(row_now, ce_c_lev4) = cy.Cells(c_row_now, db_c_lev4)
                ce.Cells(row_now, ce_c_lev5) = cy.Cells(c_row_now, db_c_lev5)

                row_now = row_now + 1
            End If
        End If
        c_row_now = c_row_now + 1
    Loop

End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM