Copying columns from multiple sheets into one sheet in the same workbook using VBA - excel

My goal is to automatically copy a range of columns (A:C) from 40+ Excel Sheet into one Sheet located in the same workbook.
The structure of all sheets is identical. Columns consist of numeric values. I want the columns to be added to the right at each iteration (so the target sheet will be enriched horizontally with the data)
My attempt (see the code below) is not automated as if I have to specify Sheet Names and Target Cell where it is possible to copy the columns
Sub macro()
Sheets("Top").Select
Columns("A:C").Select
Selection.Copy
Sheets("Low").Select
Range("D1").Select
ActiveSheet.Paste
End Sub
Any help is appreciated! Thank you

Please, try the next code. It will iterate between all existing sheets and copy all rows of columns "D:K" from all sheets in one named "Destination" (starting from "A1"). If you need it to start from "D1" it would be easy to adapt the code:
Sub copyAllSheetsInOne()
Dim ws As Worksheet, sh As Worksheet, lastRow As Long, lastEmptyCol As Long, i As Long
Set sh = Worksheets("Destination") 'a sheet named "Destination" must exist in the workbook to be processed
sh.cells.ClearContents 'clear its content (for cases when code run before)
'some optimization to make the code faster:
Application.DisplayAlerts = False: Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'iterate between all existing sheets:
For Each ws In ActiveWorkbook.Worksheets
If ws.name <> "Destination" Then
lastEmptyCol = sh.cells(1, sh.Columns.count).End(xlToLeft).Column + 1
lastRow = ws.Range("D" & ws.rows.count).End(xlUp).row
If lastEmptyCol = 2 Then lastEmptyCol = 1 'for the first sheet
ws.Range("D1", ws.Range("K" & lastRow)).Copy sh.cells(1, lastEmptyCol)
End If
Next ws
Application.DisplayAlerts = True: Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
End Sub

Related

Excel VBA remove blank rows from specific range

I have an excel macro that creates a new sheet called "Compiled", copies over the contents of every sheet in the workbook from A2 onward (so the header isn't copied). This works great, except I often get tons of completely blank rows all over the place.
My objective is to have a macro to find the last row in the Compiled sheet, and delete any fully blank rows.
Here's my current script:
Sub CombineData()
' Delete unneeded sheets
Application.DisplayAlerts = False
Sheets("Instructions").Select
ActiveWindow.SelectedSheets.Delete
Sheets("TM Contacts").Select
ActiveWindow.SelectedSheets.Delete
' Add new sheet called Compiled
Sheets.Add After:=ActiveSheet
Sheets("Sheet1").Select
Sheets("Sheet1").Name = "Compiled"
Sheets("Lastname, First Name").Select
Range("Table_1[#Headers]").Select
Selection.Copy
Sheets("Compiled").Select
Range("A1").Select
ActiveSheet.Paste
Range("A2").Select
' Copy all sheet contents onto one
Dim lastRowSource As Long, lastRowDest As Long, i As Long
For i = 1 To Sheets.Count
If Not Sheets(i).Name = "Compiled" Then
lastRowSource = Sheets(i).Cells(Sheets(i).Rows.Count, "A").End(xlUp).Row
lastRowDest = Sheets("Compiled").Cells(Sheets("Compiled").Rows.Count, "A").End(xlUp).Row
With Sheets(i)
.Range(.Cells(2, "A"), .Cells(lastRowSource, "AB")).Copy Sheets("Compiled").Range(Sheets("Compiled").Cells(lastRowDest + 1, "A"), Sheets("Compiled").Cells(lastRowDest + 1 + lastRowSource, "AB"))
End With
End If
Next i
' delete blank rows
End Sub
I tried this code from an older question to delete the blank rows, which gave me an "out of range" error:
Dim myWs As Worksheet
Set myWs = ThisWorkbook.Worksheets("Compiled") 'set your sheet name
Dim lastRow As Long
lastRow = myWs.Range("A" & myWs.Rows.Count).End(xlUp).Row 'find last used row
With myWs.Range(myWs.Cells(2, "A"), myWs.Cells(lastRow, "A"))
.Value = .Value 'convert formulas to values whithin the range from with block (column A only)
.SpecialCells(xlCellTypeBlanks).EntireRow.Delete 'delete rows where column A is blank
End With
The error with this code appears to be at "Dim myWs As Worksheet". This is where I get the "out of range" error. I'm trying to point to the compiled worksheet.
If I am not wrong, you want to combine data from different worksheets into one master sheet. But your code is producing lots of empty rows in the "Compiled" sheet. That's why you want to "remove blank rows from specific range".
What I understand from your code:
you want to:
delete sheets named "Instructions" and "TM Contacts"
add a new sheet "Compiled"
copy header from the table "Table_1" in sheet "<Last Name, First Name>" and paste it as header for sheet "Compiled"
copy data "A2" to "AB & last row" from all sheets to sheet "Compiled", starting from "A2"
Please check if this works:
Here I have tried to avoid .select
Option Explicit
Sub CombineData()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim lastRowDest As Long
Dim lastRowSource As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'delete sheets named "Instructions" and "TM Contacts". also delete "Compiled", if it exists.
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("Instructions").Delete
ActiveWorkbook.Worksheets("TM Contacts").Delete
ActiveWorkbook.Worksheets("Compiled").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'add a new sheet "Compiled"
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "Compiled"
'copy header from the table "Table_1" in sheet "Last Name, First name" and paste it as header for sheet "Compiled"
'from your code I assume you have a data formatted as a table, "Table_1"
ActiveWorkbook.Worksheets("Last Name, First Name").ListObjects("Table_1").HeaderRowRange.Copy
DestSh.Range("A1").PasteSpecial xlPasteValues
'copy data "A2" to "AB & last row" from all sheets to sheet "Compiled",starting from "A2"
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name Then
With DestSh
lastRowDest = .Range("A" & .Rows.Count).End(xlUp).Row
End With
With sh
lastRowSource = .Range("A" & .Rows.Count).End(xlUp).Row
End With
'if you want to change copy range, change here
Set CopyRng = sh.Range("A2:AB" & lastRowSource)
With CopyRng
DestSh.Cells(lastRowDest + 1, "A").Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub

How to copy the data from one Workbook and paste the value only in another Workbook and allow macro to run only one time?

When I accidentally run VBA code to copy/paste data from one Workbook to the target Workbook multiple times, it will create multiple rows with same data in the target Worksheet.
I want the VBA code to recognize the previous line is the same, to prevent data duplication.
Further, my VBA code will copy the formulas to my destination Excel file.
I want to copy the value only instead of the formula. I'm not sure how to use PasteSpecial in my VBA code.
Sub Copy_Paste_Below_Last_Cell()
Dim wsDest As Worksheet
Dim lDestLastRow As Long
Set wsDest = Workbooks("Destination.xlsx").Worksheets("DataBase")
lDestLastRow = wsDest.Cells(wsDest.Rows.Count, "C").End(xlUp).Offset(1).Row
' How to use PasteSpecial Paste:=xlPasteValues here?
Sheet4.Range("B6:F6").Copy wsDest.Range("C" & lDestLastRow)
End Sub
Edit:
Sub Copy_Paste_Below_Last_Cell1()
Dim wsDest As Worksheet
Dim lDestLastRow As Long
Set wsDest = Workbooks("Destination.xlsx").Worksheets("DataBase")
lDestLastRow = wsDest.Cells(wsDest.Rows.Count, "C").End(xlUp).Offset(1).Row
If sheetWithVariable.CellWithVariable.Value = False Then
Sheet4.Range("B6:F6").Copy
wsDest.Range("C" & lDestLastRow).PasteSpecial Paste:=xlPasteValues
sheetWithVariable.CellWithVariable.Value = True
End If
End Sub
Task: copy from main workbook and paste in target workbook
without duplicating data.
This should do it. Adjust the config section of the code before trying it.
Sub TransferData()
Dim main_wb As Workbook, target_wb As Workbook, main_sheet As String
Dim r As String, target_sheet As String, first_col As Byte, col_n As Byte
Dim next_row As Long, duplicates As Byte, pasted As Byte, last_col As Long
'CONFIG HERE
'------------------------
Set main_wb = ThisWorkbook
main_sheet = "Sheet1"
r = "B6:F6" 'range to copy in the main Workbook
'target workbook path
Set target_wb = _
Workbooks.Open("/Users/user/Desktop/target workbook.xlsm")
target_sheet = "Sheet1"
first_col = 3 'in what column does the data starts in target sheet?
'-------------------------
'turn screen updating off
Application.ScreenUpdating = False
'copy from main
main_wb.Sheets(main_sheet).Range(r).Copy
With target_wb.Sheets(target_sheet)
'target info
next_row = _
.Cells(Rows.Count, first_col).End(xlUp).Row + 1
'paste in target
.Cells(next_row, first_col).PasteSpecial xlPasteValues
last_col = _
.Cells(next_row, Columns.Count).End(xlToLeft).Column
End With
pasted = last_col - (first_col - 1)
For col_n = first_col To last_col
With target_wb.Sheets(target_sheet)
If .Cells(next_row, col_n) = .Cells(next_row - 1, col_n) Then
duplicates = duplicates + 1
End If
End With
Next col_n
If duplicates = pasted Then 'if the nÂș of cells pasted equals duplicates
For col_n = first_col To last_col 'erase pasted range
target_wb.Sheets(target_sheet).Cells(next_row, col_n).Clear
Next col_n
End If
'turn screen updating back on
Application.ScreenUpdating = True
End Sub
Go "Developer Tab" then press "Record macro" or at Excel bottom left side there is small button "Record macro". Then you press it it will create automatically code for every your click, press and etc., so go copy and paste only values, stop recording macro. And you will have Module1 with code how to "paste values".
For PasteSpecial function, copying and pasting are defined as different operations (so as to say, no Destination option should be used for Copy):
Sheet4.Range("B6:F6").Copy
wsDest.Range("C" & lDestLastRow).PasteSpecial _
Paste:=xlPasteValues
If you want your to code to run once, add a variable somewhere in your workbook that will specify that the code already run. Something like that:
Sub Copy_Paste_Below_Last_Cell()
If sheetWithVariable.CellWithVariable.Value = False Then
' Put your code here
sheetWithVariable.CellWithVariable.Value = True
End If
End Sub

How to match columns and count the matches using vba

I am working on one scenario where I have two sheets. Sheet1 is the master sheet and sheet2 which I am creating.
Column1 of Sheet1 is Object which has duplicate objects as well. So, what I have done is I have created a macro which will produce the unique Objects and will paste it in sheet2.
Now, from Sheet2, each of the objects should be matched with Sheet1 column1 and based on the matching results, it should also count the corresponding entries from other columns in sheet1 to sheet2.
Below are the snapshots of my two sheets
Sheet1
Sheet2
here is my macro code which will first copy and paste the unique objects from sheet1 to sheet2 Column1.
Sub UniqueObj()
Dim Sh1 As Worksheet
Dim Rng As Range
Dim Sh2 As Worksheet
Set Sh1 = Worksheets("Sheet1")
Set Rng = Sh1.Range("A1:A" & Sh1.Range("A65536").End(xlUp).Row)
Set Sh2 = Worksheets("Sheet1")
Rng.Cells(1, 1).Copy Sh2.Cells(1, 1)
Rng.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Sh2.Range("A1"), Unique:=True
End Sub
But, I am unable to move forward from there. I am pretty new and any help would be very greatful.
Thanks
If I'm understanding what you want correctly, you're just counting matching columns from Sheet1 where the value in the corresponding column isn't blank? If so this should do the trick.
Option Explicit
Sub GetStuffFromSheet1()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim lastRow1 As Long, lastRow2 As Long
Dim x As Long
'turn on error handling
On Error GoTo error_handler
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
'determine last row with data in sheet 1
lastRow1 = ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row
'determine last row with data in sheet 2
lastRow2 = ws2.Cells(ws2.Rows.Count, 1).End(xlUp).Row
'define columns in sheet 1
Const objCol1 As Long = 1
Const rProdCol1 As Long = 3
Const keysCol1 As Long = 4
Const addKeysCol1 As Long = 5
'define columns in sheet 2
Const objCol2 As Long = 1
Const rProdCol2 As Long = 2
Const keysCol2 As Long = 3
Const addKeysCol2 As Long = 4
'turn off screen updating + calculation for speed
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'loop through all rows of sheet 2
For x = 2 To lastRow2
'formula counts # of cells with matching obj where value isn't blank
ws2.Cells(x, rProdCol2) = WorksheetFunction.CountIfs(ws1.Columns(objCol1), ws2.Cells(x, objCol2), ws1.Columns(rProdCol1), "<>" & "")
ws2.Cells(x, keysCol2) = WorksheetFunction.CountIfs(ws1.Columns(objCol1), ws2.Cells(x, objCol2), ws1.Columns(keysCol1), "<>" & "")
ws2.Cells(x, addKeysCol2) = WorksheetFunction.CountIfs(ws1.Columns(objCol1), ws2.Cells(x, objCol2), ws1.Columns(addKeysCol1), "<>" & "")
Next x
'turn screen updating + calculation back on
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
error_handler:
'display error message
MsgBox "Error # " & Err.Number & " - " & Err.Description, vbCritical, "Error"
'turn screen updating + calculation back on
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
End Sub
In case a non VBA solution works for you, you can resume your data with a Pivot Table, take field Object into rows section and rest of fields into values section (choose Count)
This returns the exact output you are looking for. Easy to update and easy to create.
In case you want a VBA solution, because your design is tabular and you are counting values, you can use CONSOLIDATE:
Consolidate data in multiple worksheets
'change K1 with cell where to paste data.
Range("K1").Consolidate Range("A1").CurrentRegion.Address(True, True, xlR1C1, True), xlCount, True, True, False
'we delete column relation type and column value. This columns depends on where you paste data, in this case, K1
Range("L:L,P:P").Delete Shift:=xlToLeft
After executing code i get this:
Hope this helps

Use VBA in Excel to print rows on different worksheet

I have three separate worksheets in a workbook that contain thousands of rows of information and new information is added frequently. I would like to be able to create separate reports using macros and VBA to print onto another worksheet when I need the report.
For example, report one would include all completed jobs in 2014. If Completed? equals YES and Year equals 2014, print entire row on blank worksheet. However, I need to use VBA so it goes through three worksheets and prints them all together in a separate worksheet. How would I do this?
Clarification: Basically if these two cells equal this and this, print the row on a different sheet.
Practice with this.
Insert a button or some other type of object on the sheet with the data.
Once clicked the code will delete all the sheets except the active sheet.
It then loops through column A and creates the sheets.
Then it loops through the sheets and filters your data sheet, copies and pastes the data into the sheet and moves on to the next sheet.
Sub getSht()
Dim c As Range, sh As Worksheet
Dim Rws As Long, Rng As Range, fRng As Range
Dim ws As Worksheet
Set ws = ActiveSheet
Application.DisplayAlerts = 0
Application.ScreenUpdating = 0
For Each sh In Sheets
If sh.Name <> ws.Name Then sh.Delete
Next sh
With ws
Rws = .Cells(Rows.Count, "A").End(xlUp).Row
Set Rng = .Range(.Cells(2, 1), .Cells(Rws, 1))
For Each c In Rng.Cells
If WorksheetExists(c.Value) Then
Else: Sheets.Add.Name = c
End If
Next c
End With
For Each sh In Sheets
If sh.Name <> ws.Name Then
ws.Range("A:A").AutoFilter Field:=1, Criteria1:=sh.Name
Set fRng = ws.Range(ws.Cells(1, "A"), ws.Cells(Rws, "D"))
fRng.Copy Destination:=sh.Range("A1")
End If
ws.AutoFilterMode = 0
Next sh
ws.Activate
End Sub
Function WorksheetExists(WSName As String) As Boolean
On Error Resume Next
WorksheetExists = Worksheets(WSName).Name = WSName
On Error GoTo 0
End Function

Copy and paste between sheets in a workbook with VBA code

Trying to write a macro in VBA for Excel to look at the value in a certain column from each row of data in a list and if that value is "yes" then it copies and pastes the entire row onto a different sheet in the same workbook. Let's name the two sheets "Data" and "Final". I want to have the sheets referenced so it does not matter which sheet I have open when it runs the code. I was going to use a Do loop to cycle through the rows on the one data sheet until it finds there are no more entries, and if statements to check the values.
I am confused about how to switch from one sheet to the next.
How do I specifically reference cells in different sheets?
Here is the pseudocode I had in mind:
Do while DataCells(x,1).Value <> " "
for each DataCells(x,1).Value="NO"
if DataCells(x,2).Value > DataCells(x,3).Value or _
DataCells(x,4).Value < DataCells(x,5).Value
'Copy and paste/insert row x from Data to Final sheet adding a new
'row for each qualifying row
else
x=x+1
end
else if DataCells(x,1).Value="YES"
Loop
'copy and paste entire row to a third sheet
'continue this cycle until all rows in the data sheet are examined
Sub FilterAndCopy()
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Dim sh As Worksheet, sh2 As Worksheet
Dim lastrow1 As Long
Dim lastcolumn1 As Long
Set sh = ThisWorkbook.Sheets("Data")
Set sh2 = ThisWorkbook.Sheets("Final")
lastrow1 = sh.Cells(Rows.Count, "A").End(xlUp).Row ' Replace "A" With column that has the most Rows
lastcolumn1 = sh.Cells(1, Columns.Count).End(xlToLeft).Column
With sh.Range(.Cells(1, 1), .Cells(lastrow1, lastcolumn1))
'Replace the number in the field section with your Columns number
.AutoFilter , _
Field:=1, _
Criteria1:="yes"
.Copy sh2.Range("A1")
End With
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
End Sub

Resources