Call Excel Add-In function from Excel workbook VSTO - excel-2007

I want to create a Method in Excel Add-In 2007 solution which can be called from my Excel Workbook 2007 solution.
I explain, I want to call a method of Excel Add-In from code behind file of excel workbook 2007 solution. And I dont want to use VBA Macros.
Please help, thanks in advance
Thanks,
Mrinal Jaiswal

After doing much googleing i m able to answer it myself now.
Please follow the following steps,
Declare an interface with functions you want to expose from your workbook and set its ComVisible attribute to true,
Public Interface ICallMe
Sub MyFunction()
End Interface
Now create a class which implements this interface and set its ComVisible attribute to true, along with classinterface attribute to None, some what like this,
Public Class AddInUtilities
Implements ICallMe
Public Sub MyFunction() Implements ICallMe.MyFunction
Dim activeWorksheet As Excel.Worksheet = Globals.ThisAddIn.Application.ActiveSheet
If activeWorksheet IsNot Nothing Then
Dim range1 As Excel.Range = activeWorksheet.Range("A1")
range1.Value2 = "This comes from my Add-In"
End If
End Sub
End Class
5.Build your add-in project with the Register for COM interop option. To set "Register for Com Interop" option, goto project property and then to "Compile" tab (In VB.net), and set the "Register for COM interop" to check.
Now in your excel workbook project, add the refrence to this add-in and on any event of your workbook like button click, write the following code,
Dim addIn As Office.COMAddIn = Application.COMAddIns.Item("ImportData")
Dim utilities As ImportData.ICallMe = TryCast(addIn.Object, ImportData.ICallMe)
utilities.MyFunction()
You are done :)
Only thing to remeber is that do not call the add-in function from startup event of your workbook or sheet.
I hope it helps you all, as it works for me.
Thanks,
Mrinal Jaiswal

Thanks a lot that worked for me. Was struggling with it for 2 days now.
I wanted to create a new workbook on the fly in Office 2016 with my Excel Addin, user defined function.
Just a sample how I made it work :
public static void printToExcel(String writeToCell)
{
Workbook xlWorkbook = Globals.ThisAddIn.Application.Workbooks.Add();
Worksheet xlWorkSheet = xlWorkbook.ActiveSheet;
xlWorkSheet.Name = "testSheet";
xlWorkSheet.Cells[1, 1] = writeToCell;
}

Related

Using Microsoft.Office.Interop.PowerPoint with VB.NET

I use Imports statement for PowerPoint automation in my VB.NET application:
Imports PowerPoint = Microsoft.Office.Interop.PowerPoint
and of course, I have to check if PowerPoint is installed in the user's machine or not. However, because of this reference the application does not start or load to give me the chance to check if PowerPoint is installed or not. Here is the code I use to check in Form Loading
Dim officeType As Type = Type.GetTypeFromProgID("PowerPoint.Application")
If officeType Is Nothing Then
MessageBox.Show("PPT is not installed")
Else
MessageBox.Show("PPT is installed")
End If
Any suggestions to solve this issue?
Based on Jimi and TbTinMn comments I solved the problem. I replaced Imports statement by Dim powerPointType and recreated the application instance as follows:
Under Public Class Form1, add
'// PowerPoint automation
Dim PowerPointType = Type.GetTypeFromProgID("PowerPoint.Application")
Dim PowerPoint = Activator.CreateInstance(PowerPointType)
Dim oApp As New Microsoft.Office.Interop.PowerPoint.Application
Dim oPres As Microsoft.Office.Interop.PowerPoint.Presentation
Dim oSlide As PowerPoint.Slide
then you can complete your code with PPT application, for example, Export or Save as
'// open MS PowerPoint with hidden window
oPres = oApp.Presentations.Open(ppt_filename, , , Microsoft.Office.Core.MsoTriState.msoFalse)

How to prevent an Excel Workbook_Open event from firing when opened by VB.NET

I have a workbook that does some whizbang stuff when you open it. That's great and I want to keep it the way it is but I also want to share some of the internal functions with a VB.NET project that relates to this magic workbook.
My VB.NET application supersedes the functionality of the open event. So if a user opens the workbook in Excel I want the magic to occur. If I open that same workbook from my VB.NET application I want to suppress the Workbook_Open event so I can do the magic from VB.NET instead.
Is there a flag I can set before I call Open that will allow me to run macros from that workbook while also suppressing the open event?
VB.NET Code looks like this:
' Set up Excel
Dim excelApp As Application
Dim thisWorkbook As Workbook
Dim excelBooks As Workbooks
' Start Excel
excelApp = New Application With
{
.Visible = False ' Ninja mode
}
' Open the workbook
excelBooks = excelApp.Workbooks
thisWorkbook = excelBooks.Open(My.Settings.ExcelFileName)
' Run the subroutine.
excelApp.Run("WhizBang", SecretVBNETMagicPassedInToExcel)
' Close the workbook and release the COM objects.
thisWorkbook.Close(SaveChanges:=False)
Marshal.ReleaseComObject(thisWorkbook)
Marshal.ReleaseComObject(excelBooks)
excelApp.Quit()
Marshal.ReleaseComObject(excelApp)
GC.Collect()
Since the code you do not want to run is in the Workbook_Open event handler, you can disable events for the application before opening the workbook to prevent the handler code from being called.
excelApp.EnableEvents = False

Get Excel Object when Option Strict On

I have got following codes from this microsoft page.
https://msdn.microsoft.com/en-us/library/e9waz863(v=vs.90).aspx
' Add Option Strict Off to the top of your program.
Option Strict Off
.
Private Sub getExcel()
Dim fileName As String = "c:\vb\test.xls"
If Not My.Computer.FileSystem.FileExists(fileName) Then
MsgBox(fileName & " does not exist")
Exit Sub
End If
' Set the object variable to refer to the file you want to use.
Dim excelObj As Object = GetObject(fileName)
' Show Excel through its Application property.
excelObj.Application.Visible = True
' Show the window containing the file.
Dim winCount As Integer = excelObj.Parent.Windows.Count()
excelObj.Parent.Windows(winCount).Visible = True
' Insert additional code to manipulate the test.xls file here.
' ...
excelObj = Nothing
End Sub
Everything is okey when Option Strict Off
Everything is not okey when Option Strict On
So, how to solve that errors when Option Strict On?
Be careful! I want to get specific excel file from the same excel instance.
+1 for striving to use Option Strict On. :)
However, the code is using what is known as Late Binding and that requires you have Option Strict Off. You can however, minimize the scope of Option Strict Off by creating a new code file and using a Partial Class definition to contain the code that needs Late Binding.
You might be able to get by using the VB CallByName function with Option Strict On, but that would get ugly real quick and probably be very slow.
There also is an advanced technique using native API's that is called COM reflection that should work with Option Strict On. This technique is described in the article: [Basic Instincts - Inspecting COM Objects with Reflection].(https://msdn.microsoft.com/en-us/magazine/dd347981.aspx).
The typical method for early binding (Option Strict On) is to add a reference to the Excel primary interop assembly. This technique has some detractors as well, but is by far the easiest method.
Edit: The following demonstrates how to use the Excel PIA's and early binding to open a workbook directly similar to the OP's original code.
Dim wbPath As String = "*** replace with path to your workbook ***"
Dim wb As Excel.Workbook = CType(GetObject(wbPath), Excel.Workbook)
'or
'Dim wb As Excel.Workbook = CType(Marshal.BindToMoniker(wbPath), Excel.Workbook)
Dim app As Excel.Application = wb.Application
app.Visible = True
wb.Windows(1).Visible = True
As a side note, there is no need to depend on the Interop.Excel early binding, if you know that it works. You can change the Error Notifications to Warning and still compile and run.
' Imports Microsoft.Office.Interop.Excel
Dim fileName = "c:\vb\test.xls"
If Not IO.File.Exists(fileName) Then MsgBox(fileName & " does not exist") : Exit Sub
Dim obj = GetObject(fileName, "Excel.Application")
Dim wb = TryCast(obj, Workbook)
wb.Application.Visible = True
wb.Windows(1).Visible = True

How To Develop My Own Excel Add-in in VB.Net

I am trying to create an Excel Add-in using Vb.Net. I've started an Excel 2007 Add-in Project in VS2010. Sadly, I am not good with vb.net; I am more a VB6 developer in this regard, and my ThisAddin.vb code is:
Public Class ThisAddin
Private Sub ThisAddIn_Startup() Handles Me.Startup
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
End Sub
' test function; simple
Public Function getRowCount() As Long
Dim thisWB As Workbook = Me.Application.ThisWorkbook
Dim activWS As Worksheet
activWS = thisWB.ActiveSheet
Return activWS.UsedRange.Rows.Count
End Function
End Class
I've also added a Ribbon item (via Add New Item... menu option) in designer mode (not xml) - and then add a button. Then I go to code and try to call the function and I get this error when using:
MsgBox(Globals.ThisAddIn.getRowCount())
Which I got from this link: Calling a procedure within another class
To be honest, I've been trying a myriad things and I've been getting so many errors. I've been looking online as well for a tutorial on creating my own Excel Addin from scratch with no real luck. I would like not to use Add-In-Express since that's a third party app and I have to create an Excel add-in for my company from scratch.
Does anyone have an idea on how I can create a vb.net coded Excel Addin (2007) that I can use as a template or guide? I've tried several and many rely on Add-In-express and I really cannot go that way. I have a lot of VBA code (natural VBA so it's in a module in an my excel files' VBA/Developer section) and I think I can translate those from VBA/VB6 to VB.Net format so that's not my concern. It is really about getting to code my own Excel Addin in VB.Net. Any help would really be great. Thank you.
*note: I would also like not to have to ask coworkers (or do myself) to just add to the quick access toolbar the functions and subs I've created since that's really not a solution, considering that those buttons will be there when they create or open another workbook. Essentially, I've got to create my own excel addin in vb.net. Thank you once again.
The issue has to do with the definitions in Microsoft.Office.Tools.Excel and Microsoft.Office.Interop.Excel. To code an "Interop" version you could use this:
Public Function getRowCount() As Long
Dim thisWB As Excel.Workbook = Application.ActiveWorkbook
Dim activWS As Excel.Worksheet = CType(thisWB.ActiveSheet, Excel.Worksheet)
Return activWS.UsedRange.Rows.Count
End Function
To extend the functionality of the Native objects and use VSTO, you could do it like this:
Public Function getRowCount() As Long
Dim NativeWorkbook As Excel.Workbook = Application.ActiveWorkbook
Dim NativeWorksheet As Excel.Worksheet = CType(NativeWorkbook.ActiveSheet, Excel.Worksheet)
Dim thisWB As Workbook = Nothing
Dim activWS As Worksheet = Nothing
If NativeWorkbook IsNot Nothing Then
thisWB = Globals.Factory.GetVstoObject(NativeWorkbook)
End If
If NativeWorksheet IsNot Nothing Then
activWS = Globals.Factory.GetVstoObject(NativeWorksheet)
End If
Return activWS.UsedRange.Rows.Count
End Function
This is a function you can put in ThisAddin.vb that will create a new Worksheet. Note that this function names the Worksheet and adds it to the end.
Public Function AddWorkSheet(sheetName As String) As Worksheet
Dim wk = Application.ActiveWorkbook
Dim ws As Worksheet = Nothing
Try
ws = CType(wk.Sheets.Add(, wk.Sheets(wk.Sheets.Count)), Worksheet)
ws.Name = sheetName
Catch ex As Exception
Throw
Finally
AddWorkSheet = ws
End Try
End Function
To use this outside of ThisAddin.vb you could do something like this:
Dim ws As Excel.Worksheet
Dim newSheetName As String
.
'
ws = Globals.ThisAddIn.AddWorkSheet(newSheetName)

Copy VBA code from one Worksheet to another using VBA code

Ok here is what I want to accomplish: I am trying to copy all the VBA code from "Sheet2" to "Sheet 3" code pane. I'm NOT referring to copying a Module from one to another but the excel sheet object code.
I already added a Reference to MS VB for Applications Extensibility 5.3
I'm not sure where to start but this is what I have started with and its not going anywhere and probably all wrong. Please Help - Simply want to programmatically copy sheet vba code to another sheet vba pane.
Dim CodeCopy As VBIDE.CodePane
Set CodeCopy = ActiveWorkbook.VBProject.VBComponents("Sheet2").VBE
ActiveWorkbook.VBProject.VBComponenets("Sheet3").CodeModule = CodeCopy
Use the CodeModule object instead of the CodePane, then you can create a second variable to represent the destination module (where you will "paste" the code).
Sub test()
Dim CodeCopy As VBIDE.CodeModule
Dim CodePaste As VBIDE.CodeModule
Dim numLines As Integer
Set CodeCopy = ActiveWorkbook.VBProject.VBComponents("Sheet2").CodeModule
Set CodePaste = ActiveWorkbook.VBProject.VBComponents("Sheet3").CodeModule
numLines = CodeCopy.CountOfLines
'Use this line to erase all code that might already be in sheet3:
'If CodePaste.CountOfLines > 1 Then CodePaste.DeleteLines 1, CodePaste.CountOfLines
CodePaste.AddFromString CodeCopy.Lines(1, numLines)
End Sub
In addition to adding a reference to "Reference to MS VB for Applications Extensibility 5.3"
You'll also need to enable programmatic access to the VBA Project.
In Excel 2007+, click the Developer item on the main Ribbon and then
click the Macro Security item in the Code panel. In that dialog,
choose Macro Settings and check the Trust access to the VBA project
object model.
Thank you all! After testing multiple suggestions above, where "b" is the Worksheet name, you must use .CodeName, NOT .Name
Set CodePaste = ActiveWorkbook.VBProject.VBComponents(WorkShe‌ets(b).CodeName).Cod‌​eModule
If you have set your target worksheet as an object:
Dim T As Worksheet
Set T = Worksheets("Test")
Then you simply need:
Set CodePaste = ActiveWorkbook.VBProject.VBComponents(Worksheets(T.Name).CodeName).Cod‌​eModule