Visio to image command line conversion
Asked Answered
C

4

10

At work we make pretty extensive use of Visio drawing as support for documentation. Unfortunately vsd files don't play nicely with our wiki or documentation extraction tools like javadoc, doxygen or naturaldocs. While it is possible to convert Visio files to images manually, it's just a hassle to keep the image current and the image files are bound to get out of date. And let's face it: Having generated files in revision control feels so wrong.

So I'm looking for a command line tool that can convert a vsd file to jpeg, png, gif or any image that can be converted to an image that a browser can display. Preferably it will run under unix, but windows only is also fine. I can handle the rest of the automation chain, cron job, image to image conversion and ssh, scp, multiple files, etc.

And that's why I'm turning to you: I can't find such a tool. I don't think I can even pay for such a tool. Is my Google-fu completely off? Can you help me?

I mean, it has got to be possible. There has to be a way to hook into Visio with COM and get it to save as image. I'm using Visio 2007 by the way.

Thanks in advance.

Christian answered 17/7, 2009 at 19:38 Comment(0)
T
7

I slapped something together quickly using VB6, and you can download it at: http://fournier.jonathan.googlepages.com/Vis2Img.exe

You just pass in the input visio file path, then the output file path (visio exports based on file extension) and optionally the page number to export.

Also here is the source code I used, if you want to mess with it or turn it into a VBScript or something, it should work, though you'd need to finish converting it to late-bound code.

hope that helps,

Jon

Dim TheCmd As String
Const visOpenRO = 2
Const visOpenMinimized = 16
Const visOpenHidden = 64
Const visOpenMacrosDisabled = 128
Const visOpenNoWorkspace = 256

Sub Main()
    ' interpret command line arguments - separated by spaces outside of double quotes
    TheCmd = Command
    Dim TheCmds() As String
    If SplitCommandArg(TheCmds) Then
        If UBound(TheCmds) > 1 Then
            Dim PageNum As Long
            If UBound(TheCmds) >= 3 Then
                PageNum = Val(TheCmds(3))
            Else
                PageNum = 1
            End If

            ' if the input or output file doesn't contain a file path, then assume the same
            If InStr(1, TheCmds(1), "\") = 0 Then
                TheCmds(1) = App.Path & "\" & TheCmds(1)
            End If
            If InStr(1, TheCmds(2), "\") = 0 Then
                TheCmds(2) = App.Path & "\" & TheCmds(2)
            End If

            ConvertVisToImg TheCmds(1), TheCmds(2), PageNum
        Else
            ' no good - need an in and out file
        End If
    End If

End Sub

Function ConvertVisToImg(ByVal InVisPath As String, ByVal OutImgPath As String, PageNum As Long) As Boolean
    ConvertVisToImg = True
    On Error GoTo PROC_ERR

    ' create a new visio instance
    Dim VisApp As Visio.Application
    Set VisApp = CreateObject("Visio.Application")

    ' open invispath
    Dim ConvDoc As Visio.Document
    Set ConvDoc = VisApp.Documents.OpenEx(InVisPath, visOpenRO + visOpenMinimized + visOpenHidden + visOpenMacrosDisabled + visOpenNoWorkspace)

    ' export to outimgpath
    If Not ConvDoc.Pages(PageNum) Is Nothing Then
        ConvDoc.Pages(PageNum).Export OutImgPath
    Else
        MsgBox "Invalid export page"
        ConvertVisToImg = False
        GoTo PROC_END
    End If

    ' close it off
PROC_END:
    On Error Resume Next
    VisApp.Quit
    Set VisApp = Nothing
    Exit Function
PROC_ERR:
    MsgBox Err.Description & vbCr & "Num:" & Err.Number
    GoTo PROC_END
End Function

Function SplitCommandArg(ByRef Commands() As String) As Boolean
    SplitCommandArg = True
    'read through command and break it into an array delimited by space characters only when we're not inside double quotes
    Dim InDblQts As Boolean
    Dim CmdToSplit As String
    CmdToSplit = TheCmd 'for debugging command line parser
    'CmdToSplit = Command
    Dim CharIdx As Integer
    ReDim Commands(1 To 1)
    For CharIdx = 1 To Len(CmdToSplit)
        Dim CurrChar As String
        CurrChar = Mid(CmdToSplit, CharIdx, 1)
        If CurrChar = " " And Not InDblQts Then
            'add another element to the commands array if InDblQts is false
            If Commands(UBound(Commands)) <> "" Then ReDim Preserve Commands(LBound(Commands) To UBound(Commands) + 1)
        ElseIf CurrChar = Chr(34) Then
            'set InDblQts = true
            If Not InDblQts Then InDblQts = True Else InDblQts = False
        Else
            Commands(UBound(Commands)) = Commands(UBound(Commands)) & CurrChar
        End If
    Next CharIdx
End Function
Twoway answered 20/7, 2009 at 16:3 Comment(3)
I get a "This filename is not valid." NUM: -2032466859 error when invoking: "Vis2Img.exe DAG.vsd DAG.gif" from the command line. appending 0 or 1 to the command to specify a page number doesn't help. I'll look more into it when I'm off work. Thanks for a great starting point at least.Christian
Yeah you need the full path the way this is set up...You could tweak it pretty easily to just default to app.path to find the folder for a file, if a full path isn't present...Twoway
Vis2Img.exe "cygpath -w -a DAG.vsd" "cygpath -w -a DAG.gif" to the rescue in cygwin bash :). Thanks Jon.Christian
S
4

F# 2.0 script:

//Description:
// Generates images for all Visio diagrams in folder were run according to pages names
//Tools:
// Visio 2010 32bit is needed to open diagrams (I also installed VisioSDK32bit.exe on my Windows 7 64bit)

#r "C:/Program Files (x86)/Microsoft Visual Studio 10.0/Visual Studio Tools for Office/PIA/Office14/Microsoft.Office.Interop.Visio.dll"

open System
open System.IO

open Microsoft.Office.Interop.Visio

let visOpenRO = 2
let visOpenMinimized = 16
let visOpenHidden = 64
let visOpenMacrosDisabled = 128
let visOpenNoWorkspace = 256

let baseDir = Environment.CurrentDirectory;

let getAllDiagramFiles = Directory.GetFiles(baseDir,"*.vsd")

let drawImage fullPathToDiagramFile = 
    let diagrammingApplication = new  ApplicationClass()
    let flags = Convert.ToInt16(visOpenRO + visOpenMinimized + visOpenHidden + visOpenMacrosDisabled + visOpenNoWorkspace)
    let document = diagrammingApplication.Documents.OpenEx(fullPathToDiagramFile,flags)
    for page in document.Pages do
        let imagePath = Path.Combine(baseDir, page.Name + ".png")
        page.Export (imagePath)
    document.Close()
    diagrammingApplication.Quit()   

let doItAll =     
    Array.iter drawImage getAllDiagramFiles

doItAll
Supervision answered 25/5, 2011 at 11:6 Comment(2)
If anyone should need it, I created a Powershell version of the script which is available hereFrodina
For configuring output quality, this blog post describes useful properties and methods accessible from diagrammingApplication.Settings: developer.microsoft.com/en-us/visio/blogs/…Bittersweet
N
-1

You can try "Visio to image" converter

http://soft.postpdm.com/visio2image.html

Tested with MS Visio 2007 and 2010

Newhall answered 11/1, 2016 at 14:59 Comment(0)
A
-2

There has to be a way to hook into Visio with COM and get it to save as image.

Why not try writing something yourself, then, if you know how to use COM stuff? After all, if you can't find anything already made to do it, and you know you can figure out how to do it yourself, why not write something to do it yourself?

EDIT: Elaborating a bit on what I stated in my comment: writing a script of some sort does seem to be your best option in this situation, and Python, at least, would be quite useful for that, using the comtypes library found here: http://starship.python.net/crew/theller/comtypes/ Of course, as I said, if you prefer to use a different scripting language, then you could try using that; the thing is, I've only really used COM with VBA and Python at this point (As an aside, Microsoft tends to refer to "Automation" these days rather than specifically referencing COM, I believe.) The nice thing about Python is that it's an interpreted language, and thus you just need a version of the interpreter for the different OSes you're using, with versions for Windows, OSX, Linux, Unix, etc. On the other hand, I doubt you can use COM on non-Windows systems without some sort of hack, so you may very well have to parse the data in the source files directly (and even though Visio's default formats appear to use some form of XML, it's probably one of those proprietary formats Microsoft seems to love).

If you haven't used Python before, the Python documentation has a good tutorial to get people started: http://docs.python.org/3.1/tutorial/index.html

And, of course, you'll want the Python interpreter itself: http://python.org/download/releases/3.1/ (Note that you may have to manually add the Python directory to the PATH environment variable after installation.)

When you write the script, you could probably have the syntax for running the script be something like "python visioexport.py <source/original file[ with path]>[ <new file[ with path]>]" (assuming the script file is in your Python directory), with the new file defaulting to a file of the same name and in the same folder/directory as the original (albeit with a different extension; in fact, if you wish, you could set it up to export to multiple formats, with the format defaulting to that of whatever default extension you choose and being specified by an alternate extension of you specify one in the file name. As well, you could likely set it up so that if you only have the new file name after the source file, no path specified, it'll save with that new file name to the source file's directory. And, of course, if you don't specify a path for the source file, just a file name, you could set it up to get the file from the current directory).

On the topic of file formats: it seems to me that converting to SVG might be the best thing to do, as it would be more space-efficient and would better reflect the original images' status as vectored images. On the other hand, the conversion from a Visio format to SVG is not perfect (or, at least, it wasn't in Visio 2003; I can't find a source of info similar to this one for Visio 2007), and as seen here, you may have to modify the resultant XML file (though that could be done using the script, after the file is exported, via parts of the Python standard library). If you don't mind the additional file size of bitmaps, and you'd rather not have to include additional code to fix resultant SVG files, then you probably should just go with a bitmap format such as PNG.

Astraphobia answered 17/7, 2009 at 20:34 Comment(4)
While I know C, some C++ and some C# I'm pretty far from understanding the whole software stack and I'd have to take quite a bit of time out to dig into it, set up the environment at home (because if I make the app on my company laptop, then the program will belong to my company), find the right method calls, make sure that it plays kinda nicely with XP and Vista, create a web page so that others can use it, etc. There is a lot of overhead in this small program and I hoped that someone had paid for it with his time so that I could pay for it with money instead. Now I have to do it...Christian
I apologize for the wait time, and find it odd that no one else has provided an answer. Regardless, I suggest you check out Python and the available comtypes library; it provides a very nice Python binding for the COM API, and is a lot easier to work with than using COM with C, C++, or C# would be. I'd test it out myself with Visio, but I don't have a copy of Visio available.Astraphobia
Forgot to mention: Even if you don't know Python, it shouldn't take too long to learn and get familiarized with it; as well, if there's some other scripting language that you prefer, you could probably check if there's some sort of COM binding library/add-in for that as well.Astraphobia
I know a small bit of python, but since Jon is a bit closer to the mark, any edits I'll do will probably be in VB6. Thanks for your help. I noticed the issues with SVG in Visio 2003 too. Since then I've stayed clear of SVG when it comes to Visio.Christian

© 2022 - 2024 — McMap. All rights reserved.