简体   繁体   English

VBA无法将数据从多个工作簿传输到主工作簿

[英]Trouble with VBA to transfer data from multiple workbooks to master workbook

I am using Excel 2013 and trying to use the code below from a tutorial Transfer to Master from Multiple Workbooks to transfer data from multiple workbooks into a master workbook. 我正在使用Excel 2013,并尝试使用以下教程中的代码从多个工作簿传输到母版,以将数据从多个工作簿传输到母版工作簿。 It adds the data from the multiple wkbks to the master wkbk with the data pasted below the data above it each time, not on separate spreadsheets in the master. 每次将多个wkbk中的数据添加到主wkbk中,并且数据每次粘贴在其上方的数据下方,而不是在主数据库中的单独电子表格上。

I put the code in the MASTER workbook, per the tutorial but nothing happens. 按照教程,我将代码放在MASTER工作簿中,但没有任何反应。 I don't know VBA too well. 我对VBA不太了解。 I just learned how to put a break and run the code, but that doesn't really tell me anything, I don't think. 我刚刚学习了如何暂停并运行代码,但是我认为这并没有真正告诉我任何事情。

  1. I have a folder on my desktop called 'merge' with a macro enabled wkbk called MASTER, the 3 other non-macro wkbks called tblScheduleMergeTWO, tblScheduleMergeTHREE, and tblScheduleMergeFOUR. 我的桌面上有一个名为“ merge”的文件夹,其中包含启用了宏的wkbk(称为MASTER),其他3个非宏wkbks(称为tblScheduleMergeTWO,tblScheduleMergeTHREE和tblScheduleMergeFOUR)。
  2. Each wkbk, including the MASTER, has 9 columns with the same field headings, which I don't think matters with this code. 每个wkbk,包括MASTER,都有9列具有相同的字段标题,我认为这段代码无关紧要。
  3. The 3 wkbks I need to copy from each has different shading on the data so I can tell which data came from which wkbk when it does paste over to the MASTER. 我需要从每个wkbk复制的3个wkbk在数据上具有不同的阴影,因此我可以确定何时将数据粘贴到MASTER上时哪个数据来自哪个wkbk。

What I've Tried: POSTER'S EDIT - 我尝试过的内容:海报编辑 -

  1. I open the MASTER wkbk and put my cursor in that wkbk and run the code from there. 我打开MASTER wkbk,将光标放在该wkbk中,然后从那里运行代码。

  2. I've tried it with one of the other wkbks I need to copy from open and tried it with it closed and the screen will flash once sometimes but nothing happens in terms of copying any data. 我用其他需要从打开复制的wkbks进行了尝试,然后又关闭了它,屏幕有时会闪烁一次,但是复制任何数据都没有发生。

  3. Per @Tony Dallimore suggestion, moved Active.Workbook.Close after the ActiveSheet.Paste Destination: and after Loop Application.DisplayAlerts = True and it did not change anything. 根据@Tony Dallimore的建议,在ActiveSheet.Paste Destination:之后和Loop Application.DisplayAlerts = True之后,将Active.Workbook.Close移到了它,并且没有任何改变。 I'm not sure it does erase anything to close the wkbk, but he would know better. 我不确定它是否会清除任何内容以关闭wkbk,但他会更好。

  4. Per #Tony Dallimore suggestion, changed Cells(erow, 9) to Cells(erow, lastcolumn) , separately and with the other edits, and nothing changed. 根据#Tony Dallimore的建议,将Cells(erow, 9)更改为Cells(erow, lastcolumn) ,并进行了其他修改, Cells(erow, lastcolumn)任何更改。

  5. Did not understand #Tony Dallimore's 3rd suggestion. 不理解#Tony Dallimore的第3条建议。 Was it to replace Range(Cells(2, 1), Cells(lastrow, lastcolumn)).Copy with SrcRange.Copy Destination:=DestTopLeftCell? 是否Range(Cells(2, 1), Cells(lastrow, lastcolumn)).Copy with SrcRange.Copy Destination:= DestTopLeftCell替换Range(Cells(2, 1), Cells(lastrow, lastcolumn)).Copy with I didn't see that it would cover lastrow to lastcolumn.` 我没有看到它将覆盖从lastrow到lastcolumn。

  6. I also tried another tutorial but it did not work either from enter link description here . 我也尝试了另一个教程,但是从此处输入链接说明也无法使用。 Did not post code to save room. 没有发布代码以节省空间。

10/1/19 11:19 AM Poster's Edit 10. Per @Thomas Inzina's suggestion, I used F8 to troubleshoot line by line in his code that he posted. 19-10-1上午海报的编辑 10.根据@Thomas Inzina的建议,我使用F8在他发布的代码中逐行进行故障排除。 I noticed right away using F8 that the beginning line of code 'With ThisWorkbook.Worksheets("Sheet1")' shows up in the screen tip as FileName="" when you click on ThisWorkbook or click on Sheet1. 我立刻注意到使用F8,当您单击ThisWorkbook或单击Sheet1时,代码'With ThisWorkbook.Worksheets(“ Sheet1”)'的开始行在屏幕提示中显示为FileName =“”。 It doesn't look like it even recognizes ThisWorkbook, which is really called MASTER.xlsm. 它看起来甚至都无法识别ThisWorkbook,它实际上叫做MASTER.xlsm。 What's happening with that? 那是怎么回事? The screen tip does show the file name, however, when you hover your cursor over 'Do While FileName <> ""'. 但是,当您将光标悬停在“ Do While FileName <>“”“上时,屏幕提示确实显示了文件名。 When I press F8 then, it gives a popup msg saying Your MASTER file is already opened and could damage to reopen. 当我按F8键时,它会弹出消息,提示您的MASTER文件已经打开,可能会损坏重新打开。 When I select NO, that I don't want it opened again, I get an error msg asking if I want to end or Debug. 当我选择“否”时,如果我不想再次打开它,则会收到一条错误消息,询问我是否要结束或调试。 If I Debug, then 'With Workbooks.Open(FolderPath & FileName)' is highlighted as the problem. 如果我调试,则将“ With Workbooks.Open(FolderPath&FileName)”突出显示为问题。 I just need to save and close the Master wkbk and then that trouble is gone; 我只需要保存并关闭Master wkbk,然后麻烦就解决了; however, hitting F8 after 'With Workbooks.Open(FolderPath & FileName)'skips the rest of the code and goes back to the beginning. 但是,在“ With Workbooks.Open(FolderPath&FileName)”之后按F8会跳过其余代码,并返回到开头。 In all of this, I don't see that the code is giving a screen tip showing that it notices the wkbks I need to copy from. 在所有这些中,我看不到代码提供了提示显示它注意到需要复制的wkbks的屏幕提示。

I would appreciate the help. 我会很感激的。 I'm going to check into this post Other post to t/f data from multiple wkbks , too. 还将检查这个帖子, 其他帖子也可以从多个wkbks中获取t / f数据

Is FileName = Dir wrong, perhaps? 是FileName = Dir错误吗?

Sub copyDataFromMultipleWorkbooksIntoMaster()

Dim FolderPath As String
Dim FilePath As String
Dim FileName As String
'or Dim FolderPath As String, FilePath As String, FileName As String

FolderPath = "C:\Users\PC-1\Desktop\Merge\"
FilePath = FolderPath & "*.xls*"
FileName = Dir(FilePath)

'Don't know how many rows of data so define last row and column
Dim lastrow As Long
Dim lastcolumn As Long
'will use in a loop as number columns and rows from which extract data

Do While FileName <> ""
Workbooks.Open (FolderPath & FileName)

'Assign value to last row
lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
lastcolumn = ActiveSheet.Cells(1, Columns.Count).End(xlLeft).Column

Range(Cells(2, 1), Cells(lastrow, lastcolumn)).Copy
Application.DisplayAlerts = False
'to disable alerts that you have a lot of data copied to clipboard, etc.
Active.Workbook.Close

'when go back to master to paste, we need to know which is next blank row to paste data
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
'Offset to go to next row
ActiveSheet.Paste Destination:=Worksheets("Sheet1").Range(Cells(erow, 1), Cells(erow, 9))

FileName = Dir

Loop
Application.DisplayAlerts = True



End Sub

10/2/2016 Poster's Edit - In response to Tony Dallimore - Tony, I read through the code but thought I understood enough to run it and see what happens (I am, however, going to study it more in depth and retype it); 2016年10月2日海报的编辑 -针对托尼·达利摩尔(Tony Dallimore) -托尼(Tony),我通读了代码,但认为我足够理解以运行它并查看会发生什么(但是,我将对其进行深入研究并重新输入) ; however, nothing happened when I tried to run it. 但是,当我尝试运行它时,没有任何反应。 Was I supposed to substitute anything like my workbook(s) name or any worksheet name, ex: WshtDestName, into the code? 我是否应该用代码代替我的工作簿名称或任何工作表名称(例如:WshtDestName)?

I received a Run Time Error 9 Subscript out of Range error and when I debugged it, Set WshtDest = WbkDest.Worksheets(WshtDestName) was highlighted. 我收到运行时错误9下标超出范围错误,并且在调试它时,突出显示了Set WshtDest = WbkDest.Worksheets(WshtDestName)。

I thought I might ought to substitute WshtDestName above with the name of my wksht in my MASTER.xlsm file. 我认为我应该用我的MASTER.xlsm文件中的wksht名称代替上面的WshtDestName。 So, I put "Sheet1" in the parentheses. 因此,我将“ Sheet1”放在括号中。 There was no error msg, but nothing happened either. 没有错误消息味精,但也没有任何反应。

I thought maybe I was to substitute the "Data" in the 2 constants, Const WshtDestName As String = "Data" and Const WshtSrcName As String = "Data" with my wksht's name in both wkbks, so I put "Sheet1" where "Data" was, and, again, nothing happened. 我以为我可能要用两个wkbks中的wksht的名字来代替2个常量中的“ Data”,即Const WshtDestName As String = "Data"Const WshtSrcName As String = "Data" ,所以我在两个Const WshtSrcName As String = "Data"常量中都添加了“ Sheet1” ”曾经又没有任何反应。

I didn't know if the constants at the beginning were supposed to be after the Sub so I moved them to be after the Dim's under Sub and nothing happened then. 我不知道开始时的常量是否应该在Sub之后,所以我将其移动到Sub的Dim's之后,然后什么也没有发生。

When I hit F8 to look at each line of code, here is what the screen tip says: 当我按F8键查看每一行代码时,屏幕提示如下:

  • For Application.ScreenUpdating = False it says Application.ScreenUpdating = True 对于Application.ScreenUpdating = False,它表示Application.ScreenUpdating = True

  • For Set WbkDest = ThisWorkbook the screen tip says for WbkSet = Nothing and for ThisWorkbook = , but only says these things when yellow highlighted. 对于Set WbkDest = ThisWorkbook,屏幕提示显示WbkSet = Nothing和ThisWorkbook =,但仅在黄色突出显示时显示这些内容。 When hit F8 and move off that line, it doesn't say anything when I put the cursor over it. 当按F8键并移出该行时,当我将光标放在其上时,它什么也没说。

  • For Set WshtDest = WbkDest.Worksheets(WshtDestName) the screen tip says for WshtDest = Nothing and for WbkDest.Worksheets(WshtDestName) = Subscript out of range and if cursor is just over (WshtDestName), it says ("Data"), but only says these things when yellow highlighted. 对于Set WshtDest = WbkDest.Worksheets(WshtDestName),屏幕提示显示WshtDest = Nothing和WbkDest.Worksheets(WshtDestName)=下标超出范围,并且如果光标刚好在(WshtDestName)上方,则显示(“ Data”),但是仅在黄色突出显示时才说这些话。 When hit F8 and move off that line, it doesn't say anything when I put the cursor over it. 当按F8键并移出该行时,当我将光标放在其上时,它什么也没说。

  • I'm not able to F8 past this unless I change ("Data") to ("Sheet1"). 除非我将(“ Data”)更改为(“ Sheet1”),否则无法通过F8。 I can F8 to FolderPath = WbkDest.Path & "\\" = "C:\\Users|PC-1\\Destktop\\Merge\\" in the screen tip where WbkDest.Path = "C:\\Users|PC-1\\Destktop\\Merge", which is correct. 我可以在屏幕提示中F8到FolderPath = WbkDest.Path&“ \\” =“ C:\\ Users | PC-1 \\ Destktop \\ Merge \\”,其中WbkDest.Path =“ C:\\ Users | PC-1 \\ Destktop \\合并”,这是正确的。

  • FilePath = FolderPath & " .xls " = "C:\\Users|PC-1\\Destktop\\Merge\\".xls*" in the screen tip where FolderPath is correct as above, "C:\\Users|PC-1\\Destktop\\Merge\\" 屏幕提示中的FilePath = FolderPath&“ .xls ” =“ C:\\ Users | PC-1 \\ Destktop \\ Merge \\”。xls *“,其中FolderPath如上,” C:\\ Users | PC-1 \\ Destktop \\合并\\”

  • FileName = Dir$(FilePath) = "MASTER.xlsm" in screen tip and FilePath is equal to "C:\\Users|PC-1\\Destktop\\Merge*.xls*" as above. 屏幕提示中的FileName = Dir $(FilePath)=“ MASTER.xlsm”,并且FilePath等于如上所述的“ C:\\ Users | PC-1 \\ Destktop \\ Merge * .xls *”。

  • Set RngDest = .Cells.Find("*", .Range("A1"), xlFormulas, , xlByRows, xlPrevious) where RngDest = Nothing in tip and nothing pops up in screen tip except -4123 for xlFormulas, and 1 for xlByRows, and 2 for xlPrevious. 设置RngDest = .Cells.Find(“ *”,.Range(“ A1”),xlFormulas,,xlByRows,xlPrevious),其中RngDest =尖端无任何内容,屏幕尖端不显示任何东西,除了-4123对于xlFormulas和1对于xlByRows ,对于xlPrevious为2。

  • If RngDest Is Nothing Then where RngDest = Nothing in tip 如果RngDest没什么,那么RngDest =小费

  • HeaderCopied = False = HeaderCopied = False in tip which is not true b/c my destination wkbk, MASTER.xlsm has a header row already in the 1st row. HeaderCopied = False = HeaderCopied = False提示不正确b / c我的目的地wkbk,MASTER.xlsm在第一行中已有标题行。

  • RowDestNext = 1 = RowDestNext = 1 in screen tip 屏幕提示中的RowDestNext = 1 = RowDestNext = 1

  • It then jumps to EndIf and EndWith 然后跳到EndIf和EndWith

  • Do While FileName <> "" And FileName <> WbkDest.Name where both FileName and WbkDest.Name = "MASTER.xlsm" in screen tip. 在FileName <>“”和FileName <> WbkDest.Name时执行操作,其中屏幕提示中的FileName和WbkDest.Name均=“ MASTER.xlsm”。

  • F8 then jumps through the rest of the code to the end where 然后F8跳到其余的代码到最后的地方

    With WshtDest .Cells.EntireColumn.AutoFit End With, etc. 使用WshtDest .Cells.EntireColumn.AutoFit结尾为等。

I ran your code just as you typed it, as well, except I commented out the section you said to comment out if I did have headers and I uncommented the section you said to uncomment. 我也按照您键入的代码来运行您的代码,除了我注释掉了您说要注释掉的部分(如果确实有标头)并且我对您说的注释不做注释。 It still didn't work. 仍然没有用。

You can copy directly directly to the destination range and avoid using the clipboard altogether. 您可以直接复制到目标范围,而避免完全使用剪贴板。

Sub copyDataFromMultipleWorkbooksIntoMaster()

    Dim FileName As String, FilePath As String, FolderPath As String
    Dim lastrow As Long, lastcolumn As Long
    Dim LastCell As Range

    With ThisWorkbook.Worksheets("Sheet1")
        Set LastCell = .Cells(.Rows.Count, 1)
    End With

    FolderPath = "C:\Users\PC-1\Desktop\Merge\"
    FilePath = FolderPath & "*.xls*"
    FileName = Dir(FilePath)

    Do While FileName <> ""
        With Workbooks.Open(FolderPath & FileName)

            'Assign value to last row
            lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
            lastcolumn = .Cells(1, .Columns.Count).End(xlLeft).Column

            .Range("A2", .Cells(lastrow, lastcolumn)).Copy LastCell.End(xlUp).Offset(1)

            .Close False

        End With
        FileName = Dir

    Loop

End Sub

I have set up a folder and workbooks that match your description. 我已经建立了一个符合您描述的文件夹和工作簿。 The revised code below works for me. 下面的修改后的代码对我有用。 I hope the original code was all yours. 我希望原始代码全归您所有。 I can easily forgive a newbie for some of the mistakes and bad practices but I would be appalled if you got this from a tutorial as you suggest. 对于某些错误和不良做法,我可以轻易原谅新手,但如果您按照建议从教程中得到这些信息,我会感到震惊。

I have included comments to explain all my changes. 我已包含评论以解释我的所有更改。 Come back for more explanations if necessary but the more you decipher my code for yourself, the faster you will develop your skills. 如有必要,请返回以获取更多解释,但是您为自己理解我的代码的次数越多,您的技能开发就会越快。 I include comments to say what the code is doing but few comments about the statements themselves. 我添加了一些注释来说明代码在做什么,但是对语句本身的注释很少。 For example, Option Explicit is easy to look up once you know it exists so its purpose is not explained. 例如,一旦您知道Option Explicit存在,就很容易查找它,因此不解释其用途。

Option Explicit         ' Always have this statement at the top of every module

  ' Constants are fixed while a macro is running but can be changed
  ' if the data is redesigned. This defines the first data row of every
  ' worksheet is 2. That is, it allows for one header row. I could have used
  ' 2 within the code below. If you ever have to update code because the
  ' number of header rows has changed or a new column has been inserted in
  ' the middle of existing columns, you will understand why I use constants.
  Const RowDataFirst As Long = 2        ' Set to 1 if no header rows

  ' You assume that when you open a workbook, the active worksheet is the one
  ' required. This is only reliable if the workbooks only have one worksheet.
  ' I have defined one constant for the name of the worksheet within the
  ' destination workbook and one for name of the worksheet within every
  ' source workbook. I assume this is adequate. I will have alternative
  ' suggestions if it is not adequate.
  Const WshtDestName As String = "Data"
  Const WshtSrcName As String = "Data"
Sub copyDataFromMultipleWorkbooksIntoMaster()

  Dim FolderPath As String
  Dim FilePath As String
  Dim FileName As String
  Dim HeaderCopied As Boolean
  Dim RowDestNext As Long
  Dim RngDest As Range
  Dim RngSrc As Range
  Dim WbkDest As Workbook
  Dim WbkSrc As Workbook
  Dim WshtDest As Worksheet
  Dim WshtSrc As Worksheet

  Application.ScreenUpdating = False

  ' You need row numbers in both the source and the destination worksheets.
  ' Use names for variables that tell you exactly what the variable is for.
  ' While you are writing a macro, it is easy to remember odd names but if
  ' you return to the macro in six or twelve months will you still remember?
  ' I have a naming system which I always use. I can look at macros I wrote
  ' ten years ago and know what all the variable are which is an enormous help
  ' when updating old code. If you do not like my system then develop your own.
  ' My names consist of a series of keywords with the most global first.
  ' "Row" says the variable is a row number. "Wbk" says the variable is a
  ' workbook. "RowXxx" says the variable is a row number within worksheet or
  ' array Xxxx. "RowSrcXxx" says the variable is a row number for worksheet
  ' "Source". "Xxx" can be "First", "Crnt", "Next", Prev", "Last" or whatever
  ' I need for the current macro

  Dim RowSrcLast As Long

  ' My comment suggested you be consistent in your use of column numbers but
  ' comments do not allow enough room to explain. With some statements, having
  ' a different number of rows or columns in the source and destination can
  ' give funny results with truncation or duplication. If you know you only
  ' want 9 columns then use 9 in both source and destination ranges. If the
  ' number of columns might change then determine the number at runtime.
  Dim ColSrcLast As Long

  ' If you are handling multiple workbooks be explicit which workbook
  ' you are addressing.  This assumes the workbook into which the worksheets
  ' are collected is the workbook containing the macro.
  Set WbkDest = ThisWorkbook

  Set WshtDest = WbkDest.Worksheets(WshtDestName)
  ' Note a worksheet variable references the worksheet within its workbook.
  ' I do not need to write WbkDest.WshtDest.

  ' FolderPath = "C:\Users\PC-1\Desktop\Merge\"
  ' You can hard code the name of the folder into a macro but it is
  ' a bother when you move your workbooks. When all your workbooks
  ' are in the same folder, the following is more convenient
  FolderPath = WbkDest.Path & "\"

  FilePath = FolderPath & "*.xls*"

  ' Note Dir searches down the folder index for files that match the template.
  ' The sequence in which they are found depends on the sequence in which the
  ' files were added to the folder. There are other techniques if sequence is
  ' important.
  FileName = Dir$(FilePath)         ' Dir$ is marginally faster than Dir

  ' Your existing code adds new data to the end of the existing worksheet in
  ' Master.xlsm. This may be correct but it is more usual to clear the
  ' destination at the start of each run. Comment out the first block and uncomment
  ' the second block if you want to add to existing data.

  With WshtDest
    .Cells.EntireRow.Delete  ' Delete every row in worksheet
    HeaderCopied = False     ' There is no header within the destination worksheet
    RowDestNext = 1          ' First (only) header row will be copied from first
                             ' source worksheet to this row
  End With

  ' If you know that column A of the used rows of the active sheet contains no
  ' blank cells, the following is the easiest way of finding that last used row:
  '   RowDestLast = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
  ' But this technique is unreliable if there might be blank cells. No technique
  ' is 100% reliable but you would have very strange data if the technique I have
  ' used is not reliable for you.

  'With WshtDest
  '  ' Find last row with a value
  '  Set RngDest = .Cells.Find("*", .Range("A1"), xlFormulas, , xlByRows, xlPrevious)
  '  If RngDest Is Nothing Then
  '    ' No data has been found so the worksheet is empty
  '    HeaderCopied = False     ' There is no header within the destination worksheet
  '    RowDestNext = 1          ' First (only) header row will be copied from first
  '                             ' source worksheet to this row
  '  Else
  '    ' There is data within the worksheet. Assume the header row(s) are present.
  '    HeaderCopied = True
  '    RowDestNext = RngDest.Row + 1
  '  End If
  'End With

  ' Please indent your code within Do-Loops, If, etc. It makes your code
  ' much easier to read.

  ' All your workbooks are within the same folder. Master.xlsm will be one
  ' of those found but you do not want to use it as a source workbook.

  Do While FileName <> ""
    If FileName <> WbkDest.Name Then
      Set WbkSrc = Workbooks.Open(FolderPath & FileName)

      ' WbkSrc will be the active workbook but better to reference it explicitly

      With WbkSrc
        Set WshtSrc = .Worksheets(WshtSrcName)
      End With

      With WshtSrc
        ' Find last row with data if any
        Set RngSrc = .Cells.Find("*", .Range("A1"), xlFormulas, , xlByRows, xlPrevious)
        If RngSrc Is Nothing Then
          ' No data has been found so the worksheet is empty
        Else
          RowSrcLast = RngSrc.Row
          ' Find last column with data. Already know there is data
          RngSrc = .Cells.Find("*", .Range("A1"), xlFormulas, , xlByColumns, xlPrevious)
          ColSrcLast = RngSrc.Column

          If HeaderCopied Then
            ' Already have header row(s) in destination worksheet
            Set RngSrc = .Range(.Cells(RowDataFirst, 1), .Cells(RowSrcLast, ColSrcLast))
          Else
            ' Do not have header row(s) in destination worksheet. Include them in copy.
            Set RngSrc = .Range(.Cells(1, 1), .Cells(RowSrcLast, ColSrcLast))
            HeaderCopied = True
          End If
          RngSrc.Copy Destination:=WshtDest.Cells(RowDestNext, 1)  ' Copy data and formats
          RowDestNext = RowDestNext + RngSrc.Rows.Count            ' Step ready for next copy
        End If
      End With  ' WshtSrc

      WbkSrc.Close SaveChanges:=False
      Set WshtSrc = Nothing
      Set WbkSrc = Nothing

    End If  ' FileName <> WbkDest.Name

    FileName = Dir$

  Loop  ' While FileName <> "" And FileName <> WbkDest.Name

  With WshtDest
    .Cells.EntireColumn.AutoFit
  End With

  Application.ScreenUpdating = True

End Sub

New section in response to OP's comments on original answer 回应OP对原始答案的评论的新部分

There are some things I really should have included in my original answer but you have also strayed into areas I could not have expected. 我最初的答案中确实应该包含一些内容,但是您也误入了我无法预料的领域。 You have also found a bug which my own testing missed. 您还发现了我自己的测试遗漏的错误。

“Was I supposed to substitute anything like my workbook(s) name …” “我应该代替工作簿名称之类的东西吗……”

I should have made this clear. 我应该说清楚了。 In Const WshtDestName As String = "Data" , “Data” is my name for the worksheet in which I accumulate the data. Const WshtDestName As String = "Data" ,“ Data”是我在其中累积数据的工作表的名称。 I should have told you to replace “Data” with your name for the worksheet. 我应该告诉过您用工作表的名称替换“数据”。

Your comments suggest you have replaced: 您的评论表明您已替换:

 Set WshtDest = WbkDest.Worksheets(WshtDestName)

with

 Set WshtDest = WbkDest.Worksheets("Sheet1")

If so, please update the Const statement instead. 如果是这样,请改为更新Const语句。 The objective of using Const statements is to isolate things that might change from the main body of the code. 使用Const语句的目的是将可能会更改的内容与代码主体隔离开。 This makes maintenance easier. 这使维护更加容易。

Avoid using the default names “Sheet1”, “Sheet2” and so on. 避免使用默认名称“ Sheet1”,“ Sheet2”等。 As your data and your macros get more complicated, it makes life much easier if worksheet names reflect the worksheet contents. 随着数据和宏变得越来越复杂,如果工作表名称反映了工作表内容,则使工作变得更加轻松。

[ Note from OP: I renamed my master wksht to 'Combined' and my source's wkshts to 'Node Export By Hub', and replaced the 'Sheet1' name in the Constants with those names.] [ OP中的注释:我将主wkshts重命名为'Combined',将源wkshts重命名为'Node Export By Hub',并用这些名称替换了Constants中的'Sheet1'名称。]

I use WbkDest.Name as the name of the master workbook. 我使用WbkDest.Name作为主工作簿的名称。 You do not need to change this to your actual workbook name. 您无需将其更改为实际的工作簿名称。 Using properties like this makes your code much easier to maintain because the property value will change if you rename the workbook. 使用这样的属性使您的代码更容易维护,因为如果重命名工作簿,则属性值将更改。

I received a Run Time Error 9 Subscript out of Range error and when I debugged it, Set WshtDest = WbkDest.Worksheets(WshtDestName) was highlighted. 我收到运行时错误9下标超出范围错误,并且在调试它时,突出显示了Set WshtDest = WbkDest.Worksheets(WshtDestName)。

This paragraph may be beyond your current knowledge of VBA. 本段可能超出您当前对VBA的了解。 Read it and extract what understanding you can. 阅读并提取您可以理解的内容。 It will become clearer as you advance to arrays and collections. 当您进入数组和集合时,它将变得更加清晰。 Worksheets is a Collection or what most programming languages call a list. Worksheets是一个Collection或大多数编程语言称为列表。 A collection is like an array except you can add new values in the middle and delete existing values. 集合类似于数组,除了可以在中间添加新值并删除现有值。 Within arrays, entries are only accessible via an index number, for example: MyArray(5) . 在数组内,只能通过索引号访问条目,例如: MyArray(5) Entries within a collection are accessible via an index but collection entries can also have a key . 集合中的条目可通过索引访问,但是集合条目也可以具有key If I had written Worksheets(5) this would have given error 9 because there is no worksheet 5. When you ran the macro, WshtDestName had a value of “Data”. 如果我编写了Worksheets(5)则将出现错误9,因为没有工作表5。运行宏时, WshtDestName的值为“ Data”。 There was no Worksheets("Data") so you got error 9. If you update the Const statement, this error will go because Worksheets("Sheet1") exists. 没有Worksheets("Data")因此出现错误9。如果更新Const语句,则此错误将Const ,因为存在Worksheets("Sheet1")

I didn't know if the constants at the beginning were supposed to be after the Sub so I moved them to be after the Dim's under Sub and nothing happened then. 我不知道开始时的常量是否应该在Sub之后,所以我将其移动到Sub的Dim's之后,然后什么也没有发生。

Here you have strayed into the topic of "Scope". 在这里,您误入了“范围”主题。 If I declare a constant or a variable within a subroutine or a function, it is only visible within that subroutine or function. 如果我在子例程或函数中声明了常量或变量,则仅在该子例程或函数中可见。 The “scope” of the constant or variable is the function. 常数或变量的“范围”是函数。 If I declare a constant or a variable at the top of a module, it is visible to every subroutine or function within that module but not to those in other modules. 如果我在模块的顶部声明一个常量或变量,则该模块中的每个子例程或函数均可见,而其他模块中的子例程或函数则不可见。 The “scope” of the constant or variable is the module. 常数或变量的“范围”是模块。 If I add “Public” to the declaration, the constant or variable is visible to every subroutine or function in every module or user form within the workbook. 如果在声明中添加“ Public”,则工作簿中每个模块或用户形式中的每个子例程或函数都可以看到常量或变量。 The “scope” of the constant or variable is the workbook. 常量或变量的“范围”是工作簿。

[ Note from OP: This is interesting to know because I couldn't find information about constants before the Sub via Google. [ OP的注:这很有趣,因为在通过Google Sub之前,我找不到常量的信息。 Thank you.] 谢谢。]

This workbook has only one subroutine and only one module and no user forms so it does not really matter where you place the constant declarations. 该工作簿只有一个子例程,只有一个模块,也没有用户表格,因此放置常量声明的位置并不重要。 The most appropriate scope for a constant or variable is a complicated issue and I am not going to attempt an introduction. 常量或变量的最合适范围是一个复杂的问题,我将不尝试介绍。 I will just say that these constants are recording my assumptions about the workbook. 我只想说这些常数记录了我对工作簿的假设。 If there had been multiple modules I would have defined them as Public. 如果有多个模块,我将它们定义为Public。

You need to review all my assumptions. 您需要检查我所有的假设。 I do not have your data. 我没有您的数据。 I have made up data that I believe matches your data. 我整理了一些我认为与您的数据匹配的数据。 But if any of my assumptions about your data are wrong, the macro will not work. 但是,如果我对您的数据的任何假设是错误的,则该宏将无法工作。

When I hit F8 to look at each line of code, here is what the screen tip says: For Application.ScreenUpdating = False it says Application.ScreenUpdating = True 当我按F8键查看每一行代码时,屏幕提示如下:对于Application.ScreenUpdating = False它表示Application.ScreenUpdating = True

When a statement is yellow, it has not yet been executed. 语句为黄色时,尚未执行。 With most statements, you can actually amend it before pressing F8 again to execute it. 对于大多数语句,您实际上可以在再次按F8来执行它之前对其进行修改。 So if you have a yellow A = A + 2 and you think: “I meant A = A + 3 ”, you can correct the statement before execution. 因此,如果您有一个黄色的A = A + 2并且您认为:“我的意思是A = A + 3 ”,则可以在执行之前更正该语句。

True is the default value for Application.ScreenUpdating so that is the value you see before Application.ScreenUpdating = False is executed. TrueApplication.ScreenUpdating的默认值,因此这是在执行Application.ScreenUpdating = False之前看到的值。

For Set WbkDest = ThisWorkbook the screen tip says for WbkSet = Nothing and for ThisWorkbook = , but only says these things when yellow highlighted. 对于Set WbkDest = ThisWorkbook,屏幕提示显示WbkSet = Nothing和ThisWorkbook =,但仅在黄色突出显示时显示这些内容。 When hit F8 and move off that line, it doesn't say anything when I put the cursor over it. 当按F8键并移出该行时,当我将光标放在其上时,它什么也没说。

If you hover over an ordinary variable (data type = Long, String, Boolean, etc.), the interpreter will display its value. 如果将鼠标悬停在普通变量(数据类型= Long,String,Boolean等)上,则解释器将显示其值。 An object (such as WbkDest) has lots of properties; 一个对象(例如WbkDest)具有许多属性; which should the interpreter display? 口译员应该显示哪个? Some objects, such as Range , have a default property. 一些对象(例如Range )具有默认属性。 For Range this is Value so if you hover over a range, you see the value. 对于Range此值为Value因此,如果将鼠标悬停在某个范围上,则会看到该值。 A workbook has no default property so the interpreter doesn't display anything. 工作簿没有默认属性,因此解释器不会显示任何内容。

Go down to the Immediate Window and type ? WbkDest.Name 转到立即窗口并键入? WbkDest.Name ? WbkDest.Name and click Enter . ? WbkDest.Name ,然后单击Enter The interpreter will display the workbook's name. 解释器将显示工作簿的名称。 You can get the value of any of the workbook's properties displayed. 您可以获取显示的任何工作簿属性的值。 You can also display sub-properties, for example: WbkDest.Worksheets.Count or WbkDest.Worksheets("Sheet1").Range("A1").Value . 您还可以显示子属性,例如: WbkDest.Worksheets.CountWbkDest.Worksheets("Sheet1").Range("A1").Value

[ Note from OP: 1st error - I received a Run-time '424': Object required error when I typed '? [ OP中的注释:第一个错误 -我收到运行时'424':键入'?时对象必需错误? WbkDest.Name' and hit Enter in the Immediate Window. WbkDest.Name”,然后在立即窗口中按Enter。 Is it not recognizing WbkDest because it is declared in the beginning Dim and later Set = This Workbook. 它是否不能识别WbkDest,因为它是在开始的Dim和后来的Set = This Workbook中声明的。 I changed the name to my MASTER.xlsm to MASTER_DESKTOP TEST.xlsm but that shouldn't matter because we never explicitly mention it in this code, correct?] 我将名称从MASTER.xlsm更改为MASTER_DESKTOP TEST.xlsm,但这没关系,因为我们从未在代码中明确提及它,对吗?]

Response from TD to above note Dim X As Type reserves some space for X and sets its value to the default for the type. TD对上述注释的响应 Dim X As Type为X保留了一些空间,并将其值设置为该类型的默认值。 For type Long, the value will be zero. 对于Long类型,该值为零。 For type Object (Workbook is a sub-type of Object), the default value is Nothing. 对于类型Object(工作簿是Object的子类型),默认值为Nothing。 Nothing does not have any properties so at this stage ? WbkDest.Name 没有什么没有任何属性,所以在此阶段? WbkDest.Name ? WbkDest.Name will give an error. ? WbkDest.Name将给出错误。 When statement Set WbkDest = ThisWorkbook is executed, WbkDest now gives access to ThisWorkbook . 当执行语句Set WbkDest = ThisWorkbookWbkDest现在可以访问ThisWorkbook ThisWorkbook has a Name so ? WbkDest.Name ThisWorkbook有一个Name ? WbkDest.Name ? WbkDest.Name will have a value. ? WbkDest.Name将具有一个值。 You are correct; 你是对的; you can rename the workbook without changing the code. 您可以重命名工作簿,而无需更改代码。

Set RngDest = .Cells.Find("*", .Range("A1"), xlFormulas, , xlByRows, xlPrevious) where RngDest = Nothing in tip and nothing pops up in screen tip except -4123 for xlFormulas, and 1 for xlByRows, and 2 for xlPrevious. 设置RngDest = .Cells.Find(“ *”,.Range(“ A1”),xlFormulas,,xlByRows,xlPrevious),其中RngDest =尖端无任何内容,屏幕尖端不显示任何东西,除了-4123对于xlFormulas和1对于xlByRows ,对于xlPrevious为2。

I deduce from this you want to add new data to the bottom of data from previous runs of the macro. 由此推断出您想向宏的先前运行中的数据底部添加新数据。 In my experience this is unusual but I included the code for this option just in case. 以我的经验,这是不寻常的,但是为了以防万一,我包括了此选项的代码。

[ Note from OP: FYI, yes, the Master has headers and the data will be added below data that has been previously copied over via the macros.] [ OP中的注释:仅供参考,是的,Master具有标头,并且该数据将添加到先前通过宏复制过来的数据下面。]

Response from TD to above note My code is more complicated than you need but includes the functionality you want. TD对上述注意事项的响应我的代码比您所需的复杂,但包含所需的功能。 If the master worksheet is empty, the header row(s) and the data rows will be copied from the first source worksheet. 如果主工作表为空,则会从第一个源工作表中复制标题行和数据行。 Only the data rows will be copied from any other workbooks. 从所有其他工作簿中仅复制数据行。 If the master worksheet is NOT empty, only data rows are copied from the source worksheets. 如果主工作表不为空,则仅从源工作表复制数据行。

xlFormulas, xlByRows and xlPrevious are Excel defined constants so the parameters for Find are meaningful names rather than strange numbers. xlFormulas,xlByRows和xlPrevious是Excel定义的常量,因此Find的参数是有意义的名称,而不是奇数。

From the other statements listed, I deduce that the destination workbook is currently empty. 从列出的其他语句中,我推断出目标工作簿当前为空。

[ Note from OP: FYI, yes, the Master/destination wkbk has a header row in the 1st row, but is otherwise empty to begin with.] [ OP中的注释:仅供参考,是的,主站/目的地wkbk在第一行中有一个标题行,但其他情况下是空的。]

Response from TD to above note See my last response. TD对上述注意事项的回复参阅我的最新回复。

Do While FileName <> "" And FileName <> WbkDest.Name where both FileName and WbkDest.Name = "MASTER.xlsm" in screen tip. 在FileName <>“”和FileName <> WbkDest.Name时执行操作,其中屏幕提示中的FileName和WbkDest.Name均=“ MASTER.xlsm”。 F8 then jumps through the rest of the code to the end where With WshtDest .Cells.EntireColumn.AutoFit End With, etc. 然后,F8跳转到其余代码,直到With WshtDest .Cells.EntireColumn.AutoFit End With等结束。

At this point you have hit a bug in my code. 至此,您已经在我的代码中遇到了一个错误。 I do not understand why my testing did not encounter this bug. 我不明白为什么我的测试没有遇到这个错误。

You need to ask: why has the loop exited? 您需要问:为什么退出循环? Why hasn't it repeated for the next file? 为什么下一个文件没有重复? If I leave out most of the code, you get: 如果我遗漏了大部分代码,您将获得:

Do While FileName <> "" And FileName <> WbkDest.Name
  ‘ Code to process interesting file
  FileName = Dir$
Loop  ' While FileName <> "" And FileName <> WbkDest.Name

FileName <> "" is True since FileName = “MASTER.xlsm” but FileName <> WbkDest.Name is False since “MASTER.xlsm” = WbkDest.Name. 由于FileName =“ MASTER.xlsm”,所以FileName <> ""为True,但是由于“ MASTER.xlsm” = WbkDest.Name,因此FileName <> WbkDest.Name为False。 The end condition has been reached and the loop ends without checking any other files. 已达到结束条件,并且循环结束而未检查任何其他文件。

I should have written: 我应该写:

Do While FileName <> ""
  If FileName <> WbkDest.Name
    ‘ Code to process interesting file
  End If
  FileName = Dir$
Loop  ' While FileName <> ""

With this code, workbook “MASTER.xlsm” is ignored as required but the loop continues looking for further workbooks. 使用此代码,工作簿“ MASTER.xlsm”将根据需要被忽略,但是循环将继续查找其他工作簿。

Amend the macro to match the revised structure and try again. 修改宏以匹配修订后的结构,然后重试。

[ Note from OP: 2nd Error I received a Compile Error - Expected: Then or Go To, so I just added Then after If FileName <> WbkDest.Name, so it reads [ 来自OP的注释:第二个错误我收到了编译错误-预期:然后或转到,所以我刚刚在If FileName <> WbkDest.Name之后添加了Then,因此它显示为

If FileName <> WbkDest.Name Then
Set WbkSrc=Workbooks.Open (FolderPath & FileName)
'Rest of Code

Is this correct?] 这个对吗?]

Response from TD to above note Yes you are correct. TD对上述注意事项的答复是的,您是正确的。 I should have included the tested code rather than trying to create a summary. 我应该包含经过测试的代码,而不是尝试创建摘要。

[ Note from OP: 3rd error - After I added all of the edits, I ran the Compile VBA Project under Run and it said, Compile Error: Loop without Do', which I don't understand because the Loop I'm sure it is referring to is at the bottom and never had a 'Do' next to it. [ OP中的注释:第三个错误 -添加所有编辑后,我在Run下运行了Compile VBA项目,并说Compile Error:Loop Without Do',我不明白,因为Loop我确定指的是底部,并且旁边从来没有“ Do”。 In other words, I'm not sure why it is raising an error now when it never had a 'Do'.] 换句话说,我不确定为什么从来没有'Do'时为什么现在会引发错误。]

Response from TD to above note Compile errors "Loop without Do", "Do without Loop", "If within End If", "End If without If", etc. can be confusing. TD对上述注意事项的响应编译错误“没有执行循环”,“没有循环执行”,“如果在If中结束”,“如果没有If则结束”等可能会造成混淆。 Do loops, for loops and Ifs must be properly nested. Do循环,for循环和If必须正确嵌套。 If you fail to complete one structure completely, the compiler complains about the outer structure which is probably perfect. 如果您无法完全完成一个结构,则编译器会抱怨可能是完美的外部结构。 My guess, is you have not included the End If for the new If . 我的猜测是,您是否尚未将End If包括在新If When the compiler hits the Loop it is looking for the End If or the start of a nested structure. 当编译器进入Loop它正在寻找End If或嵌套结构的开始。 I have replaced my original code with my revised code which I have just tested again. 我将我的原始代码替换为经过重新测试的修订代码。 You can copy the new code and update for your names. 您可以复制新代码并更新您的姓名。 However, it may be better to work down your loop and match it against mine. 但是,最好将您的循环工作下来并与我的进行匹配。 My guess is you will find an End If in my code that is missing from yours. 我的猜测是您会在我的代码中找到一个End If ,而您的代码中却找不到。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我正在尝试使用VBA将多个工作簿中的数据复制到主文件中,而又不知道每个工作簿的名称 - I am trying to use VBA to copy data from multiple workbooks into a master file without knowing the names of each workbook EXCEL VBA-将数据从多个工作簿传输到工作簿模板 - EXCEL VBA - Transferring data from multiple workbooks to workbook template VBA中的多个范围选择 - 将多个工作簿合并到一个主工作簿中 - Multiple range selection in VBA - Consolidating multiple workbooks into one master workbook 使用VBA将多个工作簿合并到一个(新)主工作簿中 - Merge multiple workbooks in one (new) master workbook using VBA 将多个工作簿中的多个工作表中的数据复制到单个主工作簿中 - copy data from multiple worksheets in multiple workbooks, all into single master workbook 将多行从多个工作簿复制到一个主工作簿 - Copy multiple rows from multiple workbooks to one master workbook 如何基于可变条件从多个工作簿中复制数据行,然后粘贴到主工作簿中 - How to copy rows of data from multiple workbooks based on an variable criteria, then paste into a master workbook 以编程方式将数据从多个工作簿中的特定单元复制到“主工作簿” - Copying data from specific cells across multiple workbooks to 'master workbook' programmatically 如何将多个工作簿中的特殊内容粘贴到主工作簿 - How do I paste special from multiple workbooks to a master workbook 将数据从2个工作簿复制/合并到一个主工作簿 - Copy/merge data from 2 workbooks to one master workbook
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM