Apply Word Predefined Style to Text in C#

Viewed 2838

I want to apply a predefined style to my paragraph (like Heading2) so that I can update my table of content and have it auto-populated.

This is my code :

using Word = Microsoft.Office.Interop.Word;

object oMissing = System.Reflection.Missing.Value;
Word.Application oWord = new Word.Application();
Word.Document oDoc = oWord.Documents.Add(@"local path to a template", 
  ref oMissing, ref oMissing, ref oMissing);

object obrangePara = oDoc.Bookmarks[oEndOfDoc].Range;
var objpara = oDoc.Content.Paragraphs.Add(ref objrangePara);
objpara.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
objpara.Range.Text = "some text";

enter image description here

This applies the style visually, but it does not appear in the table of content when I update it. When I select the text in Word, it says that it has the normal text style even though visually it has the Heading2 style.

How can I make sure that the predefined style is applied correctly?

Here you can see the style is visually OK, but Word detects it as normal text : enter image description here enter image description here

Complete code listing :

        object oMissing = System.Reflection.Missing.Value;
        object oEndOfDoc = "\\endofdoc"; // endofdoc is a predefined bookmark
        var oTemplate = @"C:\TestLab\SantiagoReport.dotx";

        Word.Application oWord;
        Word.Document oDoc;
        oWord = new Word.Application();
        oWord.Visible = true;

        if(File.Exists(oTemplate))
        {
            oDoc = oWord.Documents.Add(oTemplate, ref oMissing, ref oMissing, ref oMissing);

            Word.Table dateTable = findTable(oDoc, "Tests Date");
            dateTable.Cell(2, 1).Range.Text = DateTime.Now.ToString();

            Word.Table snTable = findTable(oDoc, "Serial Number");
            snTable.Cell(2, 1).Range.Text = SerialNumber;

            Word.Table userTable = findTable(oDoc, "User");
            userTable.Cell(2, 1).Range.Text = User;

            Word.Table timeTable = findTable(oDoc, "Total Elapsed Time");
            timeTable.Cell(2, 1).Range.Text = String.Format("{0}h{1}m{2}s", StopWatch.Elapsed.Hours, StopWatch.Elapsed.Minutes, StopWatch.Elapsed.Seconds);

            Word.Table summaryTable = findTable(oDoc, "Summary");
            summaryTable.Cell(2, 2).Range.Text = nbLoadedTests.ToString();
            summaryTable.Cell(3, 2).Range.Text = nbSelectedTests.ToString();
            summaryTable.Cell(4, 2).Range.Text = nbPassedTests.ToString();
            summaryTable.Cell(5, 2).Range.Text = nbFailedTests.ToString();

            var testListBookmarkRange = oDoc.Bookmarks[oEndOfDoc].Range;

            foreach (TestCategory category in TestList)
            {
                //category.ShouldExecuteTest
                object objrangePara = oDoc.Bookmarks[oEndOfDoc].Range;
                //object objrangPara2 = oDoc.Bookmarks[oEndOfDoc].Range;
                //objrangePara.Select();
                Word.Range rangetest = (Word.Range)objrangePara;
                rangetest.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);

                var objpara = oDoc.Content.Paragraphs.Add(ref objrangePara);
                //objpara.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);

                //objpara.Format = new Word.ParagraphFormat();
                //objpara.Format.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
                //objpara.Range.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
                //objpara.Range.Text = String.Format("{0}: {1}{2}", category.ID, category.Name, Environment.NewLine);
                rangetest.Text = String.Format("{0}: {1}{2}", category.ID, category.Name, Environment.NewLine);
                //objpara.Range.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
                //objpara.Format.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);


                foreach (Test test in category.TestList)
                {
                    testListBookmarkRange = oDoc.Bookmarks[oEndOfDoc].Range;

                    Word.Table tbl = oDoc.Tables.Add(testListBookmarkRange, 3, 2);
                    tbl.Borders.InsideLineStyle = Word.WdLineStyle.wdLineStyleSingle;
                    tbl.Borders.OutsideLineStyle = Word.WdLineStyle.wdLineStyleSingle;
                    tbl.Cell(1, 1).Range.Text = test.ID.ToString();
                    tbl.Cell(1, 2).Range.Text = test.Name;
                    tbl.Cell(2, 1).Range.Text = "Result";
                    if (test.Result != null)
                        tbl.Cell(2, 2).Range.Text = test.Result.Pass ? "Pass" : "Fail";
                    tbl.Cell(3, 1).Range.Text = "Comment";
                    if (test.Result != null)
                        tbl.Cell(3, 2).Range.Text = test.Result.Message;
                    objrangePara = oDoc.Bookmarks[oEndOfDoc].Range;
                    objpara = oDoc.Content.Paragraphs.Add(ref objrangePara);
                    objpara.Range.Text = Environment.NewLine;
                    //test.TestItem.cbRunTest.Checked

                }
            }

            oDoc.TablesOfContents[1].Update();

            object pathtofile = @"C:\TestLab\test.docx";
            oDoc.SaveAs2(ref pathtofile);

            oDoc.Close();
            oWord.Quit();
            GC.Collect();
        }
3 Answers

The following approach works for me. In contrast to the code in the Question, the following example

  • Works exclusively with Word.Range objects
  • Collapses the Range in order to append new content
  • Uses InsertAfter("\n") to insert a new paragraph
  • Adds the text before applying the style

Note that if you plan to insert a table after text formatted with any style other than Normal you should insert a new paragraph and format it with the Normal style and then insert the table. Otherwise you may run into problems with the table formatting if you use table styles.

object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;
foreach (string s in lst)
{
    Word.Range rngEndOfDoc = oDoc.Bookmarks[oEndOfDoc].Range;
    rngEndOfDoc.InsertAfter("\n");
    rngEndOfDoc.Collapse(ref oCollapseEnd);
    rngEndOfDoc.Text = s;
    rngEndOfDoc.set_Style(Word.WdBuiltinStyle.wdStyleHeading2);
}

First install below package via NuGet package manager:

Install-Package Microsoft.Office.Interop.Word

Now you can apply custom style to any selection range.

In below sample code the Heading 1 style will apply to first paragraph in "Test.docx": document.

// Define new application and open MS Word document.
Application app = new Application();
Document doc = app.Documents.Open(@"D:\Test.docx");

// Select first paragraph.
doc.Paragraphs[1].Range.Select();

// Define style as object and assign your custom style as string to it.
object style = "Heading 1";

// Set custom style to selected range
app.Selection.set_Style(ref style);

// Close document and pass true if you want save changes and finally quit from application.
doc.Close(true);
app.Quit();

In this approach any changes like applying style to any selection range will have affect as visually applying them.

Not sure if there was a solution to this problem, but I had a similar problem with linking styles to paragraphs. I also had a problem with writing lines separated by "\n" in the text. The code below works for me and applies the style correctly to the passed text, including line breaks, and the style is linked to the text in the resulting document.

using Word = Microsoft.Office.Interop.Word;

public void WritePara(String pText, String pStyle) {
            Word.Paragraph p1 = oDoc.Content.Paragraphs.Add();

            object oStart = oDoc.Content.End - 1;
            p1.Range.Text = pText;
            object oEnd = oDoc.Content.End - 1;
                        
            Word.Range para = oDoc.Range(oStart, oEnd);
            object oStyleName = pStyle;
            para.set_Style(ref oStyleName);
        }
Related