Replacing formulas in multiple sheets with the different values based on a different sheet VBA - excel

My current code creates 9 copies of a sheet called "MasterCalculator". It decides the amount of copies to be named by counting the number of cells filled in Row 1 (starting at column C) in the other sheet Called 'LLP Disc Sheet'. Each of the 9 sheets created are then named. Sheet 1's name comes from C1 in the 'LLP Disc Sheet', Sheet 2's name comes from D1 in the 'LLP Disc Sheet', Sheet 3's names comes from E1 in the 'LLP Disc Sheet', and so on.
Option Explicit
Public Sub NewSheets()
Dim shCol As Integer
Dim i As Integer
Dim ws As Worksheet
Dim sh As Worksheet
Set ws = Sheets("MasterCalculator")
Set sh = Sheets("LLP Disc Sheet")
Application.ScreenUpdating = 0
Application.EnableEvents = 0
shCol = 2
sh.Activate
For i = 2 To sh.Range("A1:Z1").Cells.SpecialCells(xlCellTypeConstants).Count
shCol = shCol + 1
Application.StatusBar = "Processing " & sh.Cells(1, shCol).Text & Format(i / sh.Range("A1:Z1").Cells.SpecialCells(xlCellTypeConstants).Count, " #0.0 %")
Select Case shCol
Case Is = 3
ws.Copy After:=sh
Case Else
ws.Copy After:=Sheets(sh.Cells(1, shCol - 1).Text)
End Select
ActiveSheet.Name = sh.Cells(1, shCol).Text
Application.CutCopyMode = False
Next i
sh.Activate
Application.StatusBar = 0
Application.EnableEvents = 1
Application.ScreenUpdating = 1
Application.CalculateFull
End Sub
So now that all the sheets are created and named... I now want to update the formulas in each since they're copies of the sheet called 'MasterCalculator'. There are 2 cells in each sheet I need to update - cell B1 and cell M4. Cell B1 contains the formula "=+'LLP Disc Sheet'!C1". The sheet that was created based on C1 in the 'LLP Disc Sheet' can keep this formula. However, the next sheet (sheet 2) that was created and named based off of D1 in the "LLP Disc Sheet" needs to be updated to "=+'LLP Disc Sheet'!D1". This goes on with the rest of the sheets. The next has to change to =+'LLP Disc Sheet'!E1 and so on. How do I create a code to replace that cell in each of the newly created sheet with an updated formula that only changes it to cell referenced one cell after in the 'LLP Disc Sheet'?
ActiveSheet.Range(“B1:M4”).Replace_
What: ="LLP Disc Sheet'!C1", Replacement:="LLP Disc Sheet'!D1”,_ ‘but I want it to continue to the next sheet to replace D1 with E1 and so on until all of the B1 cells match their sheet names (it also allow all the data to be filled in). All of these will be found in cell B1 in the MasterCalculator copies
What: ="LLP Disc Sheet'!$C$1:$C$", Replacement:=" LLP Disc Sheet'!$D$1:$D$”,_ ‘but I want it to continue to the next sheet to replace $D$1 with E$1$ and $D$ with $E$ and so on until all of the M4 cells are set to 0.
SearchOrder:=xlByRows, MatchCase:=True

Use formulaR1C1
Option Explicit
Public Sub NewSheets()
Dim wb As Workbook, ws As Worksheet, wsMaster As Worksheet
Dim iLastCol As Integer, iCol As Integer
Dim s As String, n As Integer
Set wb = ThisWorkbook
Set wsMaster = wb.Sheets("MasterCalculator")
Set ws = wb.Sheets("LLP Disc Sheet")
iLastCol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
n = wb.Sheets.Count
For iCol = 3 To iLastCol
s = ws.Cells(1, iCol) ' sheet name
If Len(s) > 0 Then
wsMaster.Copy After:=Sheets(n)
n = n + 1
wb.Sheets(n).Name = s
wb.Sheets(n).Range("B1,M4").FormulaR1C1 = "='" & ws.Name & "'!R1C" & iCol
End If
Next
MsgBox iLastCol - 2 & " sheets added", vbInformation
End Sub

Related

How to match columns and count the matches using vba

I am working on one scenario where I have two sheets. Sheet1 is the master sheet and sheet2 which I am creating.
Column1 of Sheet1 is Object which has duplicate objects as well. So, what I have done is I have created a macro which will produce the unique Objects and will paste it in sheet2.
Now, from Sheet2, each of the objects should be matched with Sheet1 column1 and based on the matching results, it should also count the corresponding entries from other columns in sheet1 to sheet2.
Below are the snapshots of my two sheets
Sheet1
Sheet2
here is my macro code which will first copy and paste the unique objects from sheet1 to sheet2 Column1.
Sub UniqueObj()
Dim Sh1 As Worksheet
Dim Rng As Range
Dim Sh2 As Worksheet
Set Sh1 = Worksheets("Sheet1")
Set Rng = Sh1.Range("A1:A" & Sh1.Range("A65536").End(xlUp).Row)
Set Sh2 = Worksheets("Sheet1")
Rng.Cells(1, 1).Copy Sh2.Cells(1, 1)
Rng.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Sh2.Range("A1"), Unique:=True
End Sub
But, I am unable to move forward from there. I am pretty new and any help would be very greatful.
Thanks
If I'm understanding what you want correctly, you're just counting matching columns from Sheet1 where the value in the corresponding column isn't blank? If so this should do the trick.
Option Explicit
Sub GetStuffFromSheet1()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim lastRow1 As Long, lastRow2 As Long
Dim x As Long
'turn on error handling
On Error GoTo error_handler
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
'determine last row with data in sheet 1
lastRow1 = ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row
'determine last row with data in sheet 2
lastRow2 = ws2.Cells(ws2.Rows.Count, 1).End(xlUp).Row
'define columns in sheet 1
Const objCol1 As Long = 1
Const rProdCol1 As Long = 3
Const keysCol1 As Long = 4
Const addKeysCol1 As Long = 5
'define columns in sheet 2
Const objCol2 As Long = 1
Const rProdCol2 As Long = 2
Const keysCol2 As Long = 3
Const addKeysCol2 As Long = 4
'turn off screen updating + calculation for speed
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'loop through all rows of sheet 2
For x = 2 To lastRow2
'formula counts # of cells with matching obj where value isn't blank
ws2.Cells(x, rProdCol2) = WorksheetFunction.CountIfs(ws1.Columns(objCol1), ws2.Cells(x, objCol2), ws1.Columns(rProdCol1), "<>" & "")
ws2.Cells(x, keysCol2) = WorksheetFunction.CountIfs(ws1.Columns(objCol1), ws2.Cells(x, objCol2), ws1.Columns(keysCol1), "<>" & "")
ws2.Cells(x, addKeysCol2) = WorksheetFunction.CountIfs(ws1.Columns(objCol1), ws2.Cells(x, objCol2), ws1.Columns(addKeysCol1), "<>" & "")
Next x
'turn screen updating + calculation back on
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
error_handler:
'display error message
MsgBox "Error # " & Err.Number & " - " & Err.Description, vbCritical, "Error"
'turn screen updating + calculation back on
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
End Sub
In case a non VBA solution works for you, you can resume your data with a Pivot Table, take field Object into rows section and rest of fields into values section (choose Count)
This returns the exact output you are looking for. Easy to update and easy to create.
In case you want a VBA solution, because your design is tabular and you are counting values, you can use CONSOLIDATE:
Consolidate data in multiple worksheets
'change K1 with cell where to paste data.
Range("K1").Consolidate Range("A1").CurrentRegion.Address(True, True, xlR1C1, True), xlCount, True, True, False
'we delete column relation type and column value. This columns depends on where you paste data, in this case, K1
Range("L:L,P:P").Delete Shift:=xlToLeft
After executing code i get this:
Hope this helps

Check if each worksheet contains certain color and paste into target worksheet

For each worksheet in my workbook, I would like to:
- Check if rows contain cells with colour index -4142 (yellow)
- If yes, copy and paste row values into ToDo list.
I have tried:
1) For Each loop, as indicated below.
2) Dim i As Long
For i = 1 To ThisWorkbook.Worksheets.Count
Set Sh1 = Worksheets(i)
Sub Macro1()
Dim wrk As Workbook
Dim colCount As Integer
Dim ws As Worksheet
Dim Sh1 As Worksheet, Sh2 As Worksheet
Dim r As Range, r1 As Range, cell As Range
Dim iResponse As Integer
Dim LastRow As Long
iResponse = MsgBox("Do you want to COPY your 'Current List' (Hi-lighted rows) to the 'Select List' sheet?", vbYesNoCancel + vbQuestion + vbDefaultButton3, "Copy Selected Results To View In Select List")
Select Case iResponse
Case vbCancel
MsgBox "Cancelled", vbOKOnly + vbExclamation, "Cancelled copy"
Case vbNo: 'do Nothing
MsgBox "Doing nothing", vbOKOnly + vbInformation, "Doing nothing"
Case vbYes
For Each ws In ActiveWorkbook.Worksheets ' For each worksheet in workbook
Set Sh1 = Worksheets(ws.Index) ' Sh1 will be first, second, etc. worksheet
Set Sh2 = Worksheets("ToDo") ' sheet to copy to
Set wrk = ActiveWorkbook ' to get header as first row
colCount = Sh1.Cells(1, 255).End(xlToLeft).Column
With Sh2.Cells(1, 1).Resize(1, colCount)
.Value = Sh1.Cells(1, 1).Resize(1, colCount).Value
.Font.Bold = True
End With
Set r1 = Sh1.Range(Sh1.Cells(2, "D"), Sh1.Cells(Rows.Count, "C").End(xlUp))
For Each cell In r1
If cell.Interior.ColorIndex = 6 Then
If r Is Nothing Then
Set r = cell
Else
Set r = Union(r, cell)
End If
End If
Next
If Not r Is Nothing Then
LastRow = Sh2.Cells(Rows.Count, "C").End(xlUp).Row
With Sh2
r.EntireRow.Copy Destination:=.Range("A" & LastRow + 1)
.UsedRange.Offset(1).Interior.ColorIndex = -4142
Range("A1").Select
End With
Else
MsgBox "No info obtained", vbExclamation, "Nothing copied."
End If
Exit For ' Exit For loop
Next ws ' Next worksheet
End Select
End Sub
The expected output is:
If Sheet 1 has 3 rows - row 1: yellow, row 2: green, row 3: yellow
and Sheet 2 has 2 rows - row 1: yellow, row 2: blue
then ToDo sheet will show the values of Sheet 1 row 1, Sheet 1 row 3, Sheet 2 row 2
Currently the output is "No info obtained" msg.
This runs through each cell in the usedrange of each worksheet. If the interior color matches it copies all the values from that row, and puts it in the ToDo list worksheet. If the row counter for the todo list hasn't changed after the loops were complete then "no info obtained" message will pop up.
Option Explicit
Sub Test()
Dim oToDo As Worksheet
Set oToDo = Worksheets("ToDo")
Dim oToDoRow As Long
oToDoRow = 2 ' Whatever row your "todo" data starts on
Dim oCell As Range
Dim oCurWS As Worksheet
Dim oPrevRow As String
For Each oCurWS In ThisWorkbook.Worksheets
If oCurWS.Name <> "ToDo" Then
For Each oCell In oCurWS.UsedRange
' I used Interior Color you should be able to use colorindex in the same way
If oCell.Interior.Color = 65535 Then
If oPrevRow <> oCurWS.Index & "_" & oCell.Row Then
oToDo.Rows(oToDoRow).Value = oCurWS.Rows(oCell.Row).Value
oPrevRow = oCurWS.Index & "_" & oCell.Row
oToDoRow = oToDoRow + 1
End If
End If
Next
End If
Next
' Match oToDoRow with whatever is set as default at the top
If oToDoRow = 2 Then MsgBox "No info obtained"
End Sub
Update to prevent row being listed multiple times if more than one cell in a row was highlighted.
Do you need whole row to be "yellow" ? or there is allways one cell in each row ?.
I'm asking what if A1 is yellow ,B1 is blue, C1 is red, D1 is yellow you want to copy from this row only A1 and D1 to Sheet "ToDo"- into A1 and B1 or copy/paste entire row?
Have a great day

Excel VBA - Copy from multiple sheets with condition and placing in certain cell in different sheets

I'm new to VBA Excel and I have some code that will go through multiple sheets and copy values in certain range of cells if the criteria are met.
So basically I would like to copy certain data from multiple sheets and paste it in certain cells (it must be placed based on the variable in the cells)
I would like to copy from sheet 1, 2, 3, etc., cell E to L and place it in another sheet, based on the value of cell L5:
And paste it to this sheet, in cell F to M, if the value of cell C in sheet Template 1 are the same with cell L5 in sheet 1,2,3,etc:
Here are the code that I have:
Option Explicit
'Note: This example use the function LastRow
'This example copy the range A2:G2 from each worksheet.
'
'Change the range here
'
''Fill in the range that you want to copy
'Set CopyRng = sh.Range("A2:G2")
'When you run one of the examples it will first delete the summary worksheet
'named RDBMergeSheet if it exists and then adds a new one to the workbook.
'This ensures that the data is always up to date after you run the code.
'*****READ THE TIPS on the website****
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
Dim i As Integer
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the sheet "RDBMergeSheet" if it exist
'Application.DisplayAlerts = False
'On Error Resume Next
'ActiveWorkbook.Worksheets("RDBMergeSheet").Delete
'On Error GoTo 0
'Application.DisplayAlerts = True
'Add a worksheet with the name "RDBMergeSheet"
Set DestSh = ActiveWorkbook.Worksheets("Template 1")
'DestSh.Name = "RDBMergeSheet"
'loop through all worksheets and copy the data to the DestSh
For Each sh In ActiveWorkbook.Worksheets
'Loop through all worksheets except the RDBMerge worksheet and the
'Information worksheet, you can ad more sheets to the array if you want.
If IsError(Application.Match(sh.Name, _
Array("Information", "Template 1", "Template 2", "Template 3"), 0)) 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("E10:L10")
'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
'For i = 2 To LastRow(DestSh)
CopyRng.Copy
With DestSh.Cells(Last + 1, "E")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
'Optional: This 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 DestSh sheet
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
The code above succeeded to copy from sheet 1,2,3,etc in cell range but place it in the last row and not yet based on the criteria.
I would like to know how to incorporate the criteria that I need to the code above? Thanks
This code will do for loops which find the sheet where the L5 value matches the C1 value in each of the Templates. Inside that if statement is where you can put the code you have that copies and pastes the values. Good luck!
Sub matchTemplateWithSheet()
'
' matchTemplateWithSheet Macro
'
'
Dim x As Integer
Dim y As Integer
Dim a As Integer
Dim b As Integer
Dim numberOfTemplates As Integer
Dim numberOfSheets As Integer
numberOfTemplates = 3 'you can set the number of templates you're trying to fill
numberOfSheets = 5 ' you can set the number of sheets you're looking through. _
this can also easily be automated in the code
For x = 1 To numberOfTemplates
a = ActiveWorkbook.Worksheets("Template " & x).Cells(1, 3)
For y = 1 To numberOfSheets
b = ActiveWorkbook.Worksheets("Sheet" & y).Cells(5, 12)
If a = b Then
'''''This is where you can put the copy/paste code that you already have'''''
End If
Next y
Next x
End Sub

Create Sheets from column values, and insert values in column in specific cells on each sheet

I found a macro that reads values in Column A on "Sheets Insert", creates individual worksheets based on those values, and then copies "Template" to each new page.
Sub NewSheets()
Dim i As Integer
Dim ws As Worksheet
Dim sh As Worksheet
Set ws = Sheets("Template")
Set sh = Sheets("Sheets Insert")
Application.ScreenUpdating = 0
For i = 2 To Range("A" & Rows.Count).End(xlUp).Row
Sheets("Template").Copy Before:=sh
ActiveSheet.Name = sh.Range("A" & i).Value
Next i
End Sub
It works great.
So the next step for me is to take the value the worksheet was created from in Column A of "Sheets Insert", and insert that value at G3 of the created worksheet.
Then I need it to take the value in the same row in column B of "Sheets Insert" and copy it into C3 on that page.
So for example:
"Sheets insert"
Column A | Column B
Motor A 12345
Motor B 23456
Code creates sheet Motor A and pastes Motor A to [g3] and pastes 12345 to [c3] on Motor A sheet.
Code creates sheet Motor B and pastes Motor B to [g3] and pastes 23456 to [c3] on Motor B sheet.
And so on down the list. I searched for a couple of hours and had no luck. Hoping someone can help. Thanks.
If i understood your question you have to add two rows of the code:
Sub NewSheets()
Dim i As Integer
Dim ws As Worksheet
Dim sh As Worksheet
Set ws = Sheets("Template")
Set sh = Sheets("Sheets Insert")
Application.ScreenUpdating = 0
For i = 2 To Range("A" & rows.count).End(xlUp).Row
Sheets("Template").Copy Before:=sh
ActiveSheet.Name = sh.Range("A" & i).Value
'add code
Range("G3") = sh.Range("A" & i) 'copy name into cell G3
Range("C3") = sh.Range("B" & i) ' copy data into cell C3
Next i
End Sub
Hope this helps

Copy Paste VBA Code Has Blank Rows

The below code searches, copies & pastes the found data into another worksheet. However, there are blanks when this is done in the pasted worksheet. Eg: Found "To Be Copied" in Cell A1 and copied the entire row to the specified worksheet. Found "To Be Copied" in A4 and copied the entire row to the specified worksheet. However, there are two blank rows in the pasted sheet between A1 and A4. Thanks for your help.
Sub Deleting()
Application.ScreenUpdating = False
Dim wsh As Worksheet, i As Long, Endr As Long, x1 As Worksheet, p As Long
Set wsh = ActiveSheet
Worksheets.Add(Before:=Worksheets("Original Sheet")).Name = "Skipped"
Set x1 = Worksheets("Skipped")
Worksheets("ABC").Activate
i = 2
Endr = wsh.Range("A" & wsh.Rows.Count).End(xlUp).Row
While i <= Endr
If Cells(i, "A") = "To Be Copied" Then
wsh.Rows(i).Copy
x1.Rows(i).PasteSpecial
p = p + 1
Endr = Endr + 1
End If
i = i + 1
Wend
End Sub
You need two counters: i for the source rows, j for the destination rows. You only increment j when a row is copied.
Your existing code needs either
A separate counter for the written row position (Cutter's point), or
Pasting to the last used row of "Skipped" using xlUp to find the last used cell
But better still would be copying the rows in a single shot using AutoFilter. Something like below
Sub Quicker()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rng1 As Range
Application.ScreenUpdating = False
Set ws1 = Sheets("ABC")
Set ws2 = Worksheets.Add(Before:=Worksheets("Original Sheet"))
'in case Skipped exists
On Error Resume Next
ws2.Name = "Skipped"
On Error GoTo 0
ws1.AutoFilterMode = False
Set rng1 = ws1.Range(ws1.[a1], ws1.Cells(Rows.Count, "A").End(xlUp))
rng1.AutoFilter 1, "To Be Copied"
If rng1.SpecialCells(xlCellTypeVisible).Count > 1 Then
Set rng1 = rng1.Offset(1, 0).Resize(rng1.Rows.Count - 1)
rng1.EntireRow.Copy ws2.[a1]
End If
ws1.AutoFilterMode = False
MsgBox "Sheet " & ws2.Name & " updated"
End Sub

Resources