Используя OpenXML SDK, 2.0 CTP, я пытаюсь программно создать документ Word. В моем документе мне нужно вставить маркированный список, некоторые элементы списка должны быть подчеркнуты. Как я могу это сделать?OpenXML 2 SDK - документ Word - программировать программный код
ответ
Списки в OpenXML немного запутываются.
Существует NumberingDefinitionsPart, который описывает все списки в документе. Он содержит информацию о том, как должны отображаться списки (маркированные, пронумерованные и т. Д.), А также присваивать и идентификатор каждому из них.
Затем в MainDocumentPart для каждого элемента в списке, который вы хотите создать, вы добавляете новый абзац и присваиваете идентификатор списка, который вы хотите, к этому абзацу.
Таким образом, чтобы создать маркированный список, таких как:
- Здравствуйте,
- мира!
Вы должны сначала создать NumberingDefinitionsPart:
NumberingDefinitionsPart numberingPart =
mainDocumentPart.AddNewPart<NumberingDefinitionsPart>("someUniqueIdHere");
Numbering element =
new Numbering(
new AbstractNum(
new Level(
new NumberingFormat() {Val = NumberFormatValues.Bullet},
new LevelText() {Val = "·"}
) {LevelIndex = 0}
){AbstractNumberId = 1},
new NumberingInstance(
new AbstractNumId(){Val = 1}
){NumberID = 1});
element.Save(numberingPart);
Затем создать MainDocumentPart, как обычно, за исключением свойств абзаца, назначить нумерацию ID:
MainDocumentPart mainDocumentPart =
package.AddMainDocumentPart();
Document element =
new Document(
new Body(
new Paragraph(
new ParagraphProperties(
new NumberingProperties(
new NumberingLevelReference(){ Val = 0 },
new NumberingId(){ Val = 1 })),
new Run(
new RunProperties(),
new Text("Hello, "){ Space = "preserve" })),
new Paragraph(
new ParagraphProperties(
new NumberingProperties(
new NumberingLevelReference(){ Val = 0 },
new NumberingId(){ Val = 1 })),
new Run(
new RunProperties(),
new Text("world!"){ Space = "preserve" }))));
element.Save(mainDocumentPart);
Существует более подробное объяснение вариантов, доступных в разделе OpenXML reference guide в разделе 2.9.
ответ Адам выше правильно, кроме него новый NumberingInstance (вместо нового Num (как отмечено в комментарии.
Кроме того, если у вас есть несколько списков, вы должны иметь несколько элементов нумерации (каждый со своим собственным идентификатором например, 1, 2, 3 и т. д. - по одному для каждого списка в документе. Это, похоже, не проблема с списками пулей, но пронумерованные списки будут продолжать использовать одну и ту же последовательность нумерации (в отличие от повторного запуска в 1) . потому что он будет думать, что это тот же самый список NumberingId должен ссылаться в своем пункте, как это:
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "ListParagraph" };
NumberingProperties numberingProperties1 = new NumberingProperties();
NumberingLevelReference numberingLevelReference1 = new NumberingLevelReference() { Val = 0 };
NumberingId numberingId1 = new NumberingId(){ Val = 1 }; //Val is 1, 2, 3 etc based on your numberingid in your numbering element
numberingProperties1.Append(numberingLevelReference1);
numberingProperties1.Append(numberingId1);
paragraphProperties1.Append(paragraphStyleId1);
paragraphProperties1.Append(numberingProperties1);
Детский элемент уровня будет влиять на тип пули и отступ. Моих пуль были слишком малы, пока я не добавил это к элементу уровня:
new NumberingSymbolRunProperties(
new RunFonts() { Hint = FontTypeHintValues.Default, Ascii = "Symbol", HighAnsi = "Symbol" })
вдавливание было проблемой, пока я не добавил этот элемент в элемент уровня, а также:
new PreviousParagraphProperties(
new Indentation() { Left = "864", Hanging = "360" })
И если вы похожи я - создание документа из шаблона, то вы можете использовать этот код, чтобы обрабатывать обе ситуации - когда ваш шаблон, или не содержит каких-либо определений нумерации:
// Introduce bulleted numbering in case it will be needed at some point
NumberingDefinitionsPart numberingPart = document.MainDocumentPart.NumberingDefinitionsPart;
if (numberingPart == null)
{
numberingPart = document.MainDocumentPart.AddNewPart<NumberingDefinitionsPart>("NumberingDefinitionsPart001");
}
Я хотел кое-что, что позволило бы мне добавить в документ более одного списка маркеров. Некоторое время ударяя головой о стол, мне удалось собрать кучу разных сообщений и изучить мой документ с помощью Open XML SDK 2.0 Productity Tool и вычислил некоторые вещи. Документ, который он производит, теперь проходит проверку по версии 2.0 и 2.5 инструментария производительности SDK.
Вот код; надеюсь, это сэкономит кому-то время и обострение.
Использование:
const string fileToCreate = "C:\\temp\\bulletTest.docx";
if (File.Exists(fileToCreate))
File.Delete(fileToCreate);
var writer = new SimpleDocumentWriter();
List<string> fruitList = new List<string>() { "Apple", "Banana", "Carrot"};
writer.AddBulletList(fruitList);
writer.AddParagraph("This is a spacing paragraph 1.");
List<string> animalList = new List<string>() { "Dog", "Cat", "Bear" };
writer.AddBulletList(animalList);
writer.AddParagraph("This is a spacing paragraph 2.");
List<string> stuffList = new List<string>() { "Ball", "Wallet", "Phone" };
writer.AddBulletList(stuffList);
writer.AddParagraph("Done.");
writer.SaveToFile(fileToCreate);
Использование заявления:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
Код
public class SimpleDocumentWriter : IDisposable
{
private MemoryStream _ms;
private WordprocessingDocument _wordprocessingDocument;
public SimpleDocumentWriter()
{
_ms = new MemoryStream();
_wordprocessingDocument = WordprocessingDocument.Create(_ms, WordprocessingDocumentType.Document);
var mainDocumentPart = _wordprocessingDocument.AddMainDocumentPart();
Body body = new Body();
mainDocumentPart.Document = new Document(body);
}
public void AddParagraph(string sentence)
{
List<Run> runList = ListOfStringToRunList(new List<string> { sentence});
AddParagraph(runList);
}
public void AddParagraph(List<string> sentences)
{
List<Run> runList = ListOfStringToRunList(sentences);
AddParagraph(runList);
}
public void AddParagraph(List<Run> runList)
{
var para = new Paragraph();
foreach (Run runItem in runList)
{
para.AppendChild(runItem);
}
Body body = _wordprocessingDocument.MainDocumentPart.Document.Body;
body.AppendChild(para);
}
public void AddBulletList(List<string> sentences)
{
var runList = ListOfStringToRunList(sentences);
AddBulletList(runList);
}
public void AddBulletList(List<Run> runList)
{
// Introduce bulleted numbering in case it will be needed at some point
NumberingDefinitionsPart numberingPart = _wordprocessingDocument.MainDocumentPart.NumberingDefinitionsPart;
if (numberingPart == null)
{
numberingPart = _wordprocessingDocument.MainDocumentPart.AddNewPart<NumberingDefinitionsPart>("NumberingDefinitionsPart001");
Numbering element = new Numbering();
element.Save(numberingPart);
}
// Insert an AbstractNum into the numbering part numbering list. The order seems to matter or it will not pass the
// Open XML SDK Productity Tools validation test. AbstractNum comes first and then NumberingInstance and we want to
// insert this AFTER the last AbstractNum and BEFORE the first NumberingInstance or we will get a validation error.
var abstractNumberId = numberingPart.Numbering.Elements<AbstractNum>().Count() + 1;
var abstractLevel = new Level(new NumberingFormat() {Val = NumberFormatValues.Bullet}, new LevelText() {Val = "·"}) {LevelIndex = 0};
var abstractNum1 = new AbstractNum(abstractLevel) {AbstractNumberId = abstractNumberId};
if (abstractNumberId == 1)
{
numberingPart.Numbering.Append(abstractNum1);
}
else
{
AbstractNum lastAbstractNum = numberingPart.Numbering.Elements<AbstractNum>().Last();
numberingPart.Numbering.InsertAfter(abstractNum1, lastAbstractNum);
}
// Insert an NumberingInstance into the numbering part numbering list. The order seems to matter or it will not pass the
// Open XML SDK Productity Tools validation test. AbstractNum comes first and then NumberingInstance and we want to
// insert this AFTER the last NumberingInstance and AFTER all the AbstractNum entries or we will get a validation error.
var numberId = numberingPart.Numbering.Elements<NumberingInstance>().Count() + 1;
NumberingInstance numberingInstance1 = new NumberingInstance() {NumberID = numberId};
AbstractNumId abstractNumId1 = new AbstractNumId() {Val = abstractNumberId};
numberingInstance1.Append(abstractNumId1);
if (numberId == 1)
{
numberingPart.Numbering.Append(numberingInstance1);
}
else
{
var lastNumberingInstance = numberingPart.Numbering.Elements<NumberingInstance>().Last();
numberingPart.Numbering.InsertAfter(numberingInstance1, lastNumberingInstance);
}
Body body = _wordprocessingDocument.MainDocumentPart.Document.Body;
foreach (Run runItem in runList)
{
// Create items for paragraph properties
var numberingProperties = new NumberingProperties(new NumberingLevelReference() {Val = 0}, new NumberingId() {Val = numberId});
var spacingBetweenLines1 = new SpacingBetweenLines() { After = "0" }; // Get rid of space between bullets
var indentation = new Indentation() { Left = "720", Hanging = "360" }; // correct indentation
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
RunFonts runFonts1 = new RunFonts() { Ascii = "Symbol", HighAnsi = "Symbol" };
paragraphMarkRunProperties1.Append(runFonts1);
// create paragraph properties
var paragraphProperties = new ParagraphProperties(numberingProperties, spacingBetweenLines1, indentation, paragraphMarkRunProperties1);
// Create paragraph
var newPara = new Paragraph(paragraphProperties);
// Add run to the paragraph
newPara.AppendChild(runItem);
// Add one bullet item to the body
body.AppendChild(newPara);
}
}
public void Dispose()
{
CloseAndDisposeOfDocument();
if (_ms != null)
{
_ms.Dispose();
_ms = null;
}
}
public MemoryStream SaveToStream()
{
_ms.Position = 0;
return _ms;
}
public void SaveToFile(string fileName)
{
if (_wordprocessingDocument != null)
{
CloseAndDisposeOfDocument();
}
if (_ms == null)
throw new ArgumentException("This object has already been disposed of so you cannot save it!");
using (var fs = File.Create(fileName))
{
_ms.WriteTo(fs);
}
}
private void CloseAndDisposeOfDocument()
{
if (_wordprocessingDocument != null)
{
_wordprocessingDocument.Close();
_wordprocessingDocument.Dispose();
_wordprocessingDocument = null;
}
}
private static List<Run> ListOfStringToRunList(List<string> sentences)
{
var runList = new List<Run>();
foreach (string item in sentences)
{
var newRun = new Run();
newRun.AppendChild(new Text(item));
runList.Add(newRun);
}
return runList;
}
}
- 1. Программировать документ Word 2010
- 2. .NET OpenXML SDK 2 RunProperties - Null
- 3. Невозможно встроить документ openXML внутри другого с помощью OpenXML SDK
- 4. текстовый центр, обоснованный в openxml Документ Word
- 5. Открытый защищенный документ Word с OpenXML
- 6. Написать документ Word 2007 в OpenXML
- 7. Как разбить документ в OpenXML SDK
- 8. OpenXml, Word и C#
- 9. Вставить HTML-документ в OpenXML Word Document (.Net)
- 10. Word 2013 to OpenXML Converter
- 11. Программно сохранить документ OpenXml в качестве предыдущей версии (Word 2007)
- 12. Упрощенная замена токенов в документе Word с использованием OpenXML SDK
- 13. Внедрение документа OpenXML в другой документ OpenXml
- 14. Альтернативы MS OpenXML SDK
- 15. Автоматическое тестирование OpenXML SDK
- 16. OpenXml SDK - Повторное использование изображений
- 17. XtraReport DocumentViewer программный программный документ
- 18. Управлять статусом ссылок в документе Word с OpenXML SDK
- 19. Дублирующий документ Word с использованием OpenXML при открытии оригинального документа
- 20. Создать новый пустой документ Word
- 21. C# OpenXML (Word) Таблица Автоподбор в окно
- 22. Добавление нескольких изображений в документ Word в определенных местах OpenXML
- 23. Поток в документе Word Word с использованием OpenXML SDK с ASP.NET приводит к «коррумпированному» документу
- 24. OpenXml Word Сноски
- 25. Горизонтальное выравнивание текста в Word с помощью OpenXml Sdk 2.0
- 26. Mocking OpenXML SDK ТабличныйДокумент
- 27. Word Создание документа с использованием OpenXML
- 28. OpenXML SDK Как разместить изображение в MS Word?
- 29. Как вернуть MVC ActionResult документа OPENXML Word?
- 30. Поиск и комментарий с OpenXML для Word
Спасибо большое за показывая мне, как добавить список в документ. Я использовал Numbering.Append (abstactNum, numberingInstance) и не мог понять, почему он не работает – Dan
Из будущего: Спасибо вам за это! Вроде, действительно! :) –
@MariusConjeaud Добро пожаловать. Я создал что-то для написания простых текстовых документов, которые вы можете использовать (см. Https://github.com/madcodemonkey/SimpleDocument.OpenXML) –