Referencing module in stencil

Started by aledlund, August 02, 2008, 12:32:41 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

aledlund

A recent forum post brings forward an interesting question on extending Viso solution code to stencils. The ability to insert code into a stencil brings significant additional functionality to some Visio Solutions. The question "how do I call a sub from an external module?" of course is started by adding a reference to it in from the Tools menu in the vba editor. Then you just call your sub using standard notation "ado_data.modAccessData.LoadAccessNetData" (ado_data=stencil). The fun part begins when you want to manage this reference functionality in-line to allow some flexibility on options that you may/or maynot want your users to have access to. This gets us into vbProjects.

These routines assist in managing projects and references in-line



'
' requires program files\common files\microsoft shared\vba6\vbe6ext.olb
' as a reference
'
' Private Const strImptExptStencil = "imptexpt.vss"
'
' testReference(strCurrDocName, "imptexpt")
'
Private Function testReference(strProject As String, _
                                strModule As String, _
                                Optional blnRemove As Boolean = False) _
                                As Integer
                                                               
    Dim intReturn As Integer
    intReturn = -1
   
    Dim vbideVBE As vbide.Vbe
    Set vbideVBE = ThisDocument.Application.Vbe
       
    Dim currProjects As VBProjects
    Set currProjects = vbideVBE.VBProjects
    Dim currProject As VBProject
       
    Dim strTgtFile As String
    strTgtFile = ThisDocument.Path & strModule
    Dim strBaseFile As String
    strBaseFile = ThisDocument.Path & strProject
    Dim strBuild As String
    Dim strTemp As String

    Dim intX As Integer
    Dim intY As Integer
    Dim refRemove As vbide.Reference
   
        For intX = 1 To currProjects.Count
            strBuild = currProjects.Item(intX).FileName
            If LCase(strBuild) = LCase(strBaseFile) Then
                Set currProject = currProjects.Item(intX)
                For intY = 1 To currProject.References.Count
                    strTemp = currProject.References.Item(intY).Name
                    If LCase(strTemp) = LCase(strModule) Then
                        intReturn = intY
                        If blnRemove = True Then
                            Set refRemove = currProject.References.Item(intY)
                            currProject.References.Remove refRemove
                        End If
                    End If
                Next intY
            End If ' test for item name
        Next intX
       
    testReference = intReturn
    Exit Function

ErrHandler:

    MsgBox Err.Description
    testReference = intReturn

End Function

'
' get a list of projects that we are currently using
'
Private Function getCurrProjects() As VBProjects
   
    Dim vbideVBE As vbide.Vbe
    Set vbideVBE = ThisDocument.Application.Vbe

    Dim currProjects As VBProjects
    Set currProjects = vbideVBE.VBProjects

    Set getCurrProjects = currProjects

End Function


'
' what project are we running as the base document
'
Private Function getCurrBaseProject() As VBProject

    Dim vbideVBE As vbide.Vbe
    Set vbideVBE = ThisDocument.Application.Vbe
       
    Dim currProjects As VBProjects
    Set currProjects = vbideVBE.VBProjects
    Dim currProject As VBProject
       
    Dim strBaseFile As String
    strBaseFile = ThisDocument.Path & ThisDocument.Name
    Dim strBuild As String
    Dim strTemp As String

    Dim intX As Integer
        For intX = 1 To currProjects.Count
            strBuild = currProjects.Item(intX).FileName
            If LCase(strBuild) = LCase(strBaseFile) Then
                Set currProject = currProjects.Item(intX)
            End If ' test for base name
            Exit For
        Next intX
       
    Set getCurrBaseProject = currProject
    Exit Function

ErrHandler:

    MsgBox Err.Description
    Set getCurrBaseProject = Nothing


End Function

'
' check to see that a project has been loaded
'
Private Function testCurrProjects _
            (ByRef currProjects As VBProjects, _
            ByVal strModule As String) _
            As Integer

    Dim intReturn
    intReturn = -1
   
    Dim intX As Integer
    Dim intY As Integer
    Dim strBuild As String
   
        For intX = 1 To currProjects.Count
            strBuild = currProjects.Item(intX).Name
            If LCase(strBuild) = LCase(strModule) Then
                intReturn = intX
                Exit For
            End If ' test for item name
        Next intX
       
    testCurrProjects = intReturn
    Exit Function

ErrHandler:

    MsgBox Err.Description
    testCurrProjects = intReturn

End Function






This code demonstrates how it might be applied to putting support into a visio vb project dynamically




Private Sub addImptExptSupport()

    Dim ImptExpt As Visio.Document
    ' go check the property to see if it is already loaded
    If ThisDocument.pImptExptLoaded = True Then Exit Sub

    Dim docStencil As Visio.Document
    Dim strPath As String
    strPath = ThisDocument.Path
   
    Dim fs As FileSystemObject
    Set fs = CreateObject("scripting.filesystemobject")
    Dim strFile As String
    Dim strStencil As String
    strStencil = ""
   
    On Error GoTo ErrHandler
    Dim strCurrDocName As String
    strCurrDocName = ThisDocument.Name

    strStencil = strImptExptStencil
    strFile = strPath & strImptExptStencil
   
    Set docStencil = Application.Documents(strImptExptStencil)
   
    If docStencil Is Nothing Then
       
        If fs.FileExists(strFile) = False Then
            MsgBox "Stencil " & strImptExptStencil & " not in directory " & strPath
            Exit Sub
        Else
            ' add the stencil and the reference
            Application.Documents.OpenEx strFile, _
            (CInt(VisOpenSaveArgs.visOpenDocked) + _
            CInt(VisOpenSaveArgs.visAddHidden))
            DoEvents
            getCurrBaseProject.References.AddFromFile strFile
            DoEvents
            MsgBox "Please save/close document and then reload (imptexpt = new load)"
            DoEvents
        End If ' stencil not found
    Else
        If testReference(strCurrDocName, "imptexpt") = False Then
            getCurrBaseProject.References.AddFromFile strFile
            MsgBox "Please save/close document and then reload (imptexpt = new load)"
            DoEvents
        End If
    End If  'stencil not loaded
           
    Exit Sub

ErrHandler:
    If Err.Number = -2032465760 Then
        DoEvents
        Resume Next
    End If
   
    MsgBox "Load ImptExpt Failed, stencil = " & strStencil
    MsgBox Err.Description

   
End Sub







HTH,

al

vojo

or even how to tie code to a shape so that drawing is sent....code goes with it....or even preventing certain shapes from using code.   It has always been unclear to me how code is managed in relation to drawing and shape....would hate to send 50 bizzilion modules to a user as part of a simple diagram of of 5 shapes.

aledlund

The original Visio did allow some code to be in a shapesheet, but frankly that's a security nightmare so it had to go. I understand not wanting to send a lot of code along with a very simple diagram.

As Chris pointed out in one of his discussions, when working with complex Visio solutions dotnet is the way a developer should consider going. However. I like to prototype in VBA so putting code into stencils and then programmatically controlling references and loaded stencils becomes a poor man's way of working with a dotnet kinda environment. The application that I sandbox most with is a datacenter rack drawing tool that allows me to draw based upon external data.

The implementation of the sandbox is separate stencils for functions like ICMP, SNMP, WMI(wkstation/srv), ADO, IMPT/EXPT. I can then turn properties on in the base document for what I want to load. It also means that if I change a module, my users get a new stencil for that set of functions and nothing needs to go further. This also allows a (very) limited control of what a user can run against. So by not sending along the stuff that directly interacts with the network, I don't have network security breathing down my neck.

The primary stuff kept in the base drawing is eventhandlers to call the external stuff and some basic drawings classes (although right now mine is kinda bloated with a lot of experimental objects as I move it to a more production type of solution).

al

Visio Guy

Putting code in the stencils is a strategy aimed at keeping copies of VBA code to a minimum. The classic problem is that people put VBA code in documents or templates, which get copied for every Visio drawing.

Putting VBA into the stencils stops this proliferation to some extent. Updates to code or shapes occur in the same place.

It seems to me that I used to have trouble with referencing the stencil projects. It caused some instabilities and problems with not being able to close documents, though. I must admit, I haven't tried it for a while, though. Is this any better? Is there a recommended technique?
For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010

aledlund

I'm just an old guy out here in the cornfields to be asking about best practices. I usually go looking to you and the other mvp's to keep me on track. Frankly I am constantly surprised at how stable it is given the mixed models that I have been throwing at it. The challenge I am working on right now is that as I move it off of Access (adodb) to Sql  trying to maintain the interoperability with data recordsets. I'll probably use XML as the translate between the data mechanisms. Remembering that this is sidestream to the real world of moving data centers.
al

vojo

Noticed your post...thanks...sorry for not catching last month

I am definitely not fluent in VBE (resisted since the security issues and really did not want get into "raising a barn just to build a dog house")  but the post at the top seems to me to be the exact opposite of what I was looking to do.  Namely, the top seems to be "how to pull a stencil and such into a VBE project"  however I was more looking for "how to package/reference a module in some new drawing".

for example, it would be ideal the module got bundled with the stencil so that it could be shared at the stencil level (security mess aside).  It might even be ok to say the module is a separate file that must reside in some directory (with stencil, with drawing, or etc etc etc).

I was hoping that I did not have to build an entire visio instance via VBE just to access a module.

Hopefully, an alternative is to make a template out of "clean" drawing where stencils, modules, etc are included in the template.   Assuming I am correct, then somebody could send the template as a drawing to others without others becoming a rocket scientist on VBE

Visio Guy

For articles, tips and free content, see the Visio Guy Website at http://www.visguy.com
Get my Visio Book! Using Microsoft Visio 2010