0

テンプレートとして機能する Word 文書の特定の場所を置き換えようとしています。これらの場所は、 で始まる単語としてマークされています@。たとえば@Name。すべてのテキストを選択し、関数でそれらを実行して置き換えます。その背後にあるすべてのロジックは正常に機能しています。ただし、理由は不明ですが、テキストは次のように単純に定義されています。

List<Text> texts = w.MainDocumentPart.Document.Descendants<Text>().ToList();

私が期待する方法ではありません。例 (各行に 1 つのテキストがあるテキストの短いリスト):

Document date: 
@
date
, written by: 
@Name 
@
Surname

このように1行にあるはずですが: Document date: @date, written by: @Name @Surname. ご覧のとおり、@およびdateOR@およびSurnameのような場合、代わりのメソッドを適切に使用することができませ@date@Surname。だから私は自分のコードを改善しましたが、今ではその中に多くの欠陥があることがわかりました@。残念ながら、私はテーブル内の 1 つのテキストにたどり着き、それによってすべてのアルゴリズムが完全に停止してしまいました。次のようでした。

(@
sum_
words)

さまざまなスタイルで特別にフォーマットしたわけではありませんが。ご覧のとおり、 である必要が(@sum_words)あり、この場合、私のアルゴリズムは簡単に置き換えられます。残念ながら、私にはできません。したがって、私の質問は次のようになります。

  1. 単語の部分をまったく変えていないのに、部分に分かれているのはなぜですか?
  2. これを解決する方法はありますか?

アップデート

これまでにできた最高のことは次のとおりです。

for (int i = texts.Count - 1; i > 0; i--)
{
    if (texts[i - 1].Text.EndsWith("@") || texts[i - 1].Text.EndsWith("_"))
    {
        texts[i - 1].Text = texts[i - 1].Text + texts[i].Text;
        texts[i].Text = "";
    }
}

テキストが途中で分割された場合にテキストを接続します(私が見たところ、私のニーズに固有の文字でのみ分割されます@および_。最初のテキストのプロパティを保存する方が理にかなっているため、ループは逆になります最後の部分ではなく、グループの一部 (たとえば、要素の前のスペースを保持します)。

更新 2

要求されたテーブル セルは次のとおりです。

<w:tc>
    <w:tcPr>
        <w:tcW w:w="2410" w:type="dxa"/>
        <w:tcBorders>
            <w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>
            <w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/>
            <w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>
            <w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>
        </w:tcBorders>
        <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
    </w:tcPr>
    <w:p w:rsidR="009D473B" w:rsidRDefault="00385754" w:rsidP="00385754">
        <w:pPr>
            <w:jc w:val="center"/>
            <w:rPr>
                <w:lang w:val="lt-LT"/>
            </w:rPr>
        </w:pPr>
        <w:r>
            <w:rPr>
                <w:lang w:val="lt-LT"/>
            </w:rPr>
            <w:t>@sum</w:t>
        </w:r>
        <w:r w:rsidR="009D473B">
            <w:rPr>
                <w:lang w:val="lt-LT"/>
            </w:rPr>
            <w:t xml:space="preserve">(@</w:t>
        </w:r>
        <w:r>
            <w:rPr>
                <w:lang w:val="lt-LT"/>
            </w:rPr>
            <w:t>sum_</w:t>
        </w:r>
        <w:r w:rsidR="009D473B">
            <w:rPr>
                <w:lang w:val="lt-LT"/>
            </w:rPr>
            <w:t>words)</w:t>
        </w:r>
    </w:p>
</w:tc>
4

1 に答える 1

1

テンプレートの編集中に Word で文法エラーの完全なチェックとマークを無効にすることで解決される、変数名を壊す特別なタグを挿入する傾向があるスペルと文法モジュールが原因で、WordML ドキュメントの変数の置換を行っていた唯一の問題。

私の置換方法は次のようなものです(変数の命名規則は少し異なります。これはあなたのものに追加されています):

public static void Assign(XElement xe, string name, string value)
{
    XElement el = xe.Descendants()
        .FirstOrDefault(e => e.Name.LocalName == "t" && e.Value.Contains("(@" + name + ")"));
    if (el != null)
    {
        el.Value = el.Value.Replace("(@" + name + ")", value);
    }
    else
    {
        AssignFallback(xe, name, value);
    }   
}

編集2

上記が機能しない場合(el == nullの場合)に備えて、変数を置き換えるフォールバック方法を上記に書きました。パラグラフ w:p には複数の実行を含めることができ、変数名は連続した一連の実行に分割される可能性があります。したがって、それらを特定し、最初の値のみを置き換えて、残りを削除したいと考えています。変数名の前後に表示される可能性のあるテキストを保持するように注意する必要があります (プレフィックスは最初の実行にあり、サフィックスは最後の実行にあります)。

public static void AssignFallback(XElement xe, string name, string value)
{
    string varName = "(@" + name + ")";
    XElement xep = xe.Descendants()
            .FirstOrDefault(x => x.Name.LocalName == "p" && x.Value.Contains(varName));
    if (xep == null)
    {
        return;
    }
    string prefix = "", sufix = "";
    List<XElement> truns = new List<XElement>();
    List<XElement> allruns = xep.Descendants().Where(x => x.Name.LocalName == "r").ToList();
    for (int i = 0; i < allruns.Count; i++)
    {
        if (!allruns[i].Value.Contains("(@"))
        {
            continue;
        }
        int index = allruns[i].Value.IndexOf("(@");
        prefix = allruns[i].Value.Substring(0, index);
        truns.Clear();
        truns.Add(allruns[i]);
        string nameTemp = allruns[i].Value.Substring(index, allruns[i].Value.Length - index);
        if (!varName.StartsWith(nameTemp))
        {
            continue;
        }
        for (int j = i + 1; j < allruns.Count; j++)
        {
            nameTemp += allruns[j].Value;
            truns.Add(allruns[j]);
            if (nameTemp.StartsWith(varName))
            {
                sufix = nameTemp.Substring(varName.Length);
                break;
            }
            else if (nameTemp.Length > varName.Length)
            {
                break;
            }
        }
        if (nameTemp.StartsWith(varName))
        {
            XElement xet = truns[0].Descendants().FirstOrDefault(x => x.Name.LocalName == "t");
            xet.Value = prefix + value + sufix;
            for (int j = 1; j < truns.Count; j++)
            {
                truns[j].Remove();
            }
        }
    }
}
于 2013-06-27T06:59:40.780 に答える