VBA: my program is throwing compile error on Format - excel

So I'm working with my program. It works and runs, so I copied it and made a second version which I can add extra features to while still having a working program. I don't see any problems with my new code, so I prepare to step thru it. Suddenly things which work perfectly fine in my other version are throwing compile errors. Specifics below.
Dim elapsedTime As String
Dim startTime As Date
startTime = Now()
'code
elapsedTime = Format(Now() - startTime, "h:m:s")
I checked again and again, but this exact same code works fine in my other file. In this file, it highlights "Format" and throws the following Compile Error.
Does anyone know why excel would be getting so upset at this? If there are compile errors, should I even be looking at the places it highlights at all?

You have something named Format somewhere that's in-scope (i.e. accessible from where that Format function is being invoked), and that Format thing is shadowing the Format function you mean to call.
As YowE3K suggested if you right-click on that Format call and select "Definition" (or Shift+F2), that will take you to the shadowing declaration.
From there you have several options:
Rename the Format identifier [and possibly break a ton of things in your code]
Fully-qualify that Format call, i.e. VBA.Strings.Format, or just Strings.Format, or even VBA.Format.
My suggestion would be to fully-qualify that call, then try to compile again, and fully-qualify any/all calls that cause that same compile error. Then rename whatever it is that is named Format, so that it no longer shadows the function from the VBA standard library.
If you're using Rubberduck (an open-source VBIDE add-in project I manage), you can easily locate all references of the shadowing identifier:
The Rubberduck toolbar tells you when Format is referring to the correct function:
And you can easily locate all references to that as well, qualified or not - so it's easy to fully-qualify them wherever they are.
Rubberduck also makes it easy to refactor/rename the function, in a way that search/replace fails:
Coincidentally, a new code inspection is currently in works, specifically to locate shadowing identifiers like this.
As for the ByRef argument type mismatch, it seems your screenshot doesn't match with the code you posted, so anything is possible, but unless eqn is assigned in the body of that MakeEqn function (it should be returned, not assigned), then there's no need to pass it ByRef (implicitly or explicitly) - it can be passed ByVal (Rubberduck gives you an inspection result for that - and another for the implicit return type, and another for the implicit Public access modifier on both procedures, and several others for other issues in the code you posted).

Related

Did something change in Visual Studio 2015 IDL or MFC Macro compilation as they relate to the resulting COM Interfaces and registration?

We build an OCX that contains a Map control and many supporting classes (e.g. GeoProjection, Extents) which can act as standalone classes and many of which are also Properties of the Map.
One of our legacy applications that uses the OCX is built in Visual Basic 6. After updating the build from VS2013 to VS2015, we noticed differences in how we have to access some of the properties from VB6. The two in particular that we had problems with were the Map.GeoProjection and the Map.Extents properties. They both started raising "Library Not Registered" errors when attempting to use them.
In the case of the GeoProjection, I was able to resolve the problem simply by adding the VB 'Set' command to the assignment, as follows:
Dim gp As New GeoProjection
gp.ImportFromEPSG m_MapProjection ' contains the EPSG code
Set Map.GeoProjection = gp.Clone
Why the 'Set' wasn't required before this, I don't know. It seems like it should have been since it is setting an object reference.
Even so, when I tried to do the same with the Extents property, it did not resolve the problem, but instead resulted in an "Automation Error". So I next went to review the IDL and MFC macro definitions to see how the definitions differed and why the behavior might differ.
The GeoProjection IDL
[id(192)] IGeoProjection* GeoProjection;
end the Extents IDL
[id(17), propput, nonbrowsable] void Extents(IExtents* nNewValue);
[id(17), propget, nonbrowsable] IExtents* Extents();
The GeoProjection dispatch macro
DISP_PROPERTY_EX_ID(CMapView, "Projection", dispidProjection, GetGeoProjection, SetGeoProjection, VT_DISPATCH)
and the Extents dispatch macro
DISP_PROPERTY_EX(CMapView, "Extents", GetExtents, SetExtents, VT_DISPATCH)
What particularly struck me was the difference in using the DISP_PROPERTY_EX vs the DISP_PROPERTY_EX_ID. Ironically, I can find no Microsoft Documentation on DISP_PROPERTY_EX_ID. The only guidance I could find were comments in the afxdisp.h file, where it describes the two groups of macros, as follows:
on line 288, prior to the macros without the _ID suffix
// these DISP_ macros cause the framework to generate the DISPID
and on line 313, prior to the _ID suffixed macros
// these DISP_ macros allow the app to determine the DISPID
Since we have an .h file that defines dispatch IDs for every function, it seems that we should always use those IDs within the macros, as follows. This assures that the Dispatch IDs will always be the same (which I think would matter when using early-bound COM calls).
DISP_PROPERTY_EX_ID(CMapView, "Extents", dispidExtents, GetExtents, SetExtents, VT_DISPATCH)
Once I made changes to the Extents property in the IDL
[id(17)] IExtents* Extents;
and in the use of the DISP_PROPERTY_EX_ID macro, we were able to successfully set the Extents property from VB6 using the 'Set' statement.
In summary, I don't really know
why the behavior changed in the first place (from VS2013 to VS2015)?
why my changes made things start working again (I have my theories)?
what is the recommended methodology going forward?
a. IDL syntax allows for property definition without having to specify propput and propget. Is one syntax recommended over the other?
b. should I change all of our macros to use the _ID suffixed macro?
Any insight is appreciated.
Thank you.

Processing insists pause() is not a function, when it very much is

Aite, [first poster here, pls don't bash]
So, I'm using the sound library, which I of course remembered to import, and works just fine, proof being given by the fact that all the other functions I used work as expected and give no problems neither in editor nor in execution.
Except, of course, for this little bugger of a pause() function, which I wrote as per below using no different a syntax from all the other functions, only to find out Processing isn't very keen on accepting its existence.
Problem shows both using 3.3.6 and 3.5.
Oh, and also, apparently isPlaying() returns an int, what's up with that?
If, as I'd suspect, that single line below won't be enough code to couple with the info to get to the bottom of it, here's a Dropbox link to the code (since it uses a bunch of files) so you can test it yourself.
It kinda won't work if you try to run it as is tho because it messes up when trying to load all the songs (in the last line of setup), yeah I kinda need some help with that too... works fine if you only load the first one tho!
https://www.dropbox.com/sh/di7mwit0w2l4513/AABipGDAdoKx277f8Hg_ZfhDa?dl=0
(Please, don't expect clear, extensively commented coding. I started working on this way before I learnt that was a thing. Deeply sorry. Of course, you can ask away about anything baffling you)
What did I try, er, writing it well???
I used .play(), .stop(), the volume ones, and they all, as per stated, work fine.
import processing.sound.*;
SoundFile[] songs= new SoundFile[1];
void setup(){
songs[0]=new SoundFile(this,"Small Bump.mp3");
songs[0].play();
}
void draw(){
}
void keyPressed(){
if (songs[0].isPlaying()==1)songs[0].pause();
}
When I copy your code into my Processing editor, I get a couple errors:
songs[0]="Small Bump.mp3";
The sounds array holds instances of SoundFile, but you're trying to store a String value here. Maybe you're looking for the SoundFile constructor?
if (songs[0].isPlaying()==1)
The isPlaying() function returns a boolean value, but you're comparing it to an int value.
songs[i].pause();
You haven't declared this i variable anywhere. Probably meant for this to be a 0.
If I fix all of these errors, then your code compiles fine.
You might want to take a look at the reference for the Sound library here.
The Sound library I had installed was 1.3.2, or something of the likes.
All the references I'd read were for 2.0+.
Having updated that through the "add library" menu, all was solved.

VC++ EXE standalone has bugs that don't happen in IDE

My program has a very specific error that took me a while to track down - now I don't know how to fix it. My code is very long and in many files and I don't see much point in posting it here.
In the IDE, everything runs fine, in both Debug and Release (with the runtime library set to either /MTd or /MT, respectively, so I'm assuming all dependencies are included).
However, when I run the standalone, I get a crash. At first I thought it was a dependency problem but it doesn't seem so.
At some point in the code, I am accessing a vector via a method call: t->GetList(), where GetList is defined as std::vector<T*> & GetList() and the method simply returns a member variable (simply defined as std::vector<T*> field in the class).
It turns out, if I print out the size of the list while running from the IDE, I get 0 (which is the correct answer in this case).
However, when doing the same thing running from standalone, I get the size as 467467353.
I tried changing the method declaration to std::vector<T*> * GetList() and doing return &field; and updating the rest of the code but this didn't fix anything.
I then tried replacing the member variable field with a pointer, and in the constructor instantiating a new vector and deleting it in the destructor. Still no luck.
So I made a simple test case program that simply made a class with a vector field, and a method to return a reference to it. Then in main I would create an instance variable and getting the vector and printing the size. This worked both in VC++ and as a standalone - both returned zero.
This is driving me nuts and I can't figure out why I'm getting different behaviour. Why is the standalone running differently, and what should I be looking at to fix this?
Thanks
Okay so it was literally a bug in my code that was very well hidden. I was dynamically casting to a wrong type.
Somehow it slipped past when I was running on Windows and OSX in both Debug and Release, and as a standalone on OSX. Good thing I found it.

Finding the default project settings file

I'm trying to write a plugin for 3ds max, I went through the entire sdk installation process to the letter as described in the help files.
The problem I'm facing though is intellisence complaining about an invalid macro definition
"IntelliSense: command-line error: invalid macro definition:_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT =1"
I found the definition in project settigs -> c/c++ -> preprocessor definitions as inherited from parent or project default.
I tried disabling the inherited definitions and re-entered them, this time without the space between the name and the = and all works fine so I'm guessing its a typo on their part?
Anyway, I want to change the default project or whatever to not repeat it every time i start a new project. The project is created with a wizard which required me to copy over some files to appear and after which I had to enter the sdk path.
The files I copied are plain text with some fancy extensions and not much in them so I'm guessing the defaults are described in the sdk directory.. somewhere. Does anybody know what kind of a file I'm looking for?
EDIT: I found a file called root.vcxproj_template and it has a section for preprocessor definitions but all it contains is
<PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
and no mention of the broken one
EDIT2: in another part of the file there was a path to a property sheet (maxsdk\ProjectSettings\propertySheets\3dsmax.common.tools.settings) which included the faulty definition. I fixed it an no more complaints from VS.
_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT = 1 means that compiler should replace all old C run-time routines such as sprintf, strcpy, strtok with new versions such as strprintf_s, strcpy_s, strtok_s and similar. It goes in pair with following definition _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES = 1.
More you can find here: (MSDN) https://msdn.microsoft.com/en-us/library/ms175759.aspx. However I tried to use this but without success. It says that you can use this only for statically allocated buffers like char buffer[32], but compilers was still complaining bout unsecure strcpy.

Boo - Excel Automation, trouble selecting ranges

I'm investigating Boo and thought it would be a useful exercise to try converting a couple of venerable VB Scripts that automate Excel (2007, in this instance). A lot of things seem to translate very easily, however I'm having a huge amount of trouble selecting ranges - whenever I try to get or set them I get a TargetInvocationException Member not found.
Here's a (cut down) example I've run in booish:
def CreateInstance(progid):
type = System.Type.GetTypeFromProgID(progid)
return type()
xl as duck = CreateInstance("Excel.Application")
xl.Visible = true
xl.Workbooks.Add
sht as duck = xl.ActiveSheet
#Next line throws exception
rng as duck = sht.Range("A1")
Certain things work fine, such as setting the Name property of the sheet and so on, but how do I work with ranges? Are there some special methods that VB hides that I'd need to call, and if so how would I go about finding those out?
Cheers,
Lenny.
Range is actually a property, and it's a somewhat special property in that it works as an Indexer, which means that it has array- or dictionary-like semantics. In most languages, that means that you'd access sht.Range["A1"]. That is syntactic sugar, and really it's accessed just like any other method, namely:
sht.get_Range("A1",System.Reflection.Missing.Method)
I attempted to use Boo, Ruby and IronRuby to repeat your code, using both the syntactic sugar style and the explicit method call. In IronRuby, I can get it to work flawlessly, but only in the 32-bit interpreter. In regular Ruby, which is a 32-bit app on my configuration, it also worked fine. In the 64-bit interpreter, the Range property was never resolved correctly.
So that led me to suspect that the Boo Interactive Shell was running in 64-bit mode and that interop was failing because of that. Unfortunately, the same issues reproduced after setting my local Boo binaries to run in 32-bit mode using CORFLAGS.exe, so I don't think that's the real issue.
What did work, though, was to explicitly import the Excel Dotnet Interop Library as well as the Interop services namespaces, like so:
import Microsoft.Office.Interop.Excel
import System.Runtime.InteropServices
xl_type=typeof(Application).GetCustomAttributes(typeof(CoClassAttribute),true)[0].CoClass
xl=xl_type()
xl.Visible=true
xl.Workbooks.Add
Then:
xl.Range["A1","A2"].Value=12
xl.Range["A1",System.Type.Missing].Value="Alpha"
(xl.ActiveSheet as Worksheet).Range["A1","A2"].Value2='Whatever'
All of these work, but they essentially require you to give up the "Scriptiness" you're used to from late-binding (which is what your duck typing is doing).
One difference from VB/VBScript that is true for most languages (other than C# 4.0) is that, generally, optional parameters are not handled transparently, so you'd need to look at the API more carefully when you deal with methods that support optional parameters (replacing them with System.Type.Missing or the System.Reflection equivalent). You'd find this through the Excel interop docs, although you can probably use reflection to identify parameters marked as optional if you find that easier than looking it up.
Because Ruby has a reasonable solution for late binding these objects, I suspect there's a missing feature (or bug) in COM interop scenarios in Boo.
Edited to add: Sam Ng writes about indexed property support in C# 4.0; the issues described in his post likely apply to Boo, as well.

Resources