Appending into a master sheet by row after row by taking first row of each sheets from multiple sheets then move on two second rows appending [closed] - excel

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Can someone suggest me on how to appending into a master sheet by row after row by taking the first row of each sheet from multiple sheets then move on to second rows appending, suppose in the first iteration, we have each first row of each sheet, that should copy and paste as row1, row2, row3 into the master sheet, then in the next iteration the second row of each sheet comes and add/append at the end of the master sheet means it would be row4, row5...etc into the master sheet
I even tried below piece of code which sent from the user https://stackoverflow.com/users/7444507/michael
but I can't able to get the right output
Public Sub MergeTabs()
'Merges selected tabs (or all visible tabs if only 1 selected) in current workbook into a new tab
Dim i As Integer, wb As Workbook, w As Window, wsTo As Worksheet, wsFrom As Collection 'Worksheet collection
Dim strScope As String, strNewTab As String
Dim raTarget As Range
Set wb = ActiveWorkbook
Set w = ActiveWindow
Set wsFrom = New Collection
If w.SelectedSheets.Count = 1 Then
For i = 1 To wb.Worksheets.Count
If wb.Worksheets(i).Visible Then wsFrom.Add wb.Worksheets(i)
Next
strScope = "ALL VISIBLE"
Else
For i = 1 To w.SelectedSheets.Count
If w.SelectedSheets(i).Visible Then wsFrom.Add w.SelectedSheets(i)
Next
strScope = wsFrom.Count & " SELECTED"
End If
strNewTab = InputBox("Merge data from " & strScope & " sheets to new sheet named:", "Merge tabs", "All")
If strNewTab = vbNullString Then Exit Sub
Set wsTo = wb.Worksheets.Add(wsFrom(1), Count:=1) 'Add before first selected sheet
wsTo.Name = strNewTab
wsFrom(1).Range("A1").CurrentRegion.Copy
wsTo.Range("A1").PasteSpecial xlPasteFormulasAndNumberFormats
Application.CutCopyMode = False
For i = 2 To wsFrom.Count
wsFrom(i).Range("A2", wsFrom(i).Range("A1").CurrentRegion.Cells(wsFrom(i).Range("A1").CurrentRegion.Cells.Count)).Copy
wsTo.Cells(wsTo.Cells.Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
Application.CutCopyMode = False
Next i
wsTo.Range("A1").Select
MsgBox "Merge Done"
End Sub

Try this code, please. It firstly counts the maximum number of rows for sheets to be processed, the maximum number of columns and number of sheets. For maximum number of columns, it counts only the sheet first row. So, it must be the longer of the sheet! All that is done for being able to correctly dimension the arrFin array which will collect all the lines. It will have more rows then necessary, multiplying the max number of rows with the sheets number. Then the array is filled with data. I switched the rows with columns because only the second dimension of the array can be Redim, preserving the existing data. Finally the transposed array is dropped in the Master sheet at once. It should work very fast... Please, confirm that it works as you need.
Private Sub testApendCopySameRows()
Dim ws As Worksheet, wDest As Worksheet, arrWork As Variant, arrFin As Variant
Dim lastCol As Long, lastC As Long, lastColM As Long, lastR As Long, nrSheets As Long
Dim maxR As Long, maxRows As Long, i As Long, j As Long, k As Long
Set wDest = Worksheets("Master1") ' please, use here your master sheet name
For Each ws In Worksheets
If ws.Name <> wDest.Name Then
'If ws.Name = "sh1" Or ws.Name = "sh2" Then 'used (by me) for testing
nrSheets = nrSheets + 1
lastC = ws.Cells(1, Cells.Columns.Count).End(xlToLeft).Column
If lastC > lastCol Then lastCol = lastC
maxR = ws.Range("A" & Cells.Rows.Count).End(xlUp).Row
If maxR > maxRows Then maxRows = maxR
'End If
End If
Next
ReDim arrFin(1 To lastCol, 1 To maxRows * nrSheets)
ReDim arrWork(1 To 1, 1 To lastCol)
k = 1 'arrFin first row
For i = 1 To maxRows
For Each ws In Worksheets
If ws.Name <> wDest.Name Then
'If ws.Name = "sh1" Or ws.Name = "sh2" Then
lastR = ws.Range("A" & Cells.Rows.Count).End(xlUp).Row
If i <= lastR Then
'input the same rows content in the array:
arrWork = ws.Range(ws.Cells(i, 1), ws.Cells(i, lastCol)).value
For j = 1 To lastCol
arrFin(j, k) = arrWork(1, j)
Next j
k = k + 1
Erase arrWork
ReDim arrWork(1 To 1, 1 To lastCol)
End If
'End If
End If
Next
Next i
ReDim Preserve arrFin(1 To lastCol, 1 To k - 1)
wDest.Range("A1").Resize(UBound(arrFin, 2), UBound(arrFin, 1)).value = _
WorksheetFunction.Transpose(arrFin)
End Sub
Do not forget to use your Master sheet name in Set wDest = Worksheets("Master1")!

Related

Copying the data from two columns from every sheet into a new sheet

I have several workbooks with multiple worksheets. Each worksheet has two columns in positions "H" and "I". These columns in each worksheet has a different number of rows for these two columns. The worksheets are named differently as in
Sheet1: Data
Sheet2: Calc
Sheet3: Settings
Sheet4: Append1
Sheet5: Append2
.....
After the "Settings" sheet, each sheet is named append and then 1,2,3,...
I want to copy the columns H and I from every sheet except Calc and Settings into a new sheet.
It should be copied as columns. So it should look something like this in the new sheet
Data.col(H)|Data.col(I)|Append1.col(H)|Append1.col(I)|Append2.col(H)|Append2.col(I)| .....
How do I achieve this?
I have been using the formula =Append1H:H and =Append1I: I but it is too much data and cannot be done manually.
Any help is appreciated.
Please, try the next way. It will be very fast, using arrays and working mostly in memory. It does not use clipboard, it will not copy the range format. It will return in columns "A:B" of the newly created sheet (or the cleaned one, if already existing):
Sub copyColumns()
Dim wb As Workbook, ws As Worksheet, lastR As Long, arrC, arrFin, i As Long
Set wb = ActiveWorkbook 'use here the apropriate workbook
For Each ws In wb.Worksheets
If ws.name <> "Settings" And ws.name <> "Calc" And _
ws.name <> "Cons_Sheet" Then
i = i + 1
lastR = ws.Range("H" & ws.rows.count).End(xlUp).row
arrC = ws.Range("H" & IIf(i = 1, 1, 2) & ":I" & lastR).value 'copy header only from the first sheet
arrFin = buildArr(arrFin, arrC, i) 'add arrC to the one keeping all processing result
End If
Next ws
'add a new sheet, or clean it if existing:
Dim shC As Worksheet
On Error Resume Next
Set shC = wb.Worksheets("Cons_Sheet")
On Error GoTo 0
If Not shC Is Nothing Then
shC.UsedRange.ClearContents
Else
Set shC = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.count))
shC.name = "Cons_Sheet"
End If
'drop the processed array content in the new added sheet:
shC.Range("A1").Resize(UBound(arrFin), UBound(arrFin, 2)).value = arrFin
MsgBox "Ready..."
End Sub
Function buildArr(arrF, arrC, i As Long) As Variant
If i = 1 Then arrF = arrC: buildArr = arrF: Exit Function 'use the first returned array
Dim arrSum, j As Long, k As Long
arrSum = WorksheetFunction.Transpose(arrF)
ReDim Preserve arrSum(1 To UBound(arrF, 2), 1 To UBound(arrF) + UBound(arrC))
k = UBound(arrF)
For i = 1 To UBound(arrC)
k = k + 1
For j = 1 To UBound(arrC, 2)
arrSum(j, k) = arrC(i, j)
Next j
Next i
buildArr = WorksheetFunction.Transpose(arrSum)
End Function
You can Just use this formula.
I choose 3 different range in the formula just to show you, you can use any kind of range for this to work.
=FILTERXML(""&SUBSTITUTE(TEXTJOIN(",",TRUE,Table1[Fruits Name],Sheet3!E2:E128,Sheet4!A2:A73),",","")&"","//y")

Extracting data from different worksheets and transfer to master report

Guys I'm stuck with my code(the array part if not working).I would appreciate a help.
I have 6 worksheets(JAN,FEB,MAR,APR,MAY,JUN and Reports).JAN-JUN worksheets contain employees absences records.
I need to transfer the records from worksheets JAN-JUN(employees name are not in proper order) paste in master worksheets called "Report"(all name are in ascending order)
In report I have the following header(JAN ,FEB ,MAR .......JUN ) in cells B1,C1,D1,E1,F1,G1.
Range("I") in each worksheets contains total absences by employees for a given month.
Range("H") in each worksheets contain employees who absent for the month.
I need to transfer only Range("I") from each worksheet and paste based on the the relevant months and employees.
My code contains an array of cell B1 to G1 from master worksheets.
Sub transferABS1()
Dim i As Long, j As Long, lastrow1 As Long, lastrow2 As Long
Dim myname As String
Dim arRng() As Variant
Dim iRw As Integer
Dim iCol As Integer
arRng = Sheets("Reports").Range("B1:G1")
For iRw = 1 To UBound(arRng, 1)
For iCol = 1 To UBound(arRng, 2)
lastrow1 = Sheets(arRng).Range("H" & Rows.Count).End(xlUp).Row
For i = 1 To lastrow1
myname = Sheets(arRng).Cells(i, "H").Value
Sheets("Reports").Activate
lastrow2 = Sheets("Reports").Range("A" & Rows.Count).End(xlUp).Row
For j = 2 To lastrow2
If Sheets("Reports").Cells(j, "A").Value = myname Then
Sheets(arRng).Activate
Sheets(arRng).Range(Cells(i, "I")).Copy
Sheets("Reports").Activate
ActiveSheet.Cells(j, iCol).Select
ActiveSheet.Paste
End If
Next j
Application.CutCopyMode = False
Next i
Next iCol
Next iRw
End Sub
It would probably be much easier if you just created a starter table that had headers of Name/Month/Hours. From there you could run a pivot table, or variety of analysis.
To get in a table format is easier than your two dimensional Name by Month format. This code will list all values on your Report sheet.
Sub listAllNamesMonthsAndAmounts()
Const theMonths As String = "Jan,Feb,Mar,Apr,May,Jun,Jul,"
Dim ws As Worksheet, i As Long, g As Long, aCell As Range
g = 1
ReDim eList(1 To 3, 1 To g) As Variant
For Each ws In ThisWorkbook.Worksheets
If InStr(1, theMonths, ws.Name & ",", vbTextCompare) > 0 Then
For Each aCell In Intersect(ws.Range("H:H"), ws.UsedRange)
If aCell <> "" Then
ReDim Preserve eList(1 To 3, 1 To g)
eList(1, g) = ws.Name
eList(2, g) = aCell.Value
eList(3, g) = aCell.Offset(0, 1).Value
g = g + 1
End If
Next aCell
End If
Next ws
Sheets("Report").Range("A2").Resize(UBound(eList, 2), UBound(eList)).Value = Application.WorksheetFunction.Transpose(eList)
End Sub

Print value blocks into new worksheets?

I have a worksheet that I need to split out into new ones by column C values. There are 8 values, so I'll need 8 worksheets. Each value has about 2-5000 corresponding rows, so this script isn't ideal because it prints row-by-row.
Sub SplitData()
Const iCol = 3 ' names in second column (B)
Const sRow = 2 ' data start in row 2
Dim wshSource As Worksheet
Dim wshTarget As Worksheet
Dim i As Long
Dim lRow As Long
Dim lngTargetRow As Long
Application.ScreenUpdating = False
Set wshSource = Sheets(1)
lRow = wshSource.Cells(wshSource.Rows.Count, iCol).End(xlUp).Row
For i = sRow To lRow
If wshSource.Cells(i, iCol).Value <> wshSource.Cells(i - 1, iCol).Value Then
Set wshTarget = Worksheets.Add(After:=Worksheets(Worksheets.Count))
wshTarget.Name = wshSource.Cells(i, iCol).Value
wshSource.Rows(sRow - 1).Copy Destination:=wshTarget.Cells(1, 1)
lngTargetRow = 2
End If
wshSource.Rows(i).Copy Destination:=wshTarget.Cells(lngTargetRow, 1)
lngTargetRow = lngTargetRow + 1
Next i
Application.ScreenUpdating = True
End Sub
How would I change this up to print each value block (column C) to each worksheet instead of every row (i) individually? Would I need to implement auto-filtering by column C values and do a loop that way?
Try this out, as you well pointed, filtering would be the fastest way here:
Option Explicit
Sub Test()
Dim uniqueValues As Object
Set uniqueValues = CreateObject("Scripting.Dictionary")
Dim i As Long
With ThisWorkbook.Sheets("MainSheet") 'change MainSheet to the name of the sheet containing the data
'First let's store the unique values inside a dictionary
For i = 2 To .UsedRange.Rows.Count 'this will loop till the last used row
If Not uniqueValues.Exists(.Cells(i, 3).Value) Then uniqueValues.Add .Cells(i, 3).Value, 1
Next i
'Now let's loop through the unique values
Dim Key As Variant
For Each Key In uniqueValues.Keys
.UsedRange.AutoFilter Field:=3, Criteria1:=Key 'Filter column C by the value in the key
ThisWorkbook.Sheets.Add after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count) 'add a new sheet
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count).Name = Key 'change the name of the new sheet to the key's
.UsedRange.SpecialCells(xlCellTypeVisible).Copy ThisWorkbook.Sheets(Key).Range("A1") 'copy the visible range after the filter to the new sheet
Next Key
End With
End Sub

Insert one row between groups based on criteria in a column

I have a worksheet of data that has four columns. I want the spreadsheet to add 3 rows after each group based on column D. Column D has the department for the transactions. All department transactions are listed in a row. So Excel just needs to find the change in department and enter three rows after that section.
I have tried this code I found here. It puts a row after every line it sees the department in.
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("IMPORT-WIP") 'better define by name: ThisWorkbook.Worksheets("MySheet")
Dim LastRow_f As Long
LastRow_f = ws.Cells(ws.Rows.Count, "D").End(xlUp).Row
ws.Range("A1:D" & LastRow_f).AutoFilter Field:=12, Criteria1:="HR DEPARTMENT"
Dim FilteredData As Range
Set FilteredData = ws.Range("D2:D" & LastRow_f).SpecialCells(xlCellTypeVisible)
Dim iArea As Long
Dim iRow As Long
For iArea = FilteredData.Areas.Count To 1 Step -1 'loop from last to first area
For iRow = FilteredData.Areas(iArea).Rows.Count To 1 Step -1 'loop from last row to first row in each area
With FilteredData.Areas(iArea).Rows(iRow) '<-- this represents the current row we are in the loop
.Offset(RowOffset:=1).EntireRow.Insert Shift:=xlDown
.Offset(RowOffset:=1).EntireRow.Interior.Color = RGB(192, 192, 192)
End With
Next iRow
Next iArea
'remove filters
ws.Range("A1:D" & LastRow_f).AutoFilter
This code will insert 3 rows between groups of values (even unique values). The data does not need to be filtered. It will loop through Column D, test the cell above the current cell and, if not the same value, will insert 3 rows between them. You may have to sort the data first, depending on what you want.
Sub InsertRowsBetweenGroups()
Dim ws As Worksheet, lr As Long, i As Long
Set ws = ThisWorkbook.Sheets("Sheet1") 'Change as needed
lr = ws.Cells(ws.Rows.Count, 4).End(xlUp).Row
For i = lr - 1 To 2 Step -1
If Cells(i, "D") <> Cells(i - 1, "D") Then
Cells(i, "D").Resize(3).EntireRow.Insert Shift:=xlDown
End If
Next i
End Sub

Looping through worksheets and trying to count the data in columns

I have a workbook of ten sheets. In sheet 1, I want to list out sheet names (sheets 3 thru 10), column heading values in the sheet (columns 8 and beyond only) and for that column the number of cells that have data in it.
My code works for two of these three requirements. On my sheet 1 (named: SheetName Columns) I get the Sheet Names in column A and Column Heading in column B, however not having any luck getting that sheet/columns number of data rows.
On my sheet 1, column A gets duplicated per number of columns after column 7 on that sheet and that is fine.
Sub ListColumnHeadings()
Dim cNbrs As Long, i As Integer, tr As Long, tc As Long, wst As Worksheet
Dim charList(300, 300) As String
Dim ws As Worksheet, OutputRow As Long
Dim myRange As Range
Dim NumRows As Integer
Dim colNbr As Range
Set shSkip1 = ThisWorkbook.Sheets("SheetName Record Cnt")
Set shList = ThisWorkbook.Sheets("SheetName Columns")
OutputRow = 1
On Error Resume Next
For Each ws In Worksheets
If ws.Name <> shList.Name And ws.Name <> shSkip1.Name Then
cNbrs = ws.Range("A1").CurrentRegion.Columns.Count
For i = 8 To cNbrs
shList.Cells(OutputRow, "A").Value = ws.Name
shList.Cells(OutputRow, "B").Value = ws.Cells(1, i)
Set myRange = ws.Columns(i).Select
NumRows = ws.Application.WorksheetFunction.CountA(myRange)
If NumRows > 0 Then
shList.Cells(OutputRow, "C").Value = NumRows
End If
OutputRow = OutputRow + 1
Next i
End If
Next ws
End Sub
It's because of your use of Set myRange... You don't need to .Select it. Just change that line to Set myRange = ws.Columns(i)
If you want to leave .Select, then the next line should be
NumRows = ws.application.worksheetfunction.counta(selection), but it is highly recommended you avoid using .Select, this is just for your info.

Resources