Excel Macro/how to write macro to copy/paste rows from Workbook with 200 sheets to Table - excel

I have an Excel Workbook (named Peak) with 100 sheets (each Sheet starts with Sheet1 followed by a unique name, Sheet1AA), I want to copy one column from each Peak Sheet and paste into a new Workbook (named Table) using transpose, so the Table will have 100 rows of data from the Peak Workbook Sheets. Below is an example where two Sheets are copied and then pasted, with the second Sheet (Sheet1BB) pasted below the first Sheet (Sheet1AA) in the Table. I know I can record a macro as I do the copy/paste-transpose, but hoping there is a way to write a macro to do the copy/paste consecutively/in order from the Peak Workbook (Sheet1AA-Sheet1ZZ) to the Workbook Table to give 100 rows of data, with data from Sheet1AA the first row and Sheet1ZZ the last row in the Table.
Thank you
Windows("Peak.xlsm").Activate
Sheets("Sheet1AA").Select
Range("O6:O150").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Table.xlsm").Activate
Range("E4:AB4").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Windows("Peak.xlsm").Activate
Sheets("Sheet1BB").Select
Range("O6:O150").Select
Application.CutCopyMode = False
Selection.Copy
Windows("Table.xlsm").Activate
Range("E5:AB5").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True

Untested:
Dim r As Long, sht As Worksheet
r = 4
For Each sht In Workbooks("Peak.xlsm").Worksheets
sht.Range("O6:O150").Copy
Workbooks("Table.xlsm").Sheets(1).Cells(r, "E").PasteSpecial Transpose:=True
r = r + 1
Next sht

Since OP's need to maintain pasted data ordered by parent sheet name, here follows two possible codes:
temporary helper column
this approach
inserts a (temporary) column right before column "E" where to store sheet names, while corresponding data are written from the next column to rigthwards.
sorts the pasted range on sheet names in (temporary) column "E"
deletes temporary column
Option Explicit
Sub Main()
Dim iSht As Long
Dim sht As Worksheet
With Workbooks("Table.xlsm").Worksheets(1)
.Columns("E").Insert '<--| insert temporary helper column
For Each sht In Workbooks("Peak.xlsm").Worksheets '<--| loop through sheets
sht.Range("O6:O150").Copy
.Cells(4 + iSht, "E") = sht.Name '<--| write sheet name in temporary helper column
.Cells(4 + iSht, "F").PasteSpecial Transpose:=True '<--| write data from the next colum rightwards
iSht = iSht + 1
Next sht
With .Cells(4, "E").Resize(iSht, 146) '<--| consider temporary helper column cells containing sheet names
.Sort key1:=.Cells(1, 1), order1:=xlAscending '<--| sort them
.EntireColumn.Delete '<--| remove temporary helper column
End With
End With
End Sub
array with ordered sheet names
this requires writing them down in a temporary sheet (in ThisWorkbook), sorting them and reading them back (see Function GetSortedWsNames())
Sub Main2()
Dim i As Long: i = 4
Dim wb As Workbook
Dim el As Variant
Set wb = Workbooks("Peak.xlsm")
With Workbooks("Table.xlsm").Worksheets(1)
For Each el In GetSortedWsNames(wb)
wb.Worksheets(el).Range("O6:O150").Copy
.Cells(i, "E").PasteSpecial Transpose:=True
i = i + 1
Next el
End With
End Sub
Function GetSortedWsNames(wb As Workbook) As Variant
Dim ws As Worksheet
Dim iSht As Long
Set ws = ThisWorkbook.Worksheets.Add
With wb
For iSht = 1 To .Worksheets.Count
ws.Cells(iSht, 1) = .Worksheets(iSht).Name
Next iSht
End With
With ws.Cells(1, 1).Resize(iSht - 1)
.Sort key1:=ws.Cells(1, 1), order1:=xlAscending
GetSortedWsNames = Application.Transpose(.Cells)
End With
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End Function

Related

Copy and paste values only after filtering data in vba [duplicate]

I have two sheets. One has the complete data and the other is based on the filter applied on the first sheet.
Name of the data sheet : Data
Name of the filtered Sheet : Hoky
I am just taking a small portion of data for simplicity. MY objective is to copy the data from Data Sheet, based on the filter. I have a macro which somehow works but its hard-coded and is a recorded macro.
My problems are:
The number of rows is different everytime. (manual effort)
Columns are not in order.
Sub TESTTHIS()
'
' TESTTHIS Macro
'
'FILTER
Range("F2").Select
Selection.AutoFilter
ActiveSheet.Range("$B$2:$F$12").AutoFilter Field:=5, Criteria1:="hockey"
'Data Selection and Copy
Range("C3").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Hockey").Select
Range("E3").Select
ActiveSheet.Paste
Sheets("Data").Select
Range("D3").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Hockey").Select
Range("D3").Select
ActiveSheet.Paste
Sheets("Data").Select
Range("E3").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Hockey").Select
Range("C3").Select
ActiveSheet.Paste
End Sub
Best way of doing it
Below code is to copy the visible data in DBExtract sheet, and paste it into duplicateRecords sheet, with only filtered values. Range selected by me is the maximum range that can be occupied by my data. You can change it as per your need.
Sub selectVisibleRange()
Dim DbExtract, DuplicateRecords As Worksheet
Set DbExtract = ThisWorkbook.Sheets("Export Worksheet")
Set DuplicateRecords = ThisWorkbook.Sheets("DuplicateRecords")
DbExtract.Range("A1:BF9999").SpecialCells(xlCellTypeVisible).Copy
DuplicateRecords.Cells(1, 1).PasteSpecial
End Sub
I suggest you do it a different way.
In the following code I set as a Range the column with the sports name F and loop through each cell of it, check if it is "hockey" and if yes I insert the values in the other sheet one by one, by using Offset.
I do not think it is very complicated and even if you are just learning VBA, you should probably be able to understand every step. Please let me know if you need some clarification
Sub TestThat()
'Declare the variables
Dim DataSh As Worksheet
Dim HokySh As Worksheet
Dim SportsRange As Range
Dim rCell As Range
Dim i As Long
'Set the variables
Set DataSh = ThisWorkbook.Sheets("Data")
Set HokySh = ThisWorkbook.Sheets("Hoky")
Set SportsRange = DataSh.Range(DataSh.Cells(3, 6), DataSh.Cells(Rows.Count, 6).End(xlUp))
'I went from the cell row3/column6 (or F3) and go down until the last non empty cell
i = 2
For Each rCell In SportsRange 'loop through each cell in the range
If rCell = "hockey" Then 'check if the cell is equal to "hockey"
i = i + 1 'Row number (+1 everytime I found another "hockey")
HokySh.Cells(i, 2) = i - 2 'S No.
HokySh.Cells(i, 3) = rCell.Offset(0, -1) 'School
HokySh.Cells(i, 4) = rCell.Offset(0, -2) 'Background
HokySh.Cells(i, 5) = rCell.Offset(0, -3) 'Age
End If
Next rCell
End Sub
When i need to copy data from filtered table i use range.SpecialCells(xlCellTypeVisible).copy. Where the range is range of all data (without a filter).
Example:
Sub copy()
'source worksheet
dim ws as Worksheet
set ws = Application.Worksheets("Data")' set you source worksheet here
dim data_end_row_number as Integer
data_end_row_number = ws.Range("B3").End(XlDown).Row.Number
'enable filter
ws.Range("B2:F2").AutoFilter Field:=2, Criteria1:="hockey", VisibleDropDown:=True
ws.Range("B3:F" & data_end_row_number).SpecialCells(xlCellTypeVisible).Copy
Application.Worksheets("Hoky").Range("B3").Paste
'You have to add headers to Hoky worksheet
end sub
it needs to be .Row.count not Row.Number?
That's what I used and it works fine
Sub TransfersToCleared()
Dim ws As Worksheet
Dim LastRow As Long
Set ws = Application.Worksheets("Export (2)") 'Data Source
LastRow = Range("A" & Rows.Count).End(xlUp).Row
ws.Range("A2:AB" & LastRow).SpecialCells(xlCellTypeVisible).Copy

VBA not pasting into empty row in table

My goal is to copy and paste rows that meet a certain criteria into a table in another workbook.
My VBA works perfectly except for it pastes in the empty cell below the table. Not in the empty cells below the headers within the table.
PS. I know using select is generally frowned upon, but I needed to use fairly basic syntax so that if the next person needs to modify this and is unfamiliar with VBA they can.
Sub Export()
Sheets("Export Format").Select
Cells(13, "D").Calculate
With Range("A1", Cells(Rows.Count, "L").End(xlUp)) 'reference its column A:G cells from row 1 (header) down to last not empty one in column "A"
.AutoFilter Field:=6, Criteria1:="<>0" ' filter referenced cells on 6th column with everything but "0" content
If Application.WorksheetFunction.Subtotal(103, .Columns(1)) > 1 Then
.Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Copy ' copy filtered cells skipping headers
With Workbooks.Open(Filename:="Z:\Tracking\Database.xlsx").Sheets("Sheet1") 'open wanted workbook and reference its wanted sheet
.Cells(.Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone _
, SkipBlanks:=False, Transpose:=False 'paste filtered cells in referenced sheet from ist column A first empty cell after last not empty one
.Parent.Close True 'Save and closes referenced workbook
End With
Application.CutCopyMode = False
End If
End With
On Error Resume Next
Sheets("Export Format").ShowAllData 'Clears Filters
On Error GoTo 0
Sheets("Export Format").Select 'Brings back to Main request sheet
End Sub
Try using a property of the table such as InsertRowRange
Sub Export()
Const DBFILE = "Z:\Tracking\Database.xlsx"
Dim wb As Workbook, wbDB As Workbook
Dim ws As Worksheet, tbl As ListObject
Dim rngFilter As Range, x, rng As Range
Set wb = ThisWorkbook
Set ws = wb.Sheets("Export Format")
x = Application.WorksheetFunction.Subtotal(103, ws.Columns(1))
If x <= 1 Then
ws.Select
Exit Sub
End If
' set filter range
With ws
.Range("D13").Calculate
' column A:L cells from row 1 (header)
' down to last not empty one in column "A"
Set rngFilter = .Range("A1", .Cells(Rows.Count, "L").End(xlUp))
End With
' open wanted workbook and reference its wanted sheet
Set wbDB = Workbooks.Open(DBFILE)
With wbDB.Sheets("Sheet1")
Set tbl = .ListObjects("Table1")
If tbl.InsertRowRange Is Nothing Then
Set rng = tbl.ListRows.Add.Range
Else
Set rng = tbl.InsertRowRange
End If
End With
' filter on 6th column with everything but "0" content
With rngFilter
.AutoFilter Field:=6, Criteria1:="<>0"
' copy filtered cells skipping headers
.Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Copy
'paste filtered cells in referenced sheet
'from ist column A first empty cell after last not empty one
rng.PasteSpecial Paste:=xlPasteValues, _
Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
End With
wbDB.Close True 'Save and closes referenced workbook
ws.AutoFilterMode = False
ws.Select 'Brings back to Main request sheet
MsgBox "Ended"
End Sub

VBA Copy specific range in multiple worksheets

This is my first attempt to write vba code. I have a excel workbook with 19 worksheets (FVal.xls), each of them composed of 130 rows and 15 columns with data.
If I find a specific value ("Fla") in the fourth column, I want to copy data in this row from column 10 to column 15 and paste it in row 3, columns 10 - 15 in each sheet.
Code is running but it leaves blank cells in the position of copied cells.
Here is my code:
Option Explicit
Sub FinCop()
Dim wb1 As Workbook
Dim ws As Worksheet
Dim i As integer
Set wb1 = Workbooks.Open("C:\FVal.xls")
For Each ws In wb1.Worksheets
i = 1
Do While ws.Cells(i, 4).Text <> "Fla"
i = i + 1
Loop
ws.Range(ws.Cells(i, 10), ws.Cells(i, 15)).Copy
ws.Range(ws.Cells(3, 7), ws.Cells(3, 15)).PasteSpecial Paste:=xlPasteValues, _
Operation:=xlNone, _
SkipBlanks:=True, _
Transpose:=False
Next ws
End Sub

Copy specified columns in particular order

I have 80 or so columns of data. I need just 21 columns.
In my output, I would like the 21 columns to be in a particular order. For example, I want the value from the cell AX2 from my source file to go to A2, BW2 to go to B2, etc.
The source data may differ from month to month and could have as little as 1 row of data or hundreds so I would like this to loop until no data is left.
I got a run time error 424 object required. I have only outlined the rules for two columns but will work on the rest when I get the proper set up.
Sub Macro1()
'
' Macro1 Macro
'
'
Sheet4.Select
Application.ScreenUpdating = False
row_count = 2
Do While Sheet2.Range("A" & row_count) <> ""
Range("AX2:AX1000").Select
Selection.Copy
ActiveWindow.ActivateNext
Range("A").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ActiveWindow.ActivateNext
Range("BW2:BW1000").Select
Application.CutCopyMode = False
Selection.Copy
ActiveWindow.ActivateNext
Range("B").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
x = x + 1
ActiveWindow.ActivateNext
ActiveSheet.Next.Select
ActiveSheet.Next.Select
Loop
End Sub
I hope I didn't go too far. Try this subscript, it asks you to select a workbook, it will open the workbook, copy column B2 to last used Row on Column B, and paste it on the first workbook. Make sure to rename the CopyFromSheet and CopyToSheet on the code. Please read each line and try to understand what it is doing. Let me know if any questions.
Sub CopyPaste()
Dim openFile As FileDialog, wb As Workbook, sourceWb As Workbook
Dim CopyTo As String, CopyFrom As String
Dim lastRow As Long
Application.ScreenUpdating = False
Set wb = ThisWorkbook
Set openFile = Application.FileDialog(msoFileDialogFilePicker)
openFile.Title = "Select Source File"
openFile.Filters.Clear
openFile.Filters.Add "Excel Files Only", "*.xl*"
openFile.Filters.Add "All Files", "*.*"
openFile.Show
If openFile.SelectedItems.Count <> 0 Then
Set sourceWb = Workbooks.Open(openFile.SelectedItems(1), False, True, , , , True)
CopyFrom = "CopyFromSheetName"
CopyTo = "CopyToSheetName"
lastRow = sourceWb.Sheets(CopyFrom).Cells(Rows.Count, "B").End(Excel.xlUp).Row
sourceWb.Sheets(CopyFrom).Range("B2:B" & lastRow).Copy 'You can copy this Row and the Next and add as many as you want to copy the Columns Needed
wb.Sheets(CopyTo).Range("B1").PasteSpecial xlValues
Application.CutCopyMode = xlCopy
Else
MsgBox "A file was not selected"
End If
Application.ScreenUpdating = True
End Sub
I suggest you separate the copy logic from the setup of which columns to copy. That way it will be much easier to manage the setup.
In this code I have hard coded to Columns Pairs. Alternatively, you could put that data on a sheet and read it in.
Sub Demo()
'declare all your variables
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rSource As Range
Dim rDest As Range
Dim CP() As Variant 'Column Pairs array
Dim idx As Long
'Set up an array of Source and Destination columns
ReDim CP(1 To 21, 1 To 2) 'Adjust size to suit number of column pairs
CP(1, 1) = "AX": CP(1, 2) = "A"
CP(2, 1) = "BW": CP(2, 2) = "B"
'and so on
' Source and Destination don't have to be in the same Workbook
' This code assumes the Source (and Destination) worksbooks are already open
' You can add code to open them if required
' If the data is in the same book as the code, use ThisWorkbook
' If the data is in a different book from the code,
' specify the book like Application.Workbooks("BookName.xlsx")
' or use ActiveWorkbook
'Update the names to your sheet names
Set wsSource = ThisWorkbook.Worksheets("SourceSheetName")
Set wsDest = ThisWorkbook.Worksheets("DestSheetName")
' Notice that form here on the code is independent of the Sheet and Column names
'Loop the column pairs array
For idx = 1 To UBound(CP, 1)
'if the entry is not blank
If CP(idx, 1) <> vbNullString Then
'Get reference to source column cell on row 2
Set rSource = wsSource.Columns(CP(idx, 1)).Cells(2, 1)
'If that cell is not empty
If Not IsEmpty(rSource) Then
'If the next cell is not empty
If Not IsEmpty(rSource.Offset(1, 0)) Then
'extend range down to first blank cell
Set rSource = wsSource.Range(rSource, rSource.End(xlDown))
End If
'Get a reference to the destination range, from row 2, same size as source
Set rDest = wsDest.Columns(CP(idx, 2)).Cells(2, 1).Resize(rSource.Rows.Count)
'Copy the values
rDest.Value = rSource.Value
End If
End If
Next
End Sub

Copy paste Excel data between two sheets using a macro

I have 2 sheets, sheet1 and sheet2. From sheet1 data, I have to copy data and paste it into sheet2, then again from sheet1 I have to copy another different set of data and paste it into sheet2 last line, where I pasted data 1st time.
Sub Copy_chains_to_other_sheet()
ActiveSheet.Range("$A$1").AutoFilter Field:=8, Criteria1:="<>1", _
Operator:=xlAnd
ActiveSheet.Range("$A$1:$I$681").AutoFilter Field:=1, Criteria1:="=*antaris*" _
, Operator:=xlAnd
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
ActiveSheet.Next.Select
ActiveSheet.Paste
ActiveSheet.Range("$A$1").AutoFilter Field:=1
End Sub
This is the macro I wrote, but I don't know how to proceed. Because one time I have 5 rows of data that time I need to copy data from sheet1 and paste in sheet2 and with next set of data I need to paste it in 6th row, but another time I have 8 row of data that time I need to paste the next set of data from 9the row onwards, so how to deal with this.
If I understand correctly you want to copy the results of successive autofiltered data from Sheet1 to a continuous "list" in Sheet2. If this is so then perhaps try the following to get you going. You will need to alter the variables/names to suit your requirement, I have made some assumptions.
Option Explicit
Sub copyAFs()
Dim wsONE As Worksheet, wsTWO As Worksheet
Dim ONEstrow As Long, ONEendrow As Long, ONEstcol As Long, ONEendcol As Long
Dim TWOstrow As Long, TWOnextrow As Long, TWOstcol As Long
Dim crit1col As Long, crit2col As Long
Dim crit1 As String, crit2 As String
Set wsONE = Sheets("Sheet1")
Set wsTWO = Sheets("Sheet2")
ONEstrow = 1
ONEstcol = 1
ONEendcol = 10
TWOstrow = 1
TWOstcol = 1
crit1 = "antaris"
crit2 = "1"
crit1col = 1
crit2col = 8
With wsTWO
TWOnextrow = .Cells(.Rows.Count, TWOstcol).End(xlUp).Row + 1
End With
'clear autofilter
wsONE.AutoFilterMode = False
'apply autofilter
With wsONE
ONEendrow = Cells(Rows.Count, ONEstcol).End(xlUp).Row + 1
With .Range(.Cells(ONEstrow, ONEstcol), .Cells(ONEendrow, ONEendcol))
'set autofilter
.AutoFilter Field:=crit1col, Criteria1:=crit1
.AutoFilter Field:=crit2col, Criteria1:=crit2
End With
End With
'copy filtered range without header
With wsTWO
wsONE.AutoFilter.Range.Offset(1, 0).Copy Destination:=.Range(.Cells(TWOnextrow, TWOstcol), .Cells(TWOnextrow, TWOstcol))
End With
'clear autofilter
wsONE.AutoFilterMode = False
End Sub

Resources