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 ?
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"")
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 am currently working on parsing data from multiple worksheets within multiple workbooks into a summary worksheet. I have been able to select certain cells from all sheets and workbooks but would like to extract a range of columns if possible. How can I add this option to my loop condition?
for example If I have a worksheet called "Monday" and I would like to extract the cell range A2 through C57 and add it to my newly created worksheet.
Option Explicit
Sub GetMyData()
Dim myDir As String, fn As String, SheetName As String, SheetName2 As String, SheetName3 As String, n As Long, NR As Long
'***** Change Folder Path *****
myDir = "C:\attach"
'***** Change Sheetname(s) *****
SheetName = "Title"
SheetName2 = "Total"
SheetName3 = "Monday"
'***Loops through specified directory and parces data from each worksheet within each workbook by selecting specified .
fn = Dir(myDir & "\*.xlsx")
Do While fn <> ""
If fn <> ThisWorkbook.Name Then
With ThisWorkbook.Sheets("ImportTable")
NR = .Cells(Rows.Count, 1).End(xlUp).Row + 1
'Pick cells from worksheet "Title"
With .Range("A" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName & "'!A1"
.Value = .Value
End With
With .Range("B" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName & "'!A2"
.Value = .Value
End With
With .Range("C" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName & "'!B4"
.Value = .Value
End With
With .Range("D" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName & "'!B5"
.Value = .Value
End With
With .Range("E" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName & "'!B6"
.Value = .Value
End With
With .Range("F" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName & "'!B7"
.Value = .Value
End With
With .Range("G" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName2 & "'!B26"
.Value = .Value
End With
With .Range("H" & NR)
.Formula = "='" & myDir & "\[" & fn & "]" & SheetName2 & "'!A1"
.Value = .Value
End With
End With
End If
fn = Dir
Loop
ThisWorkbook.Sheets("ImportTable").Columns.AutoFit
End Sub
If you move your link creation to a separate sub your code will be more concise, and you can have the sub automatically adjust the type of formula (regular for single cells, or array formula for blocks of cells)
Sub tester()
Dim rng As Range
Set rng = ActiveSheet.Range("A2")
LinkToFile "C:\_Stuff\test", "temp report.xlsx", "Sheet1", "A1:D20", rng
Set rng = ActiveSheet.Range("F2")
LinkToFile "C:\_Stuff\test", "temp report.xlsx", "Sheet1", "A1", rng
End Sub
Sub LinkToFile(fPath As String, fName As String, shtName As String, _
addr As String, rngInsert As Range)
Dim rngTmp As Range, f As String
If Right(fPath, 1) <> "\" Then fPath = fPath & "\" 'win only!
f = "='" & fPath & "[" & fName & "]" & shtName & "'!" & addr
'linking to a range, or a single cell ?
If InStr(addr, ":") > 0 Then
Set rngTmp = rngInsert.Parent.Range(addr) 'to get num rows/cols
rngInsert.Resize(rngTmp.Rows.Count, rngTmp.Columns.Count).FormulaArray = f
Else
rngInsert.Formula = f
End If
End Sub
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