简体   繁体   中英

VBA - Copy a sheet to another workbook

I want to copy a sheet (sheet2) from certain workbooks (paths in cell column "B") to another workbook (template).

I tried the following one but Excel Return me the following error "Run-time error '1004': Application-defined or object defined error".

Private Sub SplitFile_Click()
  Dim C As Integer
  Dim x As Variant
  Dim Z As Workbook

  For C = 0 To 10

  Set x = ThisWorkbook.Sheets("SelectedFiles").Range("B" & C)
  Worlbooks.Open("x").Sheets(Sheet2).Range("A1:U1000").Copy
  Set Z = Workbooks.Open("D:\PTP\MASTERDATA\SPACCHETTAMENTO FILE\TEMPLATE.Template.xlsx")


  Z.Sheets("SPLIT TAB").Range("A1:U1000").PasteSpecial
  Workbooks("Z").SaveAs Filename:="PROVA.xlsx"
  Next C
End Sub

Can you help me?

Thanks, Ivan

VBA is blowing up on this line:

Set x = ThisWorkbook.Sheets("SelectedFiles").Range("B" & C)

Because the value of C is 0, and 0 isn't a valid row number - B0 isn't a valid range address. So you could start with C = 1 and that would fix this error.

I'd strongly recommend using a Long integer (32-bit) instead of an Integer (16-bit) when referring to row numbers (regardless of which rows you need). The maximum value of an Integer is 32,767, and a worksheet can have many more rows than that.

x is declared as a Variant . This means it can be/become literally anything you make it.

If you do this:

x = ThisWorkbook.Sheets("SelectedFiles").Range("B" & C)

Then x will contain the value of the cell referred to by the Range call.

However you did this:

Set x = ThisWorkbook.Sheets("SelectedFiles").Range("B" & C)

This instructs VBA that x should contain an object reference , so instead of assigning it the value of the cell, you're getting the cell itself .

Then you do this:

Worlbooks.Open("x").Sheets(Sheet2).Range("A1:U1000").Copy

If this compiles, it's only because Option Explicit isn't specified. Worlbooks doesn't exist anywhere, it's a typo - but because Option Explicit isn't specified, VBA allows you to use variables without declaring them, and so happily compiles Worlbooks and defers its resolution to run-time... at which point another error will pop up.

This would fix it:

Workbooks.Open("x").Sheets(Sheet2).Range("A1:U1000").Copy

Except... it's inside the loop: at every iteration of that loop, you try to open a workbook named "x" (which most probably doesn't exist). If "x" means to be a file name contained in ThisWorkbook.Sheets("SelectedFiles").Range("B" & C) , then x should be declared as a String variable, and you would refer to it like this:

Dim source As Workbook
Set source = Workbooks.Open(x)

And you would do that outside the loop , so that you don't try to open the same workbook every time the loop makes an iteration: IIRC opening a workbook that's already opened will throw yet another run-time error.

If each iteration should be working with a different workbook/file, then each iteration should also close that workbook, otherwise you end up with 12 workbooks opened, 11 of which you don't need anymore.

So you keep a reference to the workbook object you want to work with:

For C = 1 To 11
    x = ThisWorkbook.Sheets("SelectedFiles").Range("B" & C).Value
    Set source = Worlbooks.Open(x)
    source.Sheets(Sheet2).Range("A1:U1000").Copy
    '...
    source.Close
Next

Same with your destination book:

Set Z = Workbooks.Open("D:\PTP\MASTERDATA\SPACCHETTAMENTO FILE\TEMPLATE.Template.xlsx")

You're opening the same file 11 times, and not closing it once. And then you paste from the source book into that destination book...

Z.Sheets("SPLIT TAB").Range("A1:U1000").PasteSpecial

...overwriting the previous iteration's work everytime, and saving 11 times.


So, there's a lot of serious issues in that code. Recap:

  • Specify Option Explicit at the top of every module.
  • Declare all variables, with an explicit specific type whenever possible.
  • Clean up after yourself.

Learn to use the debugger. F9 sets a breakpoint, which stops execution; from that point on you can use F8 to run your code one instruction at a time, and you can use the immediate pane ( Ctrl + G ) to output anything in the current execution context. Use the locals toolwindow to visualize everything the current scope has access to.

you don't need to copy and paste data between Workbook as it will run more slowly. Here some example code, hope it can help you..!

Option Explicit

    Public Sub SplitFile_Click()
      Dim C As Integer
      Dim x As Range
      Dim Z As Workbook

      For C = 1 To 10
          Set x = ThisWorkbook.Sheets("SelectedFiles").Range("B" & C)
          Set Z = Workbooks.Open("D:\Template.xlsx")

          Z.Sheets("SPLIT TAB").Range("A1") = x 'this code is faster that copy & paste
          Z.SaveAs "PROVA" & C & ".xlsx" 'workbook should have a unique filename

          Z.Close 'close workbook
      Next C
    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