I need to open two workbooks with same defined names, however different ranges, and highlight in one of the workbooks the differences of contents of every named range.
I compare hard coded ranges on one workbook with two sheets using the attached code.
Private Sub HighlightDifferences()
Dim setOne As Range
Dim setTwo As Range
Set setOne = Sheets("Sheet1").Range("Ongoing_Activities")
Set setTwo = Sheets("Sheet1 (2)").Range("Ongoing_Activities")
'REMOVE THE COLOR FILL
setOne.Interior.ColorIndex = xlNone
For Each cellitem In setOne
If Not StrComp(cellitem, cellitem2, vbBinaryCompare) = 0 Then
cellitem.Interior.ColorIndex = 6
End If
For Each cellitem2 In setTwo
If StrComp(cellitem, cellitem2, vbBinaryCompare) = 0 Then
cellitem.Interior.ColorIndex = 0
End If
Next cellitem2
Next cellitem
End Sub
Please, try the next code:
Sub compareNamesTwoWorkbooks()
Dim wb1 As Workbook, wb2 As Workbook, N1 As Name, N2 As Name, i As Long, j As Long
Dim rngN1 As Range, rngN2 As Range, boolFound As Boolean
Set wb1 = Workbooks("first workbook.xlsx")
Set wb2 = Workbooks("second workbook.xlsx")
For Each N1 In wb1.Names
For Each N2 In wb2.Names
If N1.RefersTo = N2.RefersTo Then
Set rngN1 = Application.Evaluate("'[" & wb1.Name & "]" & _
Replace(Replace(N1.RefersTo, "=", ""), "!", "'!"))
Set rngN2 = Application.Evaluate("'[" & wb2.Name & "]" & _
Replace(Replace(N2.RefersTo, "=", ""), "!", "'!"))
rngN1.Interior.ColorIndex = xlNone: 'rngN1.Parent.Activate: Stop
For i = 1 To rngN1.rows.count
For j = 1 To rngN1.Columns.count
If Not StrComp(rngN1.cells(i, j).Value, _
rngN2.cells(i, j).Value, vbBinaryCompare) = 0 Then
rngN1.cells(i, j).Interior.ColorIndex = 6
End If
Next j
Next i
boolFound = True: Exit For
End If
Next N2
If Not boolFound Then Debug.Print "Names """ & N1.Name & _
""" could not be found in workbook """ & wb2.Name
boolFound = False
Next N1
End Sub
Please, take care of using your real names to define wb1 and wb2` workbooks. Of course, they must be open. They can also be open by the program if needed.
After testing, some feedback would be appreciated...
Related
I would like my Column named "Total Board Quantit" to have all its data go to two created columns named "Total Pallets" and "Total Boards".
Total Boards will have all values from Total Board Quantit that are greater than 28.01.
Total Pallets will have all values lower than or equal to 28.
There's also data in Total Board Quantit that are lower than 1 that I do not want to show which should be on the macro already.
Option Explicit
Sub DATA()
Dim ws As Worksheet 'Dim, dimension. Declare variable to be used later
On Error Resume Next 'Continues executing statement, ignores error
Application.DisplayAlerts = False 'Set to false to suppres prompts
Sheets("DATA").Delete
Application.DisplayAlerts = True
On Error GoTo 0 'Disables any error trapping currently present in the procedure
Dim fName As Variant, wb As Workbook 'Variant data type can be used to define variables that contain any type of data
Application.EnableEvents = False 'Disable events to avoid workbooks_open to be started
fName = Application.GetOpenFilename("Excel Files (*.xl*), *.xl*") 'fname, file with excel file ext
On Error Resume Next 'Continues executing statement, ignores error
If fName = False Then 'False, exit, msg will show
MsgBox ("No SAP Data selected!")
Exit Sub
End If
On Error GoTo 0
Set wb = Workbooks.Open(fName)
wb.Sheets(1).Copy before:=ThisWorkbook.Sheets(2) 'Importing data from first sheet on to this wb, second location
ActiveSheet.Name = "DATA" 'Naming the sheet DATA
wb.Close False 'Close workbook
On Error Resume Next
Application.EnableEvents = True
'''
Dim rngUsernameHeader As Range
Dim rngHeaders As Range
Set rngHeaders = Range("1:1") 'Looks in entire first row.
Set rngUsernameHeader = rngHeaders.Find(what:="Total Pallet Quantit", After:=Cells(1, 1))
rngUsernameHeader.Offset(0, 1).EntireColumn.Insert
rngUsernameHeader.Offset(0, 1).Value = "Total Pallets"
rngUsernameHeader.Offset(0, 2).EntireColumn.Insert
rngUsernameHeader.Offset(0, 2).Value = "Total Boards"
ActiveSheet.Range("$A$1:$P$247").AutoFilter Field:=16, Criteria1:=">1", _
Operator:=xlAnd
'''
Dim arrIn, arrOut As Variant
lastRow = Range("a" & Rows.Count).End(xlUp).Row
arrIn = rngUsernameHeader.Offset(1, 0).Resize(lastRow, 1).Value
ReDim arrOut(1 To UBound(arrIn), 1 To 2)
For x = 1 To UBound(arrIn)
num = arrIn(x, 1)
If num <= 28 Then
arrOut(x, 2) = num
ElseIf num >= 28.01 Then
arrOut(x, 1) = num
End If
Next x
rngUsernameHeader.Offset(1, 1).Resize(lastRow, 2).Value = arrOut
End Sub
What I'm getting
So you have inserted the two columns and now want to populate them with data.
I think here arrays are your friend:
Edited for comment by #TimWilliams, thanks!
Sub arrayTransfer()
Dim arrIn, arrOut As Variant
lastRow = Range("a" & Rows.Count).End(xlUp).Row
arrIn = Range("A2:A" & Range("a" & Rows.Count).End(xlUp).Row).Value
ReDim arrOut(1 To UBound(arrIn), 1 To 2)
For x = 1 To UBound(arrIn)
num = arrIn(x, 1)
If num <= 28 Then
arrOut(x, 2) = num
ElseIf num > 28.01 Then
arrOut(x, 1) = num
End If
Next x
Range("b2:c" & lastRow).Value = arrOut
End Sub
update lines 4 and 6 to reference the column the data is actually in and the last line to the columns the data is going into
note if a value is 28.01 or negative it will not be in either column as per the questions.
let me know how you get on
I have a script that maps out data and prints an array to a template based on when values in a column change (when the next set of duplicates start), basically stops and prints and array when cells M2<>M3 type deal.
It goes through and saves off a copy from the template for everyone but the final set of data, it just sits in the template and doesn't save off. How can I edit my code to go through all values and not leave the last set of data for me to manually save off?
Option Explicit
Sub Main()
Dim wb As Workbook
Dim Report_Data, Last, Login
Dim i As Long, j As Long, k As Long, a As Long
Dim Destination_Rng As Range
Workbooks.Open filename:="C:\Goal_Report_Template.xlsx"
Set wb = Workbooks("Goal_Report_Template.xlsx")
Set Destination_Rng = wb.Sheets("Sheet1").Range("A2")
With ThisWorkbook.Sheets("Q1 report")
Report_Data = .Range("W2", .Range("A" & Rows.Count).End(xlUp))
End With
wb.Activate
Application.ScreenUpdating = False
For i = 1 To UBound(Report_Data)
If Report_Data(i, 14) <> Last Then
If i > 1 Then
Destination_Rng.Select
wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Login & " - " & Last & " - Goal Reporting.xlsx")
End If
Rows(1).Offset(1, 0).Resize(Rows.Count - 1).EntireRow.ClearContents
Last = Report_Data(i, 14)
Login = Report_Data(i, 13)
j = 0
End If
a = 0
For k = 1 To UBound(Report_Data, 2)
Destination_Rng.Offset(j, a) = Report_Data(i, k)
a = a + 1
Next
j = j + 1
Next
End Sub
You need to perform another SaveAs after exiting the i loop. You can avoid duplicating code by breaking that out into a separate sub.
Untested:
Sub Main()
Dim wb As Workbook
Dim Report_Data, Last, Login, Current
Dim i As Long, j As Long, k As Long, a As Long
Dim Destination_Rng As Range
Set wb = Workbooks.Open(Filename:="C:\Goal_Report_Template.xlsx")
Set Destination_Rng = wb.Sheets("Sheet1").Range("A2")
With ThisWorkbook.Sheets("Q1 report")
Report_Data = .Range("W2", .Range("A" & .Rows.Count).End(xlUp))
End With
Application.ScreenUpdating = False
For i = 1 To UBound(Report_Data)
Current = Report_Data(i, 14)
If Current <> Last Then
If i > 1 Then SaveCopy wb, Login, Last '<< save this one
Destination_Rng.CurrentRegion.Offset(1, 0).ClearContents
Login = Report_Data(i, 13)
j = 0
Else
j = j + 1
End If
For k = 1 To UBound(Report_Data, 2)
Destination_Rng.Offset(j, k - 1) = Report_Data(i, k)
Next k
Next i
SaveCopy wb, Login, Last '<< save the last report
End Sub
Sub SaveCopy(wb As Workbook, Login, Last)
wb.SaveCopyAs ThisWorkbook.Path & Application.PathSeparator & _
ValidFileName(Login & " - " & Last & " - Goal Reporting.xlsx")
End Sub
The situation is like this:
I have 40 worksheets embedded with same Macros called RetrieveNumbers. The end results in 40 sheets will be different based upon various parameters in each worksheet.
To update the numbers, I manually click the macro buttons to retrieve numbers in the 40 worksheets. As a result of that, I'm sick of it. To simplify the testing, I only use two sheets(Sheet1, Sheet2) to test if, by clicking a Macro named RunAll, it would run through the two Macros.
Surely, I have FAILED.
I have tried :
application.run
call
Two scenarios I tried:
I hit F5 as I was in the RunAll window and my other screen on the Sheet1 worksheet. It runs perfectly and yet it runs twice in Sheet1 rather than going to Sheet2.
I hit F5 as I was in the RunAll window and my another screen on the RunAll worksheet. After clicking it, I went back to see if there were any numbers. And surely, there weren't.
I thought the Macro would go to Sheet2 and then run Macro Retrivenumbers2. But it didn't. It stayed at the current worksheet. Please give me some guidance on how to run the next sheets I want. Let me know if I need to clarify more on this question.
The Macro RetrieveNumbers
(Since the Macro RetrieveNumbers2 is as same as RetrieveNumbers1, I don't include it)
Sub RetrieveNumbers1()
Dim NumberFiles As Integer, FilesVisited As Integer, RowNumber As Integer
Let NumberFiles = ActiveSheet.Cells("2", "A").Value
Let FilesVisited = 0 'start from 0
Let RowNumber = 4 'start from column B
If NumberFiles > 30 Then
MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
Else
For FilesVisited = 1 To NumberFiles
'Open files, get path, file, tab name and cells
Dim PathFileOpen As String, NameFileOpen As String, NameTab As String, FileDir As String
Let PathFileOpen = ActiveSheet.Cells(RowNumber, "A").Text
Let NameFileOpen = ActiveSheet.Cells(RowNumber, "B").Text
Let NameTab = ActiveSheet.Cells(RowNumber, "C").Text
Dim N As Integer, Cell As String, NumberYears As String, FullLink As String
NumberYears = ActiveSheet.Cells("2", "B").Value
For N = 4 To NumberYears + 3
Cell = ActiveSheet.Cells(RowNumber, N).Text
FullLink = "(=)'" & PathFileOpen & "\[" & NameFileOpen & ".xlsm]" & NameTab & "'!" & Cell
ActiveSheet.Cells(RowNumber, N + 13).Value = FullLink
Next N
RowNumber = RowNumber + 1
Next FilesVisited
End If
ActiveSheet.Range("A1").CurrentRegion.Replace What:="(=)", Replacement:="=", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False,
SearchFormat:=False, ReplaceFormat:=False
End Sub
The Macro RunAll
Sub runall()
Call Sheet1.RetrieveNumbers1
Call Sheet2.RetrieveNumbers2
End Sub
Clear Example of the file
Working file example
There's a fair amount wrong with your code. As #PGCodeRider said in his answer - have one procedure that runs on all sheets. His code has the loop within the procedure.
This code uses a separate procedure to cycle through the sheets and passes a reference to the sheet to the RetrieveNumbers procedure.
I've replaced all instances of ActiveSheet (reference to the ActiveSheet) with wrkSht (reference to the sheet that the RunAllSheets procedure passes).
All Dims have been moved to the top of the code as they only need declaring once and not on each loop (you change the value the variables hold on each loop, but no need to declare them again).
Sub RunOnAllSheets()
Dim wrkSht As Worksheet
For Each wrkSht In ThisWorkbook.Worksheets
Select Case wrkSht.Name
Case "Sheet1", "Sheet2"
'Do nothing.
Case Else
'For all other sheets execute the RetrieveNumbers procedure
'and pass the wrkSht variable to it.
RetrieveNumbers wrkSht
End Select
Next wrkSht
End Sub
Sub RetrieveNumbers(wrkSht As Worksheet)
Dim NumberFiles As Integer, FilesVisited As Integer, RowNumber As Integer
'You only need to declare these once.
Dim PathFileOpen As String, NameFileOpen As String, NameTab As String, FileDir As String
Dim N As Integer, Cell As String, NumberYears As String, FullLink As String
'No need to use 'LET' it's a left-over from the days of Sinclair Basic
'ok, maybe not.... but it's an old way of doing it.
NumberFiles = wrkSht.Cells("2", "A").Value
FilesVisited = 0 'start from 0
RowNumber = 4 'start from column B
If NumberFiles > 30 Then
MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
Else
For FilesVisited = 1 To NumberFiles
'Open files, get path, file, tab name and cells
PathFileOpen = wrkSht.Cells(RowNumber, "A").Text
NameFileOpen = wrkSht.Cells(RowNumber, "B").Text
NameTab = wrkSht.Cells(RowNumber, "C").Text
NumberYears = wrkSht.Cells("2", "B").Value
For N = 4 To NumberYears + 3
Cell = wrkSht.Cells(RowNumber, N).Text
FullLink = "(=)'" & PathFileOpen & "\[" & NameFileOpen & ".xlsm]" & NameTab & "'!" & Cell
wrkSht.Cells(RowNumber, N + 13).Value = FullLink
Next N
RowNumber = RowNumber + 1
Next FilesVisited
End If
wrkSht.Range("A1").CurrentRegion.Replace What:="(=)", Replacement:="=", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
End Sub
Edit, after accepted as answer:
This method only references the sheet twice. Once to pull the link info, and once more to put the final formula back on the sheet.
Sub RunOnAllSheets()
Dim wrkSht As Worksheet
For Each wrkSht In ThisWorkbook.Worksheets
'Have removed the Select Case statement so it looks at all sheets.
RetrieveNumbers wrkSht
Next wrkSht
End Sub
Sub RetrieveNumbers(wrkSht As Worksheet)
Dim NumberFiles As Long, FilesVisited As Long
Dim vCellValues As Variant, vLinkValues() As Variant
Dim FullPath As String
Dim x As Long
With wrkSht
'Get the last row number that contains data in column N.
NumberFiles = .Cells(.Rows.Count, "N").End(xlUp).Row
If NumberFiles - 3 > 30 Then
MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
Else
'Pass the cell values to an array.
vCellValues = .Range("A4:C4")
'Create the full path excluding the cell reference.
FullPath = "='" & vCellValues(1, 1) & "[" & vCellValues(1, 2) & "]" & vCellValues(1, 3) & "'!"
'Create an array of full path & cell references.
ReDim vLinkValues(1 To NumberFiles - 3) 'Set the array size.
For x = 1 To NumberFiles - 3
vLinkValues(x) = FullPath & .Cells(x + 3, "N")
Next x
'Paste the array back to the sheet.
.Range(.Cells(4, "N"), .Cells(NumberFiles, "N")).Formula = vLinkValues
End If
End With
End Sub
Note: This assumes your path is just in cell A4:C4, as indicated by the code vCellValues = .Range("A4:C4") (I'm not sure this is the case now).
If your paths are on each row matching the cell values you'll need to:
Change vCellValues = .Range("A4:C4") to
vCellValues = .Range(.Cells(4, 1), .Cells(NumberFiles, 3))
Remove the FullPath='.... line.
Change vLinkValues(x) = FullPath & .Cells(x + 3, "N") to
vLinkValues(x) = "='" & vCellValues(x, 1) & "[" & vCellValues(x, 2) & "]" & vCellValues(x, 3) & "'!" & .Cells(x + 3, "N")
Try running a loop through all of the sheets in the workbook? Also make sure you run this in a module in your vba editor. Not your sheet code.
Sub RetrieveNumbers1()
Dim WS As Worksheet
'loop that goes through all sheets in your workbook. Where you used to have
'activesheet, I changed to ws
For Each WS In ThisWorkbook.Sheets
Dim NumberFiles As Integer, FilesVisited As Integer, RowNumber As Integer
Let NumberFiles = WS.Cells("2", "A").Value
Let FilesVisited = 0 'start from 0
Let RowNumber = 4 'start from column B
If NumberFiles > 30 Then
MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
Else
For FilesVisited = 1 To NumberFiles
'Open files, get path, file, tab name and cells
Dim PathFileOpen As String, NameFileOpen As String, NameTab As String, FileDir As String
Let PathFileOpen = WS.Cells(RowNumber, "A").Text
Let NameFileOpen = WS.Cells(RowNumber, "B").Text
Let NameTab = WS.Cells(RowNumber, "C").Text
Dim N As Integer, Cell As String, NumberYears As String, FullLink As String
NumberYears = WS.Cells("2", "B").Value
For N = 4 To NumberYears + 3
Cell = WS.Cells(RowNumber, N).Text
FullLink = "(=)'" & PathFileOpen & "\[" & NameFileOpen & ".xlsm]" & NameTab & "'!" & Cell
WS.Cells(RowNumber, N + 13).Value = FullLink
Next N
RowNumber = RowNumber + 1
Next FilesVisited
End If
ws.Range("A1").CurrentRegion.Replace What:="(=)", Replacement:="=", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False,
SearchFormat:=False, ReplaceFormat:=False
'restarts on the next ws
Next WS
End Sub
Hopefully the title is clear. I am trying to search through multiple tables on a single sheet. The information I am looking for is the same for all of the tables, just that the corresponding column is located in different spots (e.g. in one table the column I want to search is in I, while for another table it could be in O.) which makes it a bit more challenging for me.
I want to search through each column that has the same title (Load Number) and depending on its value, copy that entire row over to a sheet that corresponds with that value.
Below is what I have so far in VBA as well as a picture to hopefully clarify my issue.
Any help/advice is appreciated!
http://imgur.com/a/e9DyH
Sub Load_Number_Finder()
Dim ws As Worksheet
Dim i As Integer
Dim j As Integer
j = 1
Set ws = Sheets.Add(After:=Sheets("Master"))
ws.Name = ("Test Load " & j)
i = 1
Sheets("Master").Select
For Each cell In Sheets("Master").Range("M:M")
If cell.Value = "1" Then
j = 1
'Set WS = Sheets.Add(After:=Sheets("Master"))
'WS.Name = ("Test Load " & j)
matchRow = cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Test Load " & j).Select
ActiveSheet.Rows(i).Select
ActiveSheet.Paste
Sheets("Master").Select
i = i + 1
ElseIf cell.Value = "" Then
' 2, 3, 4, 5, cases
Else
' Something needs to go here to catch when it doesnt have a load number on it yet
End If
' Err_Execute:
' MsgBox "An error occurred."
Next
End Sub
Try this function. This should work for you. Let me know what the results are with your sheet. I made a mock up sheet and tested it, it worked. I can make changes if this is not exactly what you are looking for.
Option Explicit
Sub copyPaste()
Dim rowCount, row_ix, temp, i As Integer
Dim TD_COL_IX As Integer
Dim td_value As String
Dim td_values() As String
rowCount = Worksheets("Master").Cells(Rows.Count, "A").End(xlUp).Row
For row_ix = 1 To rowCount
temp = isNewTable(CInt(row_ix))
If temp > 0 Then
TD_COL_IX = temp
ElseIf TD_COL_IX > 0 Then
td_value = Worksheets("Master").Cells(row_ix, TD_COL_IX)
If Not td_value = "" Then
td_values = Split(td_value, " ")
For i = 0 To UBound(td_values)
If Not sheetExists("Test Load " & td_values(i)) Then
Sheets.Add.Name = "Test Load " & td_values(i)
End If
If Worksheets("Test Load " & td_values(i)).Cells(1, 1).Value = "" Then
Worksheets("Master").Range(Worksheets("Master").Cells(row_ix, 1), Worksheets("Master").Cells(row_ix, TD_COL_IX - 1)).Copy _
Destination:=Worksheets("Test Load " & td_values(i)).Cells(1, 1)
Else
Dim rowCount_pasteSheet As Integer
rowCount_pasteSheet = Worksheets("Test Load " & td_values(i)).Cells(Rows.Count, "A").End(xlUp).Row
Worksheets("Master").Range(Worksheets("Master").Cells(row_ix, 1), Worksheets("Master").Cells(row_ix, TD_COL_IX - 1)).Copy _
Destination:=Worksheets("Test Load " & td_values(i)).Cells(rowCount_pasteSheet + 1, 1)
End If
Next i
End If
End If
Next row_ix
End Sub
Function isNewTable(row_ix As Integer) As Integer
Dim colCount, col_ix As Integer
colCount = Worksheets("Master").Cells(row_ix, Columns.Count).End(xlToLeft).Column
For col_ix = 1 To colCount
If Not IsError(Worksheets("Master").Cells(row_ix, col_ix).Value) Then
If Worksheets("Master").Cells(row_ix, col_ix).Value = "LD #" Then
isNewTable = col_ix
Exit Function
End If
End If
Next col_ix
isNewTable = 0
End Function
' ####################################################
' sheetExists(sheetToFind As String) As Boolean
'
' Returns true if the sheet exists, False otherwise
' ####################################################
Public Function sheetExists(sheetToFind As String) As Boolean
Dim sheet As Worksheet
sheetExists = False
For Each sheet In Worksheets
If sheetToFind = sheet.Name Then
sheetExists = True
Exit Function
End If
Next sheet
End Function
I can't figure it out. I'm trying to make my formular more dynamic. But it always says prev can not be found, but I set prev as a worksheet.
PrevSheetName gives back the name of the previous worksheet (that works).
Please help me, in my other code I always tried to use "ActiveSheet.Previous" but it seems not to work with formulas.
Set prev = Worksheets(PrevSheetName)
Set rng = ActiveSheet.Range("D3")
rng.FormulaR1C1 = "=SUMIF(prev!C[1],RC[-2],prev!C[5])"
Range("D3").Copy Range("D4:D" & lRow)
This is my first code and that works
Set rng = ActiveSheet.Range("D3")
rng.FormulaR1C1 = "=SUMIF('Projekt 1'!C[1],RC[-2],'Projekt 1'!C[5])"
Range("D3").Copy Range("D4:D" & lRow)
and this is my PrevSheetName, is already puts the name in " "
Function PrevSheetName(Optional ByVal WS As Worksheet = Nothing) As String
Application.Volatile True
Dim S As String
Dim Q As String
If IsObject(Application.Caller) = True Then
Set WS = Application.Caller.Worksheet
If WS.Index = 1 Then
With Application.Caller.Worksheet.Parent.Worksheets
Set WS = .Item(.Count)
End With
Else
Set WS = WS.Previous
End If
If InStr(1, WS.Name, " ", vbBinaryCompare) > 0 Then
Q = "'"
Else
Q = vbNullString
End If
Else
If WS Is Nothing Then
Set WS = ActiveSheet
End If
If WS.Index = 1 Then
With WS.Parent.Worksheets
Set WS = .Item(.Count)
End With
Else
Set WS = WS.Previous
End If
Q = vbNullString
End If
PrevSheetName = Q & WS.Name & Q
End Function
I just want to exchange 'Projekt 1' with the previous sheet
If your sheet name has spaces as well as concatention you will need to add ' around the name in the formula like this "=SUMIF('" & PrevSheetName & "'!C[1],RC[-2],'" & PrevSheetName & "'!C[5])"
prev is a literal part of the formula. It is looking for sheet called "prev". You need to concatenate formula: "=SUMIF(" & PrevSheetName & "!C[1],RC[-2]," & PrevSheetName & "!C[5])"