Copy rows from multiple sheets to another sequentially - excel

I am trying to write a script that takes all the rows (after the header row), and copies them sequentially into the first tab. I also have 10 tabs i would like it to do this for, and sequentially paste them into the first tab (basically pull everything from the other sheets, and put it into the first sheet like a big master sheet or report)
I tried this, but its not working
Sub Report()
page = 2
row = 1
Dim lastRow As Integer
Dim pae As Integer
Dim rw As Integer
Dim WSheet(1 To 12) As Worksheet
lastRow = Worksheets(page).Cells(Rows.Count, "A").End(xlUp).rw
While (pge <= 12)
While (rw <= lastRow)
rw = rw + 1
ws1.Rows(row).EntireRow.Copy WSheet(pge).Range("A" & lastRow)
Wend
pge = pge + 1
Wend
End Sub
I was trying to get it to count how many rows have data, and then copy all of those rows to the first sheet before moving on to the next sheet,
It seems to skip over where i declare the variables, and then errors out on the lastrow assignment
Any help would be greatly appreciated

Please, try the next code:
Sub ReportMaster()
Dim ws1 As Worksheet, ws As Worksheet, lastRow As Long, lastER As Long, lastCol As Long
Set ws1 = Worksheets(1)
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> ws1.Name Then
lastRow = ws.Range("A" & ws.rows.count).End(xlUp).row
lastCol = ws.cells(1, ws.Columns.count).End(xlToLeft).Column
lastER = ws1.Range("A" & ws.rows.count).End(xlUp).row + 1 'last empty row
ws.Range(ws.Range("B1"), ws.cells(lastRow, lastCol)).Copy ws1.Range("A" & lastER)
End If
Next ws
End Sub

Related

Searching cell name to see if worksheet exists and if it does....?

I am trying to create code (Loop) so that when a task is allocated to a team member (in a cell in column H) the code searches the cell value with the existing sheet names and if there is a match, the sheet then makes the task member sheet active sheet, finds the last available line and adds the allocated tasks to the sheet. The code should run for all filled cells in the column.
However, the code i have currently written bugs out. I am finding it hard to define the worksheetname (Cell value) etc.
Sub TaskAllocation()
Dim cell As Range, Lastrow1 As Double, i As Integer
Dim SubTaskWs As Worksheet, Ws As Worksheet, Lastrow2 As Double
Set SubTaskWs = ActiveWorkbook.Worksheets("Sub tasks")
Set Ws = ActiveWorkbook.Sheets(WsName)
i = o
Lastrow1 = SubTaskWs.Range("H" & Rows.Count).End(xlUp).Row
Lastrow2 = Ws.Range("A" & Rows.Count).End(xlUp).Row
For Each cell In SubTaskWs.Range("H4:H" & Lastrow1)
For Each Ws In Sheets
If cell.value = Ws.Name Then
Ws.Range("A" + (Lastrow2 + (i))).EntireRow.Insert
Call copyFormattingAbove(Ws, "A" & Lastrow2)
Ws.Range(("A" & Lastrow2) + (i)).value = cell.Offset(, -6)
Ws.Range(("B" & Lastrow2) + (i)).value = cell.Offset(, -5)
i = i + 1
End If
Next Ws
Next cell
End Sub
I did change a bit your code to make it more readable.
Some tips for the future:
Use the Option Explicit on the top of your moduel to fource the declaration of all your variables.
Always try to declare your variables close to where they are used.
Never declare a integervariable, use Long instead. Don't use Double for rows either, Double and Single are for floating numbers.
Here is the code:
Option Explicit
Sub TaskAllocation()
Dim cell As Range
Dim SubTaskWs As Worksheet
Set SubTaskWs = ActiveWorkbook.Worksheets("Sub tasks")
Dim Lastrow1 As Long
Lastrow1 = SubTaskWs.Range("H" & Rows.Count).End(xlUp).Row
Dim ws As Worksheet
Dim cell As Range
Dim Lastrow2 As Long, i As Long
i = 0
Dim Tasks As Object
FillTasks Tasks
For Each cell In SubTaskWs.Range("H4:H" & Lastrow1) 'change this range and loop through the column with the tasks
If Tasks.Exists(cell) Then GoTo AlreadyDone
For Each ws In Sheets
If SubTaskWs.Cells(cell.Row, "H") = ws.Name Then
Lastrow2 = ws.Range("A" & Rows.Count).End(xlUp).Row + 1
copyFormattingAbove ws, "A" & Lastrow2
ws.Range("A" & Lastrow2).Value = SubTaskWs.Cells(cell.Row, 2)
ws.Range("B" & Lastrow2).Value = SubTaskWs.Cells(cell.Row, 3)
End If
Next ws
AlreadyDone:
Next cell
End Sub
Function FillTasks(Tasks As Object)
Set Tasks = CreateObject("Scripting.Dictionary")
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets 'loop through sheets
If Not ws.Name = "Sub tasks" Then
'code to find the right columnd and loop through the existing tasks
'there is no need for an item on this case, you only need to know if it exists
If Not Tasks.Exists(cell) Then Tasks.Add cell, 1
End If
Next ws
End Function

Copy data from a number of rows and specified columns to a sheet in new workbook

The below code selects every 9998 rows, creates a new Excel sheet and then pastes the content.
1) I need to give a common heading to all the new Excel files. The cell values should start from A2.
2) I don't want to select the entire row, just column A and column C.
3) I want to change the sheet name in new Excel workbook that's been created.
Sub test()
Dim lastRow As Long, myRow As Long, myBook As Workbook
lastRow = ThisWorkbook.Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For myRow = 2 To lastRow Step 9998
Set myBook = Workbooks.Add
ThisWorkbook.Sheets("Sheet1").Rows(myRow & ":" & myRow +9997).EntireRow.Copy myBook.Sheets("Sheet1").Range("A1")
Next myRow
End Sub
Try this code:
Sub test()
Dim lastRow As Long, myRow As Long, myBook As Workbook
With ThisWorkbook.Sheets("Sheet1")
lastRow = .Cells(Rows.Count, 1).End(xlUp).Row
For myRow = 2 To lastRow Step 9998
Set myBook = Workbooks.Add
.Range("A" & myRow & ":C" & myRow + 9997).Copy myBook.Sheets(1).Range("A2")
ActiveWorkbook.Sheets(1).Name = "New Name"
Next myRow
End With
End Sub
1) This is being resolved by simply changing your paste range to .Range("A2")
2) I changed your Copy range to only select columns A-C
3) Sheet name change happens in the last line of code (just before "Next myRow")
Hope it helps!

Loop through table and cut&paste to another sheet

I am a total beginner and appreciate any help I can get.
Sheet1 has a list of 30 markets.
Market1
Market2
.
.
Market30
I have a script that loops through Sheet1 and creates a new sheet for every market.
Sheet2 has all my raw data.
Looping through Sheet2 I need to move every row to its corresponding market. Market ID is in column B.
1-by-1 I can do this with the code below, but how would I put it in a loop?
I want to loop through Sheet1 and for each market ID, use that input as a variable to search Sheet2 and move the entire row to its corresponding market sheet.
Sub Market1()
Dim LR As Long, i As Long
With Sheets("Sheet2")
LR = .Range("B" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If .Range("B" & i).Value = "Market1" Then .Rows(i).Copy Destination:=Sheets("Market1").Range("A" & Rows.Count).End(xlUp).Offset(1)
Next i
End With
End Sub
Sub Market2()
Dim LR As Long, i As Long
With Sheets("Sheet2")
LR = .Range("B" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If .Range("B" & i).Value = "Market2" Then .Rows(i).Copy Destination:=Sheets("Market2").Range("A" & Rows.Count).End(xlUp).Offset(1)
Next i
End With
End Sub
Thank you
I think this should do what you want. The only tricky thing is adding a sheet if you already have the sheet name. I added a second macro that checks for it and creates if not found. Based on your code (which was a nice example), I think this should work for you.
Sub MarketAny()
Dim LR As Long, i As Long
Dim ws As Worksheet, shName As String
Set ws = Sheets("Sheet2")
LR = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
For i = 1 To LR
shName = ws.Range("B" & i).Value
Call SheetCheck(shName) ' needed to ensure that you don't create a duplicate name
ws.Rows(i).Copy Destination:=Sheets(shName).Range("A" & Rows.Count).End(xlUp).Offset(1)
Next i
End Sub
Private Sub SheetCheck(nameofSheet As String)
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
If ws.Name = nameofSheet Then Exit Sub
Next ws
'Creates new sheet
Set ws = Sheets.Add
ws.Name = nameofSheet
End Sub

How to specify a sheet to determine 'lastrow'?

I am trying to determine 'lastrow' of the sheet that the macro is being run on.
I am working with two sheets. Sheet1 has about 150 rows of data and Sheet 2 only has two.
I expected that when I selected Sheet2 and assigned lastrow that it would take the count of rows from Sheet2, instead it is storing the row count from sheet1.
sub row_count()
dim lastrow as long
lastrow = Range("A" & Rows.Count).End(xlUp).row
if lastrow = 150 then
with sheets("sheet2")
.select
lastrow = Range("A" & Rows.Count).End(xlUp).row
msgbox lastrow '<----- Always returns the value of sheet1 instead of sheet2.
end with
end sub
You're using a With block, which means the program sees anything between 'With' and 'End With' as being prefixed by whatever you put after the keyword 'With', so to modify your code in place for sheet2 only:
Sub row_count()
Dim lastrow As Long
lastrow = Sheets("sheet2").Range("A" & Rows.Count).End(xlUp).Row
If lastrow = 150 Then
With Sheets("sheet2")
' .Select = Sheets("sheet2").Select
.Select
' .Range = Sheets("sheet2").Range
lastrow = .Range("A" & Rows.Count).End(xlUp).Row
MsgBox lastrow
End With
End Sub
If you want the code to run on the currently visible sheet you should change it to use the ActiveSheet property:
Sub row_count()
Dim lastrow As Long
lastrow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
If lastrow = 150 Then
With ActiveSheet ' use the currently visible sheet
.Select
lastrow = .Range("A" & Rows.Count).End(xlUp).Row
MsgBox lastrow
End With
End Sub
However, there are some ways to improve this code: for flexibility you could pass the worksheet as a parameter. Also, your End function might return the first used row if there is already data in the last used row (it's the same as clicking in the last row and pressing Ctrl & the up arrow, so you should start in a cell below that). Lastly, you do not need to select the sheet to get the last row:
Sub GetRowCounts()
row_count Sheets("sheet1")
row_count Sheets("sheet2")
End Sub
Sub row_count(ws As Worksheet)
Dim lastrow As Long
lastrow = ws.Range("A1000000").End(xlUp).Row
MsgBox lastrow
End Sub
I think these examples are the easiest to follow.
Sub FindingLastRow()
'PURPOSE: Different ways to find the last row number of a range
'SOURCE: www.TheSpreadsheetGuru.com
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
'Ctrl + Shift + End
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
'Using UsedRange
sht.UsedRange 'Refresh UsedRange
LastRow = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Row
'Using Table Range
LastRow = sht.ListObjects("Table1").Range.Rows.Count
'Using Named Range
LastRow = sht.Range("MyNamedRange").Rows.Count
'Ctrl + Shift + Down (Range should be first cell in data set)
LastRow = sht.Range("A1").CurrentRegion.Rows.Count
End Sub
https://www.thespreadsheetguru.com/blog/2014/7/7/5-different-ways-to-find-the-last-row-or-last-column-using-vba
Keep an open mind though, there are lots of ways to do this same kind of thing.
If this statement...
lastrow = Range("A" & Rows.Count).End(xlUp).row
... really always returns the last row of Sheet1 instead of last row of Sheet2, then that is because you are looking at your Workbook open at Sheet1 all the time.
Whenever you have a Range or Cells statement like the above ( Range(...) ) without an explicit reference to a Worksheet, then ActiveSheet is what it is referenced to.
So to avoid that, this is what you do:
Dim Sht_1 as Worksheet
Dim Sht_2 as Worksheet
Dim Sht_1_Lastrow as Long
Dim Sht_2_Lastrow as Long
Set Sht_1 = ActiveWorkbook.Worksheets(1)
Set Sht_2 = ActiveWorkbook.Worksheets(2)
Sht_1_Lastrow = Sht_1.Range("A" & Sht_1.Rows.Count).End(xlUp).Row
Sht_2_Lastrow = Sht_2.Range("A" & Sht_2.Rows.Count).End(xlUp).Row
or
Sht_1_Lastrow = Sht_1.Cells(Sht_1.Rows.Count, "A").End(xlUp).Row
Sht_2_Lastrow = Sht_2.Cells(Sht_2.Rows.Count, "A").End(xlUp).Row
Above code block highlights the difference that makes a LastRow Variable explicitly tied to a certain Worksheet...
This way your problem cannot happen...

VBA macro crashing Excel

Hi fellow communiteers,
I'm running a macro to delete entire rows that contain a certain value. The code works fine on small data sets but on the current one (~22,000 records) it consistently crashes Excel (2010). The code is below. Short of splitting the data into smaller chunks and running the macro again and again I'm not sure what to do.
Any help appreciated and here's the code:
Sub CleanOcc()
'Row counting
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim Lrow2 As Long
With Sheets("Occ_Prep")
'Cleans the occ_prep sheet ready for upload (Column and value can be changed)
Sheets("Occ_Prep").Activate
'Set the first and last row to loop through
Firstrow = .UsedRange.Cells(1).Row
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
'We loop from Lastrow to Firstrow (bottom to top)
For Lrow2 = Lastrow To Firstrow Step -1
'We check the values in the A column in this example
With .Cells(Lrow2, "K")
If Not IsError(.Value) Then
If .Value = "0" Then .EntireRow.Delete
'This will delete each row with the Value "ron"
'in Column A, case sensitive.
End If
End With
Next Lrow2
End With
End Sub
Agree with Siddharth comment autofilter is way to go. This should be a lot quicker.
Option Explicit
Sub delrows()
Dim ws As Worksheet
Dim LR As Long
Dim rng As Range, frng As Range
Application.ScreenUpdating = False
Set ws = Sheets("dataset") '<-- Change this to name of your worksheet
With ws
LR = .Range("A" & Rows.Count).End(xlUp).Row
.AutoFilterMode = False
Set rng = .Range("A1:C" & LR) '<-- Assuming K is the last column
rng.AutoFilter 3, "0" '<-- 11 referes to Column K
Set frng = rng.Offset(1, 0).SpecialCells(xlCellTypeVisible) '<-- Don't delete the header
frng.EntireRow.Delete
.AutoFilterMode = False
End With
Application.ScreenUpdating = True
End Sub
Edit: I just cleaned ~20000 rows (3 columns) of data in ~5 seconds. Obviously it depends how many matches there are too.

Resources