An ingenious version tracking solution for OpenOffice.org

64

Author: Dmitri Popov

While OpenOffice.org allows you to save multiple versions of a document, that feature has a few drawbacks that limit its usefulness. For starters, saving all versions in the same file equals putting all your eggs in one basket. More importantly, this approach makes it difficult to share versions with other users and let them keep track of changes made to a document. One alternative, a full-blown version tracking system or a dedicated document management solution, is overkill if you only need a simple way to keep tabs on document versions and allow other users to keep track of them. A compromise solution uses OpenOffice.org to maintain an RSS feed of document changes.

The entire solution consists of a Writer file that contains the RSS feed data, and an OpenOffice.org Basic macro that does two things: saves a version of the currently opened documents, and creates an item in the RSS feed linking to the saved version. To better understand how the macro works, let’s take a look at an RSS feed with the information needed for version tracking.

  <?xml version="1.0"?>
  <rss version="2.0">
    <channel>
      <title>OpenOffice.org RSS Feed</title>
      <link>http://192.168.1.7</link>
      <description>A simple feed that tracks changes in OpenOffice.org documents</description>
      <language>en-us</language>
      <generator>OpenOffice.org 2.2.1</generator>
  
      <item>
        <title>Loremipsum.odt</title>
        <description>Initial version of the document.</description>
        <guid>http://192.168.1.7/Loremipsum.odt</guid>
      </item>
  
    </channel>
  </rss>

As you can see, the feed is a plain XML file consisting of two main parts: a static preamble that contains meta information about the feed (title, description, etc.) and the feed items that include their titles, descriptions, and links to the appropriate documents. Looking at the feed, it’s easy to figure out that the macro should simply create a new item for each saved document version and write it to the RSS file.

While OpenOffice.org can read and write plain text files, it’s not very good at manipulating them. That’s why you need to set up a Writer document (e.g. RSS.odt) that contains the RSS feed. The macro then uses the file to write new RSS entries to it and saves it as an .xml file. Initially, the RSS.odt file should contain just an empty feed with no items in it:

  <?xml version="1.0"?>
  <rss version="2.0">
    <channel>
      <title>OpenOffice.org RSS Feed</title>
      <link>http://192.168.1.7</link>
      <description>A simple feed that tracks changes in OpenOffice.org documents</description>
      <language>en-us</language>
      <generator>OpenOffice.org 2.2.1</generator>
  
    </channel>
  </rss>

Once the RSS.odt document is ready, you can start working on the macro. First, you need to define a couple of variables and check whether the document has been saved:

  Sub AddRSSItem()
  Dim ObjSearch As Object
  Dim Args(0) As New com.sun.star.beans.PropertyValue
  ThisDoc=ThisComponent
  
  If ThisDoc.hasLocation=False Then
  MsgBox ("You must save the document first!", , "Attention!") :End
  End If

Next, the macro has to obtain the name of the currently opened document; this is used as the title of a feed entry:

  DocURL=ThisDoc.getURL()
  FileName=Dir(DocURL, 0)

Since the macro writes the RSS entry to the RSS.odt document first and then saves it as an XML file, you need to specify three variables: the path to the RSS.odt file, the path where the resulting XML file should be stored, and the name of the XML file.

  RSSFile="ftp://user:password@192.168.1.7/web/RSS.odt"
  RSSPath="ftp://user:password@192.168.1.7/web/"
  RSSXMLFile="rss.xml"

In the example above, both RSS.odt and the resulting rss.xml files are stored in the same location on a local FTP server, so users on the local network can subscribe to the RSS feed. But you could publish the RSS feed on a Web server, while keeping the RSS.odt document on your local machine.

The macro also has to add a timestamp that acts as a unique identifier to each saved version. There are several ways to do this, depending on what data you want to append. The code below adds the prefix YYYYMMDD_HH-MM-SS_ to the document. It then uses the RSSPath to save the document version in the same location as the rss.xml file, thus making it easier to link to it:

  Timestamp=CDateToISO(Date) & "_" & Format(Hour(Now), "00") &_
  "-" & Format(Minute(Now), "00") & "-" &_
  Format(Second(Now), "00")
  VersionPath = RSSPath & Timestamp & "_" & FileName

Once the macro has all the required elements, it saves a timestamped version of the current document:

  Args(0).Name="Overwrite"
  Args(0).Value=True
  ThisDoc.storeToURL(VersionPath, Args())

Next step is to update the RSS feed to reflect the changes. First, the macro opens the RSS.odt files and prompts the user to enter a brief description of the changes:

  ThisDoc=StarDesktop.loadComponentFromURL(RSSFile, "_blank", 0, Array())
  ChangesDescription=InputBox("Summary of changes", "Enter a brief description of changes" , "")

Using the information provided, the macro then has to generate a new RSS entry and insert it into the RSS.odt file. The latter is a bit tricky since the new entry must be inserted before the </channel></rss> tags. One way to solve this problem is to use a search and replace routine to find the </channel> tag and replace it with the new RSS entry followed by </channel>. Another nuisance is that the standard search and replace routine in OOoBasic ignores line breaks specified by the Chr(13) code. This means that the entire RSS item will be inserted as a single line. While this has no effect on how the RSS is parsed, it makes it harder to read. Fortunately, there is a simple workaround that can solve the problem. You can enable regular expressions and use the n code to insert line breaks. The final search and replace code block looks something like this:

  RSSEnd="</channel>"
  NewRSSItem=Chr(13) & "<item>n <title>"& FileName & "</title>n <description>" & ChangesDescription &_
  "</description>n <guid>" & VersionPath & "</guid>n </item>nn</channel>"
  ThisDoc=ThisComponent
  ObjSearch=ThisDoc.createReplaceDescriptor
  ObjSearch.SearchString=RSSEnd
  ObjSearch.ReplaceString=NewRSSItem
  ObjSearch.SearchWords=true
  ObjSearch.SearchRegularExpression=true
  nReplace=ThisDoc.ReplaceAll(ObjSearch)

The macro is almost done; it just has to save the RSS.odt document, then save it as an XML file, and close it to keep things tidy:

  ThisDoc=ThisComponent
  ThisDoc.Store
  
  Args(0).Name="FilterName"
  Args(0).Value="Text"
  ThisDoc.StoreAsURL (RSSPath & RSSXMLFile, Args())
  
  ThisDoc.Close(True)
  End Sub

That’s it. Your DIY version tracking solution is ready to be deployed. Move the RSS.odt document to the desired location, make sure that all the paths in the macro are correct, and start using it. Other users can then subscribe to the generated RSS feed and keep track of the document changes.

Category:

  • Office Software