Create Visio file (.vsdx or .vdx) in Java

Started by peterrific, June 11, 2017, 02:01:29 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

peterrific

Hi there,

I'm looking for some info on how to create a Visio file in Java (without any commercial libraries). According to my research on this so far it seems to be quite challenging:

As a source we have a different, probably unknown file format called .epml that contains graphical information of EPCs which we should be able to convert to a .xml file. The goal here is to be able to convert the graphic information of the .epml file so Visio is able to read & display it as in the source. Therefore, it doesn't have to be the newest .vsdx file as long as Visio can handle it.

VSDX:
We already identified one critical .xml file within the unzipped .vsdx file that contains the graphical information. The question here is, even if we were able to create that file, what else has to be created so Visio can read the information?

VDX:
Since the new VSDX file structure with all it's files & folders seems to be quite complicated to create, we also took a look at the older VDX/XML format. Here it seems, the challenging part is to identify which elements of the XML file really have to be created.

Any tips on how to fulfill this task are much appreciated!
Thanks in advance!

Croc

In general, the task of creating a VDX file is very complicated.
However, in special cases it can be greatly simplified.
For example, if you can pre-create a template and write it in VDX format. And if you only need to use the master-shapes from the template to create the document.
In the simplest case, the node set can contain: Shape, Master, ID, Name, XForm, PinX, PinY, Width, Height, Text for 2D shapes. And about the same for connectors: XForm1D, BeginX, BeginY, EndX, EndY.
A minimal set of nodes depends on the task being solved and on how the resulting file will be processed in the future.

peterrific

That doesn't sound too bad.

Well, basically all we need is the two basic shapes of EPCs (functions & events), the 3 available connectors and the arrows connecting the nodes. Additionally we need to be able to color those arrows and nodes. In some cases we need two colors at once, so we probably also need some kind of shadow. The only downside of this approach is that VDX is deprecated and might not work for future releases of Visio. VSDX however (especially in combination with our limitation to Java) seems to be way more complicated.

Thanks for the quick response!

Croc

In VSDX, you have to work with three or four files from the entire package. This will not greatly complicate the task.
Still need to be able to open the package.

peterrific

Opening the .vsdx package won't be the problem. Do you have any concrete advice on how to create a .vsdx or a .vdx file?

Croc

I do not work in Java, so I can only show how it was done on VBA for VDX.
The template is made manually and is an empty Visio file, saved in VDX format.
A fragment of the main module makes a copy of the template and opens it as an XML DOM document.
Next you need to find the required nodes of the tree and add new nodes. In the example, 4 shapes are added.
    Set xmlVis = New MSXML2.DOMDocument
    ' 1- Prepare copy of VDX
    CurrPath = ActiveDocument.path
    Dim fso As New FileSystemObject
    fso.CopyFile CurrPath & "first.vdx", CurrPath & "first.xml"
    s = CurrPath & "first.xml"
    xmlVis.Load(s)

    NextID = 1
    Set Nod2 = AddShape(CStr(NextID), "4", "3.5", "2.5")
        NextID = NextID + DocMasters("4").ChldCount + 1
    Set Nod5 = AddShape(CStr(NextID), "0", "3.5", "3.5")
        NextID = NextID + DocMasters("0").ChldCount + 1
    Set Nod5 = AddShape(CStr(NextID), "3", "1.5", "1.5")
        NextID = NextID + DocMasters("3").ChldCount + 1
    Set Nod5 = AddShape(CStr(NextID), "5", "0.5", "3.5")
   
    xmlVis.Save (CurrPath & "first_out.vdx")

Parameters of the AddShape function: ID of Master-shape, coordinates X and Y in inches.
The function creates a Shape node with ID and Master attributes, finds the Pages node and the first child - Page-1, and adds the created Shape node to the Shapes node.

Private Function AddShape(ByVal id As String, _
    ByVal Master As String, _
    ByVal x As String, _
    ByVal y As String, _
    ByVal resizeScale As String) As MSXML2.IXMLDOMNode
    Dim NewShape As MSXML2.IXMLDOMNode
    Dim Page As MSXML2.IXMLDOMNode
    Dim XForm As MSXML2.IXMLDOMNode
   
    xmlns = "http://schemas.microsoft.com/visio/2003/core"
    ' Create new shape
    Set NewShape = xmlVis.createNode(1, "Shape", xmlns)
    Set nA = xmlVis.createAttribute("ID"): nA.text = id
    NewShape.Attributes.setNamedItem nA
    Set nA = xmlVis.createAttribute("Master"): nA.text = Master
    NewShape.Attributes.setNamedItem nA
    If DocMasters(Master).ChldCount > 0 Then
        Set nA = xmlVis.createAttribute("Type"): nA.text = "Group"
        NewShape.Attributes.setNamedItem nA
    End If
   
    'Check (or create) <Shapes>
    Set Page = xmlVis.DocumentElement.SelectSingleNode("//VisioDocument/Pages").ChildNodes(0)   'Page-1
    Set Shapes = Page.SelectSingleNode("Shapes")
    If Shapes Is Nothing Then
        Set tmpNod = xmlVis.createNode(1, "Shapes", xmlns)
        Set Shapes = Page.appendChild(tmpNod)
    End If
    ' Append new Shape to Shapes
    Set AddShape = Shapes.appendChild(NewShape)

Then I add the XForm node and the child nodes PinX, PinY, Width, Height.
    ' Add minimum of attributes: XForm with PinX, PinY
    Set tmpNod = xmlVis.createNode(1, "XForm", xmlns)
    Set XForm = NewShape.appendChild(tmpNod)
    Set tmpNod = xmlVis.createNode(1, "PinX", xmlns): tmpNod.text = x
    XForm.appendChild (tmpNod)
    Set tmpNod = xmlVis.createNode(1, "PinY", xmlns): tmpNod.text = y
    XForm.appendChild (tmpNod)
    res = CStr(CDbl(Replace(resizeScale, ".", ",")) * CDbl(Replace(DocMasters(Master).Width, ".", ",")))
    Set tmpNod = xmlVis.createNode(1, "Width", xmlns): tmpNod.text = Replace(res, ",", ".")
    XForm.appendChild (tmpNod)
    res = CStr(CDbl(Replace(resizeScale, ".", ",")) * CDbl(Replace(DocMasters(Master).Height, ".", ",")))
    Set tmpNod = xmlVis.createNode(1, "Height", xmlns): tmpNod.text = Replace(res, ",", ".")
    XForm.appendChild (tmpNod)

Nikolay

Quote from: peterrific on June 11, 2017, 08:49:57 PM
Opening the .vsdx package won't be the problem. Do you have any concrete advice on how to create a .vsdx or a .vdx file?

As you seem to be completely sure you dont want to buy a squirrel library,
Here is a shortcut to the interstate vsdx
- Download Apace POI open source package. You want the source code. This will give you support for ooxml packages
- Find there (in xgdf) XmlVisioDocument, and extends it to support saving (now it supports read-only access only.)

peterrific

I'm a little confused about the different opinions on the difficulty of being able to create a .vsdx file. VSDX would be the preferred approach since Nikolay already made clear that VDX is deprecated. However, being limited to Java and having only 6 more weeks to fulfill this task, I'm not sure if creating .vsdx is doable. (Especially since the Apace Team seems to be working on this for quite a while now).