我能夠使用此代碼訪問書籤我的word文檔中:插入OpenXmlElement字後書籤開放XML SDK
var res = from bm in mainPart.Document.Body.Descendants<BookmarkStart>()
where bm.Name == "BookmarkName"
select bm;
現在我要插入此書籤後一個段落和一張桌子。我怎麼做? (示例代碼,將不勝感激)
我能夠使用此代碼訪問書籤我的word文檔中:插入OpenXmlElement字後書籤開放XML SDK
var res = from bm in mainPart.Document.Body.Descendants<BookmarkStart>()
where bm.Name == "BookmarkName"
select bm;
現在我要插入此書籤後一個段落和一張桌子。我怎麼做? (示例代碼,將不勝感激)
代碼
一旦你有,你可以訪問它的父元素,並在其後添加其他項目的書籤。
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();
}
上面的代碼應該這樣做。不過,我會解釋一些特殊情況。
注意,它將書籤的父元素之後嘗試插入。如果您的書籤恰好是表格中段落的一部分,您會期望什麼行爲?是否應該在該表之後附加新的段落和表格?還是應該在桌子後面做?
您可能想知道爲什麼上述問題很重要。這完全取決於插入的位置。如果書籤的父節點在表中,那麼當前上面的代碼將試圖在表中放置一個表。這很好,但是由於OpenXml結構無效,可能會發生錯誤。原因是如果插入的表是原始表的TableCell中的最後一個元素,則需要在關閉TableCell標記之後添加一個Paragraph元素。如果嘗試在MS Word中打開文檔時發生此問題,您會立即發現此問題。
的解決方案是確定你是否真的在表內進行插入。
要做到這一點,我們可以添加到上面的代碼(父VAR後):
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());
這應該防止出現錯誤,並給你有效的OpenXML的。如果你對我之前的問題回答「是」,並且希望在父表之後執行插入操作,而不是像上面的代碼那樣在表內執行插入操作,則可以使用while循環構思。如果是這樣的情況下,上述問題將不再是一個問題,你可以替換回路上與以下布爾:
var parent = bookmark.Parent; // bookmark's parent element
while (parent.Parent != mainPart.Document.Body)
{
parent = parent.Parent;
}
這使得重新分配的父母,直到它在身體層面主要包含元素。因此,如果書籤位於表格中的段落中,它將從段落到TableCell到TableRow到表格並停止,因爲表格的父元素是主體。在這一點上,parent = Table元素,我們可以在它之後插入。
這應該涉及到一些不同的方法,這取決於你的原意。試用後,如果您需要澄清,請告訴我。
文檔反射
你也許想知道我是怎麼確定的GridColumn.Width
值。我製作了一張桌子,並使用了文檔反射器工具來獲取它。當您安裝Open Xml SDK時,生產力工具(如果您安裝了它們)將位於C:\Program Files\Open XML Format SDK\V2.0\tools
(或類似)中。
瞭解*的最佳方法。docx格式工作(或任何Open Xml格式的文檔)是使用文檔反射器工具打開現有文件。瀏覽文檔部分,然後找到要複製的項目。該工具向您顯示用於生成整個文檔的實際代碼。這是您可以複製/粘貼到您的應用程序以生成類似結果的代碼。您可以通常忽略所有參考ID;你必須看一看,並試着去感受它。
正如我所提到的,上面的表代碼是根據示例文檔改編的。我在docx中添加了一個簡單的表格,然後在工具中打開它,並複製該工具生成的代碼(我刪除了一些額外的代碼來清理它)。這給了我一個工作示例來添加一個表。
,當你想知道如何編寫代碼,生成一些東西,比如格式化的表格和段落樣式等
看看包含此鏈接的其他工具的截圖和信息,是特別有幫助在SDK中:An introduction to Open XML SDK 2.0。
代碼段
您可能也有興趣的代碼片段的Open XML。有關片段列表,請檢查this blog post。你可以從這裏下載它們:2007 Office System Sample: Open XML Format SDK 2.0 Code Snippets for Visual Studio 2008。
安裝完成後,您可以從Tools |代碼片段管理器菜單。選擇C#作爲語言,點擊添加按鈕,然後導航到PersonalFolder \ Visual Studio 2008 \ Code Snippets \ Visual C#\ Open Office SDK 2.0 for Microsoft Office以添加它們。從你的代碼中,你可以右鍵單擊並選擇「Insert Snippet」並選擇你想要的。
按設計(或定義),段落總是以新行開始。這聽起來像是你想將新文本附加到書籤的父段,所以文本繼續在同一行,是嗎?段落可以包含多個「運行」,其中又包含「文本」項目。要附加到段落,您需要爲其添加新的運行。如果這就是你想要的,創建Run var並添加它的Text後,不要將它添加到** newParagraph **。相反,將它添加到父:** parent.Append(run); **然後添加表後:** parent.InsertAfterSelf(表); ** - 看看是否它:) – 2009-10-27 13:49:50