I am trying to create a simple VB6 ActiveX exe and call it from Excel.
In VB6 I create an ActiveX DLL project called BigTrev, using all the default settings.
I create a MultiUse class called Trev with a single method containing no code
Public Sub HelloWorld()
End Sub
I make a DLL and register it from the command line (VB6 also registers it for me but I did it using cmd as well anyway).
Then it Excel I create a reference to my DLL in a new workbook. It clearly has been registered because the Intellisense knows about Trev and HelloWorld.
Sub cats()
Dim derek As BigTrev.Trev
Set derek = New BigTrev.Trev
derek.HelloWorld
End Sub
It compiles in Excel, when I step through it it fails in the second line, the Set one. Error message is "ActiveX component can't create object".
Why? I have done this or similar loads of times many years ago when VB6 was used widely, I am using Windows 7 now and I am an admin on my box.
I would suggest registering the DLL (or EXE if that's the direction you've chosen) with the relevant regsvr32.exe. In this case, where you're registering a 32bit DLL for use in 64bit environment, use the one hiding out in c:\windows\syswow64.
Sadly, I don't have Excel (shock, horror) and the spreadsheet I do have (LibreOffice) is 32bit.
Related
we can add our function with this way
https://www.youtube.com/watch?v=TEYuQmia9IY
but it in c#
i want the way in vb.net
the problem in using namspacing in vb.net
thanks
In the video posted there are some critical steps missing. It seems that they are given for granted but without it you could not achieve a successful reference to your code from the Report Designer.
First: To clarify the problem between VB.NET and C#. If you want to use VB as scripting language for your report you need to set it in the Report Properties. You will find the ScriptLanguage property in the same property grid for the report where they set the reference to your application. Changing this property is not required because this property refers to the code written inside the report not the code in which you have written your app.
Second: In your VB.NET app your code that defines the function should be as this
Namespace MyFunc
Public Class Main
Public Shared Sub ShowMessage(text As String)
MessageBox.Show(text)
End Sub
End Class
End Namespace
Usually in VB.NET you don't define explicitily a namespace (everything is inside the main namespace defined in the project properties) but if you want a separate namespace there is nothing to stop you.
Third: In the Report Code Page you write
Imports WindowsFormApplication2.MyFunc
Fourth: After completing the design of your report remember to save it in the same folder where the application is created. (Usually Project\BIN\DEBUG) Otherwise the reference to your executable will fail.
Fifth: The Stimulsoft assemblies are installed in the GAC, but to be sure that they are found when you run the report don't forget to set their references to Copy Local = True when you run your app inside Visual Studio
I am having an extraordinarily hard time trying to integrate a basic Class Library made in VB .NET 4.5 using Visual Studio 2013 Community Edition to my Excel 2013 VBA Module.
I have tried countless solutions and have followed the following steps to get here:
I created a basic Class Library (see below).
I set the properties "Make assembly COM-visible" and "Register for COM interop" to true (see here).
I've added a reference to my Excel project. Note* I have to explicitly find the name of my class library in the list of possible references I have to make, check it off, and then click OK in the references window.
VBA Intellisense recognizes the code:
Which means my class library is being properly referenced. However, when I run the code I get Error 429: ActiveX component can't create object.
I have 2 questions:
How do I fix this?
What can I do to make my class library work with as little friction as possible for users on other computers. Does everyone have to register the DLL and then import the reference or can they just download my Excel sheet and have everything imported?
I have a legacy VB6 / COM application that we are migrating all of the code to .NET (VB.NET) via a .NET DLL. All new form development is being done in the .NET DLL.
We use function pointers to call back to COM functions within .NET form:
I create a delegate in .NET
Set the delegate to the AddressOf the COM function at runtime (GetDelegateForFunctionPointer)
Show the .NET Form
Invoke the delegate
COM App --> .NET Form --> COM function
This works fine for functions. Where this breaks down is when I call a COM function that shows a form.
COM App --> .NET Form --> COM function --> COM Form
The COM function will execute and the form will show, but when executing in the VB6 IDE the COM form's logic does not execute. The controls are shown, but any click or form_load events are not executed. This is not an issue when the VB6 application is compiled.
Another issue I've noticed is that the VB6 IDE "freezes" until the .NET form unloads. I can not stop the debugger, set breakpoints, or interact with IDE's menu. It is as if the VB6 IDE allows the .NET DLL to take complete control over the thread. I believe these two issues are related.
EDIT:
The .NET form is modal, which may be the reason for the IDE thread lock. I'm just wondering if there is a way around it. Also, I've looked at the InteropForms Toolkit. It does not solve my problem. Even setting their sample forms to modal causes the same IDE thread lock to occur.
EDIT 2:
My previous edit did allude to another workaround: Make the .NET form show as modeless when the host application is VB6.
If InStr(Process.GetCurrentProcess().ProcessName, "vb6", CompareMethod.Text) > 0 Then
frm.Show()
Else
frm.ShowDialog()
frm.Dispose()
End If
The simple COM App --> .NET Form --> COM function --> COM Form scenario can work using the InteropForms Toolkit 2.1. Here is some code that does it, without using delegates or AddressOf.
First, we have our COM library which I'll call ComLibrary. We have the following code:
SimpleForm.frm:
Option Explicit
Private Sub Form_Load()
MsgBox "In SimpleForm_Load"
End Sub
Private Sub OkButton_Click()
Unload Me
End Sub
Private Sub TalkButton_Click()
MsgBox "Hello"
End Sub
SimpleClass.cls:
Option Explicit
Public Function ShowTheDialog() As Long
Dim f As SimpleForm
Set f = New SimpleForm
f.Show vbModal
ShowTheDialog = 1
End Function
Compile this to a .dll so that we can reference it in our .NET library.
Next, we'll create our .NET forms library. I did this using the "VB6 InteropForms Library" project template using the default project name of InteropFormsLibrary1. I added a reference to the ComLibrary project. The form has a single button named "CallComFunction."
InteropForm1.vb:
Imports Microsoft.InteropFormTools
<InteropForm()> _
Public Class InteropForm1
Private Sub CallComFunction_Click(sender As System.Object, e As System.EventArgs) Handles CallComFunction.Click
Dim sc As ComLibrary.SimpleClass
sc = New ComLibrary.SimpleClass
Dim result As Integer
result = sc.ShowTheDialog()
End Sub
End Class
Before compiling this, we need to create the InteropForms wrapper classes per the toolkit documentation. Do this by accessing the Tools > Generator InteropForms Wrapper Classes menu.
Finally, we create the VB6 host app.
Form1.frm:
Option Explicit
Private Sub DialogButton_Click()
Dim f As InteropFormLibrary1.InteropForm1
Set f = New InteropForm1
f.Show vbModal
End Sub
When I run the host application in the VB6 IDE, I can click the button the VB6 form which then displays the VB.NET form. From there, I click another button which uses an instance of SimpleClass to display SimpleForm. The MsgBox statements in the form load event and the button click handlers work. And everything works when compiling the VB6 host app as well.
It looks like your VB6 IDE is loading your VB application as an "in-process" COM object, although that does not make much sense to me... However if that is the case,it would mean that you have a single message loop for your application and your debugger, which might explain at least some of these issues. I have not used a VB-classic IDE in too many years, so I do not know how it works. Maybe there is an option there somewhere to load your app in a separated process?
Update -
It seems my guess was correct. See this other question and its answers for more information and possible workarounds:
https://stackoverflow.com/a/518217/501196
Thanks a lot for the received answer.the following is brief description of how my project works.
GUI is used to collect information from User and validates.have got dll named controlclass that pass input data from GUI to Business logic DLL.this dLL connect to the database and saves data.after that,it disconnected and takes the results to the control dll,then to GUI which interprets if the input data was successful or not.Is there a tool that can be used to convert VB6 GUI to .net web forms?
am not familiar to vb.net.how do you create reference to vb6 dll or COM from vb.net?
In order to create a reference to a VB6 COM object from VB.NET:
Select Project>[Your Project] Properties OR Double Click on My Project in the Solution Explorer window
Select the References tab
Click Add
Select the COM tab
Select the component you require
You will notice that Visual Studio will creates an Interop assembly which handles the interfacing to the COM object for you.
From that point on accessing the COM object is the same as VB6
Dim obj as New MyObject
obj.DoSomething
'etc
Set obj = nothing
I'm developing a VB6 standalone application that I'd like to be able to call from VBA modules running in Excel, Outlook, etc. Ideally, I'd like the VBA module to check whether the VB6 application is already running, if not, open it, then populate certain controls (textbox, listbox, etc) in the VB6 application with information from the VBA module. Is this even possible? Can I just create a reference somehow to the VB6 application, then treat it like any other object? Thanks for your help!
Make the Vb6 app into an ActiveX Exe project. Here's the VB6 manual tutorial on creating an ActiveX exe. Add a reference to the vb6 from the VBA code. You will be able to call into objects in the Vb6 from your VBA.
Use GetObject to instantiate a Vb6 object from the VBA. That will connect to any existing instance of the vb6 app, or start a new instance if necessary.
You cannot do as you describe and treat the VB6 app like and object but you could do it in the following way:
Use the FindWindow API call to determine if the VB6 application is running
Use the Shell command to start it
Use AppActivate to make VB6 window active and SendKeys to send the data to it
That would be the simplest "out of the box" solution. However, this will be quite brittle. For example, if you removed controls from the VB6 form or changed the tab order of the controls, your app will malfunction!
Another option is DDE but I think the DDE link is intended to go from the VB6 app to Word or Excel, not the other way around.