Does vba in word and excel uses different declaration? - vba

I am trying to use this json converter https://github.com/VBA-tools/VBA-JSON in microsoft word.
It works excelent in excel with ms-scripting runtime.
however it fails in microsoft word.
the problem I think is object type declaration.
In microsoft word this line gives error.
Set json_ParseObject = New Dictionary
after reading https://msdn.microsoft.com/en-us/library/office/gg251782.aspx
I tried converting it to
dim json_ParseObject As Dictionary.
It give error of duplicative declaration so i removed it.
it then gave error at:
Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
Does anybody have ever used this project for word-vba successfully?
I earlier asked this question while I was not aware of problem. after some research I am asking it again. Please try to understand the problem as it is real. Please guide if you thing this question is off-topic

In microsoft word this line gives error.
This is because in Word there already exists a class Dictionary but this Word class can't be created with New. So it is a collision of Scripting Runtime Dictionary and Word Dictionary.
In Word fully qualify the name of the Dictionaty type with the name of the library:
Dim d As Scripting.Dictionary
Set d = New Scripting.Dictionary

Related

Remove namespace or classname from VB.Net when used in VBA [duplicate]

Base Reference: Ten Code Conversions for VBA, Visual Basic .NET, and C#
Note: I have already created and imported a *.dll, this question is about aliases.
Let's say the programmatic name of a Test class is TestNameSpace.Test
[ProgId("TestNamespace.Test")]
public class Test ...
Now, say a C# solution has been sealed and compiled into a *.dll and I'm referencing it in a Excel's VBE. Note: at this point I cannot modify the programmatic name as if the *.dll wasn't written by me.
This is in VBA : Instead of declaring a variable like this:
Dim myTest As TestNameSpace.Test
Set myTest = new TestNameSpace.Test
I'd prefer to call it (still in VBE)
Dim myTest As Test
Set myText = new Test
In C# you would normally say
using newNameForTest = TestNamespace.Test;
newNameForTest myTest = new NewNameForTest;
Note: Assume there are no namespace conflicts in the VBA project
Question: is there an equivalent call in VBA to C# using or VB.NET imports aliases?
Interesting question (constantly using them but never thought about their exact meaning). The definition of the Imports statement (same for using) is pretty clear: its only function is shortening the references by removing the corresponding namespaces. Thus, the first question to ask is: has VBA such a thing (namespaces) at all? And the answer is no, as you can read from multiple sources; examples: Link 1 Link 2
In summary, after not having found a single reference to any VBA statement doing something similar to Imports/using and having confirmed that VBA does not consider the "structure" justifying their use (namespaces), I think that I am in a position to say: no, there is not such a thing in VBA.
Additionally you should bear in mind that it wouldn't have any real applicability. For example: when converting a VB.NET code where Imports might be used, like:
Imports Microsoft.Office.Interop.Word
...
Dim wdApp As Application
the code would be changed completely, such that the resulting string will not be so long:
Dim wdApp As Word.Application ' Prefacing the library's display name.
I think that this is a good graphical reason explaining why VBA does not need to have this kind of things: VB.NET accounts for a wide variety of realities which have to be properly classified (namespaces); VBA accounts for a much smaller number of situations and thus can afford to not perform a so systematic, long-named classification.
-------------------------- CLARIFICATION
Imports/using is a mere name shortening, that is, instead of writing whatever.whatever2.whatever3 every time you use an object of the given namespace in a Module/ Class, you add an Imports/using statement at the start which, basically, means: "for all the members of the namespace X, just forget about all the heading bla, bla".
I am not saying that you cannot emulate this kind of behaviour; just highlighting that having an in-built functionality to short names makes sense in VB.NET, where the names can become really long, but not so much in VBA.
The answer is no: there is a built-in VBE feature that recognizes the references added to a project and creates aliases at run-time(VBE's runtime) if there are no name collisions
In case of name conflicts in your registry all . dots will be replaces with _ underscores.
» ProgId's (Programmatic Identifiers)
In COM, it is only used in late-binding. It's how you make a call to create a new object
Dim myObj = CreateObject("TestNamespace.Test")
» EarlyBinding and LateBinding
In early binding you specify the type of object you are creating by using the new keyword. The name of you object should pop up with the VBA's intellisense. It has nothing to do with the ProgId. To retrieve the actual namespace used for your object type - open Object Explorer F2 and locate it there
This article explain where the names come from in Early Binding Section
use the same link for When to use late binding
for MSDN Programmatic Identifiers section please see this

VBA properties type

I know this is ultra basic in VBA but i have searched on 6 books (VBA for dummies 2010, Excel Bible, Proffesional Excel Development: The deffinitive guide, VBA and Macros Excel Microsoft 2010, Excel programming with VBA, Microsoft Excel VBA Proffesional Projects) and noone gives a deffinition about the 3 types of properties read-only, write-only and read/write.
They probably think is way to basic to even mention in their books but hey if you believed as i that computers were electricity purification filters 11 months ago and know you wanna code now someone has to tell ya a clean cut explanation
thanks for watching my question
As the names suggest
Read Only Property is a property from which you can read but not write to it. For example, For a range .Text is a Read Only Property
Msgbox Range("A1").Text
If you try to write to it, for example
ActiveSheet.Range("A1").Text = "Blah Blah"
then you will get the message showing an error Runtime Error 1004 - Unable to set the Text property of the Range Class
Write-only Property are moderately rare. Write Properties are simply properties that have Property Let or Set method but no Get Method.
Private MyName As String
Property Let sName(Value As String)
MyName = Value
End Property
Read/Write Property is pretty self explanatory. You can read and write to it. For example, for a Range .Value is a Read/Write Property
Range("A1").Value = "Blah Blah"
Extra Note: Courtesy #Mehow
When you press F2 in the Visual Basic Editor, the Object Browser pops up. If you click on any of the classes and then members of that class you can see in the left bottom corner which properties are read/write.

convert early binding to late binding without changing object type

This seems like a simple question but I after chasing forums for several hours I think it might be impossible.
I often want to convert a program from early binding to late binding. Usually, it is a vba, visual basic for applications, program that runs under Excel 2010 and windows 7 pro.
For discussion purposes, let’s pretend it is the following.
Sub EarlyBind()
' use IDE > Tools > references > and select “Microsoft Internet Controls”
Dim shellWins1 as shdocvw.shellwindows
Line1: Set shellWins1 = New SHDocVw.ShellWindows
MsgBox TypeName(shellWins1) ' this will display “IShellWindows”
' other code that expects to be working with an IshellWindows object …..
End Sub
In my experience, converting such a program to late binding is sometimes hard.
For instance, I found some forums that suggest I change it to
Set shellwins1 = createobject("Shell.applicaton")
But that creates a IShellDispatch5 object, not an IshellWindows object. That means I have to change other code to accommodate the new object type. And, of course I have to test that other code for subtle differences.
So, my goal is to find a general solution that will allow me to rewrite “Line1” to create the CORRECT object type with late binding. I also wish to avoid the need setting a reference to "Microsof Internet Controls. In other words, I want the code to look like this:
Sub LateBind()
Dim shellWins1 as object
Line1: Set shellWins1 = createobject(“xxxxxx.yyyyyy”).zzzzzz
MsgBox TypeName(shellWins1) ‘ this should display “IShellWindows”
….. other code that expects to be working with an IshellWindows object …..
End Sub
I know how to use the vba IDE to find the dll associated with the object. In this case the dll is Library SHDocVw C:\Windows\SysWOW64\ieframe.dll.
I have installed OleView and can find the associated IshellWindows “magic numbers” for the clsId, TypeLib, and Inteface (for instance the interface is 85CB6900-4D95-11CF-960C-0080C7F4EE85).
But, I don’t know how to convert them into a program id that can be used in line1 in the sample code posted above.
I hope someone here can help.
------ With MeHow's help, I now have the answer! ------
To switch 'set myObj = new xxxx.yyyyy' to late binding for arbitrary object types
Change set myObj = new xxxx.yyyyy
into set myObj = CreateObject("xxxx.yyyyy")
Very often that will work.
But, in the some cases, (e.g. "shDocVw.ShellWindows.") it gives error 429 ActiveX component cannot be created.
When that occurs I AM COMPLETELY OUT OF LUCK. It is impossible to use late binding with that EXACT object class. Instead I must find a substitute class that does approximately the same thing. (e.g. "Shell.Application").
Your short answer is
IShellWindows is an interface.
It
Provides access to the collection of open Shell windows.
Therefore
Take a look at the CreateObject() method.
Note:
Creates and returns a reference to a COM object. CreateObject cannot
be used to create instances of classes in Visual Basic unless those
classes are explicitly exposed as COM components.
IShellWindows is not exposed as a COM component so that's why there is no way to say CreateObject("SHDocVw.IShellWindows")
When you open your registry (regedit) and search for a key type in IShellWindows. If you find anything that means you've found your Prog ID and if you don't find anything it means that nothing like IShellWindows is registered as a prog Id therefore it would make sense to assume that you can't late bind IShellWindows
I bumped into your question trying to find something for myself. But I don't know if you have tried the following -
Set shellwins1 = createobject("Shell.Application")
MsgBox TypeName(shellWins1.Windows)
This answers your question for datatype. It prints IShellWindows for me. I'm not sure though if it could actually solve your purpose for latebinding meaning if this would be the object required though the datatype is what you need.
So, I would advise you to give it a try.
There is a slightly better approach outlined at https://www.experts-exchange.com/questions/28961564/How-to-find-the-class-id-of-an-arbitrary-object-Example-Set-x-CreateObject-New-1C3B4210-F441-11CE-B9EA-00AA006B1A69.html#a41743468.

COM Exception (code 0x800A03EC) thrown when programmatically changing page breaks in VB.Net

I am attempting to use the VB.Net Excel COM interop to programmatically change the location of the first horizontal page break on an Excel spreadsheet being generated by the program. Code to do so is as follows:
Dim range As Excel.Range
xlActualWS.Activate()
xlActualWS.PageSetup.PrintArea = "$A$1:$K$68"
range = xlActualWS.Range("A68", "A68")
xlActualWS.HPageBreaks(1).Location = range
System.Runtime.InteropServices.Marshal.ReleaseComObject(range)
On the line setting HPageBreaks, COM exception code 0x800A03EC is thrown, and I can't really find a thing related to this searching. Anyone have any idea what I'm missing here?
Based onthe code it looks like either the location of the page break cannot be set or that there are 0 page breaks and hence you're accessing an invalid index. A quick way to test this out is to do the following
Check the Count property on xlActualWS.HPageBreaks and see how many are available
Remove the set of the Location property and see if the error dissapears
Additionally you should probably remove the ReleaseComObject call. That's a very difficult API to get correct and the CLR is quite good at cleaning up COM object references on it's own.

Conversion from type 'String' to type 'String' is not valid

I'm in the process of porting an old excel addin that was writen in VBA to VB .NET. The Excel addin interacts with a number of external com objects. The code sorta looks like this:
Dim hurr as Object
Dim durr as String
hurr = CreateObject("COM Object")
durr = hurr.getString
What I'm trying to do is read the string from the COM object and get it in durr for use later in my program.
That second line results in the exception posted above. If I try casting with CStr/CType I get the same exception. The visual studio watch window reports the type of hurr.getString as a "System.__ComObject" whereas the VBA watch window reports the type as "Variant/Object/String". Microsoft.VisualBasic.Information.TypeName(hurr.getString) says the type is "String". Any ideas how I should go about getting this working?
Thanks!
This is ridiculous but I figured I would post the answer here for completeness. The solution was to add a pair of brackets to the end of hurr.getString
so the working code looks like this:
Dim hurr as Object
Dim durr as String
hurr = CreateObject("COM Object")
durr = hurr.getString()
The above code gave me the casting exception and for whatever reason it needs brackets to work here. I'm just going to add that working with late binding com objects is horrible and should be avoided at all costs.