我正在使用Open XML SDK在C#中创建WordprocessingDocument
,然后将它们转换为pdf。最初,我是使用Interop将文档保存为PDF格式的,但是现在这不是一个选择。我发现LibreOffice可以转换从cmd调用soffice.exe的文档,使用普通文档我得到了很好的结果。但是,当我用动态文档测试LibreOffice转换器时,该转换器崩溃了。
我复制了其中一个文档,并使用LibreOffice Writer打开了该文档,其结构错误,然后我使用Microsoft Word打开了相同的文档,并且其结构还不错。最后,我用Microsoft Word将其保存,并按如下所示打开两个文档作为ZIP文件:
这是好东西:
这是坏事:
我注意到,当我在Microsoft Word中保存文档时,出现了这些Open XML部分(在此问题的早期版本中称为“文件”)。当我在LibreOffice中打开以前用Microsoft Word保存的文档时,该文档又可以了。
因此,有没有一种方法可以在不打开Microsoft Word的情况下生成这些Open XML部分(在Word文档中)?
我使用以下代码(检查它是否正在创建所有文件):
using (MemoryStream mem = new MemoryStream())
{
// Create Document
using (WordprocessingDocument wordDocument =
WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true))
{
// Add a main document part.
MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
// Create the document structure and add some text.
mainPart.Document = new Document();
Body docBody = new Body();
// Add your docx content here
CreateParagraph(docBody);
CreateStyledParagraph(docBody);
CreateTable(docBody);
CreateList(docBody);
Paragraph pImg = new Paragraph();
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);
string imgPath = "https://cdn.pixabay.com/photo/2019/11/15/05/23/dog-4627679_960_720.png";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(imgPath);
req.UseDefaultCredentials = true;
req.PreAuthenticate = true;
req.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
imagePart.FeedData(resp.GetResponseStream());
// 1500000 and 1092000 are img width and height
Run rImg = new Run(DrawingManager(mainPart.GetIdOfPart(imagePart), "PictureName", 1500000, 1092000, string.Empty));
pImg.Append(rImg);
docBody.Append(pImg);
Paragraph pLink = new Paragraph();
// For the mainpart see above
pLink.Append(HyperLinkManager("http://YourLink", "My awesome link", mainPart));
docBody.Append(pLink);
mainPart.Document.Append(docBody);
mainPart.Document.Save();
wordDocument.Close();
}
result = Convert.ToBase64String(mem.ToArray());
}
上面的代码创建一个名为Result.docx的Word文档,其结构如下:
但是没有其他任何Open XML部分(例如app.xml
或styles.xml
)
答案 0 :(得分:1)
您需要在以下方面有所作为:
WordprocessingDocument
和根据标准,最低WordprocessingDocument
仅需要一个主要文档部分(MainDocumentPart
,document.xml
),其内容如下:
<w:document xmlns:w="...">
<w:body>
<w:p />
</w:body>
</w:document>
仅当您具有样式或编号时,才需要其他部分,例如StyleDefinitionsPart
(styles.xml
)或NumberingDefintionsPart
(numbering.xml
),在这种情况下,您必须明确在您的代码中创建它们。
接下来,查看您的示例代码,看来您正在创建:
CreateStyledParagraph(docBody)
),必须在StyleDefinitionsPart
(styles.xml
)中进行定义;和CreateList(docBody)
),必须在NumberingDefinitionsPart
(numbering.xml
)中定义。但是,您的代码既不会创建StyleDefinitionsPart
也不会创建NumberingDefintionsPart
,这意味着您的文档可能不是有效的Open XML文档。
现在,Word非常宽容,并且无声地修复了各种问题,而忽略了您的Open XML标记的某些部分(例如,您可能分配给段落的样式)。
相反,根据LibreOffice的容错程度,无效的Open XML标记可能会导致崩溃。例如,如果LibreOffice在您的StyleDefinitionsPart
中找到类似<w:pStyle w:val="MyStyleName" />
的元素时只是假设w:document
存在,然后在询问时不检查是否获得了null
引用StyleDefinitionsPart
可能会崩溃。
最后,要向Word文档中添加部分,您可以按以下方式使用Open XML SDK:
[Fact]
public void CanAddParts()
{
const string path = "Document.docx";
const WordprocessingDocumentType type = WordprocessingDocumentType.Document;
using WordprocessingDocument wordDocument = WordprocessingDocument.Create(path, type);
// Create minimum main document part.
MainDocumentPart mainDocumentPart = wordDocument.AddMainDocumentPart();
mainDocumentPart.Document = new Document(new Body(new Paragraph()));
// Create empty style definitions part.
var styleDefinitionsPart = mainDocumentPart.AddNewPart<StyleDefinitionsPart>();
styleDefinitionsPart.Styles = new Styles();
// Create empty numbering definitions part.
var numberingDefinitionsPart = mainDocumentPart.AddNewPart<NumberingDefinitionsPart>();
numberingDefinitionsPart.Numbering = new Numbering();
}