It was 2008 when I wrote the article for MSDN magazine that showed off the first book publishing Word add-in that I had built. It basically assembled individual Word files into one master document. We’ve used it to publish every version of The SharePoint Shepherd’s Guide (2010, 2013, 2016), Secret SharePoint, Extinguish Burnout, and more. However, it had grown quite long in the tooth. Small problems cropped up that we worked around until now. We had to do something different, because we were building an exercise handbook with page numbers that matched the lesson and exercise, which meant we had to assemble the files with section breaks in them instead of page breaks.
Being able to individually work on and track components of a large project is essential. We had that in spades. It’s a well-oiled machine as each element of the process moves from one state (and therefore queue) to another. However, when the OneDrive and Office integration happened, the book publishing tools choked, as Word and OneDrive got confused as to what was happening. We worked around the issue by copying the files to a non-synchronized folder and ran the tool from there, but it was frustrating and took time.
We also were always fighting the problem of starting new elements on the right side of a pair of facing pages. For The Shepherd’s Guide and other projects, it wasn’t such a big deal, but as we got to having separate exercises, it became important. The tool didn’t manage that – but it definitely could.
The tool didn’t do a good job of behaving well with the Word user interface. It would sometimes end up behind the user interface updates, and you’d wonder what was going on. We needed to make it reliably report status – all the time.
It also treated every file the same. You couldn’t say that you didn’t want to convert fields to text in the bibliography, but you wanted to convert all fields to their text for other parts of the file.
Other than the section/page numbering issue, everything was a small annoyance, which is why they hadn’t been fixed. However, that changed.
Visual Studio Tools for Office was the initial name of the toolset used to build a compiled DLL add-in for an Office Application. Those tools have been carried through until today. The heart of it is a set of objects that expose the internals of the Office application – in this case, Word – to another program. It’s the same object model between the macros that Word supports internally and the externally compiled objects. The initial article made this point clear by first recording steps and then transitioning those into compiled code.
However, back then, I didn’t have a deep understanding of the threading model inside of Word or – to be honest – the complexities of updating the user interface from a single thread. The result was a kludgy implementation that made the user interface both in Word and in the dialog very non-responsive.
Threading and the User Experience
Since then I’ve had more than a few primers on threading, user experience updates, call-backs, events, and other ways to make the user interface better.
I settled on an approach that used DataGridView bound to a data set that managed. The result of that is the infrastructure would handle all the screen updates if I handled my data and fired the right events. The data source turned out to be my core objects, which isn’t the most normal case, but it’s completely possible to bind your collection (IList<>) to the data grid view.
Even the preparation to start the process changed as well. Using a similar strategy, the default settings were established, and then files were added to the list. Unlike the previous iteration that only allowed you to load a manifest at the end, this version of the user interface would allow you to load files, change settings, add files, and save the results. Where the previous version only supported a text file, this version would support XML files as well – where settings were stored with the individual files.
One of the user interface components that was moved into its own component was a settings control. This control would be responsible for creating a settings object and allowing a user to adjust it – whether the settings were the default settings or the settings for an individual file. By creating an entry point in the control to load from a settings object and to push back to a settings object from the screen, it became easy to adjust settings in the user experience without making changes every place the settings user interface was needed.
While the user interface updates were relatively easy to do by leveraging a data grid view, the rest of the code was a mess that needed cleaned up. It reflected the fact that it was a macro that was converted instead of a set of objects designed to work together. The restructuring started by moving from a one-size fits all to a per-file approach to settings.
A method would bring in a file using the settings object that it was provided. This allowed for fine tuning of individual files and some isolation. Additional separation of concerns was achieved by having the settings object be a cluster of other objects for different aspects of the assembly. Page settings and image settings had their own object and their own method for addressing these concerns.
The file assembly method, then, was largely a process of sequencing these individual calls. It kept the loading of the files and the copying, but most of the other detailed work got kicked out into separate methods. One class of settings, assembly, stayed in the main method, because it impacted the overall assembly. Adding breaks – including section breaks instead of page breaks – remained in the core methods, as did copying to a temp directory was a handled in the main method.
Copying to Temp
One of the problems that we were facing was the new behavior where Word was getting confused regarding synchronization when in a OneDrive synchronized folder. The solution was to do a quick file copy to a temporary directory and open from there. The mechanisms for doing this are straightforward in .NET, so having compiled .NET code that plugged into Word was a powerful combination.
In the End
In the end, the new tool is easier to work with, supports all of the new features we wanted, and allows us to create materials quicker and more reliably than we could ever do by hand, either with individual documents or with a single master document.