My good friend and colleague, John Goldsmith, recently blogged about the Visio SaveAsWeb feature (see http://visualsignals.typepad.co.uk/vislog/2010/03/automating-visios-save-as-web-output.html ), and mentioned that I was going to blog about automating the SaveAsWeb when a linked DataRecordset refreshes … so here it is! This is my version of a poor man’s Visio Services … which is only available with Visio 2010 Premium and SharePoint 2010 with an eCAL.
Firstly, the code is written in VBA, and utilises a module that is in the Visio SDK Samples library. The modSaveAsWeb file can be found in the Publishing category:
Secondly, this example is for Visio 2007 Pro, or Visio 2010 Pro and Premium because of the DataRecordsets that I am about to discuss…
The modSaveAsWeb module contains one useful public method, SaveDocAsWebPage( ByVal vsoDocument As Visio.Document, ByVal startPage As Integer, ByVal endPage As Integer, ByVal webFileName As String, ByVal flags As Integer) As Boolean.
You will need to insert the SDK module into the VBA project of a Visio document that contains the linked DataRecordset. For this example, I have used the sample IT Asset Management drawing that is linked to the ASTMGT.XLS file. This file can be found in the <Program Files>Microsoft OfficeOffice12Samples1033 folder for Visio 2007, or the <Program Files>Microsoft OfficeOffice14Visio Content1033 for Visio 2010. You should not edit any files in these protected folders, so copy the file to one of your own, then change the data source in your Visio document to the copy that you just created.
Whilst you have the Configure Refresh dialog open, you should change the Automatic Refresh interval. I changed it to 1 minute for testing purposes.
In this example, the network equipment shapes are linked to the Excel worksheet rows, and the Status column is linked to the Status Shape Data row. This value is linked to the icon in the top right corner of each shape. So, as you can see in the following screenshot, the red circle with a white cross denotes the Unavailable status on the server with the 10.0.1.52 IP address.
In this example code, I have saved the web page to the same folder as the Visio document.
I inserted some code into the ThisDocument class of the VBA project because this class already provides an object, Document, which has events.
I created a new Visio.DataRecordsets object, mDatasets, and set it have events with the WithEvents keyword. I don’t normally like to use WithEvents because it can be very chatty and slow down your application, but the DataRecordsets object only has three events. We only need one of them, DataRecordsetChanged, however we do not want to save the file, or generate a web page, every time the DataRecordsets changes, because this event is fired each time the DataRecordsets is refreshed, regardless of whether anything was actually changed. So, we need to check if anything has indeed changed before calling SaveDocAsWebPage. Therefore, you can check the contents of data before and after the refresh. I simply stored the previous data as an string, then checked if the new data string is the same length. You could get more sophisticated than my method, but this is just an example.
1: Option Explicit
2:
3: Private WithEvents mDatasets As Visio.DataRecordsets
4: Private mlastDataXml As String
5:
6: Private Sub Document_DocumentOpened(ByVal doc As IVDocument)
7: StartListening
8: End Sub
9:
10: Public Sub StartListening()
11: Set mDatasets = ThisDocument.DataRecordsets
12: End Sub
13:
14: Public Sub StopListening()
15: Set mDatasets = Nothing
16: End Sub
17:
18: Private Sub mDatasets_DataRecordsetChanged(ByVal DataRecordsetChanged As IVDataRecordsetChangedEvent)
19: If Not mlastDataXml = DataRecordsetChanged.DataRecordset.DataAsXML Then
20: 'This means that data has changed
21: doSaveAsWeb ThisDocument, Replace(ThisDocument.FullName, ".vsd", ".htm")
22: End If
23: mlastDataXml = DataRecordsetChanged.DataRecordset.DataAsXML
24: End Sub
25:
26: Private Sub doSaveAsWeb(ByVal doc As Visio.Document, ByVal htm As String)
27: SaveDocAsWebPage doc, -1, -1, htm, _
28: modSaveAsWeb.ShowNavigationBar Or _
29: modSaveAsWeb.ShowPanAndZoom Or _
30: modSaveAsWeb.ShowPropertiesWindow Or _
31: modSaveAsWeb.ShowSearchTool Or _
32: modSaveAsWeb.RunInBatchMode
33: End Sub
So, this listening to the DataRecordsets changes is initiated by the StartListening() method, and I have hooked that into the DocumentOpened event. Therefore, this drawing will always do at least one SaveAsWeb on open, but will only then re-SaveAsWeb if any data has changed. Again, you could get more sophisticated and preserve the last saved state within the document so that you do not do the initial SaveAsWeb on open.
The upshot of this is that the Visio document (if open) will automatically save itself as a web page when ever the data source is updated!
Of course, I haven’t put anything fancy in the browser code to force a refresh … this is not Visio Services you know!
Hi says
Hi David
I have a similar requirement like yours
where i wanted to refresh the page but in my case the refresh shud also happen automatically
What can be the possible way to achieve the same.
Waiting for your reply.
Thanks
Mugdha
davidjpp says
I’m not sure I understand what extra feature you are asking for.
In my example, I am using the built-in autorefresh, which can be as often as every minute, then detecting if anything really has changed before bothering to do a SaveAsWeb.
In reality, you should check how long it takes to actually do the SaveAsWeb (depends on the complexity of the document), and ensure that the autofresh period is longer than that.