How to expose a C# class to a VBA module in a document-level add-in? How to expose a C# class to a VBA module in a document-level add-in? vba vba

How to expose a C# class to a VBA module in a document-level add-in?


You would need to create a public interface to expose the class to VBA, this works for me as a document level addin.

  1. Open a new Excel workbook and copy the following into a MODULE

    Sub CallVSTOMethod()Dim dt As DateDim VSTOSheet1 As DocLevelAddin.Sheet1    Set VSTOSheet1 = GetManagedClass(Sheet1)    dt = VSTOSheet1.GetDatePickerValEnd Sub
  2. Save Excel as "TestProj.xlsm" and close.

  3. Open VS, new project, Excel 20xx Workbook and name the project "DocLevelAddin"
  4. In the wizard, select copy an existing document and select the newly created workbook "TestProj.xlsm"
  5. On the Excel Sheet1 add the DateTimePicker control to the sheet from wihin VS, double click to create a ValueChanged event and update the code in Sheet1.cs to read

    private DateTime dtVal;private void dateTimePicker1_ValueChanged(object sender, EventArgs e){    dtVal = dateTimePicker1.Value;}
  6. Still in Sheet1.cs, add a public method to return dtVal

    public DateTime GetDatePickerVal(){    return dtVal;}
  7. Also add the following to Sheet1.cs

    protected override object GetAutomationObject(){    return this;}
  8. Above public partial class Sheet1 in Sheet1.cs add the following

    [System.Runtime.InteropServices.ComVisible(true)][System.Runtime.InteropServices.ClassInterface(     System.Runtime.InteropServices.ClassInterfaceType.None)]
  9. Now you need to create a public interface for the method. In Sheet1.cs right click select Refactor, Extract Interface and check the public method GetDatePickerVal

  10. Make the interface public and COM visible

    [System.Runtime.InteropServices.ComVisible(true)]public interface ISheet1{    DateTime GetDatePickerVal();}
  11. Double click Sheet1.cs so the Excel sheet is visible. Select any cell to open the properties window and change property ReferenceAssemblyFromVbaProject = true

  12. In Excel you may need to goto Trust Centre Settings and add the VS Solution folder and sub folders as trusted location

  13. Run the project and the code in the Excel MODULE will return the dateTimepicker through the exposed GetDatePickerVal method.

enter image description here

Sheet1.cs:

using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Text;using System.Windows.Forms;using System.Xml.Linq;using Microsoft.Office.Tools.Excel;using Microsoft.VisualStudio.Tools.Applications.Runtime;using Excel = Microsoft.Office.Interop.Excel;using Office = Microsoft.Office.Core;namespace DocLevelAddin{    [System.Runtime.InteropServices.ComVisible(true)]    [System.Runtime.InteropServices.ClassInterface(        System.Runtime.InteropServices.ClassInterfaceType.None)]    public partial class Sheet1 : DocLevelAddin.ISheet1    {        private void Sheet1_Startup(object sender, System.EventArgs e)        {        }        private void Sheet1_Shutdown(object sender, System.EventArgs e)        {        }        #region VSTO Designer generated code        /// <summary>        /// Required method for Designer support - do not modify        /// the contents of this method with the code editor.        /// </summary>        private void InternalStartup()        {            this.dateTimePicker1.ValueChanged += new System.EventHandler(this.dateTimePicker1_ValueChanged);            this.Startup += new System.EventHandler(this.Sheet1_Startup);            this.Shutdown += new System.EventHandler(this.Sheet1_Shutdown);        }        #endregion        private DateTime dtVal;        private void dateTimePicker1_ValueChanged(object sender, EventArgs e)        {            dtVal = dateTimePicker1.Value;        }        public DateTime GetDatePickerVal()        {            return dtVal;        }        protected override object GetAutomationObject()        {            return this;        }    }}

ISheet1.cs:

using System;namespace DocLevelAddin{    [System.Runtime.InteropServices.ComVisible(true)]    public interface ISheet1    {        DateTime GetDatePickerVal();    }}