I have a formula that works perfectly well in a spreadsheet, but when I try to automate the creation of the formula using VBA, I get the 1004 run time error.
I have a 3 stage process, each with a start and finish date (so 6 separate date columns). This formula looks at the series dates and calculates the time lost between each stage using the NETWORKDAYS function.
I thought the simple way to overcome this problem was to record a macro of me pasting this formula into a cell, which would generate the required VBA code that I could then adapt, but even using this method causes the 1004 error.
I'm wondering whether it's the length of the formula that's the problem? I've tried replacing the double quotation marks with & Chr(34) & Chr(34) & and I've tried assigning the formula to a variable. I can get it to work if I add it as text using .value instead of .formulaR1C1, or if I add an apostrophe to the start of the formula string. It appears to be the fact that its a formula that causes the problem. Any help is greatly appreciated.
The formula from the cell in the spreadsheet:
=IF(AND(I2="",J2="",K2="",L2=""),"",IF(AND(G2="",H2="",K2="",L2=""),"",IF(AND(G2="",H2="",I2="",J2=""),"",IF(AND(H2<>"",I2<>"",J2<>"",K2<>""),IF(NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2<1,"",NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2),IF(AND(H2<>"",I2<>""),IF(NETWORKDAYS(H2,I2)-2<1,"",NETWORKDAYS(H2,I2)-2),IF(AND(H2<>"",K2<>""),IF(NETWORKDAYS(H2,K2)-2<1,"",NETWORKDAYS(H2,K2)-2),IF(AND(J2<>"",K2<>""),IF(NETWORKDAYS(J2,K2)-2<1,"",NETWORKDAYS(J2,K2)-2),"")))))))
The code that the macro records when I enter the formula into the cell:
ActiveCell.FormulaR1C1 = _
"=IF(AND(RC[-10]="""",RC[-9]="""",RC[-8]="""",RC[-7]=""""),"""",IF(AND(RC[-12]="""",RC[-11]="""",RC[-8]="""",RC[-7]=""""),"""",IF(AND(RC[-12]="""",RC[-11]="""",RC[-10]="""",RC[-9]=""""),"""",IF(AND(RC[-11]<>"""",RC[-10]<>"""",RC[-9]<>"""",RC[-8]<>""""),IF(NETWORKDAYS(RC[-11],RC[-10])-2+NETWORKDAYS(RC[-9],RC[-8])-2<1,"""",NETWORKDAYS(RC[-11],RC[-10])-2+NETWORKDAYS(RC[" & _
"8])-2),IF(AND(RC[-11]<>"""",RC[-10]<>""""),IF(NETWORKDAYS(RC[-11],RC[-10])-2<1,"""",NETWORKDAYS(RC[-11],RC[-10])-2),IF(AND(RC[-11]<>"""",RC[-8]<>""""),IF(NETWORKDAYS(RC[-11],RC[-8])-2<1,"""",NETWORKDAYS(RC[-11],RC[-8])-2),IF(AND(RC[-9]<>"""",RC[-8]<>""""),IF(NETWORKDAYS(RC[-9],RC[-8])-2<1,"""",NETWORKDAYS(RC[-9],RC[-8])-2),"""")))))))"
Consider:
Sub EvilFormula()
Dim st As String, DQ As String
DQ = Chr(34) & Chr(34)
st = "=IF(AND(I2=~,J2=~,K2=~,L2=~),~,IF(AND(G2=~,H2=~,K2=~,L2=~),~,IF(AND(G2=~,H2=~,I2=~,J2=~),~,IF(AND(H2<>~,I2<>~,J2<>~,K2<>~),IF(NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2<1,~,NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2),IF(AND(H2<>~,I2<>~),IF(NETWORKDAYS(H2,I2)-2<1,~,NETWORKDAYS(H2,I2)-2),IF(AND(H2<>~,K2<>~),IF(NETWORKDAYS(H2,K2)-2<1,~,NETWORKDAYS(H2,K2)-2),IF(AND(J2<>~,K2<>~),IF(NETWORKDAYS(J2,K2)-2<1,~,NETWORKDAYS(J2,K2)-2),~)))))))"
st = Replace(st, "~", DQ)
ActiveCell.Formula = st
End Sub
Here we first construct a String that represents the formula, but uses tildas in place of pairs of double-quotes. We replace the tildas and deposit the formula.I use this to avoid migraine headaches.
Related
I have a worksheet with data and some columns which I fill with formulas via vba. The formula I struggle with is an array formula that looks like this:
Workbooks(job_file).Worksheets(1).Cells(h + b, 195).Formula = _
"{=IF(MAX(IF(B2:M2>$FY" & currentRow & ",$B$1:$M$1))=0,0," & _
"MAX(IF(sheet1!B2:M2>$FY" & currentRow & "," & _
"sheet1!$B$1:$M$1)))+1}"
It's supposed to be an array formula, so that's why I put {} there. However, when run it simply display the formula's text in a cell, without calculating it. I have to manually remove the brackets, and then press Ctrl+Shift+Enter myself.
Is there any way to avoid it? I have a great many rows and I can't ctrlshiftenter each.
I tried running it without brackets, it works, but gives a #VALUE! error, which can also be fixed by applying Ctrl+Shift+Enter.
To create an array formula with a simulated ctrl+shift+enter (aka CSE), use the Range.FormulaArray Property instead of the Range.Formula Property and let Excel add the 'curly braces'.
with Workbooks(job_file).Worksheets(1)
.Cells(h + b, 195).FormulaArray = _
"=IF(MAX(IF(B2:M2>$FY" & currentRow & ",$B$1:$M$1))=0,0," & _
"MAX(IF(sheet1!B2:M2>$FY" & currentRow & ", sheet1!$B$1:$M$1)))+1"
end with
I noticed in your formula that you use B2:M2 and sheet1!B2:M2. Shouldn't they both be sheet1!B2:M2?
There are some considerations.
Runtime Error: 1004 - Too long. There is a reduced character limit of 255 for FormulaArray but there are work-arounds.
Runtime Error: 1004 - Broken String. Remember that all quotes within a quoted string must be doubled up. This is easily one of the most common causes of errors when trying to write a formula into a cell through VBA. Hint: TEXT(,) can be used instead of "" so you don't have to type """" for a zero-length string.
FormulaArray accepts both xlR1C1 and xlA1 style formulas. If you can wrap your head around xlR1C1 style formula syntax, it is generally easier to construct a concatenated formula string in xlR1C1 since you can use digits to represent column numbers instead of trying to convert column ordinals to a column letter. However, do not try to mix-and-match xlA1 and xlR1C1 range references in the same formula; they must all be one style or the other.
If you are having trouble formulating a string that will be accepted as a formula, put a tick (e.g. ' ) in front of the first equals sign then run the code and return to the worksheet to see what was put in. Make modifications on the worksheet until you have a working formula then transfer those modifications to the VBA code.
As a note, it looks like this can be done without an array formula, like so:
Workbooks(job_file).Worksheets(1).Cells(h + b, 195).Formula = _
"=IF($FY" & currentRow & ">MAX(B2:M2),0," & _
"MAX(INDEX((B2:M2>$FY" & currentRow & ")*$B$1:$M$1,)))+1"
I'm trying to use this in my VBA code:
ActiveSheet.Range("A1:A1:).Formula = "='Sheet1'!A1" & Chr(34) & Chr(47) & Chr(34) & "'Sheet1'!A2"
This gives me Error: 1004, Object-defined error.
I'd like to see in the cell formula that:
='Sheet1'!A1"/"'Sheet1'!A2
And if the value of the A1 cell is 10 and the A2 value is 20, the cell value should look like that: 10/20
What can be the problem?
I assume you want the formula to either read:
='Sheet1'!A1&"/"&'Sheet1'!A2 (so: textual concatenation of A1 & A2 with a "/" in between)
or
='Sheet1'!A1/'Sheet1'!A2 (so: the result of dividing A1 by A2)
Check the result of your formula: it generates neither :) (it results in an invalid formula) And, as Jordan answered, your VBA used a colon instead of a double quote.
UPDATE (read over the fact that you asked for textual concatenation in your question, and also adding a solution)
It's best to check the result of your formula build-up while stepping through VBA with the debugger (F8): it generates an invalid formula, on which Excel will no doubt give you an error when you try to set it. The result doesn't contain any & characters to concatenate the values of A1 & A2 with the "/" in between.
The correct formula should be:
='Sheet1'!A1&"/"&'Sheet1'!A2
This is achieved by:
ActiveSheet.Range("A1").Formula = "='Sheet1'!A1&""/""&'Sheet1'!A2"
(note that you can embed a " in a VBA string by doubling it; in this case that is clearer to read than using Chr(34) for the "'s)
First of all you have a colon instead of a speech mark within Range. You could try something like:
ActiveSheet.Range("A1").Value = Sheet("Sheet1").Range("A1").Value & "/" & Sheet("Sheet1").Range("A2").Value
I'd also recommend not using ActiveSheet as much as possible and also referring to the workbook in references. If you want to refer to the workbook that contains the VBA code you can use ThisWorkbook.
Is it possible to write formulas across a range in Excel from VB.Net? I'm using a String array to hold a list of formulas that I would like to apply to an Excel range, instead of looping through and writing them one at a time.
This line is what I am attempting to use to write to a range:
xlWorkSheet.Range("AF" & intCurrentRow.ToString & ":AG" & intCurrentRow.ToString).Formula = formulas
The formula is being written to Excel, but Excel is actually displaying the formula, instead of the calculated value. If I write each formula to each cell like this:
xlWorkSheet.Range("AF" & intCurrentRow.ToString).Formula = formulas(0)
xlWorkSheet.Range("AG" & intCurrentRow.ToString).Formula = formulas(1)
It works perfectly fine and Excel displays the calculated values as it should. Almost seems like I'm missing a step but I haven't been able to find anything in my research.
As soon as I hit post I figured out the problem. Instead of using the .Formula property of an Excel.Range, you have to use the .FormulaArray property instead.
xlWorkSheet.Range("AF" & intCurrentRow.ToString & ":AG" & intCurrentRow.ToString).FormulaArray = formulas
I am trying to write this formula using VBA:
ActiveCell.Value = "=f(R[-1]C[0],Sheet1!" & ColumnLetter & i & ")"
Where ColumnLetter is some variable letter which my macro computes earlier, and f is some function, and i is some number.
The problem is that when I run this, the cell is given this instead: (if ColumnLetter = F, i = 16):
=f(R[-1]C[0],Sheet1!'F16')
but I want:
=f(R[-1]C[0],Sheet1!F16)
Why is VBA or Excel putting those single quotation marks around F16? It does not insert these extra quotation marks if I do not include R[-1][0] as an argument in my formula, but I need to include this.
Help much appreciated!
Its the combination of R1C1 and A1 addressing. You need to pick one method and use it for both parts.
Note that if you type =f(R[-1]C[0],Sheet1!F16) into a cell you will get an error for the same reason.
You say you need to use R1C1 style for the first address, but (assuming this is because you don't want
absolute address) you can use .Offset instead
ActiveCell.Value = "=f(" & ActiveCell.Offset(-1, 0).Address(False, False) _
& ",Sheet1!" & ColumnLetter & i & ")"
The Apostrophe means to Excel that it should interpret it as text.
Write it to ActiveCell.Formula. That way it is recognized as Formula.
I'm having some trouble with VLOOKUP in my VBA. Here's an example of the code I'm using:
Sub Macro15()
'
' Macro15 Macro
Dim LR As Long
LR = Cells(Rows.Count, "A").End(xlUp).Row
Range("B1:B" & LR).FormulaR1C1 = _
"=VLOOKUP(RC[-1],'https://internal_sharepoint_address
/[Vendor_Information.xlsx]Sheet1'!R3C3:R150C18,4,FALSE)"
Range("C1:C" & LR).FormulaR1C1 = _
"=VLOOKUP(RC[-2],'https://internal_sharepoint_address
/[Vendor_Information.xlsx]Sheet1'!R3C3:R150C18,5,FALSE)"
With Range("B1:C" & LR)
.Value = .Value
End With
End Sub
The problem is that the values in Columns B & C (the VLOOKUP formulas) return a value of #N/A.
However, if I stop the code before converting the formula to values (the "With Range("B1:C" & LR)" line), the VLOOKUP formula returns the correct values.
Also strange - if I clear the contents of Columns B & C and re-run the above code, the values return fine. If I try to add a second cycle to the VBA, however, it does NOT work.
Any wisdom that anyone can provide would be a huge help. I've been stuck on this for a long time, and I'm just at my wit's end.
Thanks all,
David
You'll probably need to add in a step that runs a calculation cycle before you try to replace with the value:
Application.Calculate
Edit from comment: I would imagine that retrieving lookup data from a linked workbook on a Sharepoint site would take awhile. Maybe add some delay loops? Can you make two separate macros (one ending with the formulas, and a second one starting at the Paste Values), and run them separately with a pause in between?