c# - 无法在 Open Xml 中使用现有段落样式

标签 c# ms-word openxml openxml-sdk word-2010

我正在将 HTML 文件导出到 Open XML 字文件。如果在 HTML 中 <h1>使用后,我想为该部分添加 Heading1 样式。但是不知何故,当我在 Microsoft Word 2010 中打开文档时,未应用样式。

如果我在 Libre Office 中打开创建的文档,会应用一些样式。

我还自己定义了一些样式,如果我使用其中一种样式,那么在 Word 和 Libre Office 中一切都会顺利进行。

我打开了 Open XML SDK 2.5 Microsoft Office Productivity Tool,当我查看它提供的示例代码时,它提示:

ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId(){ Val = "Kop1" };

Kop1(而不是 Heading1)是因为我的 Word 是荷兰语,所以我的模板是荷兰语,但这并没有解决问题。

在此代码示例中,我创建了段落并为其添加了样式和文本:

using (wordDocument = WordprocessingDocument.Open(documentStream, true)) 
{
    MainDocumentPart mainPart = wordDocument.MainDocumentPart;
    WP.Body body = wordDocument.MainDocumentPart.Document.Body;
    WP.Paragraph para = body.AppendChild(new WP.Paragraph());
    StyleDefinitionsPart part = wordDocument.MainDocumentPart.StyleDefinitionsPart;
    if (part != null)
    {
        WP.ParagraphProperties pPr = new WP.ParagraphProperties();
        WP.ParagraphStyleId paragraphStyleId1 = new WP.ParagraphStyleId() { Val = "Heading1" };
        pPr.Append(paragraphStyleId1);

        para.Append(pPr);
    }

    WP.Run run = para.AppendChild(new WP.Run());
    run.AppendChild(new WP.Text(value));
}

它定义了样式,因为我使用的是模板,所以代码将放在 if 语句中。

我也尝试过 title 风格(荷兰语titel),都试过了但是都没有用...

我真的不明白哪里出了问题,为什么我可以使用我自己创建的样式但不能使用 Word 的预定义样式之一,我没有这样做'在模板中删除。

它不知何故无法识别预定义的样式?

编辑/添加

我让它工作了,但不是我想要的方式,我必须单击模板文档中的预定义样式,然后保存文档。现在,在单击它们并保存这些样式后,不知何故将这些样式添加到文档中,因为如果我现在使用模板生成最终文档,我就可以使用这些样式。 但是如果不先点击文档中的样式,我就不能使用它们,因为它们没有保存?

最佳答案

不幸的是,发生这种情况是因为默认情况下样式未写入文档(即使它是“内置”到 Word),因此未应用样式。

如果您通过代码创建一个文档,然后通过应用了 Heading1 样式的 Word 创建另一个文档,然后比较\word\styles.xml 中的 XML,您将看到 Word 生成的 XML 中有一个额外的部分:

enter image description here

您可以使用以下代码生成自己的样式信息。我不知道有什么方法可以从硬编码以外的地方获取这些样式;也许可以在某处的 dotx 文件中找到它们? 有关此的更多信息,请参阅下面的编辑

using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(documentStream, true))
{
    MainDocumentPart mainPart = wordDocument.MainDocumentPart;
    Body body = wordDocument.MainDocumentPart.Document.Body;
    Paragraph para = body.AppendChild(new Paragraph());
    StyleDefinitionsPart part = wordDocument.MainDocumentPart.StyleDefinitionsPart;
    if (part != null)
    {
        Style style = new Style()
        {
            Type = StyleValues.Paragraph,
            StyleId = "Heading1",
            BasedOn = new BasedOn() { Val = "Normal" },
            NextParagraphStyle = new NextParagraphStyle() { Val = "Normal" }
        };

        StyleName styleName1 = new StyleName() { Val = "heading 1" };
        style.Append(styleName1);
        style.Append(new PrimaryStyle());
        StyleRunProperties styleRunProperties1 = new StyleRunProperties();
        styleRunProperties1.Append(new Bold());
        styleRunProperties1.Append(new RunFonts() 
            {
                ComplexScriptTheme=ThemeFontValues.MajorBidi, 
                HighAnsiTheme=ThemeFontValues.MajorHighAnsi,
                EastAsiaTheme=ThemeFontValues.MajorEastAsia, 
                AsciiTheme=ThemeFontValues.MajorAscii 
            });
        styleRunProperties1.Append(new FontSize() { Val = "28" });
        styleRunProperties1.Color = new Color() 
            {
                Val = "365F91",
                ThemeShade = "BF",
                ThemeColor = ThemeColorValues.Accent1
            };
        style.Append(styleRunProperties1);
        part.Styles.Append(style);

        ParagraphProperties pPr = new ParagraphProperties();
        ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "Heading1" };
        pPr.Append(paragraphStyleId1);
        para.Append(pPr);
    }

    Run run = para.AppendChild(new Run());
    run.AppendChild(new Text("This is a heading"));
}

编辑

我看了一下,发现 Word 默认样式确实存储在 .dotx 文件中,正如我上面猜测的那样。这些文件也可以通过 OpenXML API 读取,因此可以将样式从那里复制到您的文档中。此代码与我们已有的代码非常相似,只是增加了读取 Default.dotx 文件并从中获取样式的功能。

在我的系统上,dotx 文件位于 C:\Program Files\Microsoft Office\Office14\1033\QuickStyles 中,我在下面对其进行了硬编码。我不知道是否有某个地方可以动态获取(也许是注册表),但如果没有,我想配置文件就足够了。

using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(documentStream, true))
{
    MainDocumentPart mainPart = wordDocument.MainDocumentPart;
    Body body = wordDocument.MainDocumentPart.Document.Body;
    Paragraph para = body.AppendChild(new Paragraph());
    Paragraph para2 = body.AppendChild(new Paragraph());
    Paragraph para3 = body.AppendChild(new Paragraph());

    StyleDefinitionsPart part = wordDocument.MainDocumentPart.StyleDefinitionsPart;
    if (part != null)
    {
        //I'm looping the styles and adding them here
        //you could clone the whole StyleDefinitionsPart
        //but then you'd lose custom styles in your source doc
        using (WordprocessingDocument wordTemplate = WordprocessingDocument.Open(@"C:\Program Files\Microsoft Office\Office14\1033\QuickStyles\default.dotx", false))
        {
            foreach (var templateStyle in wordTemplate.MainDocumentPart.StyleDefinitionsPart.Styles)
            {
                part.Styles.Append(templateStyle.CloneNode(true));
            }
        }

        //I can now use any built in style 
        //I'm using Heading1, Title and IntenseQuote as examples
        //You may need to do a language conversion here as 
        //you mentione your docx is in Dutch
        ParagraphProperties pPr = new ParagraphProperties();
        ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "Heading1" };
        pPr.Append(paragraphStyleId1);
        para.Append(pPr);

        Run run = para.AppendChild(new Run());
        run.AppendChild(new Text("This is a heading"));

        ParagraphProperties pPr2 = new ParagraphProperties();
        ParagraphStyleId paragraphStyleId2 = new ParagraphStyleId() { Val = "Title" };
        pPr2.Append(paragraphStyleId2);
        para2.Append(pPr2);

        Run run2 = para2.AppendChild(new Run());
        run2.AppendChild(new Text("This is a title"));

        ParagraphProperties pPr3 = new ParagraphProperties();
        ParagraphStyleId paragraphStyleId3 = new ParagraphStyleId() { Val = "IntenseQuote" };
        pPr3.Append(paragraphStyleId3);
        para3.Append(pPr3);

        Run run3 = para3.AppendChild(new Run());
        run3.AppendChild(new Text("This is an intense quote"));
    }
}

生成的文件如下所示:

enter image description here

关于c# - 无法在 Open Xml 中使用现有段落样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25056927/

相关文章:

c# - 操作方法 : Run existing Word VBA Macros from C# Ribbon Addin

list - 如何在c#中使用OpenXml在excel文件的列/列中设置数据验证列表?

c# - 将 Drawing.Image 插入 WordprocessingDocument 正文

c# - 在 C# 中使用 OLEDB 从 Excel 中选择单元格地址

c# - 如何在 C# 中声明反斜杠常量字符?

vba - Excel VBA范围变量连接

java - Eclipse Word 文档阅读器/文本提取器

c# - 如何在 OpenXML/PresentationML/C# 中的 PowerPoint (PPTX) 中插入换行符

c# - 如何在 Parallel.For 中配置最大线程数

c# - UWP - 不可选择的 NavigationViewItem 但可点击