How to convert the VBA String() Function?
There’s a more-complicated-than-it-probably-needs-to-be subroutine in the Word2MediaWikiPlus codebase — called MW_SurroundHeader() — that seems to only be there to cleanup and reformat text in a Word document that has one of the Headings styles. It uses a function from VBA called simply String(), which is one of the first cases of a VBA function for which I cannot find an equivalent in VB.NET.
It turns out I found out what I needed from an oreilly.com article, and after running into a few brick walls in looking for a reference to this in MSDN, I started a more intelligent search. I kept coming back to references to the String Data Type, so I next looked at the “Strings in Visual Basic” topic that was referenced by “For more information on string manipulation…”. From there the next most logical leap was to “Building Strings in Visual Basic“, which led to “How to: Create Strings Using a StringBuilder in Visual Basic“.
Once there, I figured that since this was so helpful to me, I’d like to save someone the trouble next time so I added a little of that “Community Content” sauce that I myself appreciate so much.
Converting the Selection Object from VBA?
The MW_FontFormat() subroutine also uses a no-longer-supported VBA-ism, the Selection object. This isn’t all that well documented online either — or at least, I wasn’t able to find anything useful online to help figure out how to translate this into VB.NET. The best I could find was a mention that the Range object in VB shares some common methods & properties with the Selection object in VBA.
However, I happened to have a copy of an old book called the Microsoft Office XP Developer’s Guide, which was surprisingly results-oriented for an MSPress book. Pages 176-177 actually discuss “The Selection Object vs. the Range Object”, in which I am told that the Range object is actually superior to the Selection object, and should always be favoured wherever possible.
I’m not feeling up to the subtleties of Selection vs. Range right now, so I’ll leave this for another time.
Converting the Font Colour to HTML-compatible values?
This is another interesting puzzler… It seems that MediaWikiConvert_FontColors() calls RGB2HTML(), which calls OleConvertColor(), which calls OleTranslateColor(), which is a p/invoke to OLEAUT32.DLL. [Man, this is starting to read like a book of the Old Testament…]
I have a really strong gut instinct that there’s a managed code equivalent to this that will make the intended conversion in one step, and I intend to find it. There’s no good reason at this point to (a) have this many calls going on the stack, just to get access to a “simple” math function, or (b) to preserve an unmanaged call just because it’s been used all the way up to now.
I can think of at least three ways to try to find the managed class I’m after: search on OleTranslateColor, search on “RGB & HTML”, or start browsing books on managed web development.
According to this “Format Color for HTML” article, the call to OleTranslateColor is only necessary in cases where you’re using “system color constants” or “palette indices”. Since we’re getting very predictable input here that doesn’t appear to be using either of these two alternatives, right away we should be able to eliminate the unmanaged code.
That is, if I’m reading this right, then I should just be able to remove OleConvertColor() from the initial call in RGB2HTML() and leave the first line of code as
nRGBHex = Right("000000" & Hex(rgbColor), 6)
However, upon double-checking, it seems that other code blocks on the VBA macro are passing in some of the Word.WdColor enumeration constants — which I assume are equivalent to “system color constants”.
Rather than have the RGB2HTML() routine always thunk down to unmanaged code, it’d be smarter if we checked whether the color value of interest is a member of the Word.WdColor enumeration. But do the routines that generate the input parameter to RGB2HTML() generate either Long or WdColor values? Or alternatively, would the code implicitly convert from WdColor to Long as the RGB2HTML() routine initialized? I didn’t notice any overloaded instances of RGB2HTML() that took the input parameter as a WdColor value, so I have to assume that no matter what goes on outside this routine, all operations inside RGB2HTML() will only operate on colors of type Long.
If that assumption is correct, then we should be able to safely ignore the possibility that the input parameter may start out as a WdColor datatype, and that means we can safely eliminate the OleConvertColor() and OleTranslateColor() routines. [For the moment, having already had to dig them back up once, I’ll just comment them out and leave myself a note to delete them once I’ve had time to test these colour conversions and confirm this assumption is true.]
Colours in VBA vs. Colours in .NET
A more interesting question, however, is whether we’re losing colour fidelity in the conversions being performed here. According to VSTO For Mere Mortals, Chapter 4, “In VBA, colors are of type Long, and there are eight constants that can be used… In Visual Studio 2005, colors are of type Color, and there are more than 100 choices”.
Is it possible that the calls being used to derive the colours from the Active document are limited to the VBA colour constants, and that I should be looking to switch to other calls that return the .NET Color constants? I’ll just add this as another Task to the CodePlex project list, and deal with it later — it seems to me like this is hardly the biggest problem facing this Addin at the moment.