Added an extra variable to a VBA function - now has compile error stating Expected:= - excel

I have a VBA function that worked fine, until I tried to pass an extra variable to it. Now the code won't run, and I get an error stating Expected:=, I've tried renaming the function, but no help.
Was - Function GetData(site_add)
Changed to Function GetData(site_add, temporary) and failed - despite changing the call to the function accordingly...!?!
Is it possible that the compiler is glitching and I should focus on that? I have other functions in the code that use 5 call 5 variables and don't even call/use them all...!? Help...

By adding the second parameter, you are effectively telling the compiler that every call to this method now requires two parameters instead of one. So you have to find everywhere you call the GetData() function and make sure it now passes two parameters instead of one, even if the second parameter is Nothing. Now, if you want it to default to nothing so you don't need to pass it you can rewrite it as
GetData(site_add, Optional temporary)
*my vb is rusty, so take my example with a grain of salt please.

Related

Office script, Delete range name ignored, no errors

I just created this tiny Office script:
async function main(context: Excel.RequestContext) {
context.workbook.names.getItem("Newname").delete;
}
The range name 'Newname' exists in the current workbook, the code runs without error but the name is not deleted. Why? I would expect to receive a runtime error if I'm not allowed to delete range names.
I think it missed the bracket:
context.workbook.names.getItem("Newname").delete();
I just tried by this gist, you could have a try. https://gist.github.com/lumine2008/f55a6265a93b421112de210b22e9a48a
delete is a method. In JavaScript, a method requires opening and closing parentheses, even if there are no parameters to be passed:
context.workbook.names.getItem("Newname").delete();
My tests confirm this. Also, the code should include await.context.sync();
It's important to realize that JavaScript supports assigning a method to a variable (object), similar to assigning a function to an Excel Name, by leaving off the parentheses. This object can then be used at some point to execute the method. This is why no errors are thrown when the parentheses are omitted.
Example:
const deleteNewName = context.workbook.names.getItem("Newname").delete;
deleteNewName();
(Thanks to Lumpenstein for this information about JS kindly provided in a comment.)

Passing argument to lua function after evaluating function in string

I have functions process and matrix. The following code works
process(matrix({{2,4,6},{8,10,12},{14,16,20}}))
However the following doesn't work.
n='matrix({{2,4,6},{8,10,12},{14,16,20}})'
process(n)
It throws some error. The reason is obvious that process takes n as string rather than the output of the function matrix. So the basic difficulty involved here is about evaluating string from variable n and then give it as argument to the function process. Here loadstring function is of no use as matrix is local function and can't be referred from loadstring.
Is there any work around for this? I hope that I have clearly stated the problem here. It is about evaluating (or unloading) string and then passing it as argument to another function. Any help will be appreciated. Thanks.
as matrix is local function
Lua takes local declarations seriously. If a variable is declared local, it can only be accessed by code which is statically within the local scope of that variable. Strings which you later turn into code are not statically in the local scope and therefore cannot access local variables.
Now, with Lua 5.2+, you can provide load with a second parameter, a table which represents the global environment against which that Lua chunk will be built. If that table contains a matrix value, then the loaded string can access it. For Lua 5.1, you'd have to use setfenv on the function returned to load to accomplish a similar effect. The Lua 5.2+ method would look like this:
local env = {matrix = matrix}
local func = load("return matrix({{2,4,6},{8,10,12},{14,16,20}})", nil, "t", env)
process(func())
Note the following:
You must create an explicit table which is the global environment. There's nothing you can pass that says "make my locals available"; you have to put every local you'd like to access there. Which is, generally speaking, why you pass these things as parameters or just make them globals.
You explicitly need the "return " there if you want to get the results of the call to matrix.
You have to call the function. Functions are values in Lua, so you can freely pass them around. But if you want to pass the results of a function to another function, you have to actually call it.

Compile error calling a Sub Procedure

New to VBA but years of experience with assembler, C and C#. I have created a Private Sub called CPScenarioData(wsname as String, rownum As Integer). When I call the procedure using the statement:
CPScenarioData(wsname, l)
I get an error 'Compile error: Expected =', however when I preceded the statement with Call no error occurs, why is this. I have other Private subs that I call without using Call that work fine. I am sure there is a simple answer or mistake I have made and will feel very sheepish when I see the answer but that's life. I am using Excel 2013 VBA. Thank you for your help.
It's a quirk (feature according to taste) of VB. To call a sub, you don't include brackets. So simply type:
CPScenarioData wsname, 1
Normally brackets are used to denote a Function, which returns a value. In VB you must provide a variable to receive the returned value. (Hence the compile error for missing =; it is expecting a = CPScenario(wsname, 1)).
Adding the word Call enables you to keep the brackets for Subs (equivalent of c# void).

Executing functions stored in a string

Lets say that there is a function in my Delphi app:
MsgBox
and there is a string which has MsgBox in it.
I know what most of you are going to say is that its possible, but I think it is possible because I opened the compiled exe(compiled using delphi XE2) using a Resource Editor, and that resource editor was built for Delphi. In that, I could see most of the code I wrote, as I wrote it. So since the variables names, function names etc aren't changed during compile, there should a way to execute the functions from a string, but how? Any help will be appreciated.
EDIT:
What I want to do is to create a simple interpreter/scripting engine. And this is how its supposed to work:
There are two files, scr.txt and arg.txt
scr.txt contains:
msg_show
0
arg.txt contains:
"Message"
And now let me explain what that 0 is:
First, scr.txt's first line is function name
second line tells that at which line its arguments are in the arg.txt, i.e 0 tells that "Message" is the argument for msg_show.
I hope my question is now clear.
I want to make a simple scripting engine.
In order to execute arbitrary code stored as text, you need a compiler or an interpreter. Either you need to write one yourself, or embed one that already exists. Realistically, the latter option is your best option. There are a number available but in my view it's hard to look past dwscript.
I think I've already solved my problem! The answer is in this question's first answer.
EDIT:
But with that, as for a workaround of the problem mentioned in first comment, I have a very easy solution.
You don't need to pass all the arguments/parameters to it. Just take my example:
You have two files, as mentioned in the question. Now you need to execute the files. It is as simple as that:
read the first line of scr.txt
check if it's a function. If not, skip the line
If yes, read the next line which tells the index where it's arguments are in arg.txt
pass on the index(an integer) to the "Call" function.
Now to the function which has to be executed, it should know how many arguments it needs. i.e 2
Lets say that the function is "Sum(a,b : integer)".It needs 2 arguments
Now let the function read the two arguments from arg.txt.
And its done!
I hope it will help you all.
And I can get some rep :)

Runtime Error 49, Bad DLL calling convention

Q. Excel keeps throwing the following error, whenever my addin is loaded (Runtime Error 49, Bad DLL calling convention)
The dialog starts to pop up everytime with no indication of where the error is, despite having absolutely no external DLL references.
OR
Q. Excel crashes every time I save a particular line of code.
How can this be fixed?
This error is probably occurring because of a compiler-bug.
The easiest solution to this, would be to make a small code-change and recompile.
What I usually do is,
1 -> Add a Private Enum type to the top of any module in the addin
Private Enum Something
member = 1
End Enum
2 -> Compile the addin
3 -> Restart excel
4 -> Remove the code change made. It is no longer necessary.
Even though this error refers to an external (DLL) function call, it
can be triggered by a parameter or return-value type mismatch for a
VBA-defined function or subroutine. Furthermore, when it is
triggered by these causes, the debugger sometimes displays the error
point to be a different function call, often higher in the
call-stack, including calls that have been working and stable until
the problem-situation was created. Often, the problem is triggered
by a miss-match between a fixed-type parameter-argument or return value and a
Variant or vice versa.
Example: A Variant-valued function returns a
Long value at run time that is assigned to an Integer variable.
Resolution:
Carefully check all parameter-argument and return
value types and assignment statements, especially for routines that
you have been recently working on. If any are Variant-valued functions, explicitly type-cast to the correct type for the
assignment.
If the above situation is unavoidable due to using the Application.Run method to call a routine in a different workbook (for which you have no control over the parameter definitions), as a result of the Application.Run method passing all arguments ByVal, then, if the containing routine is a Sub, try converting it to a Function with no specified return type. This seems to force a clean-up of the stack and suppresses the error condition being thrown at a higher level in the call-stack.
An object method (such as AutoFit) applied to an erroneous object variation for which that method isn’t available (such as AutoFit
being applied to a range that is neither an entire row or entire
column range). Similarly to the above scenario, the error may be
thrown at the return point of the routine in which the problem
statement exists, not at the statement itself.
Resolution: Start with fixing the
syntax problem. Unfortunately fixes that should work sometimes
continue to throw the error until the VBE editor is reset. I
haven’t deduced the minimal set of steps that resolve that issue but
something like this often works:
Explicit recompile the project.
Save the file and close it.
Re-open the file and re-run the code.
If a call to an external library function is identified as the culprit, refer to Microsoft’s documentation on the error:
Bad DLL calling convention
*Arguments passed to a dynamic-link library (DLL) must exactly match
those expected by the routine. Calling conventions deal with number,
type, and order of arguments. Your program may be calling a routine
in a DLL that is being passed the wrong type or number of arguments.
To correct this error make sure all argument types agree with those
specified in the declaration of the routine that you are calling.
Make sure you are passing the same number of arguments indicated in
the declaration of the routine that you are calling.
If the DLL routine expects arguments by value, make sure ByVal is
specified for those arguments in the declaration for the routine.
Return argument:
One thing that can be easily overlooked when
talking about procedure arguments is the return argument. Make sure
its of the correct type, or that its not missing. Excel/VBA users
are used to the fact that if you leave out a return type for a
function, the system implicitly sets the return type to Variant, and
it works with any returned data. Not so with externally declared
functions!! The return type has to be declared in the DECLARE
statement.*
Broken library references: check whether the library references for your module code are valid. In the VBA IDE, select
Tools=>References to see the list of referenced libraries and make
sure none of the checked items are marked "Missing". If so, fix
those.
Or, the best option ever:
- Rewrite the name of the routine.
- Then recompile !
You're good to go now!
For info, I also experienced "Runtime Error 49, Bad DLL calling convention" in Excel VBA code that had been running fine.
The error was pointing to an internal function call and the fix for me was to change an argument from ByVal to ByRef. There existed a call to another function where that value was already passed ByRef, so this may have been a factor.
Another way instead of "change/add something and recompile" would be to /decompile your project.
Esp. in large access/excel projects that can get ride of a lot of problems.
Just to add another possible cause, I was using the Application.OnTime method to call a public sub with a parameter. The parameter is meant to be a long (the current row), but I'm guessing it's actually passed as a string value.
Here is an example of the OnTime call:
Application.OnTime Now + TimeValue("00:00:01"), "'UpdateEditedPref " & curRow & "'"
I tried performing an arbitrary update to the code and recompiling, but this didn't fix the issue. What fixed it was changing the parameter type from long to string in the called sub:
Public Sub UpdateEditedPref(ByVal inRowStr As String)
Then you just need to convert the string to a value within the sub. Thankfully, no more error.
Update: Passing a parameter using Application.OnTime seems to have caused another error, "Cannot run the macro". I was getting this error when the worksheet was locked. I'm still using Application.OnTime, but instead of passing a parameter, I'm saving the value in a global variable and using that value in the called sub. This now appears to be working correctly.
The OnTime call now looks like this:
' Set global variable
gCurRow = curRow
Application.OnTime Now + TimeValue("00:00:01"), "UpdateEditedPref"
I had a similar issue, on my development PC it was working just fine. Funny thing was I had two separate calls to the same routine, one worked and the other didn't. On a production PC, kept getting the error. Tried renaming the routine, changing the parameters, parameter types to no avail.
What worked for me was to move the failing calling routine into the same module as the called subroutine.
The routine that was working previously was already in the same module.
In my case this was "caused" by an excessive use of the continue character _ in a single if conditional
I had already recompiled, checked all return codes, moved modules around ,restarted excel , restarted my computer, copied the code to a brand new Excel spread-sheet, I read this article and the bit about return codes made me think about how many returns can be in an if statement
I had this
If CompressIntoOneLineON(rg1, rgstart, rgend) or _
CompressIntoOneLineOS(rg1, rgstart, rgend) or _
CompressIntoOneLineOGN(rg1, rgstart, rgend) or _
CompressIntoOneLineOGS(rg1, rgstart, rgend) or _
CompressIntoOneLineGO(rg1, rgstart, rgend) Then
<code>
End If
I was getting the error when the subroutine containing this code exited
So I changed to this
matched = True
If CompressIntoOneLineON(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineOS(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineOGN(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineOGS(rg1, rgstart, rgend) Then
ElseIf CompressIntoOneLineGO(rg1, rgstart, rgend) Then
Else
matched = False
End If
if matched then
<code>
and the error went away
My experiments have shown:
The error: 'Runtime Error 49, Bad DLL calling convention' disappeared when I replaced the declarations:
Dim coll as new Collection
on
Dim coll as Collection
Set coll = New Collection
The object must explicitly become Nothing on failure of creation (if it does not itself) so that its existence can be traced.
Thanks, RubberDuck VBA

Resources