I need to create a multi-level bullet list through Microsoft.Office.Interop.Word , and I'm currently struggling with its (terrible) API (again).
I just created the following example (not yet dynamic, for demo purposes only) in a VSTO level project for Microsoft Office Word 2010 in the C # programming language:
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);
The code does exactly what I want (after many attempts and errors!), But it is terrible in my opinion. The format must be applied at a VERY specific point, and I must manually back off and go beyond the paragraphs I created.
So my question is: Is there a better approach for creating a multi-level bullet list through Word.Interop , for example. through shorthand methods that I have not yet discovered?
My goal is to create a multi-level list from XML data (a more specific CustomXMLNode object)
In Qaru, there are two other questions related to bullet lists, but both do not help me (the source code above is one answer to the second question):
EDIT (2013-08-08):
I just hacked something together that outputs two arrays as a bullet list with two levels (an array with sub-items is used for each root element to make it simple). By introducing recursion, one could create a bullet list with infinite levels (theoretically). But the problem remains, the code is a mess ...
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; }
EDIT (2013-08-12):
Last Friday, I thought I had achieved what I wanted, but this morning I noticed that my solution only works if the entry point is at the end of the document. I created the following simple example to demonstrate (erroneous) behavior. To conclude my problem: I can create multi-level bullet lists at the end of the document only . As soon as I change the current selection (for example, before the start of the document), the list will be destroyed. As far as I can see, this is due to (automatic or non-automatic) extension of Range objects. I have tried a lot so far (I almost lose it), but for me this is the whole burden of cult. The only thing I want to do is insert one element after another (is it impossible to create a content control inside ) so that the paragraph text is accompanied by a content control?) And to which in any Range a Document . Tonight I will create a Gist on GitHub with my actual CustomXMLPart binding CustomXMLPart . In the end, someone can help me fix this obsessive problem.
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;
EDIT (2013-08-12): I installed the GitHub repository here , which demonstrates my problem with Word.Range objects. The OnClickButton method in the OnClickButton file calls my own mapping class. The comments describe the problem. I know that my problems are related to the reference to the Word.Range object, but all the other solutions that I tried (for example, changing the range inside the class) turned out to be even more complicated. The best solution I've reached so far is to define the Document.Content range as an argument to the MapToCustomControlsIn method. This inserts a well-formatted layered list of markers (with custom XML parts associated with content controls) to the end of the document. I want to insert this list into a user position in the document (for example, the current selection through Word.Selection.Range ).