4
votes

I have the following code which is supposed to add a bulleted list to a word document that I'm generating automatically. From other answers I believe the code is correct, but the result doesn't produce any bullet points at all, it doesn't seem to apply the indent either. Any Ideas?

Microsoft.Office.Interop.Word.Paragraph assets;
assets = doc.Content.Paragraphs.Add(Type.Missing);

// Some code to generate the text

foreach (String asset in assetsList)
{
    assetText = assetText + asset + "\n";
}

assets.Range.ListFormat.ApplyBulletDefault(Type.Missing);

// Add it to the document 
assets.Range.ParagraphFormat.LeftIndent = -1;
assets.Range.Text = assetText;
assets.Range.InsertParagraphAfter();
4

4 Answers

4
votes

This happens because you're adding multiple paragraphs to the range after the range (it seems that setting the Text property is equivalent to InsertAfter). You want to InsertBefore the range so that the formatting you set gets applied.

    Paragraph assets = doc.Content.Paragraphs.Add();

    assets.Range.ListFormat.ApplyBulletDefault();
    string[] bulletItems = new string[] { "One", "Two", "Three" };

    for (int i = 0; i < bulletItems.Length; i++)
    {
        string bulletItem = bulletItems[i];
        if (i < bulletItems.Length - 1)
            bulletItem = bulletItem + "\n";
        assets.Range.InsertBefore(bulletItem);
    }

Notice that we add an End of Paragraph mark to all items except the last one. You will get an empty bullet if you add one to the last.

2
votes

This is based on Tergiver's answer. The difference is it inserts the list items in the correct order after the initially created paragraph. For your own use make the starting range equal to the item you want to insert the list after.

Paragraph assets = doc.Content.Paragraphs.Add();
rng = assets.Range;
rng.InsertAfter("\n");
start = rng.End;
end = rng.End;
rng = _oDoc.Range(ref start, ref end);
object listType = 0;
rng.ListFormat.ApplyBulletDefault(ref listType);
string[] bulletItems = new string[] { "One", "Two", "Three" };
for (int i = 0; i < bulletItems.Length; i++)
{
  string bulletItem = bulletItems[i];
  if (i < RowCount - 1)
    bulletItem = bulletItem + "\n";
  rng.InsertAfter(bulletItem);
}

Please note I don't really understand what I'm doing with the range here. This solution was arrived at after considerable trial and error. I suspect it may have to do with the fact that I'm reusing the same range and Tergiver's solution is grabbing a new range each time the range is accessed. I particularly don't understand the following lines:

rng.InsertAfter("\n");
start = rng.End;
end = rng.End;
rng = _oDoc.Range(ref start, ref end);

Generally any alterations to the above code and the list gets intermingled with the previous element. If somebody could explain why this works, I'd be grateful.

0
votes

You can try below code block if you want list-sublist relations:

static void Main(string[] args)
    {
        try
        {
            Application app = new Application();
            Document doc = app.Documents.Add();
            Range range = doc.Range(0, 0);
            range.ListFormat.ApplyNumberDefault();
            range.Text = "Birinci";
            range.InsertParagraphAfter();
            ListTemplate listTemplate = range.ListFormat.ListTemplate;

            //range.InsertAfter("Birinci");
            //range.InsertParagraphAfter();

            //range.InsertAfter("İkinci");
            //range.InsertParagraphAfter();

            //range.InsertAfter("Üçüncü");
            //range.InsertParagraphAfter();

            Range subRange = doc.Range(range.StoryLength - 1);
            subRange.ListFormat.ApplyBulletDefault();
            subRange.ListFormat.ListIndent();
            subRange.Text = "Alt Birinci";
            subRange.InsertParagraphAfter();
            ListTemplate sublistTemplate = subRange.ListFormat.ListTemplate;

            Range subRange2 = doc.Range(subRange.StoryLength - 1);
            subRange2.ListFormat.ApplyListTemplate(sublistTemplate);
            subRange2.ListFormat.ListIndent();
            subRange2.Text = "Alt İkinci";
            subRange2.InsertParagraphAfter();

            Range range2 = doc.Range(range.StoryLength - 1);
            range2.ListFormat.ApplyListTemplateWithLevel(listTemplate,true);
            WdContinue isContinue =  range2.ListFormat.CanContinuePreviousList(listTemplate);
            range2.Text = "İkinci";
            range2.InsertParagraphAfter();

            Range range3 = doc.Range(range2.StoryLength - 1);
            range3.ListFormat.ApplyListTemplate(listTemplate);
            range3.Text = "Üçüncü";
            range3.InsertParagraphAfter();



            string path = Environment.CurrentDirectory;
            int totalExistDocx = Directory.GetFiles(path, "test*.docx").Count();
            path = Path.Combine(path, string.Format("test{0}.docx", totalExistDocx + 1));

            app.ActiveDocument.SaveAs2(path, WdSaveFormat.wdFormatXMLDocument);
            doc.Close();

            Process.Start(path);
        }
        catch (Exception exception)
        {

            throw;
        }

    }

Attention this point: If you don't know input length, you must not define the end of range value like this:

static void Main(string[] args)
    {
        try
        {
            Application app = new Application();
            Document doc = app.Documents.Add();
            Range range = doc.Range(0, 0);
            range.ListFormat.ApplyNumberDefault();
            range.Text = "Birinci";
            range.InsertParagraphAfter();
            ListTemplate listTemplate = range.ListFormat.ListTemplate;

            //range.InsertAfter("Birinci");
            //range.InsertParagraphAfter();

            //range.InsertAfter("İkinci");
            //range.InsertParagraphAfter();

            //range.InsertAfter("Üçüncü");
            //range.InsertParagraphAfter();

            Range subRange = doc.Range(range.StoryLength - 1, range.StoryLength - 1);
            subRange.ListFormat.ApplyBulletDefault();
            subRange.ListFormat.ListIndent();
            subRange.Text = "Alt Birinci";
            subRange.InsertParagraphAfter();
            ListTemplate sublistTemplate = subRange.ListFormat.ListTemplate;

            Range subRange2 = doc.Range(subRange.StoryLength - 1, range.StoryLength - 1);
            subRange2.ListFormat.ApplyListTemplate(sublistTemplate);
            subRange2.ListFormat.ListIndent();
            subRange2.Text = "Alt İkinci";
            subRange2.InsertParagraphAfter();

            Range range2 = doc.Range(range.StoryLength - 1, range.StoryLength - 1);
            range2.ListFormat.ApplyListTemplateWithLevel(listTemplate,true);
            WdContinue isContinue =  range2.ListFormat.CanContinuePreviousList(listTemplate);
            range2.Text = "İkinci";
            range2.InsertParagraphAfter();

            Range range3 = doc.Range(range2.StoryLength - 1, range.StoryLength - 1);
            range3.ListFormat.ApplyListTemplate(listTemplate);
            range3.Text = "Üçüncü";
            range3.InsertParagraphAfter();



            string path = Environment.CurrentDirectory;
            int totalExistDocx = Directory.GetFiles(path, "test*.docx").Count();
            path = Path.Combine(path, string.Format("test{0}.docx", totalExistDocx + 1));

            app.ActiveDocument.SaveAs2(path, WdSaveFormat.wdFormatXMLDocument);
            doc.Close();

            Process.Start(path);
        }
        catch (Exception exception)
        {

            throw;
        }

    }
0
votes

You just need to keep track of the start and end positions of the list and then apply the list format.

        Application wordApp = new Application() {
            Visible = true
        };

        Document doc = wordApp.Documents.Add();

        Range range = doc.Content;
        range.Text = "Hello world!";

        range.InsertParagraphAfter();
        range = doc.Paragraphs.Last.Range;

        // start of list
        int startOfList = range.Start;

        // each \n character adds a new paragraph...
        range.Text = "Item 1\nItem 2\nItem 3";

        // ...or insert a new paragraph...
        range.InsertParagraphAfter();
        range = doc.Paragraphs.Last.Range;
        range.Text = "Item 4\nItem 5";

        // end of list
        int endOfList = range.End;

        // insert the next paragraph before applying the format, otherwise
        // the format will be copied to the suceeding paragraphs.
        range.InsertParagraphAfter();

        // apply list format
        Range listRange = doc.Range(startOfList, endOfList);
        listRange.ListFormat.ApplyBulletDefault();

        range = doc.Paragraphs.Last.Range;
        range.Text = "Bye for now!";
        range.InsertParagraphAfter();