Jan 30, 2012

Intro to the SolidWorks EPDM API

SolidWorks World 2012 is less than two weeks away.  That means I’m two weeks from sharing more tips on the SolidWorks and Enterprise PDM APIs.  I’ll be presenting two sessions: one hands-on session introducing a lucky group to the guts of the Enterprise PDM API, and one sharing some of the tips and tricks I’ve learned over the years for building automation in SolidWorks. 

For now, let’s start with some API fundamentals for SolidWorks Enterprise PDM!  I had someone ask about how to compare files that are outside of EPDM with files already in the system.  For example, if a contract design group sends you a batch of files for a design, how do you know what to put back in EPDM?  The file set may contain common parts as well as new parts, assemblies and drawings.  Trying to sift through the file set to figure out what you should add to EPDM could be extremely tedious.  I can think of four or five activities involving sticks, rocks and dirt that would be more invigorating.  Yet another chance to automate!

Connecting to EPDM


As a starting point, fire up a new SolidWorks VSTA VB.NET macro.  Alternatively, you could begin with a new Visual Studio project.  The sample code below assumes using a macro.  Once you’ve started the project, add a reference to the SolidWorks Enterprise PDM library.  Select Project, Add Reference.  You should find it under the COM tab named PDMWorks Enterprise 20XX Type Library.

Open the SolidWorksMacro.vb code file if it isn’t open already and add an Imports statement to add EdmLib (the EPDM library).  Add the following code under the main procedure.

Imports SolidWorks.Interop.sldworks
Imports SolidWorks.Interop.swconst
Imports System.Runtime.InteropServices
Imports System
Imports EdmLib

Partial Class SolidWorksMacro

    Public Sub main()

        Dim vaultName As String = "EPDMVault"
        Dim CompareFolder As String = "C:\EPDM Test"

        'create a vault connection and log in
        Dim v As New EdmVault5       
        v.LoginAuto(vaultName, 0)

    End Sub

    ''' <summary>
    ''' The SldWorks swApp variable is pre-assigned for you.
    ''' </summary>
    Public swApp As SldWorks

End Class

Logging into EPDM


There’s not much to creating a connection to a local vault view and logging in.  The EdmVault5 interface just needs to be declared with the New keyword to connect.  The LoginAuto method is identical to a user opening the local view folder.  If they’re not currently logged in, the system will attempt to log them in using their Windows login.  If that fails, the login prompt is displayed.  The first argument for LoginAuto is the name of the vault.  The second argument is to help EPDM know what the calling application is (it’s window handle as an integer).  Since I’ve used a SolidWorks macro, I’m simply passing 0 to essentially ignore the argument.  It’s really a shortcut for something less than critical.

Creating a Search Interface


To compare files between the vault and an outside folder, we’ll use the EPDM search capability.  Using search through the API isn’t much different than using it through the client software.  Add the following code to the procedure to include the search definition.  We’ll fill out the details and run the search next.

    Public Sub main()

        Dim vaultName As String = "EPDMVault"
        Dim CompareFolder As String = "C:\EPDM Test"

        'create a vault connection and log in
        Dim v As New EdmVault5       
        v.LoginAuto(vaultName, 0)

        'create the search interface and initial settings
        Dim search As IEdmSearch5
        search = v.CreateSearch
        search.FindFiles = True
        search.FindFolders = False

    End Sub 

The search interface type is IEdmSearch5.  You create a search interface by calling EdmVault5.CreateSearch.  It has a handful of different settings.  Since we’re interested in finding files, we’ve set the FindFiles property to True and the FindFolders property to false.

Get the List of Files to Compare


Before we start utilizing the file and directory methods from VB.NET, it’s easiest to add a reference to the System.IO namespace.  Add the following code to import System.IO by the rest of the Imports statements.

...
Imports EdmLib
Imports System.IO

Once that’s been added, you can use FileInfo and DirectoryInfo classes from System.IO to get all files in a given folder path.  The code is finally using the CompareFolder variable to get the compare folder.

    Public Sub main()

        Dim vaultName As String = "EPDMVault"
        Dim CompareFolder As String = "C:\Test Folder"

        'create a vault connection and log in
        Dim v As New EdmVault5       
        v.LoginAuto(vaultName, 0)

        'create the search interface and initial settings
        Dim search As IEdmSearch5
        search = v.CreateSearch
        search.FindFiles = True
        search.FindFolders = False

        'get the file names from the folder to compare
        Dim searchDir As New DirectoryInfo(CompareFolder)
        Dim files As FileInfo()
        files = searchDir.GetFiles("*.*", _
            SearchOption.AllDirectories)
        Stop

    End Sub

If you run the macro to this point, you can review the array named files once you hit the Stop point.  It should have an array of FileInfo objects that include the name of every file in the test folder.

Now that we have an array of file names, we can run an EPDM search on each one.  If we find a match in EPDM, we’ll add that into a collection to later report back to the user.

Running a Search


Depending on how you have your vault configured, a search for a file name in EPDM might possibly return multiple files.  Since we’re interested in simply knowing if the file exists at all in the vault, we’ll only look for the first result.  If there isn’t a first result, we can confidently assume the file doesn’t exist in the vault.

Add the rest of the macro shown below.  If you’re looking for a shortcut, this is the entire macro.

    Public Sub main()

        Dim vaultName As String = "EPDMVault"
        Dim CompareFolder As String = "C:\Test Folder"

        'create a vault connection and log in
        Dim v As New EdmVault5       
        v.LoginAuto(vaultName, 0)

        'create the search interface and initial settings
        Dim search As IEdmSearch5
        search = v.CreateSearch
        search.FindFiles = True
        search.FindFolders = False

        'get the file names from the folder to compare
        Dim searchDir As New DirectoryInfo(CompareFolder)
        Dim files As FileInfo()
        files = searchDir.GetFiles("*.*", _
            SearchOption.AllDirectories)

        'collect any duplicates found in EPDM
        Dim duplicates As New Collection
        For Each f As FileInfo In files
            'run the search for this file name
            search.FileName = f.Name
            Dim sr As IEdmSearchResult5
            sr = search.GetFirstResult
            If Not sr Is Nothing Then
                'found a file in the vault with the same name
                duplicates.Add(f.Name)

                'optionally, get a local copy of the file
                Dim eFile As IEdmFile5
                eFile = sr 'get the file from the search result
                eFile.GetFileCopy(0) 'get the latest file copy
            End If
        Next

        'report back the files found
        Dim myMessage As String = "Duplicate file list:" & vbCrLf
        For Each dup As String In duplicates
            myMessage = myMessage & dup & vbCrLf
        Next
        MsgBox(myMessage & vbCrLf & duplicates.Count & _
            " duplicate files", MsgBoxStyle.Information)

        'reset the collection
        duplicates = Nothing

    End Sub 

I’ve used a Collection to keep track of the files found during the search.  It was easier than an array since I could simply add new elements and didn’t have to worry about resizing.
The EPDM search is run by setting the FileName property and then calling the GetFirstResult method.  The rest is simply formatting a message to return the list to the user.

I've also added a few additional lines of code to get a local file copy in the vault.  You need to first get the IEdmFile5 interface (directly from the IEdmSearchResult5 interface).  There are several optional arguments to the GetFileCopy method, but if you're just getting the latest version, you can use the exact syntax posted.

Jan 23, 2012

One Button PDFs in SolidWorks

Welcome to the beginning of SolidAPI - a blog dedicated to the SolidWorks API.  What better place to start than one of my favorite macros - one button PDF publishing.  I've had the chance to present this material several times at SolidWorks World.  But if you're coming this year and were hoping to re-live the experience - this post will have to suffice.  I'm presenting on the SolidWorks Enterprise PDM API instead.  So here's your chance to brush up on macro basics using VSTA (Visual Studio Tools for Applications) and Visual Basic.

Step #1 – Record it!


Start by opening any SolidWorks file.  Drawings are great, but models work fine too.  Start recording the macro by going to Tools, Macro, Record.
Select File, Save As.  In the Save As dialog, change the save as type to Adobe Acrobat PDF (*.pdf) and save.  That’s all we need to get started. 

Stop and save the macro by selecting Tools, Macro, Stop.  Change the save as type to SW VSTA VB Macro (*.vbproj) and save the macro as AutoPDF.vbproj.
Edit the newly saved macro by selecting Tools, Macro, Edit.  Browse to AutoPDF.vbproj (found under the newly created folders \AutoPDF\SwMacro\).  The important part of the macro is shown here.  Anything else in your recorded macro is not needed.

Imports SolidWorks.Interop.sldworks
Imports SolidWorks.Interop.swconst
Imports System.Runtime.InteropServices
Imports System
 
Partial Class SolidWorksMacro
 
    Public Sub main()
        Dim swDoc As ModelDoc2 = Nothing
        Dim longstatus As Integer = 0
        swDoc = CType(swApp.ActiveDoc, ModelDoc2)
        longstatus = swDoc.SaveAs3("C:\...\Drawing.PDF", 0, 0)
    End Sub
 
    ''' <summary>
    ''' The SldWorks swApp variable is pre-assigned for you.
    ''' </summary>
    Public swApp As SldWorks
 
End Class

Description


There are really only two lines of important code in Sub main() that do all the work. 

    swDoc = CType(swApp.ActiveDoc, ModelDoc2)

This line connects the variable named swDoc to the SolidWorks application’s active document using swApp.ActiveDoc.
Next, a Save As operation is calle from the active document interface that we’ve captured in the variable swDoc.  The main argument of interest is the first.  It must be a string containing the full path to the desired PDF file.

Code Changes


To make this macro worthwhile, we need to get a PDF path that makes sense.  The macro above would just keep overwriting the same Drawing.pdf file with a new PDF each time the macro was run.  Make the following changes to convert the active document’s current path to PDF.
    Public Sub main()
        Dim swDoc As ModelDoc2 = Nothing
        Dim longstatus As Integer = 0
        swDoc = CType(swApp.ActiveDoc, ModelDoc2)
        'get the current model path
        Dim modelPath As String = swDoc.GetPathName
        Dim pdfName As String
        'use IO.Path class to change the extension
        pdfName = IO.Path.ChangeExtension(modelPath, "pdf")
        'save the PDF
        longstatus = swDoc.SaveAs3(pdfName, 0, 0)
    End Sub

I dig the IO.Path class in .NET!  It makes it easy to manipulate file paths in all kinds of ways.  Changing a file’s extension is as easy as that.  Now the SaveAs3 method uses the newly modified path.

Make a Button in SolidWorks


Build your new macro (create the dlls) by selecting Build, Build AutoPDF.  Once that’s done, close the macro and jump back to SolidWorks.  To add a button to your toolbars or the Command Manager, select Tools, Customize.  Select the Commands tab and choose Macro from the list of command groups.  Drag and drop a new macro button onto any toolbar. 
 


Fill out the form by adding a tool tip and a prompt.  Then browse to the bin folder in your macro directory to find AutoPDF.dll.  Click OK and you’re done!  Now your PDFs are only one button away.