Copying specific ranges/cells on a standard template - vba

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

Related

Copy data from one work sheet usiing criteria to another worksheet without changing original worksheet

I've been working on a VBA macro to copy data that matches certain criteria from one worksheet to another worksheet without altering the original worksheet.
I'm locating the last row from worksheet "Prospects" and selecting the criteria that I need and it copies over to the other worksheet "Results", but both worksheets look identical.
So any rows that don't meet the filter criteria are removed from the original worksheet "Prospects".
I need the original worksheet to remain unaltered. I'm also just capturing certain columns, thus hiding the columns that I don't need on the "Results" worksheet.
Sub ProspectList()
Dim r As Range
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Range("A1").AutoFilter
LastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
LastCol = ActiveSheet.Cells(1, Columns.Count).End(xlUp).Column
With Sheets("Prospect List").Range([A2], [A2].SpecialCells(xlCellTypeLastCell))
ws.Range("A1").AutoFilter field:=13, Criteria1:="Pipeline"
[B:B].EntireColumn.Hidden = True
.Copy
[C:C].EntireColumn.Hidden = True
.Copy
[E:E].EntireColumn.Hidden = True
.Copy
[H:H].EntireColumn.Hidden = True
.Copy
[I:I].EntireColumn.Hidden = True
.Copy
[K:K].EntireColumn.Hidden = True
.Copy
[L:L].EntireColumn.Hidden = True
.Copy
[B:B].EntireColumn.Hidden = False
[C:C].EntireColumn.Hidden = False
[E:E].EntireColumn.Hidden = False
[H:H].EntireColumn.Hidden = False
[I:I].EntireColumn.Hidden = False
[K:K].EntireColumn.Hidden = False
[L:L].EntireColumn.Hidden = False
End With
With Sheets("Results")
If .Cells(Sheets(1).Rows.Count, 1).End(xlUp) = "" Then 'it's a clean sheet
.Cells(Sheets(1).Rows.Count, 1).End(xlUp).PasteSpecial Paste:=xlPasteValues
Else
.Cells(Sheets(1).Rows.Count, 1).End(xlUp).Offset(1).PasteSpecial Paste:=xlPasteValues
End If
End With
Application.CutCopyMode = False
End Sub
First: Your title is confusing; do you want to filter the data on worksheet "Prospects", copy the visible data, and move it to the "Results" worksheet?
Second: you "Dim r As Range" but you don't use it in your code.
Third: you Don't Dim "LastRow" and "LastCol" and don't even use them in your code.
Forth: Why are you filter "column A" then "filter Column M" before you hide the specific columns and u-nhide them?
Fifth: your "LastCol" code is wrong
Six: You hide and un-hide the columns for no apparent reason.
Seventh: your "With code" does not make any sense, you are testing "sheet1", not copying anything and then pasting on "sheet1" not the "Results" sheet. which worksheet is "Sheets(1)"?
I would suggest that you filter your data on the "Prospects" worksheet select the visible data using .SpecialCells(xlCellTypeV‌​isible).Copy then paste to the "Results" worksheet
This is what I ended up doing.
Sub ProspectList()
Dim ws As Worksheet
Dim LastRow As Long
Set ws = ActiveSheet
'Find last row and copy complete sheet to new sheet
LastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).row
Sheets("Prospects").Range("A1:M" & LastRow).Copy Destination:=Sheets("Results").Range("A1")
'set the new "Results" sheet to active
Worksheets("Results").Activate
'filter by criteria and hide columns not needed
With Sheets("Results")
ws.Range("A1").AutoFilter Field:=13, Criteria1:="Pipeline"
[B:B].EntireColumn.Hidden = True
[C:C].EntireColumn.Hidden = True
[E:E].EntireColumn.Hidden = True
[H:H].EntireColumn.Hidden = True
[I:I].EntireColumn.Hidden = True
[K:K].EntireColumn.Hidden = True
[L:L].EntireColumn.Hidden = True
[M:M].EntireColumn.Hidden = True
End With
Application.CutCopyMode = False
End Sub

Macro to copy first two columns from all sheets to a master sheet is skipping sheets

I'm using this macro to copy columns A and B from all of my sheets into a new sheet named Master. What I notice is that entire sheets worth of information are missing in the master sheet and I can't figure out why. The format for my sheets is column A has a string of characters that follow this structure: M2,004,005,004,007,17,096,01:07:45,45 and column B is just a date such as 4/19/2017.
I have hundreds of these sheets in my workbook and each has 224 rows that I need to copy into a single master sheet. Could anyone help me figure out how to get this code to stop skipping sheets?
Thanks.
Sub CreateMaster()
Dim J As Integer
On Error Resume Next
Sheets(1).Select
Worksheets.Add
Sheets(1).Name = "Master"
Sheets(2).Activate
Range("A1:B1").EntireRow.Select
Selection.Copy Destination:=Sheets(1).Range("A1:B1")
For J = 2 To Sheets.Count
Sheets(J).Activate
Range("A1:B1").Select
Selection.CurrentRegion.Select
Selection.Copy Destination:=Sheets(1).Range("A65536:B65536").End(xlUp)(2)
Next
End Sub
while searching for solutions online, I came across this macro that seems to do the same thing, but also seems to skip the exact same sheets as my macro does.
Sub CopyFromWorksheets()
Dim wrk As Workbook 'Workbook object - Always good to work with object
variables
Dim sht As Worksheet 'Object for handling worksheets in loop
Dim trg As Worksheet 'Master Worksheet
Dim rng As Range 'Range object
Dim colCount As Integer 'Column count in tables in the worksheets
Set wrk = ActiveWorkbook 'Working in active workbook
For Each sht In wrk.Worksheets
If sht.Name = "Master" Then
MsgBox "There is a worksheet called as 'Master'." & vbCrLf & _
"Please remove or rename this worksheet since 'Master' would be" & _
"the name of the result worksheet of this process.", vbOKOnly + vbExclamation, "Error"
Exit Sub
End If
Next sht
'We don't want screen updating
Application.ScreenUpdating = False
'Add new worksheet as the last worksheet
Set trg = wrk.Worksheets.Add(After:=wrk.Worksheets(wrk.Worksheets.Count))
'Rename the new worksheet
trg.Name = "Master"
'Get column headers from the first worksheet
'Column count first
Set sht = wrk.Worksheets(1)
colCount = sht.Cells(1, 255).End(xlToLeft).Column
'Now retrieve headers, no copy&paste needed
With trg.Cells(1, 1).Resize(1, colCount)
.Value = sht.Cells(1, 1).Resize(1, colCount).Value
'Set font as bold
.Font.Bold = True
End With
'We can start loop
For Each sht In wrk.Worksheets
'If worksheet in loop is the last one, stop execution (it is Master worksheet)
If sht.Index = wrk.Worksheets.Count Then
Exit For
End If
'Data range in worksheet - starts from second row as first rows are the header rows in all worksheets
Set rng = sht.Range(sht.Cells(2, 1), sht.Cells(65536, 1).End(xlUp).Resize(, colCount))
'Put data into the Master worksheet
trg.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
Next sht
'Fit the columns in Master worksheet
trg.Columns.AutoFit
'Screen updating should be activated
Application.ScreenUpdating = True
End Sub
as a workaround, since only the most recent data is immediately pertinent, I worked around it, but deleting the first 150 sheets. that still left around 100 sheets for my macro to work on, but now the missing pieces of data seem to be there. I wonder if there's something about the quantity of sheets that is causing this to malfunction?
Comments may not get it across correctly. Restructure your loop (and add the variables mentioned).
Dim x as Long
Dim thisSht as Worksheet
For x = 1 to wrk.Worksheets.Count
set thisSht = wrk.Worksheets(x)
'Data range in worksheet - starts from second row as first rows are the header rows in all worksheets
Set rng = thisSht.Range(sht.Cells(2, 1), sht.Cells(65536, 1).End(xlUp).Resize(, colCount))
'Put data into the Master worksheet
trg.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
Next x

Pasting data from multiple sheet at desired place

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.

How to copy multiple worksheets into a summary page but not merge the data.

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

Allow append of data to a summary sheet in another workbook

I have this code which appends data from three worksheets to a summary sheet, however on execution it is taking 12 of the 13 rows from sheet 1 and 2 and thirteen from sheet 3 to the summary I also would like this to work by sending to a summary sheet in a different workbook
Sub SummurizeSheets()
Dim ws As Worksheet
Application.ScreenUpdating = False
Sheets("Summary").Activate
For Each ws In Worksheets
If ws.Name <> "Summary" Then
ws.Range("D2:D6, D8:D15").Copy
Worksheets("Summary").Cells(Rows.Count, 4).End(xlUp).Offset(0, 0).PasteSpecial (xlPasteValues)
End If
Next ws
End Sub
Change Offset(0,0) to Offset(1,0). What's happening is not that it's copying 12 rows, but rather that the subsequent blocks are being pasted starting at the end of the previous block. That is, the first block is pasted into D1:D13, and the second block is pasted into D13:D26. By using Offset(1,0), the second block will be pasted starting with the first empty cell (that is, D14).
You can place the results in a new workbook simply by creating it in the code and referring to it in the paste, for example:
Option Explicit
Sub SummurizeSheets()
Dim ws As Worksheet
Dim currentWB As Workbook: Set currentWB = ActiveWorkbook
Dim newWB As Workbook: Set newWB = Application.Workbooks.Add
newWB.Worksheets(1).Name = "Summary"
For Each ws In currentWB.Worksheets
ws.Range("D2:D6, D8:D15").Copy
With newWB.Worksheets("Summary").Cells(Rows.Count, 4).End(xlUp)
If IsEmpty(.Value) Then
.PasteSpecial (xlPasteValues)
Else
.Offset(1, 0).PasteSpecial (xlPasteValues)
End If
End With
Next ws
End Sub
EDIT updated to paste into the first empty cell in column, even if that is row 1.