I've created an add-in for outlook 2010. I have a ribbon that has a button on it. When you click that button, I want it to call a procedure in the ThisAddIn.vb.
There are two files: ThisAddin.vb and Ribbon.vb.
I've tried several things to no avail. I've also set all the procedures to public.
Call Testing123()
Call ThisAddIn.Testing123()
Etc
How do I properly call this procedure?
****Ribbon1.vb****
Imports Microsoft.Office.Tools.Ribbon
Public Class MyOutlookTab
Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles Button1.Click
Call Testing123()
End Sub
End Class
***ThisAddIn.vb***
Public Class ThisAddIn
Public Sub Testing123()
System.Windows.Forms.MessageBox.Show("It Works!")
End Sub
End Class
The problem is that you are trying to reference class methods without creating a class.
You have three options to make this work:
1) Convert ThisAddIn to a Module. Then there won't be any issues accessing the Testing123 method as you currently have it.
2) Convert ThisAddin.Testing123 to a Shared method, i.e.:
Public Shared Sub Testing123()
Then you would access as follows:
Call ThisAddin.Testing123()
3) Create an instance of the ThisAddIn class prior to using its methods:
Dim oAddIn As New ThisAddIn
Call oAddIn.Testing123()
Update
It appears that addins are treated differently that standard classes.
This MSDN article contains specific implementation guidance for accessing AddIn functionality from other types of solutions.
Based on this article, you need to take a couple of additional steps:
1) Create an interface to expose the functionality from your AddIn:
<ComVisible(True)> _
Public Interface IAddInUtilities
Sub Testing123()
End Interface
2) Add a utilities class to your addin project:
<ComVisible(True)> _
<ClassInterface(ClassInterfaceType.None)> _
Public Class AddInUtilities
Implements IAddInUtilities
Public Sub Testing123() Implements IAddInUtilities.Testing123
System.Windows.Forms.MessageBox.Show("It Works!")
End Sub
End Class
3) Add the following to ThisAddIn to expose the utilities to external callers:
Private utilities As AddInUtilities
Protected Overrides Function RequestComAddInAutomationService() As Object
If utilities Is Nothing Then
utilities = New AddInUtilities()
End If
Return utilities
End Function
4) I am a little unclear on the exact syntax needed for the last step since I don't have automation installed in office, but you will need to do something along these lines:
' OutlookTest should be changed to the name of the project ThisAddIn is in
Dim addIn As Office.COMAddIn = Globals.ThisAddIn.Application.COMAddIns.Item("OutlookTest")
Dim utilities As OutlookTest.IAddInUtilities = TryCast( _
addIn.Object, OutlookTest.IAddInUtilities)
utilities.Testing123()
Thanks for everyones comments but I found the solution in an example here: http://msdn.microsoft.com/en-us/library/ee620548.aspx where they talk about adding a ribbon to the meeting request (2/3's of the way down).
It's actually quite simple. You call the procedure using the "Global"
Globals.ThisAddIn.Testing123()
Nothing else is needed.
You have to create a new instance of the class before you can call it in vb.net!
So something like should allow you to call it..
Public Class MyOutlookTab
Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles Button1.Click
Dim testing As New ThisAddIn()
Call testing.Testing123()
End Sub
End Class
Related
I have a few modules and classes that I need to init themselves once added to the project.
I'm looking for a method mechanism to call a routine(or something) during startup, without explicitly calling it.
I tried the following, with the hope that being MyInit public, will be initialized upon start.
Optimization is preventing creation of MyInit until the first reference.
Partial Public Module InitModule
public MyInit As New MyStart()
Public Class MyStart
Public Sub New()
Debug.Writeline("Yes, init is executed")
End Sub
End Class
End Module
I have a few modules that can be added/linked to multiple projects; when included they provide trace, code verification, version control etc. The idea is that to add or remove, the main code need no changes.
It doesn't matter is if it's a class, sub or function: I want this to run without explicit call.
Thanks #Jimi for his hint
On each module I can add this partial snippet, extending MyApplication class and using the Startup event to do the initialization.
This can be repeated multiple times and me.Startup will be cascaded as needed.
The drawback: MyApplication is available on windows forms only.
#if TARGET="winexe" then
Namespace My
Partial Friend Class MyApplication
Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As ApplicationServices.StartupEventArgs) Handles Me.Startup
My.Application.Log.WriteEntry($"Application start {My.Computer.Clock.ToString}")
' init module stuff
'...
End Sub
End Class
End Namespace
#end if
Update
I found a very easy and straightforward code that works with all targets and not just winexe (forms)
The idea is to force the creation of the class at initialization:
friend _startup_init as new startup_init with {.name="test"}
friend class startup_init
public name as string
public sub new()
'... do here your init,
' in my case a few addhandler to hook the master process
end sub
end class
I'm working on a project which has currently migrated to Visual Studio 2015. I've just encountered a problem I so far have no idea what to do with. In a chain of inherited classes, looking like this:
Public Class ControlA
Public Event CustomEvent(sender As Object, e As CustomEventArgs)
End Class
Public Class BaseForm
Public WithEvents C As ControlA
End Class
Public Class MiddleForm
Inherits BaseForm
Private Sub C_CustomEvent(sender As Object, e As CustomEventArgs) Handles C.CustomEvent
'do something
End Sub
End Class
Public Class FinalForm
Inherits MiddleForm
Private Sub C_CustomEvent(sender As Object, e As CustomEventArgs) Handles C.CustomEvent
'do something elese
End Sub
End Class
the event handler in the most "outer" class (in this case - a form that is shown to a user) do what it's supposed to do and stops the event. Handlers in the base class are not being called.
Everything worked fine in VS2010.
Anyone had similar problem and could give a hint?
EDIT
A little update: Everything works fine when I use AddHandler in both classes. If subs are defined with Handles - it breaks as described above.
Here's my problem.
I'm making a project in VB.NET that (currently) exists out of 1 class (let's call it User.vb here) and 2 WinForms (frmDisplay & frmMain).
Let's say User.vb is currently looking like this:
Public Class User
Private mName As String
Public Sub New(ByVal name As String)
Me.Name = name
End Sub
Public Property Name As String
Get
Return mName
End Get
Set(value As String)
mName = value
End Set
End Property
End Class
Let's also say the form frmDisplay is just a form with a textfield txtString and a button btnSend.
Public Class frmDisplay
Dim usr As New User()
Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
usr.Name = txtString.Text
frmMain.Show()
Me.Hide()
End Sub
End Class
On the form frmMain I want to reach the value in the property Name that I stored in the class User on the first form.
The basic idea is (I know it doesn't work):
Public Class frmMain
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblStoredString.Text = usr.Name << This is where I'm stuck
End Sub
End Class
I googled my problem and read many posts, but I just can't seem to understand it. Maybe you guys can help me. I am new to VB.NET and WinForm-stuff (about 3 months of exp.), but I have done some programming in the past in C# with webapplications.
Every bit of help is greatly appreciated.
Thanks a lot in advance!
Will there only ever be one User.Name that you are interested in throughout the app?
If yes, then change the class to:
Public Class User
Public Shared Name As String
End Class
Then you can use User.Name from any form (or anywhere in the application) to get/set that value.
Note that you can still wrap the field in a property if you like:
Public Class User
Private Shared _Name As String
Public Shared Property Name As String
Get
Return _Name
End Get
Set(value As String)
If (value.Trim <> "") Then
_Name = value.Trim
End If
End Set
End Property
End Class
My focus is ASP.NET, and I prefer C#, but I'll chime in. There are numerous ways of providing data between the forms. The first one that comes to mind is to use a cache of some kind. The idea is that once the cache is made available to your program, you can add the value to the cache when the button is clicked, and then safely read the value whenever you need it. This can be a static class with a Dictionary, or you can look into using the functionality provided by the System.Web.Caching namespace. http://www.codeproject.com/Articles/8977/Using-Cache-in-Your-WinForms-Applications has an example.
Another way would be to use a shared data source. The concept is similar to the caching, but this would allow you to pass more complex relational data between your forms, assuming your real goal is more complicated than you describe. Here is a walkthrough for that: https://msdn.microsoft.com/en-us/library/ms171925.aspx.
You could be quick and dirty, and write the values to a text file at some location, and then read the values from the second form.
The simplest way is probably to define a custom constructor for the second form, and pass the values you need when you instantiate the second form. This is best suited if the values from the first form can be considered "parameters" to the instance of the second form. Passing a textbox value from one form to another in windows application
Declare the usr variable Friend
Public Class frmDisplay
Friend usr As New User()
It will then be available from the other form
Public Class frmMain
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblStoredString.Text = frmDisplay.usr.Name
End Sub
End Class
It's a quirk of VB.NET that forms are automatically created with a public variable name the same as the class name. That's why you are able to use frmMain without having to create it (e.g. Dim frmMain as New frmMain). You can turn off this behaviour, but it isn't relevant to your problem.
On the other hand, if you want to do it "properly"...
Public Class frmDisplay
Private usr As User
Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
usr = New User(txtString.Text)
Dim f As New frmMain(Me, usr)
f.Show()
Me.Hide()
End Sub
End Class
and frmMain...
Public Class frmMain
Private myParent As Form
Private usr As User
Sub New(parent As Form, _usr As User)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
usr = _usr
myParent = parent
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Text = usr.Name
End Sub
Private Sub frmMain_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
myParent.Show()
End Sub
End Class
Here we instantiate frmMain and pass the User object to its constructor. We also pass the calling form so we can display it again when frmMain is closed.
I hope this isn't a stupid question, I can't find a reasonable answer on google.
I'm starting a project which only contains one class file. I will be turning the class file into a dll at the end. I understand that another app normally makes calls to the dll once it's referenced in the project. I need the dll to run a sub inside of it on load like a normal mybase.load sub. This sub needs to execute only once on load to populate some variables. I don't want to have to call the sub from the main app. The rest of the functions/subs in the dll will be called from the main app when needed. Please don't respond with register them globally under the class, I need a sub or function.
If there isn't such a sub how would I go about creating a function/sub that preforms an onload?
Thanks. :)
Hope I'm making sense. Thanks for your response.
Shared Sub New()
on your class.
Another option is to have a private class inside your class and initialise it with a member variable:
Public Class MyLibraryClass
Private mobjSettings As New SettingsClass
Public Function SampleLibraryFunction() As String
Return mobjSettings.SettingsProperty
End Function
Private Class SettingsClass
Friend SettingsProperty As String
Sub New()
'initialise
SettingsProperty = "This is a test"
End Sub
End Class
End Class
I'm testing and trying to understand how to create a DLL and call a function from it in my Silverlight project. I'm getting an exception: Unable to find an entry point named 'WriteTextFile' in DLL 'C:\temp\TestDLL.dll'. So I'm doing something wrong.
Here is my code for the very simple DLL:
Imports System.IO
Public Class Class1
Private Shared dir As String = "C:\TEMP"
Private Shared file As String = "TestDLL.txt"
Public Shared Sub WriteTextFile()
Using wr As New StreamWriter(System.IO.Path.Combine(dir, file))
wr.WriteLine("Call to function WriteTextFile()")
End Using
End Sub
End Class
And this is what I'm doing in my Silverlight:
Imports System.Runtime.InteropServices
Partial Public Class MainPage
Inherits UserControl
<DllImport("C:\temp\TestDLL.dll")> _
<AllowReversePInvokeCalls()> _
Friend Shared Sub WriteTextFile()
End Sub
Public Sub New()
InitializeComponent()
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
WriteTextFile()
End Sub
End Class
I need some pointing to the right direction here :)
The AllowReversePInvokeCalls part is just something I tried out after doing some reading around the web but it didn't change anything. Also I've tried to set the EntryPoint in the DLLImport but that doesn't do anything either.
Edit:
I tried this DLL and pinvoke in regular WPF application and I get the same error so this is not related to Silverligth. Maybe in my DLL then?
Ok, so it looks like this can't be done simply because using pinvoke requires a standard dll and I can't do those with VB .NET. So I'll need to try something else :)
If anyone has more information about this and like to share it I would appreciate that. Or correct me if I've understood the issue wrong.