使用C#互操作在Word中添加项目符号

5
我有以下代码,它应该向我正在自动生成的 Word 文档中添加一个项目符号列表。从其他答案中我相信代码是正确的,但结果并没有产生任何项目符号,似乎也没有适用缩进。你有什么想法吗?
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
这是因为您将多个段落添加到范围后面(似乎设置Text属性等同于InsertAfter)。您需要在范围之前插入,以便应用所设置的格式。
    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);
    }

请注意,我们在除最后一项之外的所有项目末尾添加了一个段落结束标记。如果在最后一项上添加此标记,您将获得一个空的项目符号。

使用 assets.Range.InsertBefore(bulletItem); 将列表中的元素以相反的顺序插入。你是不是想用 InsertAfter? - Giles Roberts
1
@GilesRoberts InsertAfter不起作用,因为格式(默认符号)没有应用。所以这段代码使用InsertBefore并按相反的顺序添加项目。 - Tergiver
这可能解释了为什么我在让项目符号应用于文档的正确部分时遇到了如此多的困难。最终,我不得不非常小心地设置我的范围,然后再使用插入功能。不过最终还是成功了。 - Giles Roberts
1
@GilesRoberts 我没想出如何设置范围并让InsertAfter工作,这是我首先尝试的。如果你有其他答案,可以添加进来。 - Tergiver
我根据你的答案添加了我的答案,但按正确顺序插入了列表。 - Giles Roberts

2

这是基于Tergiver的答案而来。区别在于它会在最初创建的段落后按正确顺序插入列表项。如果您自己使用,请将起始范围设置为要在其后插入列表的项目。

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);
}

请注意,我其实不太理解我在这里对范围所做的操作。这个解决方案是经过长时间的试错得出的。我怀疑这可能与我重复使用同一范围有关,而Tergiver的解决方案每次访问范围时都会获取一个新的范围。我特别不理解以下几行代码:
rng.InsertAfter("\n");
start = rng.End;
end = rng.End;
rng = _oDoc.Range(ref start, ref end);

通常情况下,对上述代码进行任何修改都会使列表与前一个元素混合在一起。如果有人能解释为什么这样做有效,我将不胜感激。


1

你只需要跟踪列表的起始和结束位置,然后应用列表格式即可。

        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();

不需要存储范围的起始和结束。在注释“// start of list”之前存储的那个“range”就足够了。然后在“// apply list format”下,你只需在那个空范围上调用“ApplyBulletDefault”。这样做是因为它是一个段落样式。 - undefined

0

如果你想要实现列表-子列表关系,你可以尝试下面的代码块:

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;
        }

    }

注意这一点:如果您不知道输入长度,就不要像这样定义范围的结束值:

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;
        }

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接