Feb 28, 2017

From Macros to Add-Ins

At some point after creating and using macros regularly, you may begin to realize that deploying and sharing them with many users isn’t always easy.  You can share them across the network, or through your SOLIDWORKS PDM, but how do you make sure all users get the same layout for new buttons in the user interface?

Building SOLIDWORKS add-ins can make macro deployment much simpler across your teams, but it does mean making some slight modifications to your existing macros.  The great news is that you don’t have to start from scratch or import your existing code into an add-in.  SOLIDWORKS also provides a comprehensive add-in template through the SOLIDWORKS API SDK.  This can make the whole process pretty simple really.

The first assumption is that you’ll be using a Visual Studio development environment.  I will use Visual Studio 2015 for this example, but older versions will work as well.  There are free Express and Community editions of Visual Studio available for personal and educational use if you don’t have access to a full edition.

This example will cover three essential tasks:  tweaking your existing macros to work from the add-in, creating the add-in itself, referencing your macros, and finally, creating a deployment package (install files).

Tweak your Macro

A quick discussion about macros.  Most SOLIDWORKS macros out there are VBA macros written in Visual Basic and are saved in the SWP file format (SOLIDWORKS Project).  These shouldn’t need any adjustment to reference in an add-in.  However, the less-common, but more interesting VSTA macros (Visual Studio for Applications) will need some preparation work.  These are compiled as DLL files and can be written in either C# or VB.NET languages.  We’ll focus on how to prepare VSTA macros for add-ins first.

.NET Macro Adjustments

To make DLL macros with an external entry point, we need a new class with a public procedure that calls your desired code.  With VSTA macros, that can include arguments that come from the add-in.  In these examples, the SOLIDWORKS application interface is passed to the Run procedure as an argument.

VB

Imports SolidWorks.Interop.sldworks
Imports SolidWorks.Interop.swconst
Public Class App
  Public Sub Run(ByVal swApp As SldWorks)
    'processing code starts here

  End Sub
End Class

C#

using System.Collections.Generic;
using System.Text;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
namespace MakePart.csproj
{
  public class App
  {
    public void Run(ISldWorks swApp)
    {
        //process code starts here

    }
  }
}

Copy everything you had in your original main procedure to the new Run procedure.  Don’t forget necessary Imports or using statements.  The following are just examples of format, not any real macro code.

VB

Public Sub Run(ByVal swApp As SldWorks)
    Dim MyDialog As New Dialog1
    AddComponentsMod.m_swApp = swApp
    MyDialog.Show()
End Sub

C#

public void Run(ISldWorks swApp)
{
  ModelDoc2 swDoc = null;
  bool boolstatus = false;
  ...
  // Zoom To Fit
  swDoc.ViewZoomtofit2();
}

If you want your macro to still work stand-alone in SOLIDWORKS (and who wouldn’t), you need to call the Run procedure from your original main procedure.  Declare a variable as a new instance of your application class and call the new Run procedure in your main procedure.  This will be the same format you use to call your macro from your add-in later in the example.

VB

Public Sub main()
  Dim myMacro As New App
  myMacro.Run(swApp)
End Sub

C#

public void Main()
{
  App MyMacro = new App();
  MyMacro.Run(swApp);                       
}

The last thing you need to do is make the .NET macro COM-Visible by enabling the setting in Project Properties, Application, Assembly Information.



After making adjustments, build and run your macro as usual to make sure it still works stand-alone.

VBA Macro Information

Now, a quick discussion about VBA macros and how to call them.
For VBA macros, you need to know the macro name, the module name and the procedure, typically “main”.  The following macro is named MakePart.swp, its module is MakePart1 and the procedure name is main (not shown).


Create your Add-In

Visual Studio 2008 through 2015 will work.  This example will use 2015.  There are free express versions available or full versions for purchase.
Install the SOLIDWORKS API SDK – found here on your SOLIDWORKS DVD or in a full media kit download.

Install_media\api\SolidWorks API SDK.msi

If the SDK has been installed successfully, when you create a new project and select Visual Basic or C#, you will see the SwVBAddin (or SwCSharpAddin) available as a template.   Give it a good name to begin.




Code Structure of an Add-In


There are several code regions in the primary class SwAddin (same in VB and C#).  The most important are ISwAddin Implementation, UI Methods and UI Callbacks.

The two functions in the ISwAddin Implementation code section run when the add-in is turned on: ConnectToSW and when it is turned off or SOLIDWORKS is closed: DisconnectFromSW.

In this example, the event handlers and property manager pages are not needed, so it is just two procedures to focus on: AddCommandMgr and RemoveCommandMgr.  Nothing needs to be modified in RemoveCommandMgr.

AddCommandMgr is found within the UI Methods code section.  The procedure sets up the user interface by adding menu items, toolbars and a Command Manager tab.  It also initializes Icons and establishes “callback” functions.  This procedure also establishes which document types the command group will display under.  We will come back to this section shortly.

The UI Callbacks section is where you add your processing code.  To reference an existing .NET macro, add the macro as a reference to the project first, then call it.  Add a reference to the macro by selecting Project, Add Reference.  Browse to the compiled .NET macro dll.  After adding the reference, based on our example, call the Run procedure as shown.

VB

Sub MakePartMacro()
  Dim myMacro As New MakePart.vbproj.App
  myMacro.Run(SwApp)
End Sub

C#

public void MakePartMacro()
{
  MakePart.csproj.App myMacro = new MakePart.csproj.App;
  myMacro.Run(SwApp);
}


To reference a VBA macro, first add it to the add-in project by selecting Project, Add Existing Item.  Browse to the macro SWP file.  After adding it to the project, find it in the Project Explorer and set its properties as follows.  Build Action should be Content and Copy to Output Directory should be Copy if newer.


Call the VBA macro from the add-ins runtime folder by using the following.  This assumes the macro name, module name and procedure name explained above.

VB

Sub MakePartVBA()
  Dim myDir As String
  myDir = IO.Path.GetDirectoryName _
    (Assembly.GetExecutingAssembly.Location)
  Dim macroPath As String
  Dim errors As String
  macroPath = myDir & "\MakePart.swp"
  SwApp.RunMacro2(macroPath, "MakePart1", _
    "main", 1, errors)
End Sub

C#

public void MakePartVBA()
{
   string myDir;
   myDir = System.IO.Path.GetDirectoryName
      (Assembly.GetExecutingAssembly().Location);
   string macroPath;
   macroPath = myDir + "\\MakePart.swp";
   int errors;
   SwApp.RunMacro2(macroPath, "MakePart1", "main", 1, out errors);
}

The RunMacro2 method of SldWorks needs the following arguments: 1) the full path to the macro file, 2) the module name, 3) the procedure name, 4) run options, and 5) an output variable for error handling.  The example above assumes you have added the VBA macro to the add-in project in Visual Studio and that it will be copied to the installation location.

Now that you have your callback function for your macro, it is time to connect that function to the buttons in the user interface.  Within the “UI Methods” code region, inside the AddCommandMgr procedure, look for the two lines that create Command Items, or buttons.  The lines will start with the following code in both VB and C#.

cmdIndex0 = cmdGroup.AddCommandItem2(...)

The AddCommandItem2 method creates a command and associates it to a callback function.  It requires nine arguments, most of which relate to button labels, tooltips and icon.  For our example, the sixth argument is the most important.  Even though it is a string, it must be the exact name of the callback function that runs your macro.  For example, if the callback function name were MakePartVBA, the AddCommandItem2 call might look like the following.

cmdIndex0 = cmdGroup.AddCommandItem2("MakePart", -1, "Make a Part", _
    "Make a part from a VBA macro", 0, "MakePartVBA", "", _
    mainItemID1, menuToolbarOption)

Edit the two existing command items to run two different macros.  If you need more than two, you will need to also declare additional variables related to command items listed below.

Public Class variables: mainItemID1, mainItemID2, ... , mainItemIDn

AddCommandMgr procedure variables: cmdIndex0, cmdIndex1, ... , cmdIndexn

AddCommandMgr arrays: cmdIDs and TextType (you will need to modify the array size as well as continue to populate the arrays with your additional command items)

Test your Add-In

Now that you’ve made edits and included your macros, try out the new add-in.  You can run in Debug mode in Visual Studio and it will automatically register the add-in with SOLIDWORKS.  Hit Debug, Start Debugging to automatically launch a session of SOLIDWORKS with your new add-in.


For more information on installation and deployment options, check out my book, Automating SOLIDWORKS Using Macros 2017 for an in-depth chapter on the subject.