使用SDK我正在构建包含报告的Word文档。这些文件需要有TOC。 有没有人有一个完整的解决方案,我可以遵循,以了解如何做到这一点?
上的所有内容答案 0 :(得分:9)
看看Eric White的Fourth and Final Screen-Cast in Series on Adding/Updating the TOC in OpenXML WordprocessingML Documents。
希望有所帮助!
更新:
According FAQ我发现不支持此功能:
8)如何在Word文档中生成TOC(目录)?
Open XML SDK 2.0不支持此功能。 但您可以生成 通过Word应用程序进行小型TOC,并使用Document反映TOC部分 Open XML SDK Productivity Tool中的Reflector组件,以了解如何操作 以编程方式生成TOC。 有关详细信息,请 参考:
更新2
根据我们以下的评论,我可以建议使用这种情况:
所有这些看起来有点棘手,但我希望有所帮助。
答案 1 :(得分:5)
使用自动目录(可单击)
设置标题
public static Paragraph SetHeading1(this Paragraph p)
{
var pPr = p.Descendants<ParagraphProperties>().First();
pPr.ParagraphStyleId = new ParagraphStyleId() { Val = "Heading1" };
return p;
}
从空文档生成目录,您可以使用以下方法:
private static string GetTOC(string title, int titleFontSize)
{
return $@"<w:sdt>
<w:sdtPr>
<w:id w:val=""-493258456"" />
<w:docPartObj>
<w:docPartGallery w:val=""Table of Contents"" />
<w:docPartUnique />
</w:docPartObj>
</w:sdtPr>
<w:sdtEndPr>
<w:rPr>
<w:rFonts w:asciiTheme=""minorHAnsi"" w:eastAsiaTheme=""minorHAnsi"" w:hAnsiTheme=""minorHAnsi"" w:cstheme=""minorBidi"" />
<w:b />
<w:bCs />
<w:noProof />
<w:color w:val=""auto"" />
<w:sz w:val=""22"" />
<w:szCs w:val=""22"" />
</w:rPr>
</w:sdtEndPr>
<w:sdtContent>
<w:p w:rsidR=""00095C65"" w:rsidRDefault=""00095C65"">
<w:pPr>
<w:pStyle w:val=""TOCHeading"" />
<w:jc w:val=""center"" />
</w:pPr>
<w:r>
<w:rPr>
<w:b />
<w:color w:val=""2E74B5"" w:themeColor=""accent1"" w:themeShade=""BF"" />
<w:sz w:val=""{titleFontSize * 2}"" />
<w:szCs w:val=""{titleFontSize * 2}"" />
</w:rPr>
<w:t>{title}</w:t>
</w:r>
</w:p>
<w:p w:rsidR=""00095C65"" w:rsidRDefault=""00095C65"">
<w:r>
<w:rPr>
<w:b />
<w:bCs />
<w:noProof />
</w:rPr>
<w:fldChar w:fldCharType=""begin"" />
</w:r>
<w:r>
<w:rPr>
<w:b />
<w:bCs />
<w:noProof />
</w:rPr>
<w:instrText xml:space=""preserve""> TOC \o ""1-3"" \h \z \u </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:b />
<w:bCs />
<w:noProof />
</w:rPr>
<w:fldChar w:fldCharType=""separate"" />
</w:r>
<w:r>
<w:rPr>
<w:noProof />
</w:rPr>
<w:t>No table of contents entries found.</w:t>
</w:r>
<w:r>
<w:rPr>
<w:b />
<w:bCs />
<w:noProof />
</w:rPr>
<w:fldChar w:fldCharType=""end"" />
</w:r>
</w:p>
</w:sdtContent>
” }
创建SdtBlock,并设置TOC xml
var sdtBlock = new SdtBlock();
sdtBlock.InnerXml = GetTOC(Translations.ResultsBooksTableOfContentsTitle, 16);
document.MainDocumentPart.Document.Body.AppendChild(sdtBlock);
设置UpdateFieldsOnOpen
var settingsPart = document.MainDocumentPart.AddNewPart<DocumentSettingsPart>();
settingsPart.Settings = new Settings { BordersDoNotSurroundFooter = new BordersDoNotSurroundFooter() { Val = true } };
settingsPart.Settings.Append(new UpdateFieldsOnOpen() { Val = true });
如果您需要从docx生成pdf文件,则可以正常工作!
答案 2 :(得分:3)
感谢Dmitri Pavlov(@DmitryPavlov)的帮助。
我不想回答我自己的问题,但这只是为了说明我采取的步骤。
对任何感兴趣的人的建议是观看由Eric White制作的5部分剧本 - Exploring Tables-of-Contents in Open XML WordprocessingML Documents。这包含有关添加和更新TOC的所有信息(更多)。
我的解决方案是使用模板(只是一个常规的空文档,其中包含我需要的所有内容的样式:标题1-5,TOC样式等)。这对于样式问题的快速修复特别有用(具有TOC的新文档将创建新的style.xml;此文件具有一些附加数据;因此TOC中的层次结构不是预期 - 即,标题2是标题1的子标题,标题3是标题2的子节点等。)
因此:
创建Word文档并添加您希望以后以编程方式添加的所有元素(例如,标题1-5,目录等)。删除所有内容并保存文档(原因是为所有必要元素创建样式)。
我个人将模板(在步骤#1中创建的文件)添加为项目中的资源。
在您的代码中,创建模板的新副本(这将是您将要处理的实际文件)。我用过:
byte[] stream = Properties.Resources.Template;
File.WriteAllBytes(@"D:\Template.docx", stream);
File.Copy(@"D:\Template.docx", @"D:\New.docx");
将所有数据刷新到此文档。
将来自屏幕播放2,3或4的源文件添加到您的项目中(为此请参见屏幕播放3) - 在这些帖子的末尾,您将找到下载 TocAdder的链接的.zip 。或者只是添加对 TocAdder.dll 的引用。
插入TOC。举个例子:
using (WordprocessingDocument wdoc = WordprocessingDocument.Open(@"D:\New.docx", true))
{
XElement firstPara = wdoc
.MainDocumentPart
.GetXDocument()
.Descendants(W.p)
.FirstOrDefault();
TocAdder.AddToc(wdoc, firstPara,
@"TOC \o '1-3' \h \z \u", null, null);
}
将新创建的文档中的样式替换为模板中的样式。您可以使用MSDN中的此资源:Replacing the Styles Parts in Word 2010 Documents by Using the Open XML SDK 2.0。再举一个例子:
string fromDoc = @"D:\Template.docx";
string toDoc = @"D:\New.docx";
var node = WDExtractStyles(fromDoc, false);
if (node != null)
WDReplaceStyles(toDoc, node, false);
node = WDExtractStyles(fromDoc);
if (node != null)
WDReplaceStyles(toDoc, node);
可选择使用屏幕播放3,4或5中描述的方法之一,以解决Word提出的模式对话框的问题。
希望这对某些人有用。
答案 3 :(得分:1)
如果您有一个TOC字段,当在Word中打开文档时(正文是对文档正文的引用),这将导致它进行更新:
DocumentFormat.OpenXml.Wordprocessing.SimpleField f;
f = new SimpleField();
f.Instruction="sdtContent";
f.Dirty = true;
body.Append(f);