ako*_*sch 6 .net c# automation ms-word openxml
我能够使用以下代码访问我的word文档中的书签:
var res = from bm in mainPart.Document.Body.Descendants<BookmarkStart>()
where bm.Name == "BookmarkName"
select bm;
Run Code Online (Sandbox Code Playgroud)
现在我想在此书签后插入一个段落和一个表格.我怎么做?(示例代码将不胜感激)
Ahm*_*eed 28
码
获得书签后,您可以访问其父元素并在其后添加其他项目.
using (WordprocessingDocument document = WordprocessingDocument.Open(@"C:\Path\filename.docx", true))
{
var mainPart = document.MainDocumentPart;
var res = from bm in mainPart.Document.Body.Descendants<BookmarkStart>()
where bm.Name == "BookmarkName"
select bm;
var bookmark = res.SingleOrDefault();
if (bookmark != null)
{
var parent = bookmark.Parent; // bookmark's parent element
// simple paragraph in one declaration
//Paragraph newParagraph = new Paragraph(new Run(new Text("Hello, World!")));
// build paragraph piece by piece
Text text = new Text("Hello, World!");
Run run = new Run(new RunProperties(new Bold()));
run.Append(text);
Paragraph newParagraph = new Paragraph(run);
// insert after bookmark parent
parent.InsertAfterSelf(newParagraph);
var table = new Table(
new TableProperties(
new TableStyle() { Val = "TableGrid" },
new TableWidth() { Width = 0, Type = TableWidthUnitValues.Auto }
),
new TableGrid(
new GridColumn() { Width = (UInt32Value)1018U },
new GridColumn() { Width = (UInt32Value)3544U }),
new TableRow(
new TableCell(
new TableCellProperties(
new TableCellWidth() { Width = 0, Type = TableWidthUnitValues.Auto }),
new Paragraph(
new Run(
new Text("Category Name"))
)),
new TableCell(
new TableCellProperties(
new TableCellWidth() { Width = 4788, Type = TableWidthUnitValues.Dxa }),
new Paragraph(
new Run(
new Text("Value"))
))
),
new TableRow(
new TableCell(
new TableCellProperties(
new TableCellWidth() { Width = 0, Type = TableWidthUnitValues.Auto }),
new Paragraph(
new Run(
new Text("C1"))
)),
new TableCell(
new TableCellProperties(
new TableCellWidth() { Width = 0, Type = TableWidthUnitValues.Auto }),
new Paragraph(
new Run(
new Text("V1"))
))
));
// insert after new paragraph
newParagraph.InsertAfterSelf(table);
}
// close saves all parts and closes the document
document.Close();
}
Run Code Online (Sandbox Code Playgroud)
上面的代码应该这样做.但是,我会解释一些特殊情况.
请注意,它将尝试在书签的父元素之后插入.如果您的书签碰巧是表格中某个段落的一部分,您会期望什么行为?它应该在该表中附加新的段落和表格吗?还是应该在那张桌子之后呢?
你可能想知道为什么上述问题很重要.这一切都取决于插入的位置.如果书签的父项在表中,则当前上述代码将尝试将表放在表中.这没关系,但是由于OpenXml结构无效,可能会发生错误.原因是如果插入的表是原始表的TableCell中的最后一个元素,则在关闭TableCell标记之后需要添加一个Paragraph元素.如果在尝试在MS Word中打开文档时发生此问题,则会立即发现此问题.
解决方案是确定您是否确实在表中执行插入.
为此,我们可以添加上面的代码(在父变量之后):
var parent = bookmark.Parent; // bookmark's parent element
// loop till we get the containing element in case bookmark is inside a table etc.
// keep checking the element's parent and update it till we reach the Body
var tempParent = bookmark.Parent;
bool isInTable = false;
while (tempParent.Parent != mainPart.Document.Body)
{
tempParent = tempParent.Parent;
if (tempParent is Table && !isInTable)
isInTable = true;
}
// ...
newParagraph.InsertAfterSelf(table); // from above sample
// if bookmark is in a table, add a paragraph after table
if (isInTable)
table.InsertAfterSelf(new Paragraph());
Run Code Online (Sandbox Code Playgroud)
这应该可以防止错误发生并为您提供有效的OpenXml.如果您对我之前的问题回答"是"并希望在父表之后执行插入而不是像上面的代码那样在表内执行,则可以使用while循环的想法.如果是这种情况,上述问题将不再是一个问题,你可以用以下代码替换该循环和布尔值:
var parent = bookmark.Parent; // bookmark's parent element
while (parent.Parent != mainPart.Document.Body)
{
parent = parent.Parent;
}
Run Code Online (Sandbox Code Playgroud)
这将继续重新分配父级,直到它是Body级别的主要包含元素.因此,如果书签位于表格中的段落中,它将从Paragraph到TableCell再到TableRow到Table并停在那里,因为Table的父级是Body.那时parent = Table元素,我们可以在它之后插入.
这应该涵盖一些不同的方法,取决于您的原始意图.如果您在尝试之后需要任何澄清,请告诉我.
文件反射器
你可能想知道我是如何确定GridColumn.Width价值的.我制作了一张桌子并使用了文档反射器工具来获取它.安装Open Xml SDK时,生产力工具(如果安装了它们)将位于C:\Program Files\Open XML Format SDK\V2.0\tools(或类似)中.
了解*.docx格式如何工作(或任何Open Xml格式化文档)的最佳方法是使用文档反射器工具打开现有文件.浏览文档部件,找到要复制的项目.该工具显示用于生成整个文档的实际代码.这是您可以复制/粘贴到应用程序中以生成类似结果的代码.您通常可以忽略所有参考ID; 你必须看看并试一试才能感受到它.
正如我所提到的,上面的表格代码是从示例文档中改编而来的.我在docx中添加了一个简单的表,然后在工具中打开它,并复制了该工具生成的代码(我删除了一些额外的东西来清理它).这给了我一个工作样本来添加一个表.
当您想要知道如何编写生成某些内容的代码时,尤其有用,例如格式化的表格和带有样式的段落等.
请查看此链接,了解SDK中包含的其他工具的屏幕截图和信息:Open XML SDK 2.0简介.
代码片段
您可能还对Open Xml的代码片段感兴趣.有关代码段列表,请查看此博文.您可以从此处下载它们:2007 Office System示例:用于Visual Studio 2008的Open XML Format SDK 2.0代码片段.
安装完成后,您可以从Tools |中添加它们 代码段管理器菜单.选择C#作为语言,单击"添加"按钮,然后导航到PersonalFolder\Visual Studio 2008\Code Snippets\Visual C#\ Open XML SDK 2.0 for Microsoft Office以添加它们.在您的代码中,您可以右键单击并选择"插入代码段"并选择所需的代码.