Создание многоуровневого списка с помощью Word.Interop
Мне нужно создать многоуровневый список с помощьюMicrosoft.Office.Interop.Word
и я в настоящее время борюсь с его (ужасным) API (снова).
Я только что создал следующий пример (пока не динамический, только для демонстрационных целей) в проекте уровня документа VSTO для Microsoft Office Word 2010 на языке программирования C #:
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
объект)
Два других вопроса, связанных со списками маркеров, существуют в Переполнении стека, но оба они не помогают мне (приведенный выше исходный код является одним из ответов на второй вопрос):
Точки в Word с помощью C # Interophttps://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):
В прошлую пятницу я думал, что достиг того, чего хотел, но сегодня утром я заметил, что мое решение работает, только если точка вставки находится в конце документа. Я создал следующий простой пример, чтобы продемонстрировать (ошибочное) поведение. В заключение моя проблема: я могу создавать многоуровневые списки маркеров в конце документатолько, Как только я изменяю текущий выбор (например, на начало документа), список уничтожается. Насколько я вижу, это связано с (автоматическим или неавтоматическим) расширениемRange
объекты. Я до сих пор много пробовал (я почти теряю это), но для меня все это культовый груз. Единственное, что я хочу сделать, это вставить один элемент за другим (невозможно создать элемент управления контентомвнутри абзац, чтобы за текстом абзаца следовал контроль контента?)а также к тому, что в любомRange
изDocument
, Я создам Gist на GitHub с моим фактическимCustomXMLPart
обязательный урок этим вечером. В конце концов кто-то может помочь мне решить эту неприятную проблему.
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 репозиторийВот который демонстрирует мою проблему сWord.Range
объекты.OnClickButton
метод в файлеRibbon.cs
вызывает мой пользовательский класс картографа. Комментарии там описывают проблему. язнать что мои проблемы связаны с аргументомWord.Range
ссылка на объект, но все другие решения, которые я пробовал (например, изменение диапазона внутри класса), потерпели неудачу еще сложнее. Лучшее решение, которого я достиг на данный момент, это указатьDocument.Content
диапазон в качестве аргумента дляMapToCustomControlsIn
метод. Это вставит красиво отформатированный многоуровневый список маркеров (с пользовательскими частями XML, привязанными к элементам управления контентом) вконец документа. Я хочу вставить этот списокпо индивидуальному заказу в документ (например, текущий выбор черезWord.Selection.Range
).