2009-12-21 27 views

risposta

24

Gli elenchi in OpenXML sono un po 'confusi.

C'è una NumberingDefinitionsPart che descrive tutti gli elenchi nel documento. Contiene informazioni su come dovrebbero apparire gli elenchi (puntati, numerati, ecc.) E inoltre assegna e ID a ciascuno di essi.

Quindi nel MainDocumentPart, per ogni elemento nell'elenco che si desidera creare, si aggiunge un nuovo paragrafo e si assegna l'ID della lista che si desidera a quel paragrafo.

in modo da creare un elenco puntato come ad esempio:

  • Ciao,
  • mondo!

Si dovrebbe prima creare 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); 

quindi si crea la MainDocumentPart come si farebbe normalmente, tranne che nelle proprietà di paragrafo, assegnare l'ID di numerazione:

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); 

C'è una spiegazione migliore delle opzioni disponibili nello OpenXML reference guide nella Sezione 2.9.

3

risposta di Adam di cui sopra è corretto tranne che è nuovo NumberingInstance (invece di nuova Num (come ha osservato in un commento.

Inoltre, se si dispone di più liste, si dovrebbe avere più elementi di numerazione (ciascuno con il proprio ID ad es. 1, 2, 3 ecc. - uno per ogni lista nel documento. Questo non sembra essere un problema con gli elenchi puntati, ma gli elenchi numerati continueranno ad usare la stessa sequenza di numerazione (invece di ricominciare da capo 1) . perché penserà che è la stessa lista la NumberingId deve essere fatto riferimento nel paragrafo in questo modo:

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); 

I bambini dell'elemento Livello avranno un effetto sul tipo di proiettile e sul rientro. miei proiettili erano troppo piccoli fino a quando ho aggiunto questo al elemento di livello:

new NumberingSymbolRunProperties(
    new RunFonts() { Hint = FontTypeHintValues.Default, Ascii = "Symbol", HighAnsi = "Symbol" }) 

rientro è stato un problema fino a quando ho aggiunto questo elemento per l'elemento di livello così:

new PreviousParagraphProperties(
    new Indentation() { Left = "864", Hanging = "360" }) 
3

E se siete come me - la creazione di un documento da un modello, quindi si consiglia di utilizzare questo codice, per gestire entrambe le situazioni - quando il modello fa o non contiene alcuna definizione di numerazione:

// 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"); 
} 
7

Volevo qualcosa che mi permettesse di aggiungere più di un elenco puntato a un documento. Dopo aver sbattuto la testa contro la mia scrivania per un po ', sono riuscito a combinare diversi post e ad esaminare il mio documento con Open XML SDK 2.0 Productity Tool e ho trovato alcune cose. Il documento che produce ora passa la convalida per la versione 2.0 e 2.5 dello strumento di produttività SDK.

Ecco il codice; si spera che risparmi qualcuno un po 'di tempo e di irritazione.

utilizzo:

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); 

Utilizzando dichiarazioni:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using DocumentFormat.OpenXml; 
using DocumentFormat.OpenXml.Packaging; 
using DocumentFormat.OpenXml.Wordprocessing;  

Codice

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; 
    } 
} 
+0

Grazie mille per avermi mostrato come aggiungere un elenco a un documento. Stavo usando Numbering.Append (abstactNum, numberingInstance) e non riuscivo a capire perché non funzionasse – Dan

+0

Dal futuro: grazie amico per quello! Mi piace, davvero! :) –

+0

@MariusConjeaud Prego. Ho creato qualcosa per scrivere semplici documenti di parole che puoi usare (vedi https://github.com/madcodemonkey/SimpleDocument.OpenXML) –