This is the code which I used to copy data from multiple sheets to single sheet.
I want to know if there is any way by which I can copy the data into "Report" sheet starting from 3rd Column, i.e, the data should be pasted into sheet from 3rd column onwards.
Sub AppendDataAfterLastColumn()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Variant
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
' Delete the summary worksheet if it exists.
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("Report").Delete
On Error GoTo 0
Application.DisplayAlerts = True
' Add a worksheet with the name "Report"
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "Report"
' Loop through all worksheets and copy the data to the
' summary worksheet.
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name Then
lastcol = DestSh.Cells(1, DestSh.Columns.Count).End(xlToLeft).Column
' Find the last column with data on the summary
' worksheet.
Last = lastcol
lastCol3 = sh.Cells(1, sh.Columns.Count).End(xlToLeft).Column
' Fill in the columns that you want to copy.
Set CopyRng = sh.Range(sh.Cells(1, 2), sh.Cells(15, lastCol3))
' Test to see whether there enough rows in the summary
' worksheet to copy all the data.
If Last + CopyRng.Columns.Count > DestSh.Columns.Count Then
MsgBox "There are not enough columns in " & _
"the summary worksheet."
GoTo ExitTheSub
End If
' This statement copies values, formats, and the column width.
CopyRng.Copy
With DestSh.Cells(1, Last + 1)
.PasteSpecial 8 ' Column width
.PasteSpecial xlPasteValues
'.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Data sheet 1 from comments:
Data sheet 2 from comments:
Expected output from comments:
This sort of copy can be done easily with Copy. In order to pick the output Range for the paste part, you can use an Application.InputBox with a Type:=8 parameter. This prompts Excel to open the Range selection dialog which works well.
Once you know those two pieces, the only difficulty is building the Ranges. This is not difficult, but is specific to the context, existing data on the sheets, and degree of robustness. For the example below, I am using CurrentRegion to get the block of data (same as hitting CTRL+A) and then Intersect to only get the desired columns. You can also make use of UsedRange and End to build ranges.
Picture of ranges shows the different sheets for input and the final sheet for output. The sheet to paste into c is empty for now.
Code does the work to get the two ranges to copy and then prompts for an output location. From there, it pastes the resulting Ranges into the desired location. There is an Offset to ensure that the 2nd range does not overlap the first.
Sub CopyFromTwoRanges()
Dim rng_set1 As Range
Dim rng_set2 As Range
Dim rng_output As Range
'build the ranges
Set rng_set1 = Intersect(Sheets("a").Range("C:F"), _
Sheets("a").Range("C1").CurrentRegion)
Set rng_set2 = Intersect(Sheets("b").Range("C:F"), _
Sheets("b").Range("C1").CurrentRegion)
'prompt for cell
Set rng_output = Application.InputBox("Pick the range", Type:=8)
'ensure a single cell only
Set rng_output = rng_output.Cells(1, 1)
'paste the ranges
rng_set1.Copy rng_output
rng_set2.Copy rng_output.Offset(, rng_set1.Columns.Count)
End Sub
Result shows the prompt with cell selected and then the output.
Related
I fairly new to VBA, using it to work on simple macros to automatize my time.
I am looking for an Excel macro which copies specific cells, on different regions of a series of worksheets from the same template(see the image, I want to copy the, yellow, gray and green cells). All sheets work on the same workbook. The main quest is: Put it all together, as values, sequentially on one sheet, with just the same headers and put a total sum in the end of this columns. If it's simpler to keep/use the template and sum the values in there, ok for me too. If I've created 20 new sheets, the macro will read the already existed and the new sheets and consolidate it in the sheet "consolidated".
I've found a code that do almost everything I need, but I'm struggling to change de range on to copy regions I want.
Like I said, using the template (create a copy from the master template and summing the values in there?) or simply combining the value side by side, so every row represent a sheet, for me ok too.
Please, any help is welcomed, thanks in advance.
The code I used follows below [source].
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the sheet "Consolidado" if it exist
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("Consolidado").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'Add a worksheet with the name "Consolidado"
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "Consolidado"
'loop through all worksheets and copy the data to the DestSh
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name And sh.Name <> "Menu" And sh.Name <> "Infos" And sh.Name <> "Log Update" And sh.Name <> "Master" Then
'Find the last row with data on the DestSh
Last = LastRow(DestSh)
'Fill in the range that you want to copy
Set CopyRng = sh.Range("A1").CurrentRegion
'Test if there enough rows in the DestSh to copy all the data
If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
MsgBox "There are not enough rows in the Destsh"
GoTo ExitTheSub
End If
'This example copies values/formats, if you only want to copy the
'values or want to copy everything look at the example below this macro
CopyRng.Copy
With DestSh.Cells(Last + 1, "A")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
'AutoFit the column width in the DestSh sheet
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
The Excel Template
EDIT:
The results can be one of the 2 below, which is easier to do.
Result sheet option 1
Result sheet option 2
EDIT 2
Clean workbook
After the clarification in the comments I would do as follows:
For simplicity lets take the following Template:
So you want Cell A2 in Sheet Consolidado to be the sum of Cell A2 of all the other sheets, and for the other cells respectivelly.
I propose the following: You create a sheet Consolidado from the template. You then fill the valueCells array with the list of cells you want to be summed up in the Consolidadosheet.
The code below then will go through the targeted sheets, and add the value from each cell in the array to an outputArray. After the targeted sheets are summed up, it is pasted to the Consolidado sheet
Sub CopyRangeFromMultiWorksheets()
Dim wb As Workbook
Dim sh As Worksheet
Dim DestSh As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set wb = ThisWorkbook
Set DestSh = wb.Sheets("Consolidado")
valueCells = Array("A2", "C2", "A4", "B4", "C4")
Dim outputArray As Double
ReDim outputArray(UBound(valueCells))
For Each sh In wb.Worksheets
If sh.Name <> DestSh.Name And sh.Name <> "Menu" And sh.Name <> "Infos" And sh.Name <> "Log Update" And sh.Name <> "Master" Then
For i = LBound(valueCells) To UBound(valueCells)
outputArray(i) = outputArray(i) + sh.Range(valueCells(i))
Next i
End If
Next sh
For i = LBound(valueCells) To UBound(valueCells)
DestSh.Range(valueCells(i)) = outputArray(i)
Next i
End Sub
I have a VBA related question which has to do with extending formulas based on the data inserted to another sheet but with some implications. More specifically, I would like formulas in sheet "Calculation" to extend from cells A3:AB3 based on the number of rows populated in column A in the sheet "Responses". Then delete the content of cells from this point below (this is to dynamically adjust populated formulas in sheet "Calculation" in case less rows are populated in sheet "Responses" compared to the last time). The tricky part is that sheet "Responses" could be either empty (so we don't want an endless loop); populated with data through copy paste, or the user can delete it completely and insert a new tab with the same name downloaded from a database (I avoid an error in my formulas using INDIRECT).
Finally because sheet "Calculation" is always hidden, and as mentioned sheet "Responses" might be deleted and re-inserted don't think the code could run by targeting changes in sheet "Responses". What could work is inserting a button into a sheet called "Output" or run the code every time this sheet ("Output") is active (so maybe save the code there).
What I have is very simple and doesn't do what I need at all. I can't get it to read from another sheet only from column AD within the same sheet.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("AD:AD")) Is Nothing Then
Application.EnableEvents = False
lastrow = Range("AD3000").End(xlUp).Row
Range("A3:AB3").AutoFill Destination:=Range("A3:AB" & lastrow), Type:=xlFillDefault
Application.EnableEvents = True
End If
End Sub
Thank you!!
In case your sheet will be deleted, you can use Workbook_SheetChange event, inside ThisWorkbook module, and check if sh.Name = "Responses" to apply the code's logic.
Code (inside ThisWorkbook module)
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim LastRow As Long
Dim CalcSht As Worksheet
' set Worksheet object
Set CalcSht = ThisWorkbook.Sheets("Calculations")
With Sh
If .Name = "Responses" Then ' check if changes were made in a worksheet named "Responses"
Application.EnableEvents = False
' --- First: clear formulas form all cells (below row 3) ---
LastRow = CalcSht.Cells(CalcSht.Rows.Count, "A").End(xlUp).Row ' get the last row in column A
If LastRow < 4 Then LastRow = 4
CalcSht.Range("A4:AB" & LastRow).ClearContents ' clear contents (formulas) from row 4 and below
' --- Second: populate formulas on all rows after row 3 (where there is data in column A) ---
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' get the last row in column A
If Not Intersect(Target, .Range("A1:A" & LastRow)) Is Nothing Then
Application.EnableEvents = False
' drag formulas until last row with data in column A (in "Responses" worksheet)
CalcSht.Range("A3:AB3").AutoFill Destination:=CalcSht.Range("A3:AB" & LastRow), Type:=xlFillDefault
End If
End If
End With
Application.EnableEvents = True
End Sub
Could someone please help with my code, I am not a million miles away from what I am looking to do but I have now come unstuck and reached a dead end. I have no programming experience & am no expert with VBA so what I have done might not make sense, or look silly; please bear with me as I am learning.
What I want to do is be able to:
Filter Column H in sheet “master” to select dates before a date
which I will input in Range “B9”.
Delete the filtered lines
Go to sheet “update”
Copy from A:18 dynamically to last column & last row
Paste everything in the last row in sheet “master”
Problem I have is that the filter for the date is not working
Sub AUTODATE()
Dim dDate As Date
Dim dbDate As Double
lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate) + 1)
Application.ScreenUpdating = False
Sheets("master").Select
If IsDate(Range("B9")) Then
dbDate = Range("B9")
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate)) + _
TimeSerial(Hour(dbDate), Minute(dbDate), Second(dbDate))
Range("H11").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.AutoFilter
Range("$11:$11").AutoFilter Field:=8, Criteria1:=">" & dbDate
Range("$12:12").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.SpecialCells _
(xlCellTypeVisible).EntireRow.Delete
Range("A11").Select
On Error Resume Next
ActiveSheet.ShowAllData
Sheets("update").Select
ActiveSheet.ShowAllData
Range("$18:$18").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("master").Select
Range("A" & lastRow).Select
Selection.PasteSpecial
End If
Application.ScreenUpdating = False
End Sub
The codes a bit messy near the bottom, and some thing's I'd normally push out to a separate function (find last cell for example).
Sub AutoDate()
Dim lastRow As Long
Dim lastUpdateRow As Long
Dim wrksht As Worksheet
Dim rFilterRange As Range
Set wrksht = ThisWorkbook.Worksheets("master")
'Any statement that starts with a '.' applies to wrksht (With... End With)
With wrksht
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
'The range to be filtered - currently columns A:J (columns 1 - 10)
Set rFilterRange = .Range(.Cells(11, 1), .Cells(lastRow, 10))
'Turn off the autofilter if it's already on.
If .AutoFilterMode Then
wrksht.AutoFilterMode = False
End If
'Apply filter to correct range.
rFilterRange.AutoFilter
If IsDate(.Range("B9")) Then
'Apply filter.
rFilterRange.AutoFilter Field:=8, Criteria1:=">" & .Range("B9")
If .FilterMode Then
'Resize to ignore header row & delete visible rows.
rFilterRange.Offset(1).Resize(rFilterRange.Rows.Count - 1) _
.SpecialCells(xlCellTypeVisible).EntireRow.Delete Shift:=xlUp
.ShowAllData
End If
'Find new last row.
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row + 1
Set rFilterRange = .Range(.Cells(11, 1), .Cells(lastRow, 10))
lastUpdateRow = ThisWorkbook.Worksheets("Update").Cells(Rows.Count, "A").End(xlUp).Row
rFilterRange.Offset(1).Resize(rFilterRange.Rows.Count - 1).Copy _
Destination:=ThisWorkbook.Worksheets("Update").Cells(lastUpdateRow, 1)
End If
End With
End Sub
Requirements:
Filter Column H in sheet master to select dates before a date located in same sheet at B9
Delete filtered lines
Copy from sheet update range A:18 dynamically to last column & last row
Paste range from previous point in the last row + 1 of sheet master
Assumptions: (in line with code posted):
Data range in sheet master starts at A11 and all cells in columns 8 of the data range have same NumberFormat
Data range in sheet update starts at A18
Data ranges in both sheets are continuous (i.e. no blank rows nor blank columns in between)
Copy of the data includes formulas & formats
Thy this code:
Option Explicit
Sub Rng_AutoFilter_Delete_And_Paste()
Dim WshMaster As Worksheet, WshUpdate As Worksheet
Dim rMaster As Range, rUpdate As Range
Dim dDate As Date
Dim rTmp As Range
Rem Application Settings - OFF
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
Rem Set Worksheet Object - End Procedure If any of them is not present
With ThisWorkbook
On Error GoTo ExitTkn
Set WshMaster = .Sheets("master")
Set WshUpdate = .Sheets("update")
On Error GoTo 0
End With
If IsDate(WshMaster.Range("B9")) Then
Rem Cleared Records in Wsh Master
With WshMaster
Rem Set Date to Filter By
dDate = .Range("B9")
Rem Set Data Ramge in Wsh Master
'Assumes range start at `A11` and it's continuous (i.e. no blank rows nor blank columns in between)
Set rMaster = .Range("A11").CurrentRegion
Rem Set AutoFilter
'Use the `AutoFilter` property instead of the `AutoFilterMode` property
If Not (.AutoFilter Is Nothing) Then .Cells(1).AutoFilter
rMaster.AutoFilter
End With
With rMaster
Rem Filter and Delete Records in Wsh Master
'Uses the `NumberFormat` to build the Filter Criteria
'Assumes all cells in has same `NumberFormat`
.AutoFilter Field:=8, Criteria1:=">" & Format(dDate, .Cells(2, 8).NumberFormat)
'Sets a Temp Range to grab the Filter results
On Error Resume Next
Set rTmp = .Offset(1).Resize(-1 + .Rows.Count).Columns(8).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
'If Temp Range is `Nothing` then there is `Nothing` to delete
If Not (rTmp Is Nothing) Then rTmp.EntireRow.Delete
.Worksheet.ShowAllData
End With
Rem Set Data Range in Wsh Update
With WshUpdate
Rem Set Data Range in Wsh Update
'Assumes range start at `A18` and it's continuous (i.e. no blank rows nor blank columns in between)
Set rUpdate = .Range("A18").CurrentRegion
Rem Set AutoFilter
If Not (.AutoFilter Is Nothing) Then .Cells(1).AutoFilter
rUpdate.AutoFilter
End With
Rem Paste Records from Wsh Update into Wsh Master
rUpdate.Copy
'In line with code posted this assumes OP wants to copy the data as it is (i.e. including formulas & format)
rMaster.Offset(rMaster.Rows.Count).Resize(1, 1).PasteSpecial
Application.CutCopyMode = False
Application.Goto WshMaster.Cells(1), 1
End If
ExitTkn:
Rem Application Settings - ON
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.EnableEvents = True
End Sub
Suggest to read the following pages to gain a deeper understanding of the resources used:
Excel Objects, On Error Statement, Range Object (Excel), Variables & Constants,
Worksheet.AutoFilter Property (Excel), Worksheet.AutoFilterMode Property (Excel),
Worksheet Object (Excel), With Statement
I have also done a review of your code see below (including only lines with comments):
'lastRow variable is not declared.
'Suggest to always have Option Explicit at the begining of the module
'To do it goto Main Menu \ Options \ Tab: Editor \ Check: Require Variable Declaration
lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1 'This is done too early as it will change after deletion of filtered rows
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate) + 1) 'Have no purpose as no value have been assigned to the variable as yet
Application.ScreenUpdating = False 'this should be done at the beginning
Sheets("master").Select 'should be qualified
dbDate = DateSerial(Year(dbDate), Month(dbDate), Day(dbDate)) + _
TimeSerial(Hour(dbDate), Minute(dbDate), Second(dbDate)) 'This line achieves nothing.
Range("H11").Select 'Select should be avoided, instead work with objects
Selection.AutoFilter 'Sould check first is the AutoFilter is ON
Range("$11:$11").AutoFilter Field:=8, Criteria1:=">" & dbDate 'Should filter the entire range
On Error Resume Next 'On error should be used for specific purposes and cleared after with On Error Goto 0
Selection.PasteSpecial 'After paste the Clipboard must be cleared with Application.CutCopyMode = False
I have an audit that is done daily. I have been asked to save the audit points to a separate sheet for review by the mgmt. team. The code is below but when I run it I get an error: Script out of range.
Sub copy1()
Dim sheet2 As Worksheet
Dim sheet10 As Worksheet
Set sheet2 = Worksheets("sheet2")
Set sheet10 = Worksheets("sheet10")
sheet2.Range("a2:g10").Copy
sheet10.Cells(Rows.count, 1).End(xlUp).Offset(1, 0).pastspecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
It's difficult to say for sure, but it is likely that you are receiving the "Subscript out of range" error because your workbook does not have the worksheets named "Sheet2" and "Sheet10".
The following code copies data from Sheet2 and pastes the values of the data to the next available row on Sheet10.
Sub Copy2()
Dim DestinationStartingCell As Range
Dim SheetRowCount As Long
Worksheets("Sheet2").Range("A2:I29").Copy
SheetRowCount = Worksheets("Sheet10").Rows.Count '1048576 for Excel 2007 and later
Set DestinationStartingCell = Worksheets("Sheet10") _
.Range("A" & SheetRowCount).End(xlUp).Offset(1, 0)
DestinationStartingCell.PasteSpecial xlPasteValues
End Sub
You could use this code
emptyrow=WorksheetFunction.CountA(Workbooks(<workbookname>).Sheets(10).Range("A:A"))+1
Workbooks(<workbookname>).Sheets(10).Cells(emptyrow,1).pastespecial xlPasteValues
to dynamically find the first empty row in Sheet10 to paste to.
Let me start by saying I know nothing of VB code in respect to actual programming, I'm trying to help out a friend with a workbook in Excel 2010. I did some Google searching and found what I thought might work for them, but it seems to not be grabbing everything and pasting it into the summary sheet like I want it to.
What I want is to take a set range of cells from each worksheet, copy it, and past it into a summary sheet, when it pasts the data I want it to past that range from sheet 2, move down a line past the same range from sheet 3, and so forth, instead of merging all that data into the same cells, like it seems to be doing now.
Here's the code I'm working with currently, when i use it it seams to only grab the last sheets data, and past it over the top of the previous sheets, instead of pasting then moving down, then pasting the next sheet of data.
Thanks for the help!
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
' Delete the summary sheet if it exists.
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("Summary Sheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
' Add a new summary worksheet.
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "Summary Sheet"
' Loop through all worksheets and copy the data to the
' summary worksheet.
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name Then
' Find the last row with data on the summary worksheet.
Last = 0
' Specify the range to place the data.
Set CopyRng = sh.UsedRange
' Test to see whether there are enough rows in the summary
' worksheet to copy all the data.
If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
MsgBox "There are not enough rows in the " & _
"summary worksheet to place the data."
GoTo ExitTheSub
End If
' This statement copies values and formats from each
' worksheet.
CopyRng.Copy
With DestSh.Cells(Last + 1, "A")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = True
End With
' Optional: This statement will copy the sheet
' name in the H column.
'DestSh.Cells(Last + 1, "H").Resize(CopyRng.Rows.Count).Value = sh.Name
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
' AutoFit the column width in the summary sheet.
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Your paste is reverting to row 1 on each pass due to
Last = 0
For the overlapping data, try the following change,
' Find the last row with data on the summary worksheet.
Last = DestSh.Rows.Count + 1