Excel VBA更新:查找数据,循环遍历多个工作表,复制范围

时间:2021-07-20 05:32:06

Update to this thread from yesterday: Excel VBA: Find data, loop through multiple worksheets, copy specific range of cells

从昨天更新到此线程:Excel VBA:查找数据,循环遍历多个工作表,复制特定范围的单元格

(Special thanks to findwindow for getting me this far!)

(特别感谢findwindow让我这么远!)

I kept getting a runtime 91 error on a certain section, and eventually put in an If/Then statement to skip to the next sheet...but now I'm getting an error 1004 on the line right below it (see below):

我一直在某个部分遇到运行时91错误,并最终输入一个If / Then语句跳到下一张表...但现在我在它下面的行上得到一个错误1004(见下文):

Sub Pull_data_Click()    
Dim A As Variant 'defines name from first subroutine
Dim B As Workbook 'defines destination file
Dim X As Workbook 'defines existing report file as source
Dim Destination As Range 'defines destination range of data pulled from report
Dim wb As Workbook
Dim ws As Worksheet
Dim rng As Variant
Dim copyRng As Variant
Dim fRow As Long

Application.ScreenUpdating = False

Set B = Workbooks("filenameB.xlsm") 'constant variable, does not change
Set X = Workbooks.Open("filenameX.xlsm") 'dependent variable, new name for each new report
A = B.Worksheets("Summary").Range("A1").Value 'constant variable, does not change
Set Destination = B.Worksheets("Input").Range("B2:S2") 'Range changes for each iteration, rows increase by 1

'check if name is entered
    If A = "" Then
    MsgBox ("Your name is not visible; please start from the Reference tab.")
    B.Worksheets("Reference").Activate
    Exit Sub
    End If


For Each ws In X.Worksheets
With ws.range("A:A")
Set rng = .Find(What:=A, After:=ActiveCell, LookIn:=xlValues, _
        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
    If ring Is Nothing Then 'do nothing
    Else
        fRow = rng.Row
        Set copyRng = ws.Range(Cells(fRow, 1), Cells(fRow, 18))
        Destination = copyRng
    End With            
Next ws

Application.ScreenUpdating = True
End Sub

Yesterday, the error 91 occurred on this:

昨天,错误91发生在此:

fRow = rng.Row

fRow = rng.Row

Today, after I put in the If/Then section in that area, I'm getting error 1004 (Method 'Range' of object "_Worksheet' failed) on:

今天,在我放入该区域的If / Then部分后,我收到错误1004(对象“方法'范围'”_Worksheet'失败):

Set copyRng = ws.Range(Cells(fRow, 1), Cells(fRow, 18))

设置copyRng = ws.Range(Cells(fRow,1),Cells(fRow,18))

The syntax is working and it seems to be looking in the correct workbook, but I'm not sure if it's getting stuck because the variable I'm searching for (Variable A) isn't present on the first sheet. Any ideas?

语法是有效的,它似乎正在查找正确的工作簿,但我不确定它是否会卡住,因为我正在搜索的变量(变量A)不在第一张表上。有任何想法吗?

2 个解决方案

#1


4  

Not sure if this is what you are looking for? There was an end if missing? You can do the copy in a single line. See below ...

不确定这是否是您要找的?如果失踪会结束吗?您可以在一行中进行复制。见下文 ...

For Each ws In X.Worksheets
    With ws.Range("A:A")
        Set rng = .Find(What:=A, After:=ActiveCell, LookIn:=xlValues, _
        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
        If rng Is Nothing Then 'do nothing
          Else
          fRow = rng.Row
           ws.Range("A" + CStr(fRow) + ":" + "R" + CStr(fRow)).Copy Destination:=Destination
        End If
    End With
Next ws

#2


2  

A quick note - and possibly the solution:

快速说明 - 可能还有解决方案:

I see you're working with multiple worksheets - this is fine, just remember to be hyper vigilant in setting ranges.

我看到你正在使用多个工作表 - 这很好,只记得在设置范围时要高度警惕。

For your Set copyRng, you correctly specify ws.Range, but you also need to do that for the Cells(). There are two fixes, use this: Set copyRng = ws.Range(ws.Cells(fRow, 1), ws.Cells(fRow, 18))

对于Set copyRng,您正确指定了ws.Range,但您还需要为Cells()执行此操作。有两个修复,使用它:设置copyRng = ws.Range(ws.Cells(fRow,1),ws.Cells(fRow,18))

Or, use With (my personal preference):

或者,使用With(我的个人偏好):

With ws
    Set copyRng = .Range(.Cells(fRow,1),.Cells(fRow,18))
End with

In the With case, you'll notice you can just use a decimal as a placeholder for whatever your With __ is. (I like With, because if your worksheet variable is long, or you're just using the actual name, having to repeat that in thisIsMyWorksheet.Range(thisismyWorksheet.Cells(1,1),thisismyworksheet.cells(... can get quite long).

在With情况下,您会注意到只需使用小数作为占位符,无论您使用__是什么。 (我喜欢With,因为如果您的工作表变量很长,或者您只是使用实际名称,则必须在thisIsMyWorksheet.Range(thisismyWorksheet.Cells(1,1)中重复这一点,thisismyworksheet.cells(...可以获得)相当长)。

If that doesn't do the trick, let me know. I've had spreadsheets hang up when I forget to explicitly give the Cells() worksheet, after giving the Range one.

如果那不成功,请告诉我。当我忘记在给出Range之后明确给出Cells()工作表时,我已经将电子表格挂起了。

Edit: Per your comment, First, it looks like there's a typo in your If ring Is Nothing - should be If rng Is Nothing Then. I don't like that "If (TRUE) Then [implicitly do nothing]".

编辑:根据你的评论,首先,看起来你的If中有一个拼写错误 - 应该是如果当时没有。我不喜欢“If(TRUE)然后[隐式无所作为]”。

Try this instead, for the worksheet loop:

请尝试使用此工作表循环:

For Each ws In X.Worksheets
    With ws.Range("A:A")
        Set rng = .Find(What:=A, After:=ActiveCell, LookIn:=xlValues, _
                        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
        If Not rng Is Nothing Then
            fRow = rng.Row
            Set copyRng = ws.Range(ws.Cells(fRow, 1), ws.Cells(fRow, 18))
            Destination.Value = copyRng.Value
        End With
    Next ws

    Application.ScreenUpdating = True
End Sub

#1


4  

Not sure if this is what you are looking for? There was an end if missing? You can do the copy in a single line. See below ...

不确定这是否是您要找的?如果失踪会结束吗?您可以在一行中进行复制。见下文 ...

For Each ws In X.Worksheets
    With ws.Range("A:A")
        Set rng = .Find(What:=A, After:=ActiveCell, LookIn:=xlValues, _
        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
        If rng Is Nothing Then 'do nothing
          Else
          fRow = rng.Row
           ws.Range("A" + CStr(fRow) + ":" + "R" + CStr(fRow)).Copy Destination:=Destination
        End If
    End With
Next ws

#2


2  

A quick note - and possibly the solution:

快速说明 - 可能还有解决方案:

I see you're working with multiple worksheets - this is fine, just remember to be hyper vigilant in setting ranges.

我看到你正在使用多个工作表 - 这很好,只记得在设置范围时要高度警惕。

For your Set copyRng, you correctly specify ws.Range, but you also need to do that for the Cells(). There are two fixes, use this: Set copyRng = ws.Range(ws.Cells(fRow, 1), ws.Cells(fRow, 18))

对于Set copyRng,您正确指定了ws.Range,但您还需要为Cells()执行此操作。有两个修复,使用它:设置copyRng = ws.Range(ws.Cells(fRow,1),ws.Cells(fRow,18))

Or, use With (my personal preference):

或者,使用With(我的个人偏好):

With ws
    Set copyRng = .Range(.Cells(fRow,1),.Cells(fRow,18))
End with

In the With case, you'll notice you can just use a decimal as a placeholder for whatever your With __ is. (I like With, because if your worksheet variable is long, or you're just using the actual name, having to repeat that in thisIsMyWorksheet.Range(thisismyWorksheet.Cells(1,1),thisismyworksheet.cells(... can get quite long).

在With情况下,您会注意到只需使用小数作为占位符,无论您使用__是什么。 (我喜欢With,因为如果您的工作表变量很长,或者您只是使用实际名称,则必须在thisIsMyWorksheet.Range(thisismyWorksheet.Cells(1,1)中重复这一点,thisismyworksheet.cells(...可以获得)相当长)。

If that doesn't do the trick, let me know. I've had spreadsheets hang up when I forget to explicitly give the Cells() worksheet, after giving the Range one.

如果那不成功,请告诉我。当我忘记在给出Range之后明确给出Cells()工作表时,我已经将电子表格挂起了。

Edit: Per your comment, First, it looks like there's a typo in your If ring Is Nothing - should be If rng Is Nothing Then. I don't like that "If (TRUE) Then [implicitly do nothing]".

编辑:根据你的评论,首先,看起来你的If中有一个拼写错误 - 应该是如果当时没有。我不喜欢“If(TRUE)然后[隐式无所作为]”。

Try this instead, for the worksheet loop:

请尝试使用此工作表循环:

For Each ws In X.Worksheets
    With ws.Range("A:A")
        Set rng = .Find(What:=A, After:=ActiveCell, LookIn:=xlValues, _
                        LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
        If Not rng Is Nothing Then
            fRow = rng.Row
            Set copyRng = ws.Range(ws.Cells(fRow, 1), ws.Cells(fRow, 18))
            Destination.Value = copyRng.Value
        End With
    Next ws

    Application.ScreenUpdating = True
End Sub