Merge tables from many separate workbooks - vba

I want to merge specific contents of 2713 workbooks into a single worksheet. Lets say the individual files contain sales revenues for different sales outlets.
Each of the workbooks uses only 1 worksheet. Each of those worksheets contains one or more tables in identical format. Worksheets contain no fuctions whatsoever. This sample shows cells A1:E7
A1 contains the number of the specific outlet
A2 contains the reference date, e.g. 31.12.2014
A3:E3 contain the column headers: No.; Item; Revenue current period; Revenue previous period
A4:E10 contain the info I want transported to the new single file
A11:E11 contains the total amounts
Row 12 is blank
Another table with info for 31.12.2013 starts from row 13.
...
Most of the worksheets have more than just one table. All of them start like the one above. The tables have identical layout.
Unfortunately, the number of products varies a lot (1-250). For the example, I just assumed its 7 products. I don't need the row for headline or total.
How can I get those rows into a new single worksheet?
The outlet number in cell A1 on every sheet should be added in the cell to the right of the cells containing comment.
I want to avoid having to open the 2713 files one after the other in order to copy and paste the info in 2713 drag and drop moves into a merged worksheet.
I hope you can help or its gonna be a long weekend.
Best wishes,
Peter

I'm assuming here that when you say tables you mean defined tables of data.
The code below assumes that all tables are the same size (target and source tables).
There's no error checking and minimal testing - so check on some test workbooks first.
Sub GetTables()
Dim colWrkBks As Collection 'Contains path to all workbooks.
Dim vPath As Variant 'Current workbook path.
Dim wrkBk As Workbook 'Current workbook.
Dim wrksht As Worksheet 'Worksheet within wrkBk.
Dim oListObject As Object 'Tables within wrksht.
Dim oTargetTable As Object 'The table to hold all the data.
Dim sTmp As String
Dim sDirectory As String
'Make sure you have a table defined to place all the data in.
'Update worksheet and table name as required.
Set oTargetTable = ThisWorkbook.Worksheets("Sheet1").ListObjects("Table1")
'Get full path of all workbooks in source folder.
'*Update directory and file extension as required
Set colWrkBks = New Collection
sDirectory = "C:\Users\Darren\Documents\Work\New folder\"
sTemp = Dir$(sDirectory & "*.xls*")
Do While Len(sTemp) > 0
colWrkBks.Add sDirectory & sTemp
sTemp = Dir$
Loop
'Open each workbook and copy the data from source table to target table.
For Each vPath In colWrkBks
Set wrkBk = Workbooks.Open(vPath, False)
'1 references the first worksheet - you can use "Sheet1" for a specific sheet name.
Set wrksht = wrkBk.Worksheets(1)
'Cycle through each table in the worksheet.
For Each oListObject In wrksht.ListObjects
oTargetTable.ListRows.Add
oListObject.DataBodyRange.Rows("1:" & oListObject.DataBodyRange.Rows.Count).Copy _
oTargetTable.DataBodyRange.Rows(oTargetTable.DataBodyRange.Rows.Count)
Next oListObject
wrkBk.Close False
Next vPath
End Sub

Related

segregate the data based on their own value

I have data where list is dynamic. I would like to segregate the data base on their own value.I am unable to predict the exact value coming every time. Example : - This time I got company code as 1959809 and 1960574. I would like to filter data based on company code and would like to paste it in new workbook. This number will get change every time. Next time the company code may be 1960574 and 1963665.
I am thinking that we need to group the company code value so that we can have it in variable. However, I am unable to get the logic.
I am not getting any logic to do so. Hence, I don't have anything to show.
We should get two or more workbooks based on company code along with respective data.
Assuming your data has first column as 'Company Code' and starts from the first row of sheet, Following code will help you achieving your goal:
Sub ExportFilteredData()
Dim Codes As String, CodesArray, Code
Dim Wb As Workbook, CurSht As Worksheet
'Get the company codes from user as comma separated values
Codes = InputBox("Enter Company codes separated by comma")
CodesArray = Split(Codes, ",") 'Split company codes to array
'Save the data sheet reference and remove any applied filter
Set CurSht = ActiveSheet
CurSht.AutoFilterMode = False
'Filter data for each company code and save as new workbook
For Each Code In CodesArray
'Change the 'Field' value to the actual 'Company Code' column number
CurSht.Range("A1").AutoFilter Field:=1, Criteria1:=Trim(Code)
Set Wb = Workbooks.Add
CurSht.AutoFilter.Range.SpecialCells(xlCellTypeVisible).Copy Wb.Sheets(1).Range("A1")
'Change the path and filename as per your requirement
Wb.SaveAs ThisWorkbook.Path & "\" & Trim(Code) & ".xlsx"
Wb.Close False
CurSht.AutoFilterMode = False
Next
End Sub

VBA - Moving large number of records - some records missing

I have a data set of around 1500 sales records. I have written a macro, which would create product category specific work books, which would have an individual work sheet for each product in the product category.
The macro is working as expected, but I have found out that it is consistently ignoring some products. I put debug statements to see if I am getting zero records when I filter based on the product code (since I use this selection to paste the records to a separate work sheet). The selection seems to be working fine, as I get the number of rows selected.
A pattern I saw was that the product codes which were having zero records were generally the first ones or the last ones to get processed before or after a file operation (either I open a category specific work book, or I am closing a work book). But even here, the table header was copied to the individual work sheet. Only the data rows were getting ignored.
Is there a chance where the macro is processing the records too fast, while there is some time lag in doing File I/O operations (which makes a few records to get ignored)?
I am attaching the code, which I have used for looping
'loop through each row and get the product id and the category (Ann & Bnn).
' Dim catWorkBook As Workbook
oProductCat = "0" 'the initial value set as 0, which would NEVER be a category
With wkScrap 'this is a rough sheet which has the product items and categories
For i = 2 To lProdRow
cProductCode = .Cells(i, 1).Value
cProductCat = .Cells(i, 2).Value
'FILE OPEN: will need to open a category specific .xls file
If (StrComp(cProductCat, oProductCat) <> 0) Then
'save the existing workbook
FileIO.CloseExcelFile oProductCat, catWorkBook
Set catWorkBook = Nothing 'clear all traces of the old worksheet
Set catWorkBook = CreateBlankWorkBook()
oProductCat = cProductCat
End If
'COPY DATA: Filtering on product code, and then moving it into a new
'worksheet
CopyCategoryToWorksheet cProductCode, catWorkBook
If i = lProdRow Then
'we are at the end of the loop. Proceed to close the current
'workbook
FileIO.CloseExcelFile oProductCat, catWorkBook
End If
Next
End With
Here is the function which does the actual copying
Private Sub CopyCategoryToWorksheet(prodCode As String, catWkBook As Workbook)
'check for a meaningful prod code
If (Trim(prodCode & vbNullString) = vbNullString) Then
Exit Sub
End If
Dim wkRData As Worksheet
Dim rRData As Range
Dim rDataMaxRows As Integer
Set wkRData = SalesReport.Sheet1
'We know that we have to create a work sheet for this product code.
'Let us do that first.
Dim prodCatSheet As Worksheet
catWkBook.Activate
Set prodCatSheet = catWkBook.Sheets.Add(After:=catWkBook.Sheets(catWkBook.Sheets.Count))
prodCatSheet.Name = prodCode
wkRData.Activate 'for this sub routine, all processing is happening on the raw data sheet
rDataMaxRows = Cells(rows.Count, 1).End(xlUp).Row
Set rRData = Range("A1:H" & rDataMaxRows)
rRData.AutoFilter 3, Criteria1:="=" & Trim(prodCode)
rRData.Select
Selection.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
'activate the newly created sheet, and paste all the selected rows there
prodCatSheet.Activate
prodCatSheet.PasteSpecial
Set wkRData = Nothing 'just clear some memory
End Sub

updating column and row values of the list which has duplicate values

I have merged variable amount of worksheets which are called anything includes the word "data" through this code;
Dim masterSheet As Worksheet
Set masterSheet = Sheets("Komko")
'Variable to save the used Range of the master sheet
Dim usedRangeMaster As Integer
Dim ws As Worksheet
'loop through each worksheet in current workbook
For Each ws In Worksheets
'If sheetname contains "data" (UCase casts the Name to upper case letters)
If InStr(1, UCase(ws.Name), "DATA", vbTextCompare) > 0 Then
'calculate the used range of the master sheet
usedRangeMaster = masterSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row + 1
'Variable to save the used Range of the sub sheet
Dim usedRangeSub As Integer
'calculate the used range of the sub sheet
usedRangeSub = ws.UsedRange.SpecialCells(xlCellTypeLastCell).Row
'copy relevant range from the subsheet
ws.Range("C1:C" & usedRangeSub).Copy
'paste the copied range after the used range in column a
masterSheet.Range("A" & usedRangeMaster).PasteSpecial
End If
Next ws
This code copies the C column of the "data" including Sheets and then pastes it to my master Sheets( which is called "Komko") Column A. Now i would like identify the same values in Column C and delete the complete row of the previous matching value. (e.g if C1 has value "123" and if C7 has value "123" the whole row which includes C1 should automatically be deleted)
How can i do this ?
See http://analysistabs.com/vba/find-duplicate-values-column/ to find your duplicate entries and Delete a row in Excel VBA to get some ideas how to delete the row in a good way.
Start searching after you merged your column C. Use a Boolean variable to skip the first found entry if necessary. Replace the code Cells(iCntr, 2) = "Duplicate" from the first link and put your way of deleting the row there.

How can I copy & paste entire rows with distinct values to a new sheet on varying cell ranges?

I know there's many StackOverlow Q&A's on copying & pasting from a cell value in VBA. However, I can't seem to make it work for my own project. I want to copy the entire row(s) if it matches the Distinct Store# (non incremental) in Column H into a new sheet (in this code below, "Sheet1") which already has a template layout where I copy/paste the values. The template looks the same on every sheet before any data is filled in, except the first 2 tabs which have the data ("Appointments" and "Invoices").
I came up with the VBA below, but here's the catch- the cell# that it pastes the row(s) (in the code below, "A10") changes based on the Store #. This is because I am copying rows from the 1st sheet ("Appointments") in the workbook from the distinct Store#, then deleting the empty rows above the area where the 2nd sheet ("Invoices") data goes. Some stores may return 10 rows or none at all. The Case, which is the Store #, is currently manually put in one by one. Should it be an array instead?
Anyway...I was hoping to automate the copying/pasting and loop for each store to their sheet. Maybe I'm going about this wrong, but would anyone be kind enough to suggest how to solve my error code "Method or data member not found." as well as provide any suggestions on making my code better for a loop for filtered cell copying to different spots for each sheet.
Simple explanation of my step by step process:
1.Filter Store # from "Appointments" sheet.
2. Copy all rows for that store and paste into a new sheet with template named "Sheet1" in B3.
3. Filter Store # from "Invoices" sheet.
4. Copy all rows for that store and paste into the previously made sheet named "Sheet" under the above rows. (Some stores do not have invoices, so this section is blank/NULL). Paste destination cell for "Invoices" will be different for each store# depending on how many rows they get from the "Appointments" sheet (could be A10 or A25).
5. LOOP- Next store #, next sheet (sheet2).
Sub CopyToNewSheetInv()
Dim i As Range
Dim book As Workbooks
Dim sheet1 As Worksheets
Dim sheet2 As Worksheets
Set book = Workbooks("SampleWorkbookName")
Set sheet1 = Worksheets("AllInvoices")
Set sheet2 = Worksheets("Sheet1")
For Each i In sheet1.Range("H:H")
Select Case i.Value
Case 1243
sheet2.Range("A10").End(xlUp).Offset(1, 0).EntireRow.Value = i.EntireRow.Value
Case Else
End Select
Next i
End Sub
Try this:
Sub CopyToNewSheetInv()
Dim i As Range
Dim book As Workbook
Dim sheet1 As Worksheet
Dim sheet2 As Worksheet
Set book = Workbooks("SampleWorkbookName.xlsx")
Set sheet1 = book.Worksheets("AllInvoices")
Set sheet2 = book.Worksheets("Sheet1")
'iterate only thorugh those cells in H that have data, not all 1.04 million
For Each i In sheet1.Range("H1", sheet1.Range("H" & sheet1.Rows.Count).End(xlUp))
Select Case i.Value
Case 1243,"1243"
sheet2.Rows(sheet2.Range("A10000").End(xlUp).Offset(1, 0).Row).Value = sheet1.Rows(i.Row).Value
Case Else
End Select
Next i
End Sub

Union multiple excel sheets. (Paste underneath each other)

What would be the cleverst way of copy and pasting Excel-Tables from multiple files to one single file. So espacially how do I determine the Range of the used Rows for the copy and paste within the makro?
If this is a one time operation, probably the quickest way would be to activate the office clipboard (arrow in bottom right corner on Home tab). This allows up to 24 separate ranges to be collected and pasted below one another.
Assuming data is in one workbook and starts in row 2 on each sheet, as in the example below, you can:
Select all the tabs
Select all the rows on the first sheet
Press Ctrl+C, Ctrl+Page Down, repeatedly to copy all the data
Select a new sheet and click Paste All
Note that only the used range is copied so you can copy whole sheet ranges instead of needing to locate the last cell on each sheet.
If you really mean Tables you can reference them using the ListObjects collection.
Try this (code located in destination workbook)
This code copies all source tables as separate tables with a blank row between. If you want to merge the data into a single table you will need to copy lo.DataBodyRange rather than lo.Range and handle the header row and conversion to a table separetly.
Sub CopyTables()
Dim wbFrom As Workbook
Dim shFrom As Worksheet
Dim shTo As Worksheet
Dim lo As ListObject
Dim clTo As Range
' Setup Destination for copied tables
Set shTo = ThisWorkbook.Worksheets("DestinationSheet") ' <-- change name to your destination sheet name
' remove any existing data
shTo.UsedRange.EntireRow.Delete
Set clTo = shTo.Cells(1, 1)
' Loop through open workbooks
For Each wbFrom In Application.Workbooks
' except destination wb
If wbFrom.Name <> ThisWorkbook.Name Then
' loop through all sheets
For Each shFrom In wbFrom.Worksheets
' loop through all tables on sheet
For Each lo In shFrom.ListObjects
lo.Range.Copy clTo
' offset to next paste location, leave one empty row between tables
Set clTo = clTo.Offset(lo.ListRows.Count + 2, 0)
Next
Next
End If
Next
End Sub
Alternative inner For loop to paste to a single range
For Each lo In shFrom.ListObjects
lo.DataBodyRange.Copy clTo
Set clTo = clTo.Offset(lo.ListRows.Count, 0)
Next