Error '424' on calling other worksheet's sub - excel

I've looked on some similar question of "Object required on calling sub", but None of them seems to help with my problem. I want to call a sub(for example, in sheet2) from a sub in sheet1 like
Private Sub Worksheet_Activate()
ThisWorkbook.ActiveSheet.Cells.Clear
Call sheet2.generate <== where the error comes from
End Sub
where generate is the sub name on sheet2 which don't require any parameter
but it tells me that Object required and sendback an error.
I've tried:
without using call
sheet2.generate
without sheet name
generate
call generate
and adding a useless parameter for calling( also added to generate sub)
call sheet2.generate(1)
but it's not working too, so i detele that parameter as it have no use in the code.
there is no problem on generate sub(which i test for many time)
still, all of the above do not work for me, can someone provide a vaild way to solve this?

I've found that the problem is not at calling function,but instead, stuffs INSIDE function have problem, and debug arrow goes function and says "error 1004", after fixing some variable problem of the function, the problem no longer shows.
BRUH

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.)

Finding out which function called other funciton in VBA excel

Problem
I have an excel file with a quite complicated VBA code behind and I am having some problems to track back and debug the errors.
Sometimes a function B gets a value that it should not get and crashes, but at this point it is not possible for me to know which other funciton called that function B, and the anylys process to finding it out is very much time consuming.
My solution
The solution could be transform all the functions I have in the following way:
Sub foo1(variable1 as string)
'do whatever
End Sub
into
Sub foo1(variable1 as string, inforvariable as string)
'do whatever
End Sub
Infovariable being the name of the function calling.
This is obviously very time consuming (refactoring everything). Besides I dont know neither how to access the name of the "sub" of funcion of the code calling, something like:
infovariable = self.name
call foo1(variable1, inforvariable)
Does not seems to exists in VBA
Some ideas?
I have a look here, here, and here
Debug your macro, put a breakpoint on the line with the problem (in case the line gets called too often, add a condition only to break upon that condition), and view the call stack (keyboard shortcut Ctrl+L).

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).

Subroutine not fully executing when called indirectly

I have a spreadsheet, with the following two subroutines in it (there's a lot more to them, but I've stripped out all the code not directly relevant to the question):
Sub HF_Reset()
Feats_Reset
End Sub
Sub Feats_Reset()
Range("TblAllFeatsSelected").Value = CVErr(xlErrNA)
Range("Test").Value = "Success"
Range("Test2").Value = 1
End Sub
Test is a single cell, Test2 is a two-cell range, TblAllFeatsSelected is a large range.
If I call Feats_Reset, it executes absolutely fine, does what it's intended to do. If I call HF_Reset, then Testgets "Success" put into it, and Test2 is filled with 1s, but TblAllFeatsSelected doesn't change. I have absolutely no clue what's going on - any ideas?
For debugging purposes, I've also tried setting Range("TblAllFeatsSelected").Value = 1 and Range("TblAllFeatsSelected").Value = 0, and again it works fine when calling Feats_Reset but not when calling HF_Reset.
EDIT: I've played some more, and traced the problem to another subroutine called in Feats_Reset. I suspect I'm not going to be able to provide enough information here to get a useful answer - it's a complicated sheet, and there's a lot of interactions that could be the problem. Bother.
EDIT2: Found the problem. The subroutine was setting TblAllFeatsSelected to the value of another range, which when calling from HF_Reset needed to have an Application.Calculate or it would justset it back to what it used to be.
Is there any way I can delete this question as not useful? It's such a specific thing, I doubt it could help anyone else.
Problem Exists Between Keyboard and Chair. I was missing an Application.Calculate in a completely different part of the code.

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