0

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
lamostreta
  • 2,359
  • 7
  • 44
  • 61
  • 1
    Should this be accomplished by using MS Word only? Or may it be handled by implementing a C# application that communicates with MS Word via COM objects? You give an example of some of the "fields" in your document - to me the examples look like headings - do you mean headings? So in general, if you could elaborate a bit more on the details, that would be great :) – Lasse Christiansen Sep 12 '12 at 20:48
  • Sorry for the late reply. You're right Col1 and Col2 are headings, which are from different files and will be combined to form a table in another file. Unfortunately we need to find a solution in MS Word, only. But any plugin or sth like that will also be applicable. – lamostreta Oct 18 '12 at 15:00
  • Should the combined cols form a cartesian product in the final matrix? Like if you find heading 2.1 and 3.1 in doc. A and heading 4.1 in doc. B, should the final matrix then contain a row for 2.1 and 4.1 and a row for 3.1 and 4.1? In general, could you elaborate more on how the final matrix should look like? :) – Lasse Christiansen Oct 18 '12 at 16:23
  • no the combined cols shouldn't be a Cartesian product in the final matrix, i.e. there is only one 4.2 corresponding to 2.1. I am giving a concrete example, maybe it can be more helpful ;) – lamostreta Oct 22 '12 at 07:44
  • So, how did this end up? Did you find my answer (http://stackoverflow.com/a/13037098/700926) helpful? :) – Lasse Christiansen Nov 01 '12 at 20:17

1 Answers1

1

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 :)

Lasse Christiansen
  • 10,205
  • 7
  • 50
  • 79