質問

Infopath 2010フォームがあります。学生情報として設計されています。指定されたレポートテンプレートを使用してOpenXMLを使用してWord文書としてレポートを生成したいと思います。私はそのようなフォームを設計しました、

  • すべてのフィールドは、今のところテキストとしてInfopathフォームに配置されています。

  • ボタン制御を追加しました。

  • ボタン]クリックで、XpathNavigatorオブジェクトを使用してフィールドの値を取得しています。
  • 今、私は値を持つ文字列変数のセットを持っています。
  • コンテンツコントロールを備えた.DOTXファイルを準備しました。 (各コントロールにIDを与える必要がありますか?)

ただし、C#を使用して、変数値をWord Templateコンテンツにプログラムでマップする方法を理解できません。 ここに] [1] Webを使用したOpenXMLの素晴らしい例。ただし、XMLファイルからWordテンプレートへのデータをダンプするために使用するカスタムXMLパーツを使用しています。

文字列変数をテンプレートコンテンツコントロールとマッピングするために何をしなければなりませんか?これに対する参照リンクはありますか?

役に立ちましたか?

解決

私は非常によく似たものを痛む必要があり、最終的には単語フィールドの代わりにカスタム「プレースホルダー」フィールドを使用することになりました(ヘッダー、フッター、ボディなど、さまざまなオブジェクトを使用してさまざまな制限があります)。

私の言葉のテンプレートでは、このようなプレースホルダーをマークしました - ## myplaceholdername!#。次に、単語テンプレートのテキストを解析して、Regexを使用してすべてのプレースホルダーを見つけ、InfoPathフォームの実際の値に置き換えました。

このソリューションの唯一の欠点は、プレースホルダーとインフォパスフィールドが同じ名前を持つ必要があることです。そうしないと、一致することはできません。

この方法を考慮してください:

private void FillDocument(Stream documentStream, string xmlFields)
{
    var doc = new XmlDocument();
    doc.LoadXml(xmlFields);

    var props = doc.SelectSingleNode("properties");
    if (props == null) throw new Exception("No properties found.");

    //transform the xml properties to dictionary for easier replacement
    var fields = props.ChildNodes.Cast<XmlNode>().ToDictionary
        (node => string.Format("##{0}!#", node.Name), node => node.InnerText);


    using (var document = WordprocessingDocument.Open(documentStream, true))
    {
        var main = document.MainDocumentPart;

        //replace the fields in the main document
        main.Document.InnerXml = ReplaceFields(main.Document.InnerXml, fields);

        //replace the fields in the headers
        foreach (var headerPart in main.HeaderParts)
            headerPart.Header.InnerXml = ReplaceFields(headerPart.Header.InnerXml, fields);

        //replace the fields in the footers
        foreach (var footerPart in main.FooterParts)
            footerPart.Footer.InnerXml = ReplaceFields(footerPart.Footer.InnerXml, fields);

        main.Document.Save();
    }
}

private string ReplaceFields(string xmlPart, Dictionary<string, string> fields)
{
    //searches the xml for the declared fields
    var fieldRegex = new Regex("##[^#]*!#");
    var matches = fieldRegex.Matches(xmlPart);

    foreach (Match match in matches)
    {
        //the fields are within tags (InnerText) so remove all other xml stuff
        var innerRegex = new Regex("<[^>]*>");
        string fieldName = innerRegex.Replace(match.Groups[0].Value, "");

        //replace the actual value of the field
        if(fields.ContainsKey(fieldName))
            xmlPart = xmlPart.Replace(match.Groups[0].Value, fields[fieldName]);
    }

    return xmlPart;
}

次のように使用します:

//open the file from as stream (in this example, the file is opened from SP
using (var stream = templateFile.OpenBinaryStream())
{
    //iterate the properties you need and add them in this format 
    var xmlProperties = "<properties><MyPlaceHolderName>MyPlaceHolderValue</MyPlaceHolderName></properties>";

    //fill out the fields
    FillDocument(stream, xmlProperties);
}

私はXML複製とXMLPropertiesが比較的クレイジーであることを知っていますが、私の要件のためにこのように実装する必要がありました(方法はInfopathからのWebサービスによって呼び出されます)。さらに支援が必要な場合はお知らせください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top