lamostreta
lamostreta

Reputation: 2409

Referencing other documents' content

We need to create a matrix from 2 other documents' contents. For example:

  1. doc has fields like:

    4.2 Requirements A Blah

  2. doc has fields like:

    2.1 Analysis A Blah Blah

and we want to create another document (called Traceability Matrix) which is like:

Col1    Col2    Col3
4.2     2.1     Blah Blah Blah

4.2 and 2.1 should be dynamically updated in doc3.

We checked using hyperlink, cross referencing but nothing seems to be useful for combining different documents. Is there anyway to do this?

EDIT: Here is an example:

Technical Specification Num         Requirement Num     Requirement
4.2                                 2.1                 A sentence that explains the relationship btw 2 cols: Technical Specification and Requirement Num

Upvotes: 0

Views: 178

Answers (1)

Lasse Christiansen
Lasse Christiansen

Reputation: 10325

I have now created a working example of how this can be implemented using MS Word Interop and C#.

The code contains comments that should explain the most interesting parts.

The sample is implemented as a C# console application using:

  • .NET 4.5
  • Microsoft Office Object Library version 15.0, and
  • Microsoft Word Object Library version 15.0

... that is, the MS Word Interop API that ships with MS Office 2013 Preview.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Office.Interop.Word;
using Application = Microsoft.Office.Interop.Word.Application;

namespace WordDocStats
{
    internal class Program
    {
        private static void Main()
        {
            // Open word
            var wordApplication = new Application() { Visible = true };

            // Open document A, get its headings, and close it again
            var documentA = wordApplication.Documents.Open(@"C:\Users\MyUserName\Documents\documentA.docx", Visible: true);
            var headingsA = GetHeadingsInDocument(documentA);
            documentA.Close();

            // Same procedure for document B
            var documentB = wordApplication.Documents.Open(@"C:\Users\MyUserName\Documents\documentB.docx", Visible: true);
            var headingsB = GetHeadingsInDocument(documentB);
            documentB.Close();

            // Open the target document (document C)
            var documentC = wordApplication.Documents.Open(@"C:\Users\MyUserName\Documents\documentC.docx", Visible: true);

            // Add a table to it (the traceability matrix)
            // The number of rows is the number of headings + one row reserved for a table header
            documentC.Tables.Add(documentC.Range(0, 0), headingsA.Count+1, 3);

            // Get the traceability matrix
            var traceabilityMatrix = documentC.Tables[1];

            // Add a table header and border
            AddTableHeaderAndBorder(traceabilityMatrix, "Headings from document A", "Headings from document B", "My Description");

            // Insert headings from doc A and doc B into doc C's traceability matrix
            for (var i = 0; i < headingsA.Count; i++)
            {
                // Insert headings from doc A
                var insertRangeColOne = traceabilityMatrix.Cell(i + 2, 1).Range;
                insertRangeColOne.Text = headingsA[i].Trim();

                // Insert headings from doc B
                var insertRangeColTwo = traceabilityMatrix.Cell(i + 2, 2).Range;
                insertRangeColTwo.Text = headingsB[i].Trim();
            }

            documentC.Save();
            documentC.Close();

            wordApplication.Quit();
        }

        // Based on:
        // -> http://csharpfeeds.com/post/5048/Csharp_and_Word_Interop_Part_4_-_Tables.aspx
        // -> http://stackoverflow.com/a/1817041/700926
        private static void AddTableHeaderAndBorder(Table table, params string[] columnTitles)
        {
            const int headerRowIndex = 1;

            for (var i = 0; i < columnTitles.Length; i++)
            {
                var tableHeaderRange = table.Cell(headerRowIndex, i+1).Range;
                tableHeaderRange.Text = columnTitles[i];
                tableHeaderRange.Font.Bold = 1;
                tableHeaderRange.Font.Italic = 1;
            }

            // Repeat header on each page
            table.Rows[headerRowIndex].HeadingFormat = -1;

            // Enable borders
            table.Borders.Enable = 1;
        }

        // Based on:
        // -> http://stackoverflow.com/q/7084270/700926
        // -> http://stackoverflow.com/a/7084442/700926
        private static List<string> GetHeadingsInDocument(Document document)
        {
            object headingsAtmp = document.GetCrossReferenceItems(WdReferenceType.wdRefTypeHeading);
            return ((Array)(headingsAtmp)).Cast<string>().ToList();
        }
    }
}

Basically, the code first loads all headings from the two given documents and stores them in memory. Then it opens the target document, creates and styles the traceability matrix, and finally, it inserts the headings into the matrix.

The code is based on the assumptions that:

  • A target document (documentC.docx) exists.
  • The number of headings in the two input documents (documentA.docx, and documentB.docx) contains the same amount of headings - this assumption is made based on your comment about not wanting a Cartesian product.

I hope this meets your requirements :)

Upvotes: 1

Related Questions