I have a workbook with about 14 worksheets. A selected set of worksheets contains the data which will be updated. They need to stay separated for the users.
To summarize this data to produce a report, I need to combine all the data sheets (all in the same format) into one for the final summary calculation (so the =AVERAGEIFSfunction could work and some other manually calculated averaging formulae would be more accurate).
I'm thinking of tackling the problem with either of two approaches:
Have the combined datasheet reference each cell on the data sheet individually. My formula is =Sheet1!A1.
The issue is that if any of the rows on the original datasheet gets deleted, it will cause calculation errors on the combined datasheet.
I saw a recommendation of =INDIRECT("Sheet!A1"), but this will not fill correctly across and down the worksheet, meaning I would have to update about 40K cells individually.
A macro or a set of formulae that will pick up data automatically (I'd prefer not to have a running command for the macro).
The design of the macro/formula is to pick up each row from selected worksheets, discontinue once it hits the first blank row and move onto the next selected worksheet, like a loop.
Any other suggestions on how to achieve this would also be highly welcome.
Sub combineDatasheets()
Dim sh As Worksheet
For Each sh In Sheets
If sh.Name <> "Combined datasheet" Then
a = sh.Cells(1, 1).End(xlDown).Row 'count rows untill blank
b = Sheets("Combined datasheet").Cells(1, 1).End(xlDown).Row 'last row with data
'find if there's any data already in "Combined datasheet" by looking at cell A1
If Sheets("Combined datasheet").Cells(1, 1).Value = "" Then
b = 0
End If
sh.Rows("1:" & a).Copy Destination:=Sheets("Combined datasheet").Range("A" & b + 1)
End If
Next sh
End Sub
This will get you all the rows with data until the first blank row from each worksheet (ignoring the one where you are consolidating the data, of course) and paste them in the "Combined datasheet" contiguously.
Change the name of the "Combined datasheet" worksheet if necessary.
Note: if the first row is blank, no data will be retrieved from that worksheet.
Hope this helps!
EDIT:
Ok so, if I understood correctly, you want to refresh the data in your consolidated sheet every time a value changes in any other datasheet.
So for that use the following code in every worksheet that you want to retrieve data from (the 7 worksheets you mentioned, I guess):
Private Sub Worksheet_Change(ByVal Target As Range)
Call combineDatasheets
End Sub
Now the following code goes to a module (VBA->Insert->Module):
Sub combineDatasheets()
Dim sh As Worksheet
'Clear data in "Combined datasheet"
c = Sheets("Combined datasheet").Cells(1, 1).End(xlDown).Row
Sheets("Combined datasheet").Range("A1:A" & c).EntireRow.ClearContents
For Each sh In Sheets
If sh.Name <> "Combined datasheet" Then
a = sh.Cells(1, 1).End(xlDown).Row 'count rows untill blank
'fix error when there's only 1 row with data
If sh.Cells(2, 1).Value = "" Then
a = 1
End If
b = Sheets("Combined datasheet").Cells(1, 1).End(xlDown).Row 'last row with data
'find if there's any data already in "Combined datasheet" by looking at cell A1
If Sheets("Combined datasheet").Cells(1, 1).Value = "" Then
b = 0
Else
'fix error when "Combined datasheet" worksheet has only one row with data
If Sheets("Combined datasheet").Cells(2, 1).Value = "" Then
b = 1
End If
End If
sh.Rows("1:" & a).Copy Destination:=Sheets("Combined datasheet").Range("A" & b + 1)
End If
Next sh
End Sub
Regarding the error you're getting, I think it's because you haven't changed the name of the worksheet that consolidates the information. You need to either change the name to "Combined datasheet" (without quotation marks) so it can work with the code I've written, or you go directly to the code and change the name in there to one of your own choice (every time you see "Combine datasheet" change to the name you want inside the quotation marks).
I hope this will work correctly this time to you :)
Related
I am aware that there are many questions like this one in this forum. Yet, none of them gives satisfying reply.
I need a macro that will copy values from 3 cells from various sheets (all in the same Excel file): E6 (actually it is a merged cell containing columns EFG), E(FG)5 and E21. Then pastes those values into new sheet into columns A, B and C. There are 2 problems that do not let me solve this issue with traditional copy cell value code or answers in other threads in this forum:
There are 3 cells merged.
The number of worksheets might differ for different period of times, and they might change their names as well.
This is the code that I have found for another similar problem:
Sub CopyToMaster()
ShtCount = ActiveWorkbook.Sheets.Count
For i = 2 To ShtCount
Worksheets(i).Activate
Range("E6").Select
Selection.Copy
Sheets("Master").Activate
'Required after first paste to shift active cell down one
Do While Not IsEmpty(ActiveCell)
ActiveCell.Offset(1, 0).Select
Loop
ActiveCell.Offset(0, -3).Select
Selection.PasteSpecial
Next i
End Sub
Source Data (This is source data, I where I marked with yellow 3 cells that values, I need to copy):
Needed result (Here is the expected outcome, where each from previous yellow marked cells should be pasted in respective column):
Thx for your help.
Please, test the next (working) code. It should be faster than yours, not using clipboard. You must know that the value of a merged range is kept in its top left cell. So, having ranges with a single row, it is enough to try extracting the value of the first marge cells cell:
Sub CopyToMasterWorking()
Dim ws As Worksheet, wsM As Worksheet, lastR As Long, i As Long
Set wsM = Worksheets("Master")
wsM.UsedRange.Resize(wsM.UsedRange.rows.count - 1).Offset(1).ClearContents 'clear everything, except headers
For Each ws In ActiveWorkbook.Worksheets
If ws.name <> wsM.name Then
lastR = wsM.UsedRange.SpecialCells(xlCellTypeLastCell).row + 1
wsM.Range("A" & lastR).Value = ws.Range("E6").Value
wsM.Range("B" & lastR).Value = ws.Range("E5").Value
wsM.Range("C" & lastR).Value = ws.Range("E21").Value
wsM.Range("D" & lastR).Value = ws.name 'you may comment this line if not necessary...
End If
Next ws
End Sub
I thought that it would be good to have a little traceability, I mean to know from which sheet the data comes (per row). If you do not need it, you may comment last code line from iteration between sheets.
The code also clear everything in "Master" sheet, except the header, before starting processing. If you need to add at the end of existing data, you have to comment that line, too.
Please, send some feedback after testing it. If something not clear enough, do not hesitate to ask for clarification...
I think your only problem is copying merged-cell ranges, correct? This shows how to copy a merged-cell range to 1) same-sized range 2) single cell 3) different-sized range:
Option Explicit
Sub sub1()
Dim variant1
Cells.Delete
' define a merged-cell range and populate:
Range("b2:c3").MergeCells = True
Range("b2:c3") = " B2:C3 "
' to copy to a like-sized merged-cell range:
Range("b5:c6").MergeCells = True
Range("b2:c3").Copy Range("b5:c6")
' to copy to a single cell
variant1 = Range("b2:c3").Value
Range("b8").Value = variant1
' to copy to a different-sized merged-cell range:
Range("b10:d12").MergeCells = True
variant1 = Range("b2:c3").Value
Range("b10:d12").Value = variant1
End Sub
I have a table with 15 columns. I'm trying to copy and paste 3 of the columns into another sheet and then duplicate that info below itself in the destination sheet a specified number of times based on the number layers in the test I'm conducting. I'm having trouble with the code finding the bottom row of the copied data and I haven't found code that will eliminate the gaps in the data.
this is my first post so I cant add pictures yet.
here's my current code for the button that is supposed to populate the destination sheet:
Private Sub PRTButton_Click()
CopyInfo
PasteInfo
End Sub
Sub CopyInfo()
Dim aLastRow As Long
aLastRow = Sheets("Test Ammo").Cells(Rows.Count, 1).End(xlUp).Row
'ammo description
Sheets("PRT Endurance").Range("B6:B" & aLastRow - 1).Value = Sheets("Test Ammo").Range("O64:O113" & aLastRow).Value
'Ammo Spec
Sheets("PRT Endurance").Range("C6:C" & aLastRow - 1).Value = Sheets("Test Ammo").Range("C64:c113" & aLastRow).Value
'QTY Shot
Sheets("PRT Endurance").Range("D6:D" & aLastRow - 1).Value = Sheets("Test Ammo").Range("N64:N113" & aLastRow).Value
End Sub
Sub PasteInfo()
Dim LRow As Long
With ActiveSheet
LRow = .Cells(.Rows.Count, "B").End(xlUp).Row
End With
Range("B6:D" & LRow).Copy
MsgBox "Info is already in clipboard. Select your layers from the dropdown and paste at the bottom of the copied info for each layer."
End Sub
I know i haven't told the code to only copy the values with a number in the M column and paste them into the destination sheet. for reference, I only want to copy the rows that have a value in the M column in my origin sheet. I'm not sure how to tell the code to select the 3 row dynamic range in the destination sheet and paste it a certain amount of times below it.
If I missed any explanations or there's any confusion, let me know and I'll try to clarify.
Origin table
Table after pressing "Populate ammo info"
I have an excel spread sheet set up for my partner's home business where she can input data relating to people joining the business. I am looking to have the data from that row cut and paste to a separate sheet depending on the criteria in one of the cells. The main sheet is called "Workspace".
If the person on row 6 has agreed to join the business then a "Yes" would be placed in cell V6. Once the Yes has been input I am aiming for the columns A:G to be cut and paste onto the sheet "Joined" as well as the rest of that row being deleted and preferably the rows underneath moving up one (if that is possible). The data would be pasted onto the next blank row on the "Joined" sheet.
On the flip side, if the person on row 6 states they are uninterested then a "Not Interested" would be placed in cell H6. Once the not interested has been input I am aiming for the columns A:G to be cut and paste onto the sheet "Not Interested" as well as the rest of that row being deleted, like above.
Is it also possible to have the spread sheet sort names alphabetically each time a new name is added? The starting row for data is 6.
I hope this all makes sense and really hope someone is able to assist. I am quite good when it comes to formulas but not got a clue where to start with regards to macros.
This is my code so far:
Sub Test()
For Each Cell In Sheets("Workspace").Range("V:V")
If Cell.Value = "Yes" Then
matchRow = Cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Joined").Select
ActiveSheet.Rows(matchRow).Select
ActiveSheet.Paste
Sheets("Workspace").Select
End If
Next
End Sub
Here is a good starting point for you. I added comments to the code so you can see what every line does.
This sub searches for "yes" in column V and copies Range A:G of the columns with "yes" into sheet Joined. Then it deletes the entire row where the "yes" was found.
I think from here you can do the second part for "Not Accepted" on your own.
Sub Test()
Dim MatchRow As Long, FirstRow As Long, LastRow As Long
Dim Destination As Range
Dim ws As Worksheet
Set ws = Sheets("Workspace") 'define ws as sheet workspace (shortcut)
FirstRow = 6 'First row with data below headline
LastRow = ws.Cells(ws.Rows.Count, "V").End(xlUp).Row 'Get last used row in column V (so we don't need to go through the full column)
Dim i As Long
i = FirstRow
Do While i <= LastRow 'start searching for "Yes" in FirstRow and end in LastRow
If ws.Range("V" & i).Value = "Yes" Then
MatchRow = ws.Range("V" & i).Row 'remember matched row number
'find last free row in column A of sheet Joined and remember in Destination
With Sheets("Joined")
Set Destination = .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0)
End With
'Copy range A:G from matched row to destination found above
ws.Range("A" & MatchRow & ":G" & MatchRow).Copy Destination
'Delete copied entire row
ws.Rows(MatchRow).EntireRow.Delete
'reduce LastRow by one (because we deleted one row)
LastRow = LastRow - 1
Else
'go to next row
i = i + 1
End If
Loop
End Sub
I have 2 main sheets ( "kids" and "parents") and another 3 sheets that I use for data input. What I want the code to do is to copy the values of the 3 sheets from column A TO L and transfer them to the main sheets depending on the value chosen in column D. So if I insert data to one of the 3 sheets and I have as a value in column D "kids" it should transfer it to SHEET "KIDS" if I choose value "parents" the data should go to sheet "parents". In any case, I do want it to remove duplicates and not copy the same data each time I open the file.
Private Sub Workbook_Open()
Dim i As Long, lastRow As Long, ws As Worksheet
Sheets("Kids").Range("A3:L500").ClearContents
For Each ws In Worksheets
If ws.Name <> ("Kids") Then
ws.Activate
lastRow = ws.Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To lastRow
If ws.Cells(i, "D").Value = "Kids" Then
Rows(i).Copy Destination:=Sheets("Kids").Range("A" & Rows.Count).End(xlUp).Offset(1)
ElseIf ws.Cells(i, "D").Value = "Parents" Then
Rows(i).Copy Destination:=Sheets("Parents").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next i
End If
Next ws
End Sub
So this is the code I have used but it doesn't remove duplicates for main sheet "parents". Something is wrong...
Your question is not conveying total situation of your problem as mentioned by #Nicolas. However to help you with your problem go to the code posted by #fbonetti in the following thread to remove duplicates.
[delete-all-duplicate-rows-excel-vba:]Delete all duplicate rows Excel vba
Further to transfer Copy Data to Another Excel WorkBook Based on Criteria Using VBA to do is the following:
1. Identify data in a workbook sheet based on a text criterium and a date criterium or condition using a looping process
2. Select the specific data which meets the two or multiple conditions
3. Copy the identified data
4. Open another workbook
5. Find the first blank row in a specific worksheet in the workbook
6. Paste the data in the identified blank or empty row – erow
7. Save the workbook
8. Close the workbook
Go through the link mentioned below.
http://www.exceltrainingvideos.com/copy-data-to-another-excel-workbook-based-on-criteria-using-vba/
HTH
Re: Creating a master sheet from multiple sheets.
Multiple sheet description: table with many rows and columns. Columns headings are identical but rows vary. Each sheet is a date.
Task: to take a single value from a specific column (always happens to be column M). the value I want is the total of that column. Take this summed value and insert into a master sheet.
My attempt so far is:
Sub append_master_sheet()
Dim wAppend As Worksheet, wSheet As Worksheet
Dim LastRow As Long
Set wAppend = Worksheets("Master")
For Each wSheet In Worksheets
If wSheet.Name <> wAppend.Name Then
LastRow = WorksheetFunction.Max(3, wAppend.Cells(65536, 2).End(xlUp).Row)
wSheet.UsedRange.Resize(, 13).Copy Destination:=wAppend.Cells(LastRow, 2)
End If
Next wSheet
End Sub
1). it takes all 13 columns rather than only the 13th column. (I see that is because I have set it at 13 as I do not know how to cycle through the preceding columns and skip them to only return the 13th column data (and within this column return the total of the column, not the discrete line items
2) Besides returning all the data which is a problem, it actually consistently skips the final value in the column M.
Can you advise how to amend above code to
1) only return the summed value from column M in the multiple sheets (calendar dates) and insert into master.
thanks,
N
Is this what you are trying (UNTESTED)
Like I mentioned in the comment above, see THIS link on how to find a last row in a column.
I have commented the code so that you will not have a problem understanding it. But if you do, simply post back :)
Note: I am assuming that the last cell in Col M has the SUM
Option Explicit
Sub append_master_sheet()
Dim wAppend As Worksheet, wSheet As Worksheet
Dim wApLRow As Long, wShLRow As Long
Set wAppend = ThisWorkbook.Worksheets("Master")
'~~> Get the last row where the ouput should be placed
wApLRow = wAppend.Range("B" & wAppend.Rows.Count).End(xlUp).Row + 1
For Each wSheet In Worksheets
If wSheet.Name <> wAppend.Name Then
With wSheet
'~~> Fuind the last row in Col M which has the sum
wShLRow = .Range("M" & .Rows.Count).End(xlUp).Row
'~~> Copy over the values to Master Sheet
wAppend.Range("B" & wApLRow).Value = .Range("M" & wShLRow).Value
'~~> Increment the row for next output
wApLRow = wApLRow + 1
End With
End If
Next wSheet
End Sub