Dale Logan
asked on
Edit formulas in unopened Excel file using VBA
Back in the spring I created a template to be used to collect data throughout the summer. Those files are starting to come in and I now realize there were a couple of formulas that needed to be modified. Is there any way to create something in VBA that will make the necessary changes in these files as they come in?
Here's an example for cell CJ2. All formulas are on the first sheet.
Current: =(IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))=0, "",IF(INDE X('Data Entry'!$Q:$Q,ROW($Q18))=0, "",INDEX(' Data Entry'!$Q:$Q,ROW($Q18)))))
Should be: =(IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))="" ,"",IF(IND EX('Data Entry'!$Q:$Q,ROW($Q18))="" ,"",INDEX( 'Data Entry'!$Q:$Q,ROW($Q18)))))
NOTE: All formulas needing to be changed are in 2 columns and all will be copied down for about 50 rows.
There will be about a thousand of these files coming in. So, you can see my wish for having something somewhat automated.
Thanks, Dale
Here's an example for cell CJ2. All formulas are on the first sheet.
Current: =(IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))=0,
Should be: =(IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))=""
NOTE: All formulas needing to be changed are in 2 columns and all will be copied down for about 50 rows.
There will be about a thousand of these files coming in. So, you can see my wish for having something somewhat automated.
Thanks, Dale
It would be better to open each of the files, make the modifications and then save the results. The following code opens every file in a user selected folder and makes the desired modifications. Install it in a regular module sheet.
Sub FormulaUpdater()
Dim rg As Range
'Replicate the next four lines as necessary
Set rg = ActiveSheet.Range("CJ2")
rg.Formula = "=(IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))="""","""",IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))="""","""",INDEX('Data Entry'!$Q:$Q,ROW($Q18)))))"
rg.Copy
Range(rg, rg.End(xlDown)).PasteSpecial xlPasteFormulas
End Sub
Sub LoopThroughWorkBooksInFolder()
'Runs a macro on every workbook in a user-specified folder
Dim ws As Worksheet
Dim wb As Workbook
Dim celHome As Range
Dim f As String, flPath As String
'Change the default folder name in the following statement to a reasonable starting place
flPath = Application.GetSaveAsFilename( _
"C:\", _
Title:="Please pick any file in the desired folder, then click 'Save' button")
If flPath = "False" Then Exit Sub
Set celHome = ActiveCell
flPath = Left(flPath, InStrRev(flPath, "\"))
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Application.EnableEvents = False 'Comment out if workbooks don't contain event macros
f = Dir(flPath & "*.xls") 'Make sure file extension matches
Do Until f = ""
Set wb = Workbooks.Open(f)
Application.StatusBar = "Processing " & wb.Name
On Error Resume Next
Set ws = Nothing
Set ws = Worksheets("Sheet1") 'The worksheet that needs to be changed
If Not ws Is Nothing Then
ws.Activate
FormulaUpdater
End If
wb.Close SaveChanges:=True
f = Dir 'Get next filename & path
Loop
Errhandler:
Application.GoTo celHome
On Error GoTo 0
'Application.EnableEvents = True 'Comment out if workbooks don't contain event macros
Application.StatusBar = False
Application.DisplayAlerts = True
End Sub
byundt - "It would be better..." Were you addressing me or the OP?
Dave
Dave
Dale,
I see that my code to loop through files in a folder duplicates that of dlmille.
It is worth noting that the formulas you want to update include double-quotes. Since you must pass the new formula to the worksheet as text, you need to double up on each of the double-quotes contained in the formula. I did that for you in my FormulaUpdater sub. If you choose to modify Dave's macro for your updating, please be aware of this requirement.
Brad
I see that my code to loop through files in a folder duplicates that of dlmille.
It is worth noting that the formulas you want to update include double-quotes. Since you must pass the new formula to the worksheet as text, you need to double up on each of the double-quotes contained in the formula. I did that for you in my FormulaUpdater sub. If you choose to modify Dave's macro for your updating, please be aware of this requirement.
Brad
byundt - FWIW - I like the formulaUpdater() routine you added - it is a nice compartmentalization.
Cheers,
Dave
Cheers,
Dave
Dave,
My remarks were aimed at Dale.
I checked the thread several times for other posts, but didn't bother at the very end. Had I seen your Comment, I would have posted just my sub to modify the formulas. Your macro to loop through files in a folder is obviously battle-tested.
Brad
My remarks were aimed at Dale.
I checked the thread several times for other posts, but didn't bother at the very end. Had I seen your Comment, I would have posted just my sub to modify the formulas. Your macro to loop through files in a folder is obviously battle-tested.
Brad
hi everyone,
Here is a small change to the formulaUpdater code which removes the use of ".copy" & acts on the whole range in one go. I hope it is right...
Dale,
This formula seems to be the same on both sides of the IF statement (ie it has duplicated Index statements), or am I missing it something?
Should one of the tests be for "=0"?
If the files are large (or even if they are not), I would use a separate "helper column" to remove duplicated calculations for efficiency (see Charles Williams site: http://www.decisionmodels.com/optspeedb.htm). For example, assuming that the CK column is empty...
hth
Rob
Here is a small change to the formulaUpdater code which removes the use of ".copy" & acts on the whole range in one go. I hope it is right...
Option Explicit
Sub FormulaUpdater_v2()
Dim rg As Range
Dim ws As Worksheet
'RB: If possible I would try to modify the next line to state
'the explicit workbook & sheet (perhaps supply them as parameters/arguments).
Set ws = ActiveWorkbook.ActiveSheet
'Replicate the next four lines as necessary
With ws.Range("CJ2").Offset(0, 1)
Set rg = ws.Range(.Cells(1, 1), .End(xlDown))
'rg.Formula = "=(IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))="""","""",IF(INDEX('Data Entry'!$Q:$Q,ROW($Q18))="""","""",INDEX('Data Entry'!$Q:$Q,ROW($Q18)))))"
rg.FormulaR1C1 = "=(IF(INDEX('Data Entry'!R1C17:R" & ws.Rows.Count & "C17,ROW(R[16]C17))="""","""",IF(INDEX('Data Entry'!R1C17:R" & ws.Rows.Count & "C17,ROW(R[16]C17))="""","""",INDEX('Data Entry'!R1C17:R" & ws.Rows.Count & "C17,ROW(R[16]C17)))))"
End With
Set rg = Nothing
Set ws = Nothing
End Sub
Dale,
This formula seems to be the same on both sides of the IF statement (ie it has duplicated Index statements), or am I missing it something?
Should one of the tests be for "=0"?
If the files are large (or even if they are not), I would use a separate "helper column" to remove duplicated calculations for efficiency (see Charles Williams site: http://www.decisionmodels.com/optspeedb.htm). For example, assuming that the CK column is empty...
Sub FormulaUpdater_v3()
Dim rg As Range
Dim ws As Worksheet
'RB: If possible I would try to modify the next line to state
'the explicit workbook & sheet (perhaps supply them as parameters/arguments).
Set ws = ActiveWorkbook.ActiveSheet
'Replicate the next few lines as necessary
With ws.Range("CJ2")
Set rg = ws.Range(.Cells(1, 1), .End(xlDown))
End With
'the helper column formula in CK (note: I would normally make the flow of a spreadsheet's calculations
'go from left to right but I'm putting this in CK to keep your
'existing result in the CJ column and on the assumption that CK is empty).
With rg
.Offset(0, 1).FormulaR1C1 = "=INDEX('Data Entry'!C17,ROW(R[16]C17))"
.FormulaR1C1 = "=(IF(RC[1]="""","""",IF(RC[1]="""","""",RC[1])))"
''or is it meant to be...?
'.FormulaR1C1 = "=(IF(RC[1]="""","""",IF(RC[1]=0,0,RC[1])))"
End With
Set rg = Nothing
Set ws = Nothing
End Sub
hth
Rob
Ooopps!
I forgot to simplify my R1C1 code. The string in FormulaUpdater_v2 can be stated as:
I forgot to simplify my R1C1 code. The string in FormulaUpdater_v2 can be stated as:
rg.FormulaR1C1 = "=(IF(INDEX('Data Entry'!C17,ROW(R[16]C17))="""","""",IF(INDEX('Data Entry'!C17,ROW(R[16]C17))="""","""",INDEX('Data Entry'!C17,ROW(R[16]C17)))))"
ASKER
Dave,
That's awesome. I got it to work just fine. However, I want to point out that the first time I ran it I got an error message saying the file could not be saved. So, I changed 2 lines:
From this:
wBook.SaveAs Filename:=fSaveAsFilePath
wBook.Close savechanges:=False
To this:
' wBook.SaveAs Filename:=fSaveAsFilePath
wBook.Close savechanges:=True
Question:
Some of these files may be: xls, xlxs, or xlsm. How can I modify this line to cover all of them?
fileType = "*.xlsx" 'MAKE CHANGES HERE
Brad,
Thanks for catching the double quotes. I spend most of my time in Access and don't know a lot of the little tricks in Excel. Isn't there something else I can use to refer to a blank cell? I never understood why an Excel formula returns 0 when pointing to an empty cell.
Rob,
You are correct. There is some redundancy in that formula. Someone on EE helped me with that back in the spring. I have no idea what INDEX is doing. I must have modified it at some point and failed to realize what I had done. I will check out the link you provided.
Thanks, Dale
That's awesome. I got it to work just fine. However, I want to point out that the first time I ran it I got an error message saying the file could not be saved. So, I changed 2 lines:
From this:
wBook.SaveAs Filename:=fSaveAsFilePath
wBook.Close savechanges:=False
To this:
' wBook.SaveAs Filename:=fSaveAsFilePath
wBook.Close savechanges:=True
Question:
Some of these files may be: xls, xlxs, or xlsm. How can I modify this line to cover all of them?
fileType = "*.xlsx" 'MAKE CHANGES HERE
Brad,
Thanks for catching the double quotes. I spend most of my time in Access and don't know a lot of the little tricks in Excel. Isn't there something else I can use to refer to a blank cell? I never understood why an Excel formula returns 0 when pointing to an empty cell.
Rob,
You are correct. There is some redundancy in that formula. Someone on EE helped me with that back in the spring. I have no idea what INDEX is doing. I must have modified it at some point and failed to realize what I had done. I will check out the link you provided.
Thanks, Dale
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Here's an example...
See "MAKE CHANGES HERE" for where changes need to be made to customize your application.
Here's the code:
Open in new window
See attached,Hopefully, you can take it from here. However, if you need more help, you'll need to provide sheet name and addresses where things need to be changed, etc., to be precise.
Dave
loopAndFixFormulas-r1.xlsm