Copy/Paste n Times Based on Other Cell Values

2019-08-02 07:41发布

问题:

I've run in to a wall with this. Despite posts on SO like this one that is very similar or this one on Kioskea, I just cannot connect the dots in my head between filtering cells and copying based on a formula result that's needed to make this work. Here is the data table - simplified - I am working with:

     A    B   C        D     E      F    G    H
 R1 Name Num Status   #Orig #InPro #Act #Rem #RemStatus
 R2 ABC  032 Complete 22    0      11   11   Purged
 R3 LMN  035 In Prog  25    21     4    21   Pending Scan
 R4 XYZ  039 Not Act  16    16     0    16   Not Active

This depicts the status of boxes of paper files and their disposition:

  • Column D is the number of boxes planned to be scanned
  • Column E is the number of boxes out for scanning
  • Column F is the number of boxes actually scanned

Column G and H can have three meanings, based on status:

  • If the status is Not Active, Column G and H match it, and nothing needs to be done
  • If the status is In Progress, it is assumed the number in Column G is the number of boxes pending scanning (simply original minus actual)
  • If the status is Complete, it is assumed the number in Column G is the number of boxes that did not need to be scanned and were Purged

What my code (shown below) is supposed to do is iterate through each row in a range (A2:H61). If the status is Not Active the row can be ignored and it moves on to the next row. If the status is In Progress or Complete, the macro, in whatever row it's 'reading', needs to copy cells A, B, and H and paste it (column)"G" number of times in another worksheet - within the same workbook - starting in the next available row. Deep breath

I know. It hurts my brain, too. Here is the code I have so far:

Sub TEST_Copy_Process()

Dim srcrange As Range
Dim wb As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet

Set wb = ActiveWorkbook
Set ws1 = Worksheets("SIS Agregate")
Set ws2 = Worksheets("Center Detail")
Set srcrange = Range(wb.ws2.Cells("A2:H61"))


For Each Row In srcrange.Rows

If Row = "Not Active" And Row.Offset(0, 3) = SectorType Then
Continue
ElseIf Row = "In Progress" And Row.Offset(0, 3) = SectorType Then

ElseIf Row = "Complete" And Row.Offset(0, 3) = SectorType Then

End If

    Set LastCell = wb.ws1.Cells(wb.ws1.Rows.Count, "A").End(xlUp)
    LastCellRowNumber = LastCell.Row + 1

Next Row

End Sub

Once I get to the code that is actually doing the grunt-work, I don't have the knowledge to sort out which is best. As noted above, posts like this have helpd get me here. And I am slowly starting to make sense of what I found on Mr. Excel. This person seems to be doing the If/Then work but I don't understand how it's copying or pasting.

I appreciate any and all help. Even if you can point me to a resource that will help explain this a bit (besides books on Amazon :] ) it would be a great help!

回答1:

Let's see if this gets you on the right track. Your code looks very good for someone who doesn't know much, so maybe you are a quick study :)

I am confused why you are using .Offset(0, 3) (which doesn't seem to be mentioned anywhere in your explanation) and also why you are comparing to SectorType which is an undefined variable in the code you have provided. I am going to assume these are unnecessary, and inadvertently copied from other examples (please let me know if I'm mistaken).

I haven't tested it but I would change this assignment:

Set srcrange = Range(wb.ws2.Cells("A2:H61"))

to this, if for no other reason than it's a little more direct. I am also changing this range to only refer to column H, since that is the column round which your logic is centered (note: we can always access the other cells using Offset and/or Resize methods).

Set srcrange = wb.ws2.Range("H2:H61")

The meat of your logic is in this block, note removal of Row.Offset(9, 3) = SectorType. I am also going to use a Select Case instead of If/Then. I find these easier to read/comprehend when there are more than one or two conditions to test:

For Each Row In srcrange.Cells  '## In this case, Cells/Rows is the same, but I use Cells as I find it less ambiguous
    Select Case Row.Value
        Case "Not Active"
        '## If the status is Not Active, Column G and H match it, and nothing needs to be done
            'Do nothing

        Case "In Progress", "Complete"
        '## If the status is In Progress or Complete, ... copy cells A, B, and H _
        '    and paste it (column)"G" number of times in another worksheet - _
        '    within the same workbook - starting in the next available row.

        '# Get the next empty cell in column A of the ws1
        '  I modified this to use Offset(1, 0), to return the cell BENEATH
        '  the last cell.
            Set LastCell = wb.ws1.Cells(wb.ws1.Rows.Count, "A").End(xlUp).Offset(1)

        '## copy the values from columns A, B, H to ws1
        '## Column A goes in column A
            LastCell.Value = Row.Offset(0, -7).Value 
        '## Column B goes in column B
            LastCell.Offset(0, 1).Value = Row.Offset(0, -6).Value 
        '## Column H goes in column C (because you did not specify)
            LastCell.Offset(0, 2).Value = Row.Value 
    End Select
Next Row