How to loop through sheet and copy some specific range - vba

So I would like my code to loop through sheets, depend on sheet name I would like to copy different range (if sheet will not be listed i want just to skip it) (lets say i know number/adress of the columns i would like to copy (number of rows might be different, depends on the orginal file i got) and i would like to copy all of these ranges one under another into sheet called check_data with additional column to the right saying from which sheet this part is comming from. I'm stuck sometimes this part of code works but it seems like it doesnt loop through the sheets.
So far i got this (but im totally new to vba)
Sub Copy_data()
Dim wb As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Set wb = ActiveWorkbook
Set ws1 = wb.Sheets("A")
Set ws2 = wb.Sheets("B")
Set ws3 = wb.Sheets("Check_data")
For Each ws In Worksheets
If ws.Name = "A" Then
ws1.Activate
ws1.Range("A1:Q1").Select
ws1.Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ws3.Select
If ws3.Range("A1") = "" Then
ws3.Range("A1").Select
ActiveSheet.Paste
Else
Selection.End(xlDown).Offset(1, 0).Select
ActiveSheet.Paste
End If
ElseIf ws.Name = "B" Then
ws2.Activate
ws2.Range("A1:Q1").Select
ws2.Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ws3.Select
If ws3.Range("A1") = "" Then
ws3.Range("A1").Select
ActiveSheet.Paste
Else
Selection.End(xlDown).Offset(1, 0).Select
ActiveSheet.Paste
End If
Else
End If
Next ws
End Sub
Thanks for any suggestions

A couple of things here. Always fully specify both the workbook and worksheets with objects, and preprend methods like Sheets with those objects, like this:
Dim wb As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set wb = ThisWorkbook
ws1 = wb.Sheets("A")
ws2 = wb.Sheets("Check_data")
ws1.Range("A1:Q1").Select
ws1.Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
...and same thing when you are ready to paste, except that you need to explicitly activate the sheet that you are pasting into:
ws2.Activate
If ws2.Range("A1") = "" Then
ws2.Range("A1").Select
Selection.Paste
Else
Selection.End(xlDown).Offset(1, 0).Select
Selection.Paste
End If
Obviously, this isn't your entire code snippet rewritten, but it's the direction that you want to head in.

Related

Set current worksheet as a variable in order to work with formulas easier

I want to set my current active worksheet as a variable in order to be able to use vlookups easier without having issues. The reason that I want to do that is because I run this macro daily and each day the active worksheet has new name (the new date). Now inside my macro I use ActiveSheet but I use a lot of vlookups and go back and forth so it crushes.. I will provide the beginning of the code so as to be more clear.. All I need is a way to set the current active book as a variable. This way, even if the active worksheet changes, the old current worksheet will be saved as a variable
Application.DisplayAlerts = False
ActiveSheet.Cells.Copy
Worksheets.Add.Name = ActiveSheet.Name & "_Daily_RCCP"
With ActiveSheet
.Cells.PasteSpecial xlValues
.Cells.PasteSpecial xlFormats
End With
Application.DisplayAlerts = True
As you can see the active worksheet changes two times.. So, I want to set the last active worksheet as a variable
To draw out what #ScottCraner mentioned in comment.
Dim ws1 as Worksheet
Set ws1 = ActiveSheet
Worksheets.Add.Name = ws1.Name & "_Daily_RCCP"
Dim ws2 as Worksheet
Set ws2 = ActiveSheet 'bc adding a sheet automatically makes it active
ws1.Cells.Copy
With ws2.Cells
.PasteSpecial xlValues
.PasteSpecial xlFormats
End With
'n.b. - i would personally avoid copying all the cells in a worksheet
'instead copying the usedrange or some defined range
I would like to slightly rewrite Scott Holtzman answer:
Dim ws1 as Worksheet, ws2 as Worksheet
Set ws1 = ActiveSheet
'here you add a sheet and directly assign it to a variable
Set ws2 = Worksheets.Add.Name = ws1.Name & "_Daily_RCCP"
ws1.Cells.Copy
With ws2.Cells
.PasteSpecial xlValues
.PasteSpecial xlFormats
End With
Also take notice that each sheet has 2 names: the tab name the user sees (.Name), and the other name you can only see from VBE (.CodeName).
Actually, if you put some code behind Sheet1 (CodeName), you can also refer to it using Me (current class object), exactly like you can use ThisWorkbook to designate the workbook containing the code.
You could therefore rewrite the above this way:
Dim ws2 as Worksheet
'here you add a sheet and directly assign it to a variable
Set ws2 = Worksheets.Add.Name = Sheet1.Name & "_Daily_RCCP"
'No need for an extra variable ws1 since we use the CodeName
sheet1.Cells.Copy
With ws2.Cells
.PasteSpecial xlValues
.PasteSpecial xlFormats
End With
or if the code is behind Sheet1:
Dim ws2 As Worksheet
Set ws2 = Worksheets.Add
ws2.Name = Me.Name & "_Daily_RCCP"
'No need for an extra variable ws1 since we use Me
Me.Cells.Copy
ws2.PasteSpecial xlPasteValuesAndNumberFormats

VBA Select & Copy ignores first row

I have a code I could use some help on. This script I wrote is meant to copy a range from the first row to the last row to another sheet. It works perfectly if there are more than 2 rows containing data, but if there is only 1 row (the first row), it ignores that data, does not copy it, and outputs an error.
Is there anything you can identify that might fix this code? I've searched endlessly with no results. Thanks!
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Set ws1 = Worksheets("HCA")
Set ws2 = Worksheets("FormA")
Set ws3 = Worksheets("NamedRange")
ws3.Range("T1:U1").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("FormA").Select
ws2.Range("AQ7").PasteSpecial
End(xlDown) will have undesirable effects when there is only one row being used. It's much more reliable to use xlUp from the bottom of your worksheet instead
Sub test()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Set ws1 = Worksheets("HCA")
Set ws2 = Worksheets("FormA")
Set ws3 = Worksheets("NamedRange")
With ws3
.Range(.Range("T1"), .Cells(.Rows.Count, "U").End(xlUp)).Copy
End With
ws2.Range("AQ7").PasteSpecial
End Sub
Replace,
ws3.Range("T1:U1").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
... with,
with ws3
.Range(.cells(1, "T"), .cells(.rows.count, "U").end(xlup)).copy
end with
When looking for the last non-blank cell, look from the bottom up; not from the top down.

How to select and copy first and last rows of excel in vba?

I want to select and copy the first 3 rows and the last row in an Excel worksheet but in my code below the line Selection.Copy gives an error.
Sub SaveLastLine()
Dim WB As Workbook, filename As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Range("B1").Select
Selection.End(xlDown).Select
Union(Range("1:3"), Range(Selection, Selection.End(xlToRight))).Select
Selection.Copy
Workbooks.Add
ActiveSheet.Paste
End Sub
Please anyone can help me.
Working with selected ranges is probably your problem. Kellsens has given you a solution that works around this by first copying the first three rows, then copying the last row to the new worksheet.
If you want to do this all in one shot, you can first define the range, then copy the content of that range to the new workbook. Something like this:
Sub SaveLastLine()
Dim WB As Workbook
Dim myRange As Range
'copy the content
Set myRange = Union(Range(Range("B1:B3"), Range("B1:B3").End(xlToRight)), _
Range(Range("B1").End(xlDown), Range("B1").End(xlDown).End(xlToRight)))
myRange.Copy
'paste the content
Set WB = Workbooks.Add
WB.ActiveSheet.Range("A1").PasteSpecial
End Sub
When you create your new workbook, there's no activesheet to paste, that's the error cause. You could instantiate your new workbook to the declared variable Wb.
Considering that your data starts in "B1" and considering that your new worksheet will have 4 rows, I made some modifications to your code:
Sub SaveLastLine()
Dim wb As Workbook
Dim ws As Worksheet
Dim filename As String
Dim lastCol As Integer
Dim lastRow As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set ws = ActiveSheet ' Here I instantiate the active worksheet
Set wb = Workbooks.Add ' Here I instantiate the new workbook
lastCol = ws.Range("B1").End(xlToRight).Column
lastRow = ws.Range("B1").End(xlDown).Row
ws.Range(ws.Cells(1, 2), ws.Cells(3, lastCol)).Copy wb.Worksheets(1).Range("B1") ' Here I copy the first 3 rows and paste in the first worksheet of your new workbook
ws.Range(ws.Cells(lastRow, 2), ws.Cells(lastRow, lastCol)).Copy wb.Worksheets(1).Range("B4") ' Here I copy the last row and paste
filename = "yourfilename.xlsx"
wb.SaveAs filename
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Excel how to Copy and insert the first row into all other sheets without overwriting data

As the title I tried this one, but it overwrites existing data, I am looking for something that
add the header row in all sheets moving the data down. I have got 50 sheets that's why I am asking :-)
Sub CopyToAllSheets()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("sheet1")
Sheets.FillAcrossSheets ws.Range("1:1")
End Sub
Thank you in advance
You could insert a line in each sheet before filling the headers:
Sub CopyToAllSheets()
Dim sheet As Worksheet
For Each sheet In Sheets
sheet.Rows("1:1").Insert Shift:=xlDown
Next sheet
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("sheet1")
Sheets.FillAcrossSheets ws.Range("1:1")
End Sub
I will be assuming that your header will be coming from another sheet. Recording a macro gives me:
Sub Macro4()
Sheets("Sheet1").Select
Rows("1:1").Select
Selection.Copy
Sheets("Sheet2").Select
Rows("1:1").Select
Selection.Insert Shift:=xlDown
Application.CutCopyMode = False
End Sub
Cleaning it up gives:
Sub InsertOnTop()
Sheets("Sheet1").Rows("1:1").Copy
Sheets("Sheet2").Rows("1:1").Insert Shift:=xlDown
Application.CutCopyMode = False
End Sub
Applying it safely across all sheets except the source sheet:
Sub InsertOnTopOfEachSheet()
Dim WS As Worksheet, Source As Worksheet
Set Source = ThisWorkbook.Sheets("Sheet1") 'Modify to suit.
Application.ScreenUpdating = False
For Each WS In ThisWorkbook.Worksheets
If WS.Name <> Source.Name Then
Source.Rows("1:1").Copy
WS.Rows("1:1").Insert Shift:=xlDown
End If
Next WS
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Let us know if this helps.
I believe you will need to loop through each sheet and insert a blank row, or just use the range.insert method on each sheet. Perhaps something like:
Option Explicit
Sub CopyToAllSheets()
Dim WS As Worksheet
For Each WS In ThisWorkbook.Worksheets
If Not WS.Name = "Sheet1" Then
If WorksheetFunction.CountA(WS.Rows(1)) > 0 Then _
WS.Rows(1).Insert
End If
Next WS
Worksheets.FillAcrossSheets Worksheets("Sheet1").Rows(1), xlFillWithAll
End Sub

copy paste data from a different workbook to current worksheet

I am basically stuck. I have a code which allows me to browse a file, once the file is selected it copies all the data in that file and then allows me to select a worksheet, from any workbook that is open at that time. Once the worksheet is selected [this is where i get stuck] i want it to paste it into j7. instead it doesn't do that, baring in mind i will be changing the file name everyday as it has the current days date on it.
here is my code:
Sub Macro4()
'
' Macro4 Macro
'
'
Range("A1").Select
Dim fileStr As String
fileStr = Application.GetOpenFilename()
If fileStr = "False" Then Exit Sub
Workbooks.Open fileStr
Range("A2").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Window.Sheets(Array("Forecast_workings")).Select{**this is where i want to be able to select a worksheet from any open workbook and it will paste the data in cell J7 of that worksheet.**
Range("J7").Select
Application.CutCopyMode = False
Range("C16:C27").Select
Selection.Copy
Range("E16").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Range("G16:G27").Select
Selection.Copy
Range("C16").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Range("O16").Select
End Sub
I can see lot of errors in your code.
First things first. You avoid the use of .Select. INTERESTING READ
If I understand you correctly then to get the name of the sheet which user selects at runtime, you can use Application.InputBox with Type:=8. This will return a range and from that you can use .Parent.Name to get the name of the worksheet.
Is this what you are trying?
Your code can be written as (UNTESTED)
Sub Macro4()
Dim fileStr As String
Dim wb As Workbook, thiswb As Workbook
Dim ws As Worksheet, thisws As Worksheet
Dim Lcol As Long, LRow As Long
Dim Ret As Range
'~~> Set an object for thisworkbook and worksheet
Set thiswb = ThisWorkbook
'~~> Change this to the sheet from where you want to copy
Set thisws = thiswb.Sheets("Sheet1")
'~~> Let user choose a file
fileStr = Application.GetOpenFilename()
If fileStr = "False" Then Exit Sub
'~~> Set an object for workbook opened and it's worksheet
Set wb = Workbooks.Open(fileStr)
On Error Resume Next
Set Ret = Application.InputBox("Select a cell from the sheet you want to choose", Type:=8)
On Error GoTo 0
If Ret Is Nothing Then Exit Sub
Set ws = wb.Sheets(Ret.Parent.Name)
With thisws
'~~> Find Last column in row 2
Lcol = .Cells(2, .Columns.Count).End(xlToLeft).Column
'~~> Find last cell in Col 1
LRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Copy your range directly to new worksheet selected
.Range(.Cells(2, 1), .Cells(LRow, Lcol)).Copy ws.Range("J7")
.Range("C16:C27").Copy ws.Range("E16")
.Range("G16:G27").Copy ws.Range("C16")
Application.CutCopyMode = False
End With
End Sub
when working with multiple workbooks, dont use range() but wb.range(), where wb is defined with the set function.
Also activesheet can be tricky. Preferably name the sheet you are using sheets("whatever").
And for last, to copy things dont use activate/select, just do as this:
wb.sheets("whatever").range() thisworkbook.sheets("watever2").range("").
I also saw you dont use application.enableevents=false/true, so events will trigger like crazy and your activesheet (or cell) will change like crazy if you have code in worksheet_change section.