简体   繁体   中英

Iterate through populated rows, Match based on criteria, add value to specific cell in another sheet in Excel using VBA

I am trying to select a value in column hours in tab Time and put it in the appropriate column in tab Month. I would like to iterate through every row in sheet Time and add all of the Data to tab Month.

For every line in Tab TIME add the Hours to the appropriate engagement in Tab Month based on Engagement Number, Engagement Phase, Staff Level. I do this manually every month. I create a copy of last months tab and add on to that each month. Most columns have cells with something like this in them: =1+3+6+4+14+5+2+5 which are the hours that have been worked on that engagement. For cells with something in them i would just like to add on to what is there. For cells with nothing in them i would like to make the new value: = 1 if the value was 1. I want to automate this as it takes up a few days every first of the month, This one just so happens to be on a weekend so guess what I'll be doing. :)

This is where I am at.

Sub Recon()

'Macro to add time to reconciliation report


'Declare variables

Dim Last_Row_TIME As Double
Dim Last_Row_MONTH As Double
Dim wb As Workbook
Dim ws As Worksheet
Dim rw As Range
Dim wstime As

Set wb = ActiveWorkbook
Set wstime = Sheets("TIME")
Set wsmonth = Sheets("MONTH")

wstime.Select

'Find the last non-blank cell in column A(1)
Last_Row_wstime = wstime.Cells(Rows.Count, 1).End(xlUp).Row

'Find the first blank cell in column A
First_Empty_Row_wstime = Last_Row_wstime + 1

I_Col = 1

For i = 1 To Last_Row_wstime

For Each rw In wstime.Rows

If wstime.Cells(rw.Row,1).Value = wsmonth.Cells(rw.Row, 3).Value
And

End Sub

I am stuck at the if statement and not sure how to make this work.

IF 
TIME.Eng. No. (Column A) = Month.Eng. No (Column B)
AND
TIME.Eng. Phase (Column C)  = Month.Eng.Phase (Column C)
AND
TIME.Staff Level (Column M) = PARTNER or MANAGING DIRECTOR

THEN

Add Value TIME.Hours (Column Y) to  Month.Partner/MD (Column I) 

'If blank then "=TIME.Hours) elseif add to the previous value "previous     addition statement +(hours)"


ELSEIF

TIME.Eng. No. (Column A) = Month.Eng. No (Column B)
AND
TIME.Eng. Phase (Column C)  = Month.Eng.Phase (Column C)
AND
TIME.Staff Level (Column M) = SR. MANAGER/DIRECTOR

THEN 

Add Value TIME.Hours (Column Y) to  Month.Director (Column J)

ELSEIF

TIME.Eng. No. (Column A) = Month.Eng. No (Column B)
AND
TIME.Eng. Phase (Column C)  = Month.Eng.Phase (Column C)
AND
TIME.Staff Level (Column M) = MANAGER

THEN

Add Value TIME.Hours (Column Y) to  Month.Manager (Column K)

ELSEIF

TIME.Eng. No. (Column A) = Month.Eng. No (Column B)
AND
TIME.Eng. Phase (Column C)  = Month.Eng.Phase (Column C)
AND
TIME.Staff Level (Column M) = SENIOR ASSOCIATE

THEN

Add Value TIME.Hours (Column Y) to  Month.Sr.Assoc (Column L)

ELSEIF

TIME.Eng. No. (Column A) = Month.Eng. No (Column B)
AND
TIME.Eng. Phase (Column C)  = Month.Eng.Phase (Column C)
AND
TIME.Staff Level (Column M) = ASSOCIATE

THEN

Add Value TIME.Hours (Column Y) to  Month.Associate (Column M)

ELSEIF

'Create a new line after the biggest primary key, located in Month.Primary Key (Column A) 

TIME.Eng. No. (Column A) = Month.Eng. No (Column B)
AND
TIME.Eng. Phase (Column C)  = Month.Eng.Phase (Column C)
AND
TIME.Eng. Description (Column B) = Month.Project Name (Column D)


End If

This is a very brave effort you have made. I shall be glad to help you, but for the moment I don't understand what you want. As far as my understanding goes, I have written code as follows.

Sub Recon()
    ' Macro to add time to reconciliation report
    ' 01 Apr 2017
    
    Dim Wb As Workbook
    Dim WsTime As Worksheet, WsMonth As Worksheet
    Dim Crit As String                          ' Search criterium
    Dim Rl As Long                              ' last row (Time)
    Dim R As Long                               ' row counter (Time)
    
    With WsTime
        Rl = .Cells(.Rows.Count, 1).End(xlUp).Row
        For R = 2 To Rl                         ' skip captions row
            Crit = .Cells(R, 1).Value
            Debug.Print Crit                    ' print value to Immediate Window (for testing)
        Next R
    End With
End Sub

In fact, this code goes further than my understanding because it presumes that both worksheets are in the same workbook. It presumes that the workbook containing those two sheets will be the active workbook. The implication is that the code might be in another workbook, perhaps one you keep for having the code in it.

Now, proceeding in somewhat smaller steps than you would probably like, the above code loops through all rows in the Time worksheet and finds the value in column A. Just so that you see if it works, it prints these values to the Immediate Window ( Ctrl + G , if it isn't shown in your VBE window).

And this is where it gets murky: I presume that this value must be name, perhaps, and you now need to find that same name in the Month sheet. For that one would need to know the column in the Month sheet where that name might be found, what to do if it is found, and what to do if it isn't found.

This is how I read your problem.

  • You want to go through each row in the TIME worksheet.
  • For each row, you want to find a two column matching row in the MONTH worksheet. The first match compares the Eng. No. (TIME!A:A) with the Eng. no in MONTH!B:B and a secondary match on the Phase (Column C) with MONTH!C:C.
  • If a two column MATCH is found, append the rudimentary SUM formula (eg =n+=n+=n+=n+=n... ) in the MONTH worksheet with the current value from TIME!Y:Y. This would go into one of the columns in MONTH!I:M depending on the salary position in TIME!M:M.
  • If no match is found, create a new entry in MONTH and fill in the time to the appropriate column in the new entry.

In a standard code module sheet:

Option Explicit

Sub Recon()
    Dim timeRow As Long, monthCol As Long, monthRow As Variant
    Dim wsTime As Worksheet, wsMonth As Worksheet, wb As Workbook
    Dim rw As Range

    Set wb = ActiveWorkbook
    Set wsTime = wb.Worksheets("TIME")
    Set wsMonth = wb.Worksheets("MONTH")

    With wsTime
        For timeRow = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
            'preload the next available row in MONTH
            With wsMonth
                monthRow = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
            End With
            'evaluate for a two-column MATCH
            Debug.Print "=MATCH(" & wsTime.Cells(timeRow, "A").Address(external:=True) & Chr(38) & wsTime.Cells(timeRow, "C").Address(external:=True) & ", " & wsMonth.Columns("B").Resize(monthRow, 1).Address(external:=True) & Chr(38) & wsMonth.Columns("C").Resize(monthRow, 1).Address(external:=True) & ", 0)"
            monthRow = Application.Evaluate("MATCH(" & wsTime.Cells(timeRow, "A").Address(external:=True) & Chr(38) & wsTime.Cells(timeRow, "C").Address(external:=True) & ", " & wsMonth.Columns("B").Resize(monthRow, 1).Address(external:=True) & Chr(38) & wsMonth.Columns("C").Resize(monthRow, 1).Address(external:=True) & ", 0)")
            'if there is no two-column matching record, create one
            If IsError(monthRow) Then
                With wsMonth
                    monthRow = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
                    .Cells(monthRow, "A") = Application.Max(.Columns("A")) + 1   'you need something in MONTH!A:A for this to work
                    .Cells(monthRow, "B") = wsTime.Cells(timeRow, "A").Value2
                    .Cells(monthRow, "C") = wsTime.Cells(timeRow, "C").Value2
                    .Cells(monthRow, "D") = wsTime.Cells(timeRow, "B").Value2
                End With
            End If

            'at this point we know we have a matching record in the MONTH worksheet
            'choose the MONTH column to add TIME to according to the position in TIME!M:M
            monthCol = 0
            Select Case UCase(.Cells(timeRow, "M").Value2)
                Case "PARTNER", "MANAGING DIRECTOR"
                    monthCol = 9    'MONTH!I:I
                Case "SR. MANAGER/DIRECTOR"
                    monthCol = 10   'MONTH!J:J
                Case "MANAGER"
                    monthCol = 11   'MONTH!K:K
                Case "SENIOR ASSOCIATE"
                    monthCol = 12   'MONTH!L:L
                Case "ASSOCIATE"
                    monthCol = 13   'MONTH!M:M
                Case Else
                    'do nothng - no match on staff level
            End Select

            'if monthCol is not zero then we matched the staff level
            If CBool(monthCol) Then
                With wsMonth
                    'is there already a formula in the cell?
                    If .Cells(monthRow, monthCol).HasFormula Then
                        .Cells(monthRow, monthCol).Formula = _
                            .Cells(monthRow, monthCol).Formula & Chr(43) & wsTime.Cells(timeRow, "Y").Value2
                    Else
                        .Cells(monthRow, monthCol).Formula = _
                            Chr(61) & wsTime.Cells(timeRow, "Y").Value2
                    End If
                End With
            End If

        Next timeRow
    End With

End Sub

I've added comments throughout the code.

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