我需要通过创建多级项目符号列表Microsoft.Office.Interop.Word
我目前正在(再次)与它的(可怕的)API 作斗争。
我刚刚使用编程语言 C# 在 Microsoft Office Word 2010 的 VSTO 文档级项目中创建了以下示例(还不是动态的,仅用于演示目的):
Word.Paragraph paragraph = null;
Word.Range range = this.Content;
paragraph = range.Paragraphs.Add();
paragraph.Range.Text = "Item 1";
paragraph.Range.ListFormat.ApplyBulletDefault(Word.WdDefaultListBehavior.wdWord10ListBehavior);
// ATTENTION: We have to outdent the paragraph AFTER its list format has been set, otherwise this has no effect.
// Without this, the the indent of "Item 2" differs from the indent of "Item 1".
paragraph.Outdent();
paragraph.Range.InsertParagraphAfter();
paragraph = range.Paragraphs.Add();
paragraph.Range.Text = "Item 1.1";
// ATTENTION: We have to indent the paragraph AFTER its text has been set, otherwise this has no effect.
paragraph.Indent();
paragraph.Range.InsertParagraphAfter();
paragraph = range.Paragraphs.Add();
paragraph.Range.Text = "Item 1.2";
paragraph.Range.InsertParagraphAfter();
paragraph = range.Paragraphs.Add();
paragraph.Range.Text = "Item 2";
paragraph.Outdent();
该代码完全符合我的要求(经过多次尝试和错误!),但在我看来它很糟糕。该格式必须在非常具体的点应用,我必须手动缩进和减少缩进创建的段落。
所以我的问题是:是否存在更好的方法来创建多级项目符号列表Word.Interop
,例如通过我还没有发现的速记方法?
我的目标是从 XML 数据创建一个多级列表(更具体地说是CustomXMLNode
object)
Stack Overflow 上还存在另外两个与项目符号列表相关的问题,但这两个问题都对我没有帮助(上面的源代码是第二个问题的答案):
- Word 中的项目符号与 C# Interop https://stackoverflow.com/questions/11508286/bullet-points-in-word-with-c-sharp-interop
- https://stackoverflow.com/questions/3768414/ms-word-list-with-sub-lists https://stackoverflow.com/questions/3768414/ms-word-list-with-sub-lists
编辑(2013-08-08):
我刚刚将一些东西组合在一起,输出两个数组作为具有两个级别的项目符号列表(带有子项的数组用于每个根项,以保持简单)。通过引入递归,人们将能够创建一个具有无限级别的项目符号列表(理论上)。但问题依然存在,代码一团糟......
string[] rootItems = new string[]
{
"Root Item A", "Root Item B", "Root Item C"
};
string[] subItems = new string[]
{
"Subitem A", "Subitem B"
};
Word.Paragraph paragraph = null;
Word.Range range = this.Content;
bool appliedListFormat = false;
bool indented = false;
for (int i = 0; i < rootItems.Length; ++i)
{
paragraph = range.Paragraphs.Add();
paragraph.Range.Text = rootItems[i];
if (!appliedListFormat)
{
paragraph.Range.ListFormat.ApplyBulletDefault(Word.WdDefaultListBehavior.wdWord10ListBehavior);
appliedListFormat = true;
}
paragraph.Outdent();
paragraph.Range.InsertParagraphAfter();
for (int j = 0; j < subItems.Length; ++j)
{
paragraph = range.Paragraphs.Add();
paragraph.Range.Text = subItems[j];
if (!indented)
{
paragraph.Indent();
indented = true;
}
paragraph.Range.InsertParagraphAfter();
}
indented = false;
}
// Delete the last paragraph, since otherwise the list ends with an empty sub-item.
paragraph.Range.Delete();
编辑(2013-08-12):
上周五,我以为我已经实现了我想要的目标,但今天早上我注意到,我的解决方案仅在插入点位于文档末尾时才有效。我创建了以下简单示例来演示(错误)行为。总结我的问题:我可以在文档末尾创建多级项目符号列表only。一旦我更改当前选择(例如更改为文档的开头),列表就会被销毁。据我所知,这与(自动或非自动)扩展有关Range
对象。到目前为止我已经尝试了很多(我几乎要失去它了),但这对我来说都是货物崇拜。我唯一想做的就是一个接一个地插入元素(是否无法创建内容控件inside一个段落,以便该段落的文本后面跟着内容控件?)and到任何Range
of a Document
。我将用我的实际情况在 GitHub 上创建一个 GistCustomXMLPart
今晚绑定课程。最终有人可以帮助我解决这个麻烦的问题。
private void buttonTestStatic_Click(object sender, RibbonControlEventArgs e)
{
Word.Range range = Globals.ThisDocument.Application.Selection.Range;
Word.ListGallery listGallery = Globals.ThisDocument.Application.ListGalleries[Word.WdListGalleryType.wdBulletGallery];
Word.Paragraph paragraph = null;
Word.ListFormat listFormat = null;
// TODO At the end of the document, the ranges are automatically expanded and inbetween not?
paragraph = range.Paragraphs.Add();
listFormat = paragraph.Range.ListFormat;
paragraph.Range.Text = "Root Item A";
this.ApplyListTemplate(listGallery, listFormat, 1);
paragraph.Range.InsertParagraphAfter();
paragraph = paragraph.Range.Paragraphs.Add();
listFormat = paragraph.Range.ListFormat;
paragraph.Range.Text = "Child Item A.1";
this.ApplyListTemplate(listGallery, listFormat, 2);
paragraph.Range.InsertParagraphAfter();
paragraph = paragraph.Range.Paragraphs.Add();
listFormat = paragraph.Range.ListFormat;
paragraph.Range.Text = "Child Item A.2";
this.ApplyListTemplate(listGallery, listFormat, 2);
paragraph.Range.InsertParagraphAfter();
paragraph = paragraph.Range.Paragraphs.Add();
listFormat = paragraph.Range.ListFormat;
paragraph.Range.Text = "Root Item B";
this.ApplyListTemplate(listGallery, listFormat, 1);
paragraph.Range.InsertParagraphAfter();
}
private void ApplyListTemplate(Word.ListGallery listGallery, Word.ListFormat listFormat, int level = 1)
{
listFormat.ApplyListTemplateWithLevel(
listGallery.ListTemplates[level],
ContinuePreviousList: true,
ApplyTo: Word.WdListApplyTo.wdListApplyToSelection,
DefaultListBehavior: Word.WdDefaultListBehavior.wdWord10ListBehavior,
ApplyLevel: level);
}
编辑(2013-08-12):我已经设置了 GitHub 存储库here https://github.com/FlorianWolters/CSharp-WordInterop-Temp这说明了我的问题Word.Range
对象。这OnClickButton
文件中的方法Ribbon.cs
调用我的自定义映射器类。那里的评论描述了这个问题。我know我的问题与论证有关Word.Range
对象引用,但我尝试的所有其他解决方案(例如修改类内部的范围)都更加失败。到目前为止我所实现的最佳解决方案是指定Document.Content
范围作为参数MapToCustomControlsIn
方法。这会将格式良好的多级项目符号列表(具有绑定到内容控件的自定义 XML 部分)插入到end该文件的。我想要的是插入该列表在自定义位置进入文档(例如当前选择通过Word.Selection.Range
).