Vb.net interface with power point - vb.net

Hi i tried the following simple code, but it has error of
Object variable or With block variable not set.
Module Module1
Sub main()
Dim ppt As Presentation = Nothing
ppt.LoadFromFile("C:\Users\310238479\Desktop\test.pptx")
End Module
End Sub

I seems that you are not using vb.net only, but spire.presentation.
As the commands are correct, please verify, that you try to access an existing file and you have sufficient rights ...

Related

Error using built-in dialog box "xldialogApplyNames"

I wanted to use the named built-in dialog box in Excel via VBA. I learned to use it like this here.
That is working for many named built-in boxes, but not for ApplyNames. All arguments are optional, so that is not the problem. I also tried to define a boolean variable and say variable = dialogbox so that the box (outcome is a boolean as far as I understood it) has something to write the result in. But that didn't work either.
My code looks like this:
Public Sub Box()
Application.Dialogs(xlDialogApplyNames).Show
End Sub
The error which occurs is:
Laufzeitfehler 1004: Objekt- oder Anwendungsdefinierter Fehler"
or in english (hope I translated it correctly):
"runtime error 1004: error of object or application"
Thank you in advance!
Simon
I just tested and I can reproduce the error if the active workbook does not contain any range names. As soon as you add one the dialog is displayed. So:
Public Sub Box()
If ActiveWorkbook.Names.Count >0 Then
Application.Dialogs(xlDialogApplyNames).Show
End If
End Sub

VBA - Custom Function to close work book - not working

I am trying to write a simple function (in a module FileIO) which would take an instance of a work book, and just close it. This function is invoked from another module Business.
Below is the code snippet.
Public Function CloseExcelFile(wkBook As Workbook)
If (wkBook Is Not Nothing) Then
wkBook.Save
wkBook.Close
End If
End Function
I invoke this method by using the command FileIO.CloseExcelFile(catWorkBook). Variable catWorkBook is the object reference to the workbook I created (in a step before).
When ever I try too invoke the custom function, I am getting the error
object does not support this method or property
The below command closes the work book with no errors.
catWorkBook.Close
But the same does not happen when I use the custom function. What is going wrong here?
You just have your Not in the wrong place. Try it like this:
Public Function CloseExcelFile(wkBook As Workbook)
If Not wkBook Is Nothing Then
wkBook.Save
wkBook.Close
End If
End Function
As braX pointed out, your Not isn't in the right place.
You also don't need a Function here. Change it to a Sub. In fact, you barely need the Sub when you reduce it to one line like this:
Public Sub CloseExcelFile(wkBook As Workbook)
If Not wkBook Is Nothing Then wkBook.Close(SaveChanges:=True)
End Sub
The error was due to the INCORRECT way I was invoking a sub routine. I invoked the sub routine as:-
FileIO.CloseExcelFile(catWorkBook)
The CORRECT way to invoke a function would have been.
FileIO.CloseExcelFile catWorkBook

How to instantiate a vba class and call a method from vb.net?

As I guess many are, I'm sitting with an ms access application with a mixture of tables, VBA Modules and VBA Classes. I intend to migrate that application to VB.NET.
However it will take some time and I would like to make use of automation to slowly move the code to VB.NET
Now I can call regular SUB and Functions from my VB.NET application but wonder if there is a way to invoke the methods of user defined objects.
Rough example what I want to do
VBA
'Class1
Public Sub Test()
Print "Hello world"
End Sub
'Module1
Public oClass1 as Class1
Public Sub Init()
Set oClass1 = New Class1
End Sub
VB.Net
' Left out the opening of the access db
oAccess.Run("Init")
oAccess.Run("oClass1.Test())
Is it even possible?
The Application.Run method requires a string containing "The name of the Function or Sub procedure to be run" as its first argument. But "oClass1.Test" is neither.
You could work around that issue by creating another VBA procedure which wraps your oClass1.Test method, and run the wrapper procedure ...
oAccess.Run("Wrap_oClass1_Test") ' no parentheses after procedure name
Public Sub Wrap_oClass1_Test()
oClass1.Test
End Sub
I confirmed that approach worked with the rest of your sample code when called from VBScript so I believe it should also work from VB.Net.
Tim's CallByName suggestion also looks promising, but I didn't test that one.

Missing VBA compiler message for wrong method name

Consider the following code:
Public Sub VBACompilerIsMad()
Dim Ap As Application
Dim Wb As Workbook
Dim Ws As Worksheet
Debug.Print Ap.XXX ' No compile error
Debug.Print Wb.XXX ' No compile error
Debug.Print Ws.XXX ' Compile error
End Sub
When I compile this, I get a compiler error for referring to an inexisting member of Worksheet. However, if I comment out the last line, there is no compiler error, even though neither Application nor Workbook have a method or property XXX. It is as if I declared Ap and Wb as Object variables.
Why does the compiler treat Application / Workbook differently from Worksheet?
Are there any other classes like this, that the compiler seems to treat as if they were Object?
As I have been explained (kudos go respectively), this is a COM feature.
By default COM assumes an interface is extensible, that is, it allows adding members at run time. If that is not the desired behaviour, one can apply the [nonextensible] attribute to the interface definition, which declares the interface only accepts methods explicitly defined in the type library.
dispinterface _Application and dispinterface _Workbook do not have this flag set in the Excel type library, dispinterface _Worksheet does.
Similarly, ADO's dispinterface _Connection does not have [nonextensible], dispinterface _Command does.
To learn which are extensible, add a reference to TypeLib Info in the project's References and run:
Dim t As tli.TLIApplication
Set t = New tli.TLIApplication
Dim ti As tli.TypeLibInfo
Set ti = t.TypeLibInfoFromFile("excel.exe")
Dim i As tli.InterfaceInfo
For Each i In ti.Interfaces
If (i.AttributeMask And tli.TYPEFLAG_FNONEXTENSIBLE) <> tli.TYPEFLAG_FNONEXTENSIBLE Then
Debug.Print i.Name
End If
Next
You will see that almost all interfaces are extensible here, so most of them get pushed out of the debug window and you will only see the last ones. Change the <> to = to print those that are not extensible, there are much less of them.
A bit of a hypothesis:
You can call a stored procedure on an ADODB.Connection object like a native method (at the bottom).
(The examples for this on several msdn sites look oddly messed up).
So there is some mechanism like 'anonymous/dynamic methods' in VBS/VBA.
It may be a similar mechanism activated here for Application and Workbook classes - although I don't see where and how exactly.
A test supports the basic idea:
I have tested this with a reference to Microsoft ActiveX Data Objects 2.8 Library:
Public Sub testCompiler()
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Debug.Print cn.XXX
Debug.Print cmd.XXX
End Sub
cn.XXX does not throw a compile error, cmd.XXX does.
GSerg's answer is indeed outstanding, I love the whole COM type library IDL and how some attributes there can govern the behaviour in the Excel VBA IDE. Long may this arcane knowledge of COM be handed down! And, I realise this question has been bountied to give that answer more rep but when a bounty is set it appears on my radar and I have a view on this matter.
So although GSerg's answer gives the mechanism it does not give the rationale, i.e. it gives the how but not the why. I'll attempt to answer the why.
Some of the answer why is already given by Martin Roller (OP) in his comments about Application and WorksheetFunction. This, to me, is a convincing reason to keep Application extensible and I'll not consider Application further.
Let us turn to Workbook and Worksheet and we best start with some code to demonstrate, so you will need to begin with two fresh workbooks, call them MyWorkbook.xlsm and OtherWorkbook.xlsm. So some instructions:
In OtherWorkbook.xlsm go the code module ThisWorkbook and paste the code
Option Explicit
Public Function SomeFunctionExportedOffOtherWorkbook() As String
SomeFunctionExportedOffOtherWorkbook = "Hello Matt's Mug!"
End Function
In MyWorkbook.xlsm go the Sheet1 code module and paste the code
Option Explicit
Public Function SomeFunctionExportedOffCodeBehindSheet1() As String
SomeFunctionExportedOffCodeBehindSheet1 = "Hello Martin Roller!"
End Function
Now, in the VBA IDE change the codename of Sheet1 to codebehindSheet1
Now, in a new standard module in MyWorkbook.xlsm add the following code
Sub TestingObjectLikeInterfacesOfWorkbookAndCodeBehindWorksheet_RunMany()
'* For this example please rename the 'CodeName' for Sheet1 to be "codebehindSheet1" using the IDE
Debug.Assert ThisWorkbook.Worksheets.Item("Sheet1").CodeName = "codebehindSheet1"
Dim wb As Workbook
Set wb = Application.Workbooks.Item("OtherWorkbook")
'* Workbook dispinterface needs to not marked with nonextensible attribute
'* so that it doesn't trip up over exported function in another workbook
'* below SomeFunctionExportedOffOtherWorkbook is defined in the ThisWorkbook module of the workbook "OtherWorkbook.xlsm"
Debug.Print wb.SomeFunctionExportedOffOtherWorkbook
'*Not allowed --> Dim foo As Sheet1
'*have to call by the 'code behind' name which is usually Sheet1 but which we changed to illustrate the point
Debug.Print codebehindSheet1.SomeFunctionExportedOffCodeBehindSheet1
End Sub
Now run this code above.
You've probably read the code and hopefully understood the point I'm making but let me spell it out. We need Workbook to remain extensible because it may contain a reference to another workbook which may be exporting a method or function and we'd like no compile errors.
However, for the Worksheet, to do a similar export we again add code to the code behind module but there is a difference in referencing the module: one grabs a reference to that code behind module by using its VBA code name, most people do not change this from Sheet1 (that is why you were invited to change it above).
So the interface obtained by the code behind module name needs to extensible and not the Excel.Worksheet interface.
P.S. Anyone got a copy of TLI.dll?
As a workaround it could still be possible to create your own interface and implement this interface. Then declare a variable as INewInterface and all the compiler messages will be there :). Here simple example with custom interface for a UserForm. HTH
Interface
Public CancelButton As MSForms.CommandButton
Public DataList As MSForms.ListBox
Public CommandBox As MSForms.TextBox
Implementation
Implements IMyForm
Private Property Set IMyForm_CancelButton(ByVal RHS As MSForms.ICommandButton)
End Property
Private Property Get IMyForm_CancelButton() As MSForms.ICommandButton
End Property
Private Property Set IMyForm_CommandBox(ByVal RHS As MSForms.IMdcText)
End Property
Private Property Get IMyForm_CommandBox() As MSForms.IMdcText
End Property
Private Property Set IMyForm_DataList(ByVal RHS As MSForms.IMdcList)
End Property
Private Property Get IMyForm_DataList() As MSForms.IMdcList
End Property
Usage
Note: MyForm is existing VBA Form which has been added to the project.

VBA: Access to registry while preprocessing

I want to conditionally compile code in one VBAproject, with a condition that depends on some registry-entry. Is this somehow possible in VBA?
I know that there are some simple preprocessing possibilites in VBA, but I can not see if it is possible to somehow access the registry while preprocessing. Or Maybe some other possibility to check the registry before compiling.
Since I get a compile error because of some missing reference(and thus missing class object), I aim to check the registry before compiling.
P.s. I only want to read registry-entries.
As an example. How to reach debug.print in the following, i.e. avoiding compile errors.
sub sub1()
dim testobj as new nonexistingobject
sub2 testobj
debug.print "Arrived at this point"
end sub
sub sub2( byref testobj as nonexistingobject)
*do some stuff with testobj*
end sub
Instead of using early binding (Dim obj as myObject), use late bindings with CreateObject. This way you will be able to handle the case where the object doesn't exists:
Sub test()
Dim obj As Object
On Error Resume Next
obj = CreateObject("myObject")
if Err then Exit Sub 'if the object wasn't found exit the function
on error goto 0 'set back the error handling to its previous state
'rest of the code
End Sub
VBA does not directly provide access to the entire Windows Registry, but you can use a workaround.
Dim RegObj as Object
Set RegObj = CreateObject("WScript.Shell")
RegObj.RegDelete RegKeyString
RegObj.RegWrite RegKeyString
Str = RegObj.RegRead RegKeyString
Set RegObj = Nothing
If the RegKeyString is not found, it'll throw an error, so you need some OnError -> Key Doesn't Exist kind of code.
Not sure of the preprocessing part, but you could run your code in the Workbook_Open event handler to make sure this part runs before anything else.
It is not feasible. All the symbols and conditions that are tested by VBA Directives are build from literals or expressions that include only operators (excepting the Is operator, I think).
Function calls are not allowed when declaring directive symbols and conditions, and the only way to access registry in VBA is via API (like WScript.Shell for example), which means function call.
Further reading: http://msdn.microsoft.com/en-us/library/tx6yas69.aspx