I am trying to put together one main spreadsheet that pulls from over 100 workbooks containing various data. I haven't been able to figure out how to access a closed Workbook in order to calculate the standard deviation from one of the rows.
Sub RefreshSourceData()
Dim sourceFile, fileName As String, path As String
Dim dispersionRange As Range
path = "U:\SPACE Info\Meeting Materials\Strategy Files\"
fileName = "[" & ActiveCell.EntireRow.Cells(1, 1).Value & ".xls]"
sourceFile = "=" & path & fileName
dispersionRange = "=" & path & fileName & "Account'!R:R"
Range("B" & ActiveCell.Row).Formula = sourceFile & "Summary'!$F$2"
Range("C" & ActiveCell.Row).Formula = sourceFile & "Summary'!$F$3"
Range("D" & ActiveCell.Row).Formula = sourceFile & "Summary'!$B$10"
Range("E" & ActiveCell.Row).Formula = sourceFile & "Summary'!$D$10"
Range("F" & ActiveCell.Row).Formula = WorksheetFunction.StDev(dispersionRange)
End Sub
I have received various errors, right now it is "Object Variable or With Object Variable not set."
I have also tried creating a workbook variable consisting of path & filename, but this hasn't worked either.
These are some best effort suggestions, since I can't test everything (I don't have your data).
For your immediate error, I think you intended dispersionRange to be a String, not a Range.
Also, when adding the formula references, make sure you add single quotes around your sourceFile, e.g.:
Range("B" & ActiveCell.Row).Formula = "'" & sourceFile & "Summary'!$F$2"
Range("C" & ActiveCell.Row).Formula = "'" & sourceFile & "Summary'!$F$3"
Range("D" & ActiveCell.Row).Formula = "'" & sourceFile & "Summary'!$B$10"
Range("E" & ActiveCell.Row).Formula = "'" & sourceFile & "Summary'!$D$10"
^^^^^
Similarly for dispersionRange (notice the missing =):
dispersionRange = "'" & path & fileName & "Account'!R:R"
Finally, the last .Formula (for the "F" column) should be .Value, as StDev returns a Double. In addition, the function StDev doesn't take a range as String but a proper Range object, so try this instead:
Range("F" & ActiveCell.Row).Value = WorksheetFunction.StDev(Range(dispersionRange))
UPDATE
To avoid confusion, I've modified your code and I'm listing it below. Please note this is untested, as I don't have access to your workbook, but it should work.
Sub RefreshSourceData()
Dim sourceFile, fileName As String, path As String
Dim dispersionRange As String
path = "U:\SPACE Info\Meeting Materials\Strategy Files\"
fileName = "[" & ActiveCell.EntireRow.Cells(1, 1).Value & ".xls]"
sourceFile = path & fileName
dispersionRange = "'" & path & fileName & "Account'!R:R"
Range("B" & ActiveCell.Row).Formula = "='" & sourceFile & "Summary'!$F$2"
Range("C" & ActiveCell.Row).Formula = "='" & sourceFile & "Summary'!$F$3"
Range("D" & ActiveCell.Row).Formula = "='" & sourceFile & "Summary'!$B$10"
Range("E" & ActiveCell.Row).Formula = "='" & sourceFile & "Summary'!$D$10"
Range("F" & ActiveCell.Row).Value = WorksheetFunction.StDev(Range(dispersionRange))
End Sub
Related
In VBA I am trying to create a sumifs formula with multiple criteria across different workbooks, but I am struggling on the syntax.
WorkbookRecut.Worksheets("Summary").Activate
Dim CountRows As Long
Dim CountRows2 As Long
CountRows = WorkbookRecut.Worksheets("Summary").Range("I" & WorkbookRecut.Worksheets("Summary").Rows.Count - 1).End(xlUp).Row
CountRows2 = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("I" & CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Rows.Count - 1).End(xlUp).Row
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Activate
Range("O6").Formula = _
"=Sumifs(" & [WorkbookRecut].Sheets("Summary").Range("I9").Address & ":" & [WorkbookRecut].Sheets("Summary").Range("I" & CountRows).Address _
& "," & [WorkbookRecut].Sheets("Summary").Range("A9").Address & ":" & [WorkbookRecut].Sheets("Summary").Range("A" & CountRows).Address _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("K6").Address(Rowabsolute:=False) _
& "," & [WorkbookRecut].Sheets("Summary").Range("D9").Address & ":" & [WorkbookRecut].Sheets("Summary").Range("D" & CountRows).Address _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("N6").Address(Rowabsolute:=False) & ")"
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("O6:O" & CountRows2).FillDown
Update
I have updated the most recent code. The only pending issue is the workbooks aren't changing, but all else works as I want :)
When creating a formula string to add to a cell you need to take into account where the different ranges are relative to the sheet where you're going to place the formula. Just calling Address() on one of the inputs may not give you what you want.
You can try something like the code below to abstract that part into a separate function:
Sub Tester()
Dim wsSumm As Worksheet, wsCBM As Worksheet
Dim lr As Long, f
Set wsSumm = WorkbookRecut.Worksheets("Summary")
Set wsCBM = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics")
lr = wsSumm.Cells(Rows.Count, "I").End(xlUp).Row
f = "=SUMIFS(" & RealAddress(wsCBM, wsSumm.Range("I9:I" & lr)) & "," & _
RealAddress(wsCBM, wsSumm.Range("A9:A" & lr)) & ",$K6," & _
RealAddress(wsCBM, wsSumm.Range("D9:D" & lr)) & ",$N6)"
With wsCBM.Range("O9")
.Formula = f
End With
End Sub
'get a range address for `rngRef`,
' suitable for use in a formula on worksheet `ws`
Function RealAddress(ws, rngRef As Range) As String
Dim s As String
If ws.Parent Is rngRef.Worksheet.Parent Then 'same workbooks?
If Not ws Is rngRef.Worksheet Then s = "'" & rngRef.Worksheet.Name & "'!" 'diff. worksheets?
s = s & rngRef.Address(True, True)
Else
s = rngRef.Address(True, True, external:=True) 'different workbooks
End If
RealAddress = s
End Function
For the formula: You're probably looking for the .Address property from each of your Ranges. Something like Range1.Address & ":" & Range2.Address To get an output like $I$9:$I$307.
But for your Ranges, you need to put the CountRows inside the Range input like WorkbookRecut.Sheets("Summary").Range("A" & CountRows) and then add the .Address to it.
I also agree with #TimWilliams that your formula code could benefit greatly in terms of readability by adding some nicknames for your worksheets.
Here is what your code would look like with those 3 things corrected:
Public CashBreaksMetricsWorkbookFinal As Workbook
Public WorkbookRecut As Workbook
Dim SumSh As Worksheet
Set SumSh = WorkbookRecut.Sheets("Summary")
Dim CountRows As Long
CountRows = SumSh.Range("I" & SumSh.Rows.Count - 1).End(xlUp).Row
Dim CSCIG As Worksheet
Set CSCIG = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics")
CSCIG.Activate
Range("O9").Formula = _
"=Sumifs(" & SumSh.Range("I9") & ":" & SumSh.Range("I" & CountRows).Address _
& "," & SumSh.Range("A9").Address & ":" & SumSh.Range("A" & CountRows).Address _
& "," & CSCIG.Range("K6").Address _
& "," & SumSh.Range("D9").Address & ":" & SumSh.Range("D" & CountRows).Address _
& "," & CSCIG.Range("N6").Address & ")"
CSCIG.Range("O9").FillDown
We were missing .Address(External:=True)
Thanks all for helping me get there (Finally!)
Final Code Below
Public CashBreaksMetricsWorkbookFinal As Workbook
Public WorkbookRecut As Workbook
Dim CountRows As Long
Dim CountRows2 As Long
CountRows = WorkbookRecut.Worksheets("Summary").Range("I" & WorkbookRecut.Worksheets("Summary").Rows.Count - 1).End(xlUp).Row
CountRows2 = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("I" & CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Rows.Count - 1).End(xlUp).Row
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Activate
Range("O6").Formula = _
"=Sumifs(" & [WorkbookRecut].Sheets("Summary").Range("I9").Address(External:=True) & ":" & [WorkbookRecut].Sheets("Summary").Range("I" & CountRows).Address(External:=True) _
& "," & [WorkbookRecut].Sheets("Summary").Range("A9").Address(External:=True) & ":" & [WorkbookRecut].Sheets("Summary").Range("A" & CountRows).Address(External:=True) _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("K6").Address(Rowabsolute:=False) _
& "," & [WorkbookRecut].Sheets("Summary").Range("D9").Address(External:=True) & ":" & [WorkbookRecut].Sheets("Summary").Range("D" & CountRows).Address(External:=True) _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("N6").Address(Rowabsolute:=False) & ")"
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("O6:O" & CountRows2).FillDown
In the formula, you have to double-quote existing quotes:
Change
Sheets("Summary")
to:
Sheets(""Summary"")
EndRowH = ActiveSheet.Range("H65536").End(xlUp).Row
ActiveSheet.Range("H1").Formula = "=SUMIFS(H3:H" & EndRowH & ", C3:C" & EndRowH & ", "">=" & lngStart & """)"
I Have a criteria on the C column where it has to be greater than the lngStart Value.
The code is working till here.. But I have to add an extra criteria where the sumif needs to be done only if there is blank value in the column I
Dim Blank As Long
Blank = ""
ActiveSheet.Range("H1").Formula = "=SUMIFS(H3:H" & EndRowH & ", C3:C" & EndRowH & ", "">=" & lngStart & "",I3:I" & EndRowH & ", ""!=" & Blank & "" ")"
When working with complex strings you want to put as a Formula, you might want to use an "helper" string, in the code below I use FormulaString, so when you run the Debug.Print line, you can see if the formula string is valid.
Also, and it's only my preference, to get the " inside, I prefer to use Chr(34).
Code
Dim FormulaString As String
FormulaString = "=SUMIFS(H3:H" & EndRowH & ", C3:C" & EndRowH & "," & Chr(34) & ">=" & lngStart & Chr(34) & ",I3:I" & EndRowH & "," & Chr(34) & "<>" & Chr(34) & ")"
Debug.Print FormulaString
ActiveSheet.Range("H1").Formula = FormulaString
Running this code, you will get in the immediate window the following formula:
=SUMIFS(H3:H10, C3:C10,">=5",I3:I10,"<>")
I'd go this way
ActiveSheet.Range("H1").Formula = "=SUMIFS(H3:H" & EndRowH & ", C3:C" & EndRowH & ", concatenate("">=""," & lngStart & "),I3:I" & EndRowH & ", ""="")"
First of all, I have tried to look at all the other examples of adding a formula using VBA, and I think I have tried to apply all the answers in this code
Sub AddFormulas(SheetName As String)
Dim i As Integer
'Switch worksheet
Set Wksht = ThisWorkbook.Worksheets(SheetName)
Wksht.Activate
Application.Calculation = xlCalculationManual
i = 2
While Not IsEmpty(Cells(i, 1))
Wksht.Cells(i, 18).Formula = "=IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")"
i = i + 1
Wend
Application.Calculation = xlCalculationAutomatic
End Sub
But still, it gives me this anoying error, that I can't interpret
If I change my line to
Wksht.Cells(i, 18) = "'IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")"
Then I get no error, and the correct formula is added, although as a text string
What is wrong, since it would not add what to me looks like a valid formula?
//V
The Formula property requires formulas to be written in English, i.e. English function names (not an issue here) and commas as separators rather than semi-colons.
So your statement should be:
Wksht.Cells(i, 18).Formula = "=IFERROR(VLOOKUP(A" & i & "," & Wksht.Cells(1, 18) & "!$A:$A,1,FALSE)," & Chr(34) & "MISSING" & Chr(34) & ")"
If you don't mind having "portability" issues, you could also use the FormulaLocal property, i.e.
Wksht.Cells(i, 18).FormulaLocal = "=IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")"
Write the formula as it should be in Excel, select it and run the following code:
Public Sub PrintMeUsefulFormula()
Dim strFormula As String
Dim strParenth As String
strParenth = """"
strFormula = Selection.Formula
strFormula = Replace(strFormula, """", """""")
strFormula = strParenth & strFormula & strParenth
Debug.Print strFormula
End Sub
It should print it as it should be.
I believe your code is giving error becouse of this Wksht.Cells(1, 18) part of line in this row Wksht.Cells(i, 18).Formula = "=IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")". Make sure that Wksht.Cells(1, 18) really contains name of worksheet your are trying to address. If this cell is blank, you will receive previously mentioned error.
I am using cells as the file path and filename to save a copy of my workbook.
Here's the code am using now but it puts spaces in between each cell.
Note only the ActiveSheet.Range cells will have the possibility of being blank
Dim NewWb As Workbook
sFile = Control_Sheet_VB.Range("H2") & "\" & ActiveSheet.Range("H8") & " " & ActiveSheet.Range("E10") & " " & ActiveSheet.Range("D14") & " - Ticket #" & Control_Sheet_VB.Range("B2") & Control_Sheet_VB.Range("C2") & ".xlsm"
Set OldWb = ActiveWorkbook
OldWb.SaveCopyAs sFile
Set NewWb = Workbooks.Open(sFile)
How can I make it so if some of the cells that are used as the file name are blank then it dose not put the extra space in the filename
you may go like this:
sFile = Control_Sheet_VB.Range("H2") & "\" & _
IIf(ActiveSheet.Range("H8") <> "", ActiveSheet.Range("H8") & " ", "") & _
IIf(ActiveSheet.Range("E10") <> "", ActiveSheet.Range("E10") & " ", "") & _
IIf(ActiveSheet.Range("D14") <> "", ActiveSheet.Range("D14") & " ", "") & _
" - Ticket #" & Control_Sheet_VB.Range("B2") & _
Control_Sheet_VB.Range("C2") & ".xlsm"
i'm trying to write formula with 2 variables to cell.
formula in cell should be:
=(SUM('C:\Users\[Excel.xlsm]Sheet1'!H:H)-SUM('C:\Users\[Sheet1.xlsm]Sheet1'!I:I))
i want use path to file as variable, as well sheet name.
path = C:\Users\Excel.xlsm 'from msofiledialog
sheetname = Sheet1
what am i missing ?
Cells(1, 1).FormulaR1C1 = "=(SUM('[" & Path & "] " & sheetname & " '!C8) _
-SUM('[" & Path & "] " & sheetname & " '!C9))
thanks, this worked for me :
Sub main
Dim LastRow as String
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
Dim path as String
Path = "C:\users\username\Desktop\"
Dim filename as String
Filename = "Excel.xlsm"
Dim sheetname as String
sheetnameCR = "CR_" & supname
Dim myrangeH as String
Dim myrangeI as String
myrangeH = ("H5:H" & LastRow)
myrangeI = ("I5:I" & LastRow)
Cells(1, 1).Formula = "=SUM('" & Path & "[" & Filename & "]" & sheetnameCR & "'!" & myrangeH & ")" & "-SUM('" & Path & "[" & Filename & "]" & sheetnameCR & "'!" & myrangeI & ")"
End Sub
i had to add "RangeH" variable, because otherwise excel took cell C8, instead of column H, which i wanted.
that's great, but even after i give him full path to desired cell, excel is still asking me for path to excel with FileDialogOpen. any idea why ?