OpenXML SDK, 2.0 CTP kullanarak, programlı bir Word belgesi oluşturmaya çalışıyorum. Belgemde madde işaretli bir liste eklemem gerekiyor, listenin bazı öğelerinin altı çizilmelidir. Bunu nasıl yapabilirim?OpenXML 2 SDK - Word belgesi - Programlı olarak madde işaretli liste oluştur
cevap
OpenXML'de listelenenler biraz kafa karıştırıcıdır.
Belgedeki tüm listeleri açıklayan bir NumaralandırmaDefinitionsPart bulunmaktadır. Listelerin nasıl görünmesi gerektiği (madde işareti, numaralandırılmış vb.) Hakkında bilgiler içerir ve her birine aynı zamanda kimlik ve kimlik atar.
Ardından, oluşturmak istediğiniz listedeki her öğe için MainDocumentPart'da yeni bir paragraf ekleyin ve bu paragrafa istediğiniz listenin kimliğini atayın.
- Merhaba,
- dünyada:
Yani örneğin bir kurşun listesi oluşturmak için!
Önce bir NumberingDefinitionsPart oluşturması gerekecektir: numaralandırma kimliği,
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);
Sonra paragraf özellikleri dışında, her zamanki gibi MainDocumentPart oluşturmak atayı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);
Bölüm 2.9'da OpenXML reference guide'da bulunan seçeneklerin daha iyi bir açıklaması vardır.
Adem'in cevabı yukarıda bunun dışında doğru bir yorum da belirtildiği gibi (yerine yeni Num yeni NumberingInstance (olduğunu.
Ayrıca, birden çok liste varsa, birden Numaralandırma öğe olmalı (kendi kimliği ile her Örneğin, 1, 2, 3 vb. - Belgedeki her liste için bir tane. Bu, mermi listelerinde bir problem gibi görünmüyor, ancak numaralandırılmış listeler aynı numaralandırma dizisini kullanarak devam edecek (1'den başlayarak tekrar başlayacak) çünkü aynı liste olduğunu düşünür çünkü NumberingId paragrafınızda şu şekilde başvuruda bulunulmalıdır:
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);
Seviye elemanının çocukları merminin türü ve girinti üzerinde bir etkiye sahip olacaktır. Ben de Seviye elemana bu eleman katma kadar
new NumberingSymbolRunProperties(
new RunFonts() { Hint = FontTypeHintValues.Default, Ascii = "Symbol", HighAnsi = "Symbol" })
Girinti bir sorun oldu: Benim mermi ben Seviye elemana bu ilave kadar çok küçük
new PreviousParagraphProperties(
new Indentation() { Left = "864", Hanging = "360" })
Ve gibiyseniz beni - bir şablondan doküman oluştururken, o zaman her iki durumları ele almak, bu kodu kullanmak isteyebilirsiniz - şablonunuzu yapar veya herhangi bir numaralandırma tanımlarını içermiyorsa:
// 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");
}
Bir belgeye birden fazla mermi listesi eklememe izin verecek bir şey istedim. Kafamı bir süredir masamıza çarptıktan sonra, bir grup farklı yazıyı birleştirmeyi ve belgemi Açık XML SDK 2 ile incelemeyi başardım.0 Productity Tool ve bazı şeyler anladım. Ürettiği belge artık SDK Üretkenlik aracının 2.0 ve 2.5 sürümlerine göre geçerliliğini geçer.
İşte kod; Umarım birileri zaman kaybeder ve ağırlaştırır.
Kullanımı:
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);
kullanma ifadeleri:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
Kod
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;
}
}
nasıl bir belgeye listesi eklemek için bana gösterdiğin için sana çok teşekkür ederim. Ben Numbering.Append (abstactNum, numberingInstance) kullanıyordum ve neden işe yaramadı anlamadı – Dan
Gelecekte: Teşekkürler bu biri için dostum! Gerçekten, gerçekten! :) –
@MariusConjeaud Rica ederim. Kullanmaya hazırlandığınız basit word belgeleri yazmak için bir şeyler hazırladım (bkz. Https://github.com/madcodemonkey/SimpleDocument.OpenXML) –