Al utilizar el SDK de OpenXML, 2.0 CTP, intento crear un documento de Word mediante programación. En mi documento tengo que insertar una lista con viñetas, algunos de los elementos de la lista deben estar subrayados. ¿Cómo puedo hacer esto?SDK OpenXML 2 - Documento de Word - Crear lista con viñetas programáticamente
Respuesta
Las listas en OpenXML son un poco confusas.
Hay una NumberingDefinitionsPart que describe todas las listas del documento. Contiene información sobre cómo deberían aparecer las listas (con viñetas, numeradas, etc.) y también asigna e identifica a cada una.
Luego en MainDocumentPart, para cada elemento de la lista que desea crear, agrega un nuevo párrafo y asigne el ID de la lista que desea a ese párrafo.
Así que para crear una lista de viñetas, tales como:
- Hola,
- mundo!
primero tendría que crear un 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);
A continuación, se crea el MainDocumentPart como lo haría normalmente, excepto en las propiedades de párrafo, asignar la identificación de numeración:
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);
Hay una mejor explicación de las opciones disponibles en el OpenXML reference guide en la Sección 2.9.
respuesta de Adán anterior es correcto, excepto que es nuevo NumberingInstance (en lugar de nuevo Num (como se señala en un comentario.
Además, si tiene varias listas, debe tener varios elementos de Codificación (cada uno con su propia ID por ejemplo, 1, 2, 3, etc., uno para cada lista en el documento. Esto no parece ser un problema con las listas de viñetas, pero las listas numeradas continuarán usando la misma secuencia de numeración (en lugar de comenzar de nuevo en 1) . porque va a pensar que es la misma lista el NumberingId tiene que ser referenciado en el párrafo de la siguiente manera:
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);
Elemento Niños del nivel tendrá un efecto en el tipo de viñeta y la sangría. Mis balas eran demasiado pequeños hasta que he añadido esto al elemento Nivel:
new NumberingSymbolRunProperties(
new RunFonts() { Hint = FontTypeHintValues.Default, Ascii = "Symbol", HighAnsi = "Symbol" })
sangría era un problema hasta que he añadido este elemento al elemento Nivel así:
new PreviousParagraphProperties(
new Indentation() { Left = "864", Hanging = "360" })
Y si usted es como yo - creando un documento a partir de una plantilla, entonces puede usar este código para manejar ambas situaciones - cuando su plantilla contiene o no definiciones de numeración:
// 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");
}
Quería algo que me permitiera agregar más de una lista de viñetas a un documento. Después de golpear mi cabeza contra mi escritorio por un tiempo, logré combinar un montón de publicaciones diferentes y examinar mi documento con Open XML SDK 2.0 Productity Tool y descubrió algunas cosas. El documento que produce ahora pasa la validación por la versión 2.0 y 2.5 de la herramienta de productividad SDK.
Aquí está el código; con suerte, le ahorra a alguien algo de tiempo y agravación.
de uso:
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);
Uso de declaraciones:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
Código
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. Creando documento Excel con OpenXML sdk 2.0
- 2. documento Duplicación Word utilizando OpenXml y C#
- 3. Insertar HTML en documento de Word OpenXML (.Net)
- 4. Transmitir en la memoria Documento de Word con OpenXML SDK w/ASP.NET da como resultado un documento "corrupto"
- 5. ¿Cómo desbloqueo un control de contenido utilizando OpenXML SDK en un documento de Word 2010?
- 6. Inmovilizar paneles en OpenXml SDK 2.0 para documento de Excel
- 7. Prueba automatizada SDK de OpenXML
- 8. Cómo agregar control de contenido en un documento de Word 2007 con OpenXML
- 9. Crear documento de Word 2010 mediante programación
- 10. Word/OpenXML - ¿Cómo creo un marcador oculto?
- 11. Uso de TDD con OpenXML-SDK
- 12. ¿Cómo crear una lista con viñetas en ReportLab
- 13. Obtener un CheckBox en Word usando OpenXML
- 14. Agregar encabezado y pie de página a un documento de palabra vacía existente con OpenXML SDK 2.0
- 15. ¿Cómo se cambia el contenido de un control de contenido en Word 2007 con OpenXML SDK 2.0?
- 16. Kits de inicio de hoja de cálculo OpenXML SDK
- 17. Documento dañado después de llamar AddAlternativeFormatImportPart utilizando OpenXml
- 18. Guardar un documento OpenXML (Word) generado a partir de una plantilla
- 19. Crear salto de página usando OpenXml
- 20. Plantillas de WordML con esquema XML y SDK de OpenXML
- 21. ¿Cómo puedo crear un documento de Word utilizando Python?
- 22. Insertar nuevas filas y mover existentes con OpenXML SDK 2.0
- 23. Justificación en el texto de tableCell con OpenXML SDK 2.0
- 24. Reemplazar las balas con guiones en un documento de Word
- 25. comparando programáticamente documentos de Word
- 26. Sangría lista de viñetas en TextView
- 27. UIWebView, documento de Word Office y paginación
- 28. Documento de Word en Sharepoint - VSTO
- 29. ¿Cómo se tiene una lista con viñetas en migradoc/pdfsharp
- 30. WPF Lista de viñetas con enlaces de datos
Muchas gracias por mostrarme cómo agregar una lista a un documento. Estaba usando Numbering.Append (abstactNum, numberingInstance) y no podía entender por qué no funciona – Dan
Desde el futuro: ¡Gracias, compañero por ese! Como realmente ! :) –
@MariusConjeaud De nada. Creé algo para escribir documentos de texto simple que puede usar (vea https://github.com/madcodemonkey/SimpleDocument.OpenXML) –