Object Defined or Application Defined Error, Formula String - excel

I seem to be having a type mismatch error in the below formula. Numbering, Approval, PeakShare, and RampUp are all stored as ranges, app as an integer. I believe I have escaped my quotes correctly in trying to include the value of 'app'. But I get a "Type mismatch" error in return. I have also tried including a non-variable integer and receive an "Object defined or application defined error." I have read some things about the use of indirect and approval in Excel formulas but haven't found much out there with its use in VBA, is this the problem?
formulaUp = "=IF(" & Numbering.Address(True, False) & "<" & Approval.Address & ","""", " & PeakShare.Address & " * " & RampUp.Offset(0, -"" & app & "" + 1).Address(True, False) & ")"

The type mismatch comes from
RampUp.Offset(0, -"" & app & "" + 1)
The second argument you are trying to pass to Offset does not make much sense, and throws because according to operator precedence it's (-"") & app & ("" + 1), and neither of the bracketed expressions can be calculated.
Apparently you meant
RampUp.Offset(0, -app + 1)

Related

Expression.Error when dynamically passing in Teradata SQL query (with column aliases) to ODBC query

I have a macro that prompts me for a SQL query (unless it was called by another Sub, in which case it uses the argument that was passed into its optional string parameter as the query) and then executes the query against my Teradata SQL database.
It works fine, unless there's a column alias containing a space in the query.
Example query:
SELECT 2 + 2 AS "Query Result";
Error:
Run-time error '1004':
[Expression.Error] The name 'Source' wasn't recognized. Make sure it's spelled correctly.
The line of code which I believe is the culprit is as follows (my apologies for the readability-- I recorded the macro, modified it just enough to get it to work somewhat dynamically and then haven't touched it since).
ActiveWorkbook.Queries.Add Name:=queryName, formula:= _
"let" & Chr(13) & "" & Chr(10) & " Source = Odbc.Query(""dsn=my-server-name"", " & Chr(34) & code & Chr(34) & ")" & Chr(13) & "" & Chr(10) & "in" & Chr(13) & "" & Chr(10) & " Source"
I assume it has to do with the fact that the example query above has double quotes for the alias, which are confusing the syntax when trying to be interpolated. Any help would be greatly appreciated!
Here's what the string for the formula is set to in this line:
ActiveWorkbook.Queries.Add Name:=queryName, formula:=<string here>
after all the chr() and concatenation are done:
let
Source = Odbc.Query("dsn=my-server-name", "<code>")
in
Source
That token <code> is replaced by whatever is in your variable code. So I suspect you are correct in that this formula would need to have it's double quotes escaped fully.
In other words this string you are building form Formula is going to be evaluated as code itself, and even in that evaluation it will be passing more code (your SQL) onto the Teradata server to be evaluated there.
You are in code inception. VBA code writing powerquery code writing Teradata code.
Understanding that and guessing a bit here, I'm thinking your current code variable looks something like:
code="SELECT 2 + 2 AS ""Query Result"";"
Your double quotes are already escaped for VBA. BUT because you have to survive another round of eval in powerquery you need to escape once again. Instead:
code="SELECT 2 + 2 AS """"Query Result"""";"
*I think...

Runtime Error 1004 when replacing formula

I am using the following code to add something to a Formula in VBA (for debugging purposes I am using the variable currentFormula, instead of doing it directly):
currentFormula = Range("A" & row).Formula
currentFormula = currentFormula & "+" & CStr(difference)
Range("A" & row).Formula = currentFormula
When going through the code step by step, the variable currentFormula has the correct value before the final step, e.g. "=A1/A2+0.5". However, then the script Fails with runtime error 1004. When I am Setting currentFormula manually to something like "=10+10", the script works.
CStr formats the number according to the current system locale.
Formula accepts formulas in English.
The function that converts numbers to strings in an invariant way is Str. Note that it prepends a space to positive numbers which you might want to remove:
currentFormula = currentFormula & "+" & LTrim$(Str$(difference))

How can I use Index Match as Worksheet Functions?

I have a variable named 'searchVal' that is generated dynamically. Now, I'm trying to pass this string into Index/Match, and I'm getting tripped up somewhere. Maybe it's some kind of double-quotes thing, but I tried that and it still didn't work.
Here is my non-working function.
ID = Application.WorksheetFunction.Index(Sheets(""360Tasklist"").Range(""B2:B1000""), Application.WorksheetFunction.Match(" & searchVal & ", Sheets(""360Tasklist"").Range(""C2:C1000""), 0), 0)
This isn't right either.
ID = "Application.WorksheetFunction.Index(Sheets(""360Tasklist"").Range(""B2:B1000""), Application.WorksheetFunction.Match(" & searchVal & ", Sheets(""360Tasklist"").Range(""C2:C1000""), 0), 0)"
I must be close though... Any thoughts?
Thanks.

Division by zero with positive or no divisor (vba)

I'm new to macros and vba in Excel. Currently, I'm working on a vba macro for an invoice template at work.
However, I'm running in a division by zero error that I'm having trouble tracing the cause of.
There are two specific lines of code where it pops up, sometimes..
First part:
VATRMB = 0
Second part:
VATRMB = VATRMB + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593)))
The Dim VATRMB is stored as follows:
Dim startRow As Integer, endRow As Integer, VATRMB As Single, VATEUR As Single, VATUSD As Single, VATRMBCell As Range, VATEURCell As Range, VATUSDCell As Range
The way I see it these lines should never throw up a division by zero error. In the first case there is no divisor whatsoever and in the second it is always positive.
Have any of you got an idea as to why this might cause an error? Could it have anything to do with the fact that the sub gets called multiple times, reusing the same VATRMB Dim? It should be reset after each call of the sub, right? Or could it have to do with the fact that I specify VATRMB as Single? This is appropriate for 'small' (sub-1,000,000) floating numbers, correct?
EDIT:
1. Added exact line used for calling Dim storage
2. Here is the full block of code used, maybe it helps to clarify a thing or two:
'Debug.Print Tab(10); ("Items will be searched in rows " & startRow & " thru " & endRow) 'Serves for debugging and testing
For i = startRow To endRow 'Loop the following code through all rows mentioned above
If ActiveSheet.Range("B" & i).Find("Membership") Is Nothing Then 'If nothing is returned when searching for "Membership"; i.e. if the item in this row is not a membership payment
If Not ActiveSheet.Range("H" & i).Find("RMB") Is Nothing Then 'If the value for this item is RMB denoted
'Debug.Print Tab(20); "Item on Row " & i & " is RMB denoted, VAT = " & ((ActiveSheet.Range("I" & i).Value / (1 + 0.0593)) * 0.0593) 'Serves for debugging and testing
VATRMB = VATRMB + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) 'Add row's VAT to VAT total
End If
If Not ActiveSheet.Range("H" & i).Find("EUR") Is Nothing Then 'If the value for this item is EUR denoted
'Debug.Print Tab(20); "Item on Row " & i & " is EUR denoted, VAT = " & ((ActiveSheet.Range("I" & i).Value / (1 + 0.0593)) * 0.0593) 'Serves for debugging and testing
'MsgBox VATEUR + 0.0593 * ActiveSheet.Range("I" & i).Value / (1 + 0.0593)
VATEUR = VATEUR + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) 'Add row's VAT to VAT total
End If
If Not ActiveSheet.Range("H" & i).Find("USD") Is Nothing Then 'If the value for this item is USD denoted
'Debug.Print Tab(20); "Item on Row " & i & " is USD denoted, VAT = " & ((ActiveSheet.Range("I" & i).Value / (1 + 0.0593)) * 0.0593) 'Serves for debugging and testing
VATUSD = VATUSD + (0.0593 * (ActiveSheet.Range("I" & i).Value / (1 + 0.0593))) 'Add row's VAT to VAT total
End If
Else 'Else, i.e. if the row contains a membership payment, then essentially nothing happens
'Debug.Print Tab(20); ("Item on Row " & i & " is a membership payment; no VAT paid.") 'Serves for debugging and testing
End If
Next
So what I'm trying to do is basically loop through all the items in the invoice, from startRow to endRow, and determine whether the item is a membership payment by parsing the 'type' string (column B). Then, depending on whether or not it is a membership payment determine the VAT, also checking the currency in which it is paid. The amount for the payment is stored in Column I as a floating number.
Not sure if this is the answer to your problems since you would need to provide the entirety of your workbooks etc to confirm. Nevertheless, we can create this type of "it should be impossible" situation with 100% reproducibility for not only Div0, but also for pretty much any error, with a line like:
VarX = 10 ' we can make this fail with Div0, Overflow or whatever
In our test, the problem is not actually the "direct" or "explicit" code where the error is reported, but rather, the error occurs elsewhere, and VBA in its infinite wisdom just happens to "report" the error in an odd way at an odd time (in fact it should not be reporting certain errors at all, see below).
Does your package involve any external executables, dll's, addins', etc?
If so, then that is likely the place to start.
If not, the error may actually be occurring directly or indirectly in the Range you are accessing, but not necessarily in the cell currently accessed.
Here is an example creating a "Div0" via a DLL accessed in VBA as an addin: Suppose you write a bit of code in another language, here Fortran (we use Implicit None everywhere, and everything is declared correctly etc.):
Pure Subroutine FortDLL(x, U)
:
Real(DP), Intent(In) :: x
Real(DP), Intent(Out) :: U
:
Real(DP) :: QQ
:
:
QQ = Log10(x) ! Notice this is not the return var and has nothing to do with anything on the VBA side (or so you would think)
:
U = 10.D0 ! Notice, this is the return var, and is a constant = 10.D0
:
End Subroutine FortDLL
compile as DLL and access in the usual way.
Then suppose you have some VBA as:
Function VBAFunc(x) as Variant
:
Call FortDLL(x, U)
:
Dim VarU as Variant
:
VarU = U ; you can replace this with VarU = 10, or whatever, and will get same result/failure
Now, if x < 0, then the DLL will crap out since Log10 is not defined for x < 0. This will throw a Fortran run time error, and depending on how you set this up, you can get it to throw a Div0, an Overflow (e.g. on the Fortran side the MaxExponent for a Double here is 1024, whereas on the VBA side it is around 308 depending on a number of things, etc. etc. etc. )
Now even though QQ has nothing at all to do with the VBA side, when the VBA code executes FortDLL(), it returns U = 10, and it actually does that part correctly.
HOWEVER, the DLL would have thrown a Div0 (or whatever you desire to create) error, and that "error message" is/can be buried in the return to the Call FortDLL().
If you are not using DLL's etc, it is possible that something comparable is happening in your "range" or elsewhere during you looping etc.
We have not performed explicit tests as to why the Dim as Currency "fix" works, but we are guessing that as Currency is a very special Type (it is actually a structured type with at least TWO fields), the "error message" may be buried in one of those "fields", and which may not be required/relevant to the size of number you are using, and obviating the crash by "fluke" (i.e. a kind of "lucky KLUDGE". You can test this by putting in numbers too large for Double, and requiring the full machinery of the Currency Type. If it is a "lucky KLUDGE", then one day when you are not around and somebody else is using your code, and they enter a number requiring the full Currency machinery, then it will likely crash, and nobody will know why.
Here is an alternate test, suppose you have the crash on a line like VarX = 10, then replace/amend as follows:
:
On Error Resume Next
VarX = 10
VarX = 10
:
... if this "works" (i.e. obviates the error/crash), then your problem is likely along the lines explained above (whether "external" or "internal"). In this case, basically, the "Div0 problem" is treated as a VBA error on the first time VarX is assigned 10, since the Error Trap is set, that "first time" catches and ignores the "DLL side error", and moves on.
... clearly this is just a TEST, not a solution.
This may also be Excel/Win/Compiler (and especially with GCC, compiler VERSION also since they have some pretty wacky things/changes sometimes) dependent and so the reproducibility and exact behaviour may vary.

vba Using Eval but maintaing internal string

So I am using Instr with Evaluation and facing some difficulties
The code is as follows
myIneq=">"
myString1="Hello"
myString2="el"
Evaluate( "Instr(" & myString1 & "," & myString2 & ")" & myIneq & cstr(0)
I am getting an Error 2029. Based off this msdn link I am assuming it is trying to evaluate "Hello" as a variable name. What is the work around for this, I know there must be one.
Thanks
I infer from the Error 2029 (#NAME?) and the link that you're using Excel. In this case the answer is simple. Application.Evaluate evaluates Excel expressions, not VBA code. That is, any functions you call in your expression have to be things you could call from an Excel formula. (And you're correct that Excel is trying to evaluate the value of a symbol it doesn't recognize, and is thus giving you back a #NAME? error.)
There is an Excel worksheet function, FIND, that does pretty much the same thing that the VBA function Instr does, so if your example is not too simplified, that might be all you need to do.
I just typed this into the Immediate window:
x="Hello"
y="el"
?Evaluate("FIND(""" & y & """, """ & x & """)")
2
ineq = ">"
?Evaluate("FIND(""" & y & """, """ & x & """)" & ineq & "0")
True
and it seems to work.
Note that Evaluate is a function, so it expects to receive a string argument, and then return what that string evaluates to if treated as an Excel formula-syntax expression. In your example, you don't seem to be doing anything with the return value, so I thought I'd mention it.
"Evaluate" doesn't understand all excel functions.
For example, trying to evaluate "instr" will give an Error 2029. But there is a nice workaround:
"evaluate" recognizes all added vba functions of your excel sheet
so just wrap a single-line function around the reluctant function.
Code will be similar to this:
Sub test()
MsgBox Evaluate(" Instring(""Hello"",""el"") ")
Msgbox "\o/ ! ... I owe a beer to someone out there"
End Sub
Function Instring(a, b)
'make instr visible to 'evaluate'
Instring = InStr(a, b)
End Function
You're evaluating the string InStr(Hello,el).
Obviously, that's not what you want.
You need to use a quoted string literal.

Resources