Excel VBA looping through multiple worksheets - vba

VBA beginner here, I've got a little problem with program I'm working on.
I need to copy data from last cell in column B from first worksheet and paste it into column A in another worksheet xws, and repeate this operation for five other worksheets with data.
Here's the code, it doesn't work the way it should:
Sub exercise()
Dim ws As Worksheet
Dim rng As Range
'Finding last row in column B
Set rng = Range("B" & Rows.Count).End(xlUp)
For Each ws In ActiveWorkbook.Worksheets
'Don't copy data from xws worksheet
If ws.Name <> "xws" Then
'Storing first copied data in A1
If IsEmpty(Sheets("xws").[A1]) Then
rng.Copy Sheets("xws").Range("A" & Rows.Count).End(xlUp)
'Storing next copied data below previously filled cell
Else
rng.Copy Sheets("xws").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
End If
End If
Next ws
End Sub
There is a problem with ws. referring, but whenever I put it before rng in if statements or before range (set rng = ...) I get errors.
Thanks in advance for any pointers.

You should be declaring rng for each ws inside the loop, like:
Sub exercise()
Dim ws As Worksheet
Dim rng As Range
For Each ws In ActiveWorkbook.Worksheets
'Finding last row in column B
Set rng = ws.Range("B" & ws.Rows.Count).End(xlUp) '<~~ Moved inside the loop
'Don't copy data from xws worksheet
If ws.Name <> "xws" Then
'Storing first copied data in A1
If IsEmpty(Sheets("xws").[A1]) Then
rng.Copy Sheets("xws").Range("A" & Rows.Count).End(xlUp)
'Storing next copied data below previously filled cell
Else
rng.Copy Sheets("xws").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
End If
End If
Next ws
End Sub
As your code is now, rng will be pointing to the ActiveSheet at the time you run the macro, and your code will then copy the same cell on each iteration of the code.

Related

Looping through Worksheet, and assigning named ranged of worksheet range to Worksheet name

I have a workbook book that has worksheets for each state in the US.
I want to loop through each worksheet, and assign a named range for the data in the table to be the worksheet name.
Right now I have it set up where it is looping through everysheet, skipping the sheet I want it to skip, and setting the proper range. However, it ended up creating a 50 named ranges for the first sheet.
Sub Sheetloop()
Dim ws As Worksheet
Dim rng As Range
Dim ws_name As String
For Each ws In Worksheets
If ws.Name <> "GA_AVERAGE" Then
ws_name = ws.Name
Set rng = Range("A2:N" & Range("A" & Rows.Count).End(xlUp).Row)
rng.Name = ws_name
End If
Next
End Sub
I expect each sheet to has its respective namedrange attached to the data within the sheet.
You are not referencing the sheet each time, so you need.
ws.Range("A2:N" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row)

Copying the matched row in another sheet

I have two Sheets, sheet1 and sheet 2.
I am looking into column T of sheet1 and pasting the complete row if T contains 1 in sheet 2.
The code, works good, but it paste the result in sheet2 in the same row in sheet1.
This results in blanks, between the rows. Can anyone suggest, what i should Change with my code, so that i get them in sequence without any blank rows.
Also, how can I copy the Header in row 1 from sheet 1 to sheet2?
Sub Test()
For Each Cell In Sheets(1).Range("T:T")
If Cell.Value = "1" Then
matchRow = Cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets(2).Select
ActiveSheet.Rows(matchRow).Select
ActiveSheet.Paste
Sheets(1).Select
End If
Next
End Sub
There's no need to use Select and Selection to copy paste, it will only slows down your code's run-time.
Option Explicit
Sub Test()
Dim Cell As Range
Dim NextRow as Long
Application.ScreenUpdating = False
For Each Cell In Sheets(1).Range("T1:T" & Sheets(1).Cells(Sheets(1).Rows.Count, "T").End(xlUp).Row)
If Cell.Value = "1" Then
NextRow = Sheets(2).Cells(Sheets(2).Rows.Count, "T").End(xlUp).Row
Rows(Cell.Row).Copy Destination:=Sheets(2).Range("A" & NextRow + 1)
End If
Next
Application.ScreenUpdating = True
End Sub
Not For Points
Apologies, but I couldn't stop myself from posting an answer. It pains me when I see someone wanting to use an inferior way of doing something :(
I am not in favor of looping. It is very slow as compared to Autofilter.
If you STILL want to use looping then you can make it faster by not copying the rows in the loop but in the end in ONE GO...
Also if you do not like living dangerously then always fully qualify your object else you may end up copying the wrong row.
Option Explicit
Sub Sample()
Dim wsI As Worksheet, wsO As Worksheet
Dim lRow As Long, i As Long, r As Long
Dim copyRng As Range
Set wsI = Sheet1: Set wsO = Sheet2
wsO.Cells.Clear
'~~> first available row in sheet2
r = 2
With wsI
lRow = .Range("T" & .Rows.Count).End(xlUp).Row
'~~> Copy Headers
.Rows(1).Copy wsO.Rows(1)
For i = 1 To lRow
If .Range("T" & i).Value = 1 Then
If copyRng Is Nothing Then
Set copyRng = .Rows(i)
Else
Set copyRng = Union(copyRng, .Rows(i))
End If
End If
Next i
End With
If Not copyRng Is Nothing Then copyRng.Copy wsO.Rows(r)
End Sub
Screenshot

Copy rows starting from certain row till the end using macro

I need to copy values of one excel and create a new one with required format. Say i need to copy columns from B11 to BG11 and rows will be till the end.( i don't know how to find the end of rows). And I have column heading in b7 to bg7. In between there are unwanted rows and i don't need it. So in the new excel i want column headings(which is from b7 to bg7) as first row and the values from b11 to bg11 till the end.
This is my first excel Macro. I don't know how to proceed. So with references from some stackoverflow question and other site, i have tried the below code. but it is not giving the required output.
Sub newFormat()
Dim LastRow As Integer, i As Integer, erow As Integer
LastRow = ActiveSheet.Range(“B” & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
Sheets("MySheetName").Range("B7:BG7").Copy
Sheets("MySheetName").Range("B11:BG11").Copy
Workbooks.Open Filename:=”C:\Users\abcd\Documents\Newformat.xlsx”
Worksheets(“Sheet1”).Select
erow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Cells(erow, 1).Select
ActiveSheet.Paste
ActiveWorkbook.Save
ActiveWorkbook.Close
Application.CutCopyMode = False
End If
Next i
End Sub
this may be simple. any help would be appreciated.
Few things...
Do not use Integer for rows. Post xl2007, the number of rows have increased and Integer can't hold that. Use Long
You do not need to select a range to paste on it. You can directly perform the action.
You do not need to use a loop. You can copy ranges in two chunks
Work with objects so Excel doesn't get confused by your objects.
Since Sheet1 is empty, you don't need to find the last row there. Simply start at 1.
To output the data to new workbook, you have to use Workbooks.Add
See this example (Untested)
Sub newFormat()
Dim wbO As Workbook
Dim wsI As Worksheet, wsO As Worksheet
Dim LastRow As Long, erow As Long
'~~> Set this to the relevant worksheet
Set wsI = ThisWorkbook.Sheets("HW SI Upload")
'~~> Find the last row in Col B
LastRow = wsI.Range("B" & wsI.Rows.Count).End(xlUp).Row
'~~> Open a new workbook
Set wbO = Workbooks.Add
'~~> Set this to the relevant worksheet
Set wsO = wbO.Sheets(1)
'~~> The first row in Col A for writing
erow = 1
'~~> Copy Header
wsI.Range("B7:BG7").Copy wsO.Range("A" & erow)
'~~> Increment output row by 1
erow = erow + 1
'~~> Copy all rows from 11 to last row
wsI.Range("B11:BG" & LastRow).Copy wsO.Range("A" & erow)
'~~> Clear Clipboard
Application.CutCopyMode = False
'
'~~> Code here to do a Save As
'
End Sub
Different but the same
Rename the sheet
Sub Button1_Click()
Dim wb As Workbook, ws As Worksheet, sh As Worksheet
Dim LstRw As Long, Rng As Range, Hrng As Range
Set sh = Sheets("MySheetName")
With sh
Set Hrng = .Range("B7:BG7")
LstRw = .Cells(.Rows.Count, "B").End(xlUp).Row
Set Rng = .Range("B11:BG" & LstRw)
End With
Application.ScreenUpdating = 0
Workbooks.Open Filename:="C:\Users\abcd\Documents\Newformat.xlsx"
Set wb = Workbooks("Newformat.xlsx")
Set ws = wb.Sheets(1)
Hrng.Copy ws.Cells(Rows.Count, "A").End(xlUp).Offset(1)
Rng.Copy ws.Cells(Rows.Count, "A").End(xlUp).Offset(1)
ws.Name = sh.Name 'renames sheet
wb.Save
wb.Close
End Sub

Copy and Paste a range from one worksheet to multiple worksheets

I am trying to copy a range from one worksheet to about 600 more worksheets in the same workbook.
I have found some code that enables me to copy the range and paste it at the end of the next worksheet. The code below only pastes the range to 1 worksheet (Sheet3). But I am unable to figure out how to loop it to paste in all the other worksheets. How can I add a loop to the code below to to do so?
Sub copypaste()
Dim i As Long
With Sheets("Sheet3")
i = .Range("B" & Rows.Count).End(3).Row
Sheets("Cert").Range("A1:K27").Copy .Range("A" & i + 1)
End With
End Sub
If by 600 worksheets, you mean that you would like to copy to all the worksheets, then consider:
For Each WS In Worksheets
With WS
i = .Range("B" & Rows.Count).End(3).Row
Sheets("Cert").Range("A1:K27").Copy .Range("A" & i + 1)
End With
Next WS

Excel 2007 macro fills to end of first sheet for all sheets in workbook

The code below creates a new column (A), gives the it the header "Class" and then fills column A with the worksheet name until the last row of B for all worksheets in workbook. It is working except that it fills all worksheets to the the last row of B from the first sheet processed for all subsequent sheets. What have I done wrong? I like the fill to be determined by the last row of B for each sheet.
Option Explicit
Sub AddColumnFill()
Dim sht As Worksheet
For Each sht In ActiveWorkbook.Worksheets
sht.Range("A1").EntireColumn.Insert xlShiftToRight
sht.Cells(1, 1) = "Class"
sht.Range("A2:A" & Cells(Rows.Count, "B").End(xlUp).Row).Value = sht.Name
Next sht
End Sub
This works for me.
Option Explicit
Sub AddColumnFill()
Dim sht As Worksheet
Dim lRow As Long
For Each sht In ActiveWorkbook.Worksheets
With sht
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Columns("A:A").Insert Shift:=xlToRight
.Cells(1, 1) = "Class"
.Range("A2:A" & lRow).Value = .Name
End With
Next sht
End Sub
Use
sht.Range("A2:A" & sht.Cells(sht.Rows.Count, "B").End(xlUp).Row).Value = sht.Name
Instead of
sht.Range("A2:A" & Cells(Rows.Count, "B").End(xlUp).Row).Value = sht.Name