C# & Microsoft & Software DeerashaSingh - 18 Jun 2009 05:46 pm
Guji in Habanero Land #4: Using XSLT and XML to list Business Objects in a Word Document
Use cases are an important part of the communication between a client and a developer, or a user and a business analyst. That much is evident, since they are written in plain English and describe the business process in detail from the user’s point of view. All this is great except these use cases seem to create a huge administration overhead. What’s that I hear you say? “That’s the Project administrator/co-ordinators job”? No, we don’t have such a luxury! (We chose premium filter coffee and an espresso machine over having a co-ordinator).
In one of my less noob- like moments, I have realised that a requirements phase more often than not results in an abundance of use cases, which need to be tracked and managed. I did not choose to be an administrator, so I have promptly recognised the dire need for the Use Case Manager. To date use case management applications have focused on the analyst’s need to keep track of use cases. This works well for classic software methodologies like the water fall approach, but requirements are extremely fluid in agile software development, so transparency and simplicity in communication is vital. For a start, the use cases need to be available to everyone, making rapid feedback possible. Since there are often multiple revisions of Requirements Documents, the user must be able to generate a new document whenever changes are made to the use cases.
My tasks for this month include implementing the following use cases in the Use Case Manager:
And now to the technical bit. How do I get the Use Cases into a word document? Converting objects from C# code into a document seemed to require the use of some third party software. “GloryDev” aka Brett suggested two free utilities: stringTemplate and NVelocity . Now having the attention span of a gnat does not help when trying to decipher what these things are. Having barely any experience with .NET alone, I have to figure out the what, why and when of templates. Templates?! I’m sure both tools are well defined for their purpose, but this noob has no idea what that is. I couldn’t join the dots between generating documents from code and using these “template engines”. So I puzzled over what to do…. for a while.
In a world where another option is but a google away, it is very difficult to try and stick with something that isn’t producing results fast and after two weeks of mucking about I needed results….fast! My helpful fellow devs suggested using Active Reports, but again my lack of knowledge was a stumbling block. Also, it’s not free, so I only wanted to try it as a last resort.
Finally, the mention of XSLT took me down a viable path. There was still a learning curve, but perhaps not as steep a climb towards completion of the task. I was warned that XSLT was very hard to maintain, and it violated the requirement that it must be open to automated testing. The other devs took pity on me though, and allowed me to try it since I was not getting anywhere with the other methods yet.
The Habanero Business Object can be saved to XML, so I had the Project along with Packages, Use Cases and Use Case Steps saved to a file I could transform.
I googled “Xml to Word” and found some interesting articles. This article certainly took the pain out of producing word documents. Following it step by step along with the w3 schools tutorials on XML, XSLT and XPATH, I produced a listing of Use Cases in a Project, sorted by Package. This is the trick Chris Bennett thankfully chose to share with the world in the above article:
1. Create the layout you want in Word.
2. Save the document to XML (which Word allows you to do)
3. Then tweak the XML into XSLT by (get this!) adding a few lines
That’s one more use case done. Next, I needed to find a way to insert the table from this listing at a specified point in the Requirements Document. Another chance to investigate something I know nothing about… google help me! And the search for examples to study and documentation to read begins.
I have found that to make the best use of MSDN, its best to google to get there; the site search is just shameful (don’t snigger its true). Google found a detailed how-to (105 printed pages… ahem) using the word object model which even had snippets of C# code. So I read through that and tried out some of the code to get a better idea of the domain.
Another resource that came in handy- this straightforward article from techrepublic. And you’ve got to love the description of seeing an open word instance as “both intriguing and scary”.
There was also an older, Visual Basic, Chillisoft-developed project that used bookmarks in the word object model to produce reports. This was the approach I was advised to use, and the code for it didn’t turn out as unwieldy as I thought it would. And another trick: record a macro for what you’re trying to do in Word, and attempt to translate that into C# code.
If I got anything out of this long, strange trip it would be that modelling what you want to do before you do it in code is very helpful. To save someone else the toil, this is C# code for inserting the content of one Word document into another:
public static void WriteRequirementsToWordDocument(string projectDocName, string requirementsTemplateName, string generatedDocName, string insertionPointBookmark) { object missing = Type.Missing; _Application oWord = new Application { Visible = false}; _Document oDoc; _Document projectDoc; try { object fileName = Path.Combine(Environment.CurrentDirectory, requirementsTemplateName); oDoc = oWord.Documents.Open(ref fileName, ref missing,ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); object projectFileName = Path.Combine(Environment.CurrentDirectory, projectDocName); projectDoc = oWord.Documents.Open(ref projectFileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); projectDoc.Activate(); oWord.Selection.WholeStory(); oWord.Selection.Copy(); oDoc.Activate(); object insertAtBookmark = insertionPointBookmark; oWord.Selection.GoTo(ref missing, ref missing, ref missing, ref insertAtBookmark); oWord.Selection.Paste(); object requirementsFileName =Path.Combine(Environment.CurrentDirectory,generatedDocName); oDoc.SaveAs(ref requirementsFileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); } finally { oWord.Quit(ref missing, ref missing, ref missing); } }
To look at this technique in context you can download the Use Case Manager off Codeplex.

