Copy and paste Excel sheets - vba

Private Sub CommandButton1_Click()
Dim ws As Worksheet
With Application.FileDialog(msoFileDialogFilePicker)
.Show
If .SelectedItems.Count <> 0 Then
fldr = .SelectedItems(1)
End If
End With
Sheets.link.Value = fldr
For i = 1 To Worksheets.Count
Set ws = Worksheets(i)
If ws.Cells(2, 1) = "X" Then
Sheets.ComboBox1.AddItem (ws.Name)
End If
Next i
Workbooks.Open (fldr)
Sheets.Show
End Sub
Private Sub Add_Click()
Dim x As String
Dim ws As Workbook
x = Right(link.Value, (Len(link.Value) - InStrRev(link.Value, "ild") - 3))
Workbooks("Test.xlsm").Activate
Worksheets(ComboBox1.Value).Copy Before:=Workbooks(x).Worksheets("Contract")
End Sub
So the basic idea is, you click a button on an Excel sheet. The user then finds the file they want to copy the sheets to. It will find all of a specific type of sheet, put it in a forms combobox and open the selected Excel file.
Then you choose a sheet from the combobox and copy it from one workbook to the other. It all works until the copying part. I get a long error:
Excel cannot insert the sheets into the destination workbook, because it contains fewer rows and columns that the source workbook. To move or copy the data to the destination workbook, you can select the data and then use Copy and Paste commands to insert it into the sheets of another workbook.

If the destination workbook comes from an older version of Excel (extension .xls for instance, Excel 97 or Excel 2003), the limit of number of rows in old worksheets is 2^16-1, as the row number is encoded on 16 bits. In newer versions, this number is encoded on 32 bits.
Hence, copying a worksheet "as a whole" from a newer version into a workbook from an older version raises this error. From my test, this error occurs even if the actually used range in the copied worksheet is small.

I had this same problem.
Following #A.S.G. suggestion, I saved the old workbook with the new file format (xlsx), closed and reopened it and everything worked fine afterwards.
Hope it helps.

Related

Comparing columns in different excel 2013 files and deleting the duplicates from one of the workbooks (need macro)

This is my first question on this site and I'm not a programmer, so please bear with me.
I am trying to create an Excel 2013 macro that will compare values in column A on one workbook ("active workbook") to column A's of other Excel files in a particular directory. Duplicate values (rows) would then be deleted from the active workbook.
I have been working piece by piece trying to figure this out as I am not a programmer. So far I have been able to use conditional formatting to highlight unique values when the two columns are side by side (same worksheet). I used =ISNA(MATCH($A2,$B$2:$B$12,0)).
Then I used a macro to print out the duplicate values to another column (instead of highlighting them.. I am still at this stage comparing two columns within the same worksheet). I did this by using the following macro:
Sub Find_Matches()
Dim CompareRange As Variant, x As Variant, y As Variant
' Set CompareRange equal to the range to which you will
' compare the selection.
Set CompareRange = Range("C1:C12")
' NOTE: If the compare range is located on another workbook
' or worksheet, use the following syntax.
' Set CompareRange = Workbooks("Book2"). _
' Worksheets("Sheet2").Range("C1:C5")
'
' Loop through each cell in the selection and compare it to
' each cell in CompareRange.
For Each x In Selection
For Each y In CompareRange
If x = y Then x.Offset(0, 1) = x
Next y
Next x
End Sub
Then I tried removing duplicate values from two different worksheets but that didn't work:
Sub ProcessFiles()
Dim Filename, Pathname As String
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim Sheet As Worksheet
Dim PasteStart As Range
Dim Counter As Integer
Set wb1 = ActiveWorkbook
Set PasteStart = [RRimport!A1]
Pathname = ActiveWorkbook.Path & "\For Macro to run\"
Filename = Dir(Pathname & "*.xls")
Do While Filename <> ""
Set wb2 = Workbooks.Open(Pathname & Filename)
For Each Sheet In wb2.Sheets
With Sheet.UsedRange
.Copy PasteStart
Set PasteStart = PasteStart.Offset(.Rows.Count)
End With
Next Sheet
wb2.Close
Filename = Dir()
Loop
End Sub
I've been reading this site for couple of days and also searched through YouTube. I haven't had much success after the first two basic things I did.
Background of the project: Everyday we have a list called "Pending List" which essentially is all of the projects we need to get done. Everyday this list grows. Each project is given a unique identifier (numeric value) that is listed in column A of the active workbook. Every day I create my own files of the projects that are being completed. Instead of manually checking off each project one by one by comparing several files every day, I would like Excel to be able to delete the duplicates (meaning the projects that are both on my pending list and in the other files, and only leave the unique projects that still need to be done. Hope I didn't confuse anyone but if I did, please let me know.
The question here:
I am trying to create an Excel 2013 macro that will compare values in
column A on one workbook ("active workbook") to column A's of other
Excel files in a particular directory. Duplicate values (rows) would
then be deleted from the active workbook.
So, let's break this down:
There is a directory from which workbooks need to be opened.
When one of the workbooks is open, you want to check column A (I assume this is on the first worksheet for the sake of the example below) for values you have in column A in your active workbook (the one that will run the macro).
If there's a match, delete the row from the active workbook in which the value was stored.
When done, continue with the next workbook in the directory.
Point 1 and 4: Open some files from a specific directory:
We will need some function to open and close the files. This question has been asked many times on SO, for example here
Also, we're going to need the workbooks to be stored in some variable that we will pass to the comparison in the next step.
Public Sub LoopOverFiles()
'Our variables:
Dim wb1 As Workbook 'To hold the active workbook / the macro workbook
Dim wb2 As Workbook 'To hold the workbook we'll be comparing to later on
Dim scanFolder As String 'To set the folder in which the files will be located
Dim fileNameToOpen As String 'To get the filenames that we will open
Set wb1 = ThisWorkbook
scanFolder = "C:\temp\"
fileNameToOpen = Dir(scanFolder & "*.xlsx")
'And loop over the files:
Do While Len(fileNameToOpen) > 0 'To exit the loop when there's no more xlsx files
Set wb2 = Workbooks.Open(scanFolder & fileNameToOpen)
'To do the actual comparison of the 2 workbooks, we call our compare routine.
DoTheComparison wb1, wb2 'Note we'll be passing the two workbooks as parameters to the compare function
wb2.Close SaveChanges:=False 'We don't want to leave it open after we're done with it.
fileNameToOpen = Dir 'To continue with the next file.
Loop
End Sub
Point 2 and 3: Do the comparison and delete some rows
As you can see, the actual comparison will be done by a routine that's called DoTheComparison and that takes 2 workbooks as parameters. Based on the first routine, we know that the workbooks that will be passed are the correct ones (wb1 being the active one, wb2 being the variable one that gets opened during the loop).
In this example we'll stick to the first worksheet in wb2.
Public Sub DoTheComparison(wb1 as Workbook, wb2 as Workbook)
'Dim compareFrom as Range - Not needed.
Dim compareTo as Range
Dim compareFromCell as Range
Dim compareToCell as Range
Dim i as Integer
'EDIT: Since we delete, we need a backwards loop. This can't be done with "for each" so we'll use "for" with step -1.
'That is why we also don't need the "CompareFrom" range variable anymore.
Set compareTo = wb2.Worksheets(1).Range("A2:A20")
For i = 20 to 2 step -1
Set compareFromCell = wb1.Worksheets("RemoveValsFromHere").Range("A" & i) 'We get the cells based on the index.
For Each compareToCell in compareTo
If compareFromCell.Value = compareToCell.Value Then 'Point 3:
compareFromCell.EntireRow.Delete shift:=xlUp
Exit For
'Note that we need to exit the inner loop:
'After a match was found, the "compareFromCell" is deleted after all.
'Therefore we have to continue with the next compareFromCell, otherwise we'll get an error.
End If
Next compareToCell
Next i
End Sub
Note that especially DoTheComparison is written for maximum clarity, not for optimal speed (far from it!). I see in your question you've been looking into comparing variants / arrays, which is indeed a lot faster.
EDIT: I altered the code above since you're facing the "skipping cells" issue due to cell deletion. In short: The index changes, so when moving to the next cell after deletion the index is wrong. The fix is an easy backwards for loop. Also see this question and answer

Table Reference in Formula Changes When Worksheets Copied

I have two sheets in "Property" Workbook that I am copying to "UQP" Workbook.
PropertyCoverage - Houses formula =VLOOKUP("PF",tPremium,2,0) among other text and simple SUM formula.
xmlProperty - Houses table tPremium (among other tables; all tables mapped to XML Source)
When I copy these two sheets (simultaneously) into the UQP workbook the tPremium reference in the formula in the PropertyCoverage sheet automatically changes to tAutoForms, which is another table in the UQP workbook (that has nothing to do with the formula). UQP workbook has several other sheets and tables.
I don't know why this changes automatically, but I think it has something to do with the fact that Excel cannot copy multiples sheets when at least one sheet contains a table.
I have tried the solution below (referenced from here). However, the same issue happens. The issue does not happen if I copy to a new workbook. ... Bear with ActiveWorkbook, etc, I only used this as test to see if it would work
Sub Copy_Worksheets()
Dim wbMaster As Workbook
Set wbMaster = Workbooks("UniversalQuoteProposal.xlsb")
Dim TheActiveWindow As Window
Dim TempWindow As Window
With ActiveWorkbook
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
.Sheets(Array("PropertyCoverage", "xmlProperty")).Copy Before:=wbMaster.Worksheets(1)
End With
TempWindow.Close
End Sub
Here is my original copy code:
Sub CopySheetsToMaster()
Dim wbMaster As Workbook
Set wbMaster = Workbooks("UniversalQuoteProposal.xlsb")
Dim sSheetName As String
sSheetName = Replace(ThisWorkbook.Name, ".xlsb", "")
Dim sSheets As Variant
sSheets = Array(sSheetName & "Coverage", "xml" & sSheetName)
'*** => This is where tPremium gets automatically changed to tAutoForms
ThisWorkbook.Worksheets(sSheets).Copy Before:=wbMaster.Worksheets(1)
wbMaster.ChangeLink ThisWorkbook.FullName, wbMaster.FullName, xlLinkTypeExcelLinks
End Sub
Lastly, I can work around this by doing a Replace after the sheets are copied, but since this will scale out to a need to bring a possible 7-10 other workbooks with potential formula references to tables and such, I would rather find a cleaner solution if it exists.
Lastly, I am using Excel 2010.

Copy and moving an entire sheet to another workbook. 1mil rows to 65536 rows

The following is part of my code that involves copying an entire named sheet from one master file to a new unsaved file that's being worked on:
ActiveWorkbook.Sheets("VehicleList").Copy _
After:=Workbooks(2).Sheets(1)
So this worked fine to place the sheet into workbook 2 but now the files we're dealing with are in old excel mode which is throwing up the following error due to old excel having less rows:
"Excel cannot insert the sheets into the destination workbook, because it contains fewer rows and columns"
How can I tweak the copy and pasting into Workbooks(2) without breaking the code? I thought defining a range of 1000 rows to copy and move would work, but this also gave an error. Thanks for your help.
Assuming you just want the values (i.e. I'm speeding it up by not doing a copy paste) you can do:
Workbooks(2).Sheets.Add After:=Sheets(1)
Workbooks(2).Sheets(2).Range("A1:F1000").Value = ActiveWorkbook.Sheets("VehicleList").Range("A1:F1000").Value
I'd go like follows
Option Explicit
Sub main()
Dim targetWs As Worksheet
With Workbooks("MyWorkbookname").Sheets("VehicleList") '<--| fully qualify reference wanted worksheet in the wanted workbook
Set targetWs = SetOrGetSheet(Workbooks(2), .name) '<--| get the (new) target worksheet on the target workbook named after referenced sheet
Intersect(.Range("A1:F1000"), .UsedRange).Copy targetWs.Cells(1, 1) '<--| copy range to target worksheet on the target workbook
If targetWs.name <> .name Then MsgBox "a new sheet has been created in " & targetWs.Parent.name & " with name " & targetWs.name
End With
End Sub
Function SetOrGetSheet(targetWb As Workbook, shtName As String) As Worksheet
targetWb.Worksheets.Add '<--| add a new sheet in the target workbook
On Error Resume Next
Set SetOrGetSheet = targetWb.Worksheets(shtName) '<--| try and get any possible target workbook sheet with the passed name
If SetOrGetSheet Is Nothing Then targetWb.ActiveSheet.name = shtName '<--| if target workbook has no worksheet with passed name then name the new one after it
Set SetOrGetSheet = targetWb.ActiveSheet 'return the new worksheet
End Function
should you be afraid your range-to-copy could exceed 65 rows and/or 256 columns than you should add its size check
edit for values pasting only
should you be interested in pasting values only then you can go like follows:
Sub main()
SetOrGetSheet(Workbooks(2), "VehicleList").Range("A1:F1000").value = ActiveWorkbook.Sheets("VehicleList").Range("A1:F1000").value '<--| copy values form source to target worksheet
End Sub
while SetOrGetSheet() function stays the same as above
as you may have guessed that function is there for a more general approach where you may want (or just have) to handle the possibilty of target workbook having a worksheet named after "VehicleList" already

Create a new workbook and paste data 3 different workbooks one after the other

I have a question (incidentally I have multiple questions, which will be posted later) regarding Creating a new workbook and paste data 3 different workbooks one after the other.
This is a part of daily routine, where concerned people will be posting 3 different sets of data in 3 different folders. File names will be given based on date. Example: My book 01 22, NT book 01 21 etc.
Instead of manually taking each file and copying data into one single sheet, I want to use a Macro to create a new workbook, save it as per the date and copy data from the 3 different workbooks stored in different folders, one after the other in one single sheet.
Below is the code I am using:
Sub Main()
Dim fd As FileDialog
Dim SelectedItem As Variant
Set NewBook = Workbooks.Add
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
If .Show = -1 Then
For Each SelectedItem In .SelectedItems
Workbooks.Open (SelectedItem)
'Workbooks.Application.Worksheets("Sheet1").Copy
Workbooks("NewBook").Activate
LastRow = ActiveSheet.UsedRange.Rows.Count
MsgBox (LastRow)
NewBook.Worksheets("Sheet1").Cells(LastRow + 1, 1).PasteSpecial (xlPasteValues)
LastRow = ActiveSheet.UsedRange.Rows.Count
MsgBox (LastRow)
Next SelectedItem
End If
End With
Set fd = Nothing
End Sub
You could use the macro recorder (http://m.dummies.com/how-to/content/how-to-record-a-macro-to-automate-tasks-in-excel-2.html). It simply reproduces the steps you do manually in Excel as VBA-Code. You can use that as a first step if you dont know much about VBA. Look at the code and try to alter it. I often use it if I dont know the VBA Commands for standard Excel Features.

copy excel sheets with table references

I have an Excel 2007 document with multiple sheets, let's call it source.xls. I'd like to copy some of the sheets into all Excel documents within a folder, say C:\some_folder.
I figured how to loop over a directory:
Dim file As String
file = dir("C:\some_folder\*.xlsx")
Do While file <> ""
Rem do_stuff
file = dir()
Loop
And how to copy sheets between workbooks:
For Each ws in ActiveWorkbook.Worksheets
Dim wb as Workbook
Set wb = Workbook.Open(file)
ws.Copy , wb.sheets(w.sheets.Count)
wb.Close SaveChanges:=True
Next ws
So far so good.
Now one of the sheets contains a table with external data from an SQL Server. Copying it works well.
Another sheet references data in that table as Table_MYSERVER_MYDB[[row][col]]. When I copy it, the references are automatically turned into source.xls!Table_MYSERVER_MYDB[[row][col]]
UPDATE:
I just tried to reference the data in the table by sheet and cell, e.g. =Other_Sheet!A1. Still the same problem, the reference magically turns into =[source.xls]Other_Sheet!A1.
UPDATE 2:
The next try was to access the cells in the other sheet with =INDIRECT("Other_Sheet!"&CELL("address")), but that seems to trigger a bug in Excel 2007. All cells will show the same value. Try it for yourself :)
I'd like the sheets in the target document to reference the table in the same workbook. How would I do that?
I'm open for other solutions than VBA too
I just figured it out myself:
My last desperate attempt was using Search&Replace over all formulas to remove [source.xls].
That's when a workmate suggested using:
wb.ChangeLink Name:=source.xls NewName:=wb.Name Type:=xlExcelLinks
Exactly what I was looking for!
Try this:
Sub CopyFormula()
Dim R1,R2 As Range
Set R1 = Workbooks("wb2.xls").Sheets(1).Range("A1")
Set R2 = Workbooks("wb1.xls").Sheets(1).Range("A1")
R1.Formula = R2.Formula
End Sub