私はIIS 7.5上で実行されているASP.NET 4.5 Webフォームアプリケーションを持っています。OpenXMLでword docを生成
私はカスタムフォームを持っているページの1つからワードドキュメントを生成しようとしています。
マージフィールドを含むワードドキュメントテンプレートをアップロードしました。 コードの背後に、SQLデータベースクエリに基づいてマージフィールドを設定します。
一部のマージフィールドでは、複数行のテキストを挿入する必要があります。それらの中には弾丸リストさえあるものもあります。これらのテキスト断片は私がSQLに保存することはできませんので、ブックマークを使って別の単語文書に追加しました。ただ要約するので
、:
Template.dotx - >ブックマークでマークされたテキストの断片が含まれています - > [差し込みフィールド
Data.docxが含まれています。
私は、Template.dotxのマージフィールドをOpenXMLで置き換えることができましたが、ブックマークからマージフィールドにデータを取得する方法が見つかりません。
これはInteropでうまくいきますが、サーバーにアップロードしたときに問題が発生してOpenXMLに切り替えました。
これは私がこれまでにしようとしているものです:
はprivate string GetBookmarkData(WordprocessingDocument secondWordDoc, string bookmarkKey)
{
string returnVal = "";
foreach (BookmarkStart bookmarkStart in secondWordDoc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
{
if(bookmarkStart.Name == bookmarkKey)
{
foreach(Run run in bookmarkStart.Parent.Descendants<Run>())
{
returnVal += run.Descendants<Text>().FirstOrDefault().Text + "<br/>";
}
}
}
return returnVal;
}
protected void PrintBtn_Click(object sender, EventArgs e)
{
string mainTemplate = Server.MapPath("~/MyFolder/Template.dotx");
string savePath = Server.MapPath("~/SaveFolder/Final.docx");
File.Copy(mainTemplate, savePath);
using(WordprocessingDocument firstDoc = WordprocessingDocument.Open(savePath, true))
{
using (WordprocessingDocument secondDoc = WordprocessingDocument.Open(Server.MapPath("~/MyFolder/Data.docx"), true))
{
foreach (FieldCode field in firstDoc.MainDocumentPart.RootElement.Descendants<FieldCode>())
{
var fieldNameStart = field.Text.LastIndexOf(" MERGEFIELD", System.StringComparison.Ordinal);
String fieldText = field.InnerText;
if (fieldText.StartsWith(" MERGEFIELD"))
{
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
fieldName = fieldName.Trim();
string autoFill = "";
switch (fieldName)
{
case "MergeField1":
autoFill = mergefield_1;
break;
case "MergeField2":
autoFill = mergefield_2;
break;
case "MergeField3":
autoFill = GetBookmarkData(secondDoc, "Bookmark1");
break;
case "MergeField4":
autoFill = GetBookmarkData(secondDoc, "Bookmark2");
break;
case "MergeField5":
autoFill = GetBookmarkData(secondDoc, "Bookmark3");
break;
}
}
foreach (Run run in firstDoc.MainDocumentPart.Document.Descendants<Run>())
{
foreach (Text txtFromRun in run.Descendants<Text>().Where(a => a.Text == "«" + fieldName + "»"))
{
txtFromRun.Text = autoFill;
}
}
}
}
}
firstDoc.ChangeDocumentType(WordprocessingDocumentType.Document);
firstDoc.MainDocumentPart.Document.Save();
}
}
だから、これは何をするのでしょうか?
ボタンをクリックすると、メソッドPrintBtn_Clickが呼び出されます。いくつかのSQLマジック(これには含まれていない)を実行した後、各マージフィールドを満たすいくつかの変数を初期化します。この例は短く編集されたバージョンです。オリジナルははるかに大きいです。このコードを使用して、マージフィールドを作成しました。それは素晴らしい作品です。しかし、方法: `
string GetBookmarkData(WordprocessingDocument secondWordDoc, string bookmarkKey)`
それは本当に何をするかはしません。それはData.docxに移動し、指定したブックマークからすべてのテキストを取得する必要があります。それは、箇条書きや奇妙な書式のない行だけを返します。
私はInteropを使用して同じプロセスを使用しましたが、問題はありませんでした。 OpenXMLでこれをどうすればできますか?弾丸のある行は別のXMLに格納されていますか?
私は、BookmarkStartとBookmarkEndの間のすべてのRunを取得し、そこからTextを取得しようとしました。
何か助けていただければ幸いです。 ありがとうございました!
更新
secondDocが実際にData.docxで、次のようになります。
Bookmark1
• Text-Information 1 (This is just an example)
• Text-Information 2 (This is just an example)
• Text-Information 3 (This is just an example)
• Text-Information 4 (This is just an example)
Bookmark2
This is a list of multiple items:
Item 1 x.000,00
Item 2 x.000,00
Item 3 x.000,00
Item 4 x.000,00
Item 5 000,00
This is the conclusion for this list.
Following is a list of other multiple items:
Item 1 x.000,00
Item 2 x.000,00
Item 3 x.000,00
Item 4 x.000,00
Item 5 000,00
This is the conclusions for this list
Bookmark3
a) Another example of text that needs to go in the mergefield:
• Article 1 xxxx Quantity/Producer etc
• Article 2 xxxx Quantity/Producer etc
Some details about this block of text that is not relevant but I need to insert it in the merge field as well
ので、テキスト全体が "Bookmark1"/"Bookmark2"/"Bookmark3" の後に、行く必要特定のラジオボタンが押された場合は、その特定のマージフィールドに表示されます。私はこれらのテキストブロックをブックマークしました。上記のように、弾丸のない行を挿入するだけです。たとえば、Bookmark2に対応するマージフィールドは、 "これは複数のアイテムのリストです:"のみを受け取ります。
まず:
私たちはsecondDocを参照する必要があります。構造を表示できたら、コードのトラブルシューティングに役立てることができます。 – Taterhead
私は最初の投稿を更新しました。私はそれがはっきりしていることを望むありがとうございました! – Cosmos24Magic
明らかですが、十分明確ではありません。正確なxml構造を調べるためには、実際の文書が必要です。これは、あなたのメソッドが正しい値を返さない理由を判断するのに役立ちます。ファイルを共有したくない、または共有できない場合、私は理解しています。あなたがする必要があるのは、Open XMLの生産性ツール(https://www.microsoft.com/en-us/download/details.aspx?id=30425)をダウンロードし、ドキュメントを開いてXML構造を調べることです。次に、構造に従ってGetBookmarkDataメソッドを書き換えます。あなたが文書を投稿すれば、あなたのためにそれを行います;) – Taterhead