Runtime Error 1004 Copy Formula Array - vba

I have the following array formula in cell B2 in my Excel spreadsheet:
{=IF(COUNT(IF(ISNUMBER(A30:A1000);IF(B30:B1000>A30:A1000-1;A30:A1000)))>=COUNT(IF(ISNUMBER(A30:A1000);COUNT(B30:B1000>A30:A1000-1;A30:A1000)));COUNT(IF(ISNUMBER(A30:A1000);COUNT(B30:B1000>A30:A1000-1;A30:A1000))))}
Now I want to use the following VBA code to copy this code into cell A2:
Sheets("Sheet1").Range("A2").FormulaArray = Sheets("Sheet1").Range("B2").Formula
However, when I use this code I get runtime error 1004.
Do you have any idea how to solve this issue?

Your array formula is too long to pass along like that as the Range.FormulaArray property.
You don't need to keep repeating all of the conditions. As you cycle through rows 30 to 1000, if the first or second condition fails, the remainder of the formula for that cycle is not processed. IFs in a formula stop processing at the first FALSE.
=IF(COUNT(IF(ISNUMBER(A30:A1000), IF(B30:B1000>A30:A1000-1, A30:A1000)))>=COUNT(B30:B1000>A30:A1000-1,A30:A1000),COUNT(B30:B1000>A30:A1000-1,A30:A1000))
Now the code works just fine.
With Worksheets("Sheet3")
.Range("A2").FormulaArray = .Range("b2").Formula
End With
Note that I could not test this using semi-colons as the system list separator; only with my own system's commas. VBA does not like anything by EN-US regional settings in a .Formula, .FormulaR1C1 or .FormulaArray property. If you still have trouble, use debug,print to see how the .Formula is being returned. If it contains semi-colons, then use,
With Worksheets("Sheet3")
.Range("A2").FormulaArray = Replace(.Range("b2").Formula, Chr(59), Chr(44))
End With

Related

VBA Runtime error 1004 when trying to access range of sheet

I am building a small vba script that is merging tables from several workbook into one single worksheet of another workbook. The error is raised when I try to set the destination range's value:
wksPivotData.Range(wksPivotData.Cells(CurrentRow, 1)).Resize(tbl.ListRows.Count, tbl.ListColumns.Count).Value = _
tbl.Range.Value
The error: "Run-time error '1004': Application-Defined or object-defined error"
I went through similar questions, and the general answer is what I found in this one: The selected cell belongs to another worksheet than the one desired.
While this makes complete sense, I still can't figure why my code breaks as I'm only using numerical reference (CurrentRow is a Long) and Resize, which should prevent me from doing such a mistake.
Additionally, I ran a couple quick tests in the Immediate window and it turns out that while the worksheet wksPivotData exists and I can access its name and a cell value, the range function simply doesn't work:
Debug.Print wksPivotData.Name
PivotData
Debug.Print wksPivotData.Cells(1, 1).Value
123
Both of those work but the next one doesn't:
Debug.Print wksPivotData.Range(1, 1).Value
Your last line, Debug.Print wksPivotData.Range(1, 1).Value won't print because you're misuing Range(). I assume you want A1?
When using Range(1,1), you're referring to a non-existent range. If you want to do cell A1, you need
With wksPivotData
myData = .Range(.Cells(1,1),.Cells(1,1)).Value
End with
Since you're using multiple worksheets, I'd use the with statement as above. Another way to write the same thing is wksPivotData.Range(wksPivotData.Cells(1,1),wksPivotData.Cells(1,1)) (You need to explicitly tell Excel what sheet you want to refer to when using Range() and cells().
Finally, for your resize, if I recall correctly, you're going to have to add the same Cell() twice in your range:
wksPivotData.Range(wksPivotData.Cells(CurrentRow, 1),ksPivotData.Cells(CurrentRow, 1)).Resize(tbl.ListRows.Count, tbl.ListColumns.Count).Value = _
tbl.Range.Value
Or, for the same thing, but different way of doing it:
With wksPivotData
.Range(.Cells(currentRow, 1), .Cells(currentRow, 1)).Resize(tbl.ListedRows.Count, tbl.ListColumns.Count).Value = tbl.Range.Value
End With

VBA - getting column # with Find(), get error 91 - object var. or with block var. not set

I have a VBA script wherein I am trying to use find() to get the column number of a column on a separate worksheet (same workbook).
So, from "Sheet 1" I run this macro, to find the column on "Sheet 2" that has the word "Ins Val" in row 1. What's odd is that earlier in the macro, I use the same formula to get a column number without issue. However, the below code throws a "Run Time Error 91, Object Variable or With Block Not Set" but I can't figure why.
dim useDataWS as Worksheet, typeValColumn as Integer, theType as String, mainWS as Worksheet
Set mainWS = worksheets("Sheet 1")
Set useDataWS = worksheets("Sheet 2")
theType = mainWS.Cells(49,5).Value
'' the below line gives the error
typeValColumn = useDataWS.rows(1).Find(what:=theType, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False).Column
But, earlier in that macro, I do the same thing- with no error :?
With useDataWS
noOneCol = .Rows(1).Find(what:=theType, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False).Column
End With
Note: Even if I change that first part to use "with", the same error occurrs.
Any ideas? (Note: It's a more robust script, but I tried to get the parts that apply. If there's something else that might be causing this, let me know what other kinds of things I'm doing that could mess this up and I'll post more of the code).
edit: Thanks #Branislav Kollár - using search by "xlFormulas" instead of "xlValues" solves the issue. (Although I still don't know why Excel throws the error with 'values', but hey - it works!)
The reason, why the following line
typeValColumn = useDataWS.rows(1).Find(what:=theType, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False).Column
was giving an error is because the Find()method found Nothing, and applying .column to a Nothing results in error.
Solution can be replacing LookIn:=xlValues with LookIn:=xlFormulas.
I'd like to provide more info about why it does work, but I don't know honestly. One thing I found out is that LookIn:=xlFormulas will find even hidden cells and I guess it has more general usage.
More about Find() method can be found on MSDN Range.Find Method, or Find Method in Excel VBA or .Find and .FindNext in Excel VBA
Sometimes it is better to revert back to the native worksheet functions. While .Find is better for a worksheet-wide search, both .CountIf and .Match can easily locate a value in a single row or column. I typically use .CountIf to see if the value if there and .Match to retrieve the column index number.
with useDataWS
if cbool(application.countif(.rows(1), theType)) then
typeValColumn = application.match(theType, .rows(1), 0)
else
debug.print "not found in row 1"
end if
end if
You can also check for the value's existence with If IsError(app.Match(...)) but I prefer the two-function approach. If you can write a MATCH worksheet function that does not return #N/A then the above code will locate theType.
This is not so much an answer as a quick diagnostic tool. You swear that Ins Val is in row 1 of Sheet 2. Put this formula in the cell directly below the one containing Ins Val.
=CODE(MID(H$1, ROW(1:1), 1))
Adjust H$1 for the cell that actually contains Ins Val and fill down for at least 9 rows.
Excel 2013 addendum:
Excel 2013 introduced the UNICODE function that may be more appropriate for this purpose.
=UNICODE(MID(H$1, ROW(1:1), 1))
        
If you are receiving anything other than the results shown above, then you have rogue characters in the cell value.
The easiest one-off solution is to retype the value. If this is a repeated import then other methods need to be in place to compensate. The best method is to adjust the import at the source but that is not always possible. The worksheet function CLEAN does a reasonable job of removing rogue characters but it is not the best. Sometimes custom routines need to be written that address specific circumstances.

Excel VBA conditional formatting auto-change

Question:
Is there anything that would cause the Formula1 parameter of the FormatConditions.Add method to change automatically, or to change from what is hard-coded in an Excel-VBA macro?
If so, where is the documentation for this behavior?
Description of Problem:
When applying the FormatConditions.Add method to a range, the formula does not match what is specified in the code.
My macro code assigns a formula to a variable named ConditionalRangeFormula. After running the macro the actual conditional formatting formula does not match ConditionalRangeFormula, and the row in the formula does not match the row that was specified in the code. See the "Details" section below for more info.
Hypothesis:
Note 1:
I've noticed that with a range, Excel will automatically "fit" a conditional formatting formula to match the specifics for each cell in a range. For example, in a worksheet with random numbers between 1 and 10 in column A:
I choose column A.
I add a conditional format to column A, with a formula "=IF(A1=2,1)". The cell font is formatted bold red if this formula is true.
Every cell in column A that contains "2" will be bold red, not just cell A1, even though the formula is just for A1.
Is it possible that in the background Excel is doing some changing of my formula in the code above, in an attempt to "guess" what the formula actually should be?
Note 2:
I don't think this is a result of using too many conditional formats for a range. In Microsoft's Excel developer notes for "FormatConditions.Add Method", there is a remark that "You cannot define more than three conditional formats for a range." However, I've successfully added more than three conditional formats with no changes (see details below). Also, I've tested with all other conditional formatting commented out (inactivated), so that only one conditional format is applied, with no changes.
Details:
I'm using Excel 2007 on a Win7 machine.
My code is a little more complex than the example given in the hypothesis above.
The conditional format function is designed to check if a cell in column "AP" is blank, then apply a red outline.
If I place a breakpoint at the With conditionalRange.FormatConditions _.add(xlExpression, , ConditionalRangeFormula) line, I can confirm ConditionalRangeFormula is correct ("=ISBLANK($AP1)"). However, after running, the conditional formatting formula for every cell in the specified range is "=ISBLANK($AP2)". This does what my code specifies.
Please note the working range (ConditionalRange is the code below) actually starts with row 2 of column AP, since row 1 is a header row. As an interesting note, if I make ConditionalRangeFormula "=ISBLANK($AP2)", the conditional formatting formula for every cell in the specified range is "=ISBLANK($AP3)". Notice how the row in the formula is +1 from what is hard coded, just as in the first situation described in the previous paragraph. Interesting behavior, but I can't find documentation for this.
Also, please note that there are four With...End With statements that apply conditional formatting to that cell, before the conditional formatting that gives problems is applied. Each of those first four statements use formulas that work as expected, so I've simplified those code blocks to make the overall code easier to follow. See "Note 2" under the Hypothesis section above for more details.
Here is the code outline:
'define string to identify workbook
Dim w2 As String
w2 = "myworksheet.xlsx"
'define ws2 as worksheet to work on
Dim ws2 As Worksheet: Set ws2 = Workbooks(w2).Worksheets(1)
'define working range
Dim ws2r As range
Set ws2r = ws2.range("E2", ws2.range("E2").End(xlDown))
'add conditional formatting to the working range
With ws2
'see below for .colDiff function
Set ConditionalRange = ws2r.Offset(0, colDiff("E", "AP"))
'The following 4 With...End With statements assign other
'conditional formats, none of which have problems.
'I've simplified these statements to outline what's being done.
'See the last (5th) With...End With statement for
'the unexpected behavior.
WithConditionalRange.FormatConditions _
.add(xlExpression, , ADifferentFormula1)
.Font.Color = someRGBValue
End With
WithConditionalRange.FormatConditions _
.add(xlExpression, , ADifferentFormula2)
.Font.Color = someRGBValue
End With
WithConditionalRange.FormatConditions _
.add(xlExpression, , ADifferentFormula3)
.Font.Color = someRGBValue
End With
WithConditionalRange.FormatConditions _
.add(xlExpression, , ADifferentFormula4)
.Font.Color = someRGBValue
End With
'This With...End With block has unexpected behavior.
ConditionalRangeFormula = "=ISBLANK($AP1)"
With ConditionalRange.FormatConditions _
.add(xlExpression, , ConditionalRangeFormula)
.Borders.color = RGB(192, 0, 0)
End With
End With 'with ws2
Here's the "colDiff" function called in the procedure above:
Public Function colDiff(col1 As String, col2 As String) As Long
With ActiveSheet
'return the number of columns between col1 and col2
colDiff = Abs(.range(col1 & "1").Column - .range(col2 & "1").Column)
End With
End Function
I tested this functionality by placing a header "Data" in AP1, placing random data from AP2 to AP16, then deleting AP1,5,7,13 to make BLANKS and the following worked correctly:
Public Sub Test()
With Range("E2:AP16").FormatConditions.Add(xlExpression, , "=ISBLANK($AP2)")
.Borders.Color = RGB(192, 0, 0)
End With
End Sub
Does the above single function work correctly for you? If not, I would suspect that perhaps there are merged cells or some other spreadsheet specific issue going on.

did I accidentally create a vba race condition?

I was hoping for some insight on a bug that I haven't been able to replicate.
I have a very complicated worksheet that changes many variables to get a certain cell aa5 to return a string. if any condition is not met, it returns 0. the formula for that cell is
=IF(SUM(AA2:AA4)=0,SubItem,0)
where aa2:aa4 are the conditions which must be 0 to return a string and subitem is a named cell range.
Once it returns a string, I have a module to paste the cell aa5 onto a different sheet export. The problem is that after I run the routine, (it takes about 20 min) I find 0 values in the export sheet.
I have tried manually changing all the variables to the condition that created the error and none appears. I've also tried running through the code line-by-line and can't seem to replicate it there either.
My last straw was inserting in the module that pastes into export sheet
If Worksheets("analysis").Range("aa5").Value = 0 Then
Exit Sub
And still I have 0 values after running!
I am not really a programmer but I have some experience with VBA code, is it possible I've created a race condition where the 0 is copied before the if is updated but it still passes the vba check?
Try to calculate your value before using it in VBA:
With Worksheets("analysis").Range("aa5")
.Calculate
If .Value <> 0 Then
Worksheets("export").Range("A1").Value = .Value
End If
End With

How do I convert this Excel formula into VBA code?

'I am using this formula in an Excel worksheet, in cell A6. It is working fine.
=IF(O6="Hand","Manual Entry",IF(O6="JET",R6,IF(O6="COKE","Red Bull",IF(O6="Freight","Logistics",IF(O6="TAX","Tax",IF(O6="TRANSFER COST","Transfer Cost Transactions",IFERROR(IF(FIND("INV#",R6,1)>=1,MID(R6,FIND("INV#",R6,1),10),""),"")))))))
Now, my question is: how do I convert this to VBA? I have tried recording it, and the code is as follows:
ActiveCell.FormulaR1C1 = _
"=IF(RC[14]=""Hand"",""Manual Entry JE"",IF(RC[14]=""JET"",RC[17],IF(RC[14]=""COKE"",""Red Bull"",IF(RC[14]=""FREIGHT"",""Logistics"",IF(RC[14]=""TAX"",""Tax"",IF(RC[14]=""TRANSFER COST"",""Transfer Cost Transactions"",IFERROR(IF(FIND(""INV#"",RC[17],1)>=1,MID(RC[17],FIND(""INV#"",RC[17]" & _
"""""),"""")))))))"
When I run this, I am receiving Run Time Error 1004: Application-defined or object-defined error.So I Changed this to something like this, this doing same as above formula except the find option, everything is running fine.
![VBA For Above formula][Any Help on the find?]
End sub.How do i get the fine option in the above VBA code.`
This works for me:
Range("L6").Formula = "=IF(O6=""Hand"",""Manual Entry"",IF(O6=""JET"",R6,IF(O6=""COKE"",""Red Bull"",IF(O6=""Freight"",""Logistics"",IF(O6=""TAX"",""Tax"",IF(O6=""TRANSFER COST"",""Transfer Cost Transactions"",IFERROR(IF(FIND(""INV#"",R6,1)>=1,MID(R6,FIND(""INV#"",R6,1),10),""""),"""")))))))"
This is just your original Excel formula, but with the " characters escaped as "".
You need to escape your quotes.
ActiveCell.Formula = "=IF(O6=""Hand"",""Manual Entry"",IF(O6=""JET"",R6,IF(O6=""COKE"",""Red Bull"",IF(O6=""Freight"",""Logistics"",IF(O6=""TAX"",""Tax"",IF(O6=""TRANSFER COST"",""Transfer Cost Transactions"",IFERROR(IF(FIND(""INV#"",R6,1)>=1,MID(R6,FIND(""INV#"",R6,1),10),""""),"""")))))))"
And use .Formula since you're using specific cell names that are not relative to the currently selected cell.