2

リストの前にテキストを挿入しようとしています。私はリストのを持っておりMicrosoft.Office.Interop.Word.Range、リストの前に前の範囲を取得します。次に、段落テキストを前の範囲に追加しようとしましたが、段落はリストの前ではなく、リストの最初の項目として追加されます。

// rangeObj is the Range object for the list
var previousRange = rangeObj.Previous(MSWord.WdUnits.wdCharacter, 1);

Paragraph paragraph;
if (previousRange == null)
{
  var rangeCopy = rangeObj.Duplicate;
  rangeCopy.InsertParagraphBefore();
  paragraph = rangeCopy.Paragraphs[1];
}
else 
{
  paragraph = previousRange.Paragraphs[1];  
}

Range range = paragraph.Range;
range.Text = String.Format("{0} {1}", "My list", range.Text);

例:前:

  1. アイテム1
  2. アイテム2

後(私が欲しいもの):

私のリスト

  1. アイテム1
  2. アイテム2

後(私が現在得ているもの):

  1. 私のリスト
  2. アイテム1
  3. アイテム2

編集: ラッセの答えと私のコメントによると、次のエッジケースを除いてすべてが機能するようになっています。注:2番目のリストは最初のリストのサブリストではなく、各リストの間に空の行はありません。

if (previousRange.ListParagraphs.Count > 0)

前:

  1. アイテム1
  2. アイテム2

    1. アイテム3
    2. アイテム4

後(私が欲しいもの):

  1. アイテム1
  2. アイテム2

    別のリスト:

    1. アイテム3
    2. アイテム4
4

1 に答える 1

1

このコードでは:

else 
{
  paragraph = previousRange.Paragraphs[1];  
}

..リストの前にあるもの(リストにのみ含まれる空の行を含む\r)を上書きするリスクがあります。サンプルで実行すると、上書きされて最終的に奇妙に発生することは理にかなっています。

このコードでは:

if (previousRange == null)
{
  var rangeCopy = rangeObj.Duplicate;
  rangeCopy.InsertParagraphBefore();
  paragraph = rangeCopy.Paragraphs[1];
}

..リストの前に新しい段落を挿入し(これは問題ありませんが、範囲が自動的に拡張されて新しく挿入された段落が含まれるため、範囲を複製する必要がある理由がわかりません)、次に範囲を格納しますローカル変数の新しい段落paragraph。この時点で、paragraph = '\r'-の内容(これは、デバッグフェーズ中に単語を表示したまま、デバッガーを使用してアプリケーションをステップ実行した場合に表示されます)。したがって、この時点で、カーソルはリストの直前に配置されます。これは、リストを配置したい場所です。ただし、次のようにします。

Range range = paragraph.Range;
range.Text = "My paragraph";

...つまり、段落の前に\rテキストを追加する代わりに、を含むすべてを上書きするだけです。これにより、Wordはテキストをリストの前ではなくリストに挿入します。

これを回避するために、私はうまくいくように見える代替の実装を作成しました。これは、リストの前の範囲を使用してテキストを挿入するというあなたの考えに基づいています。ほとんどの行にコメントを追加したので、何が起こっているのかを簡単に理解できるはずです:)

using System;
using System.Linq;
using Microsoft.Office.Interop.Word;
using Application = Microsoft.Office.Interop.Word.Application;

namespace WordDocStats
{
    internal class Program
    {
        private static void Main()
        {
            var wordApplication = new Application() { Visible = true };

            // Open document A
            var documentA = wordApplication.Documents.Open(@"C:\Users\MyUser\Documents\documentA.docx", Visible: true);

            // This inserts text in front of each list found in the document
            const string myText = "My Text Before The List";
            foreach (List list in documentA.Lists)
            {
                // Range of the current list
                var listRange = list.Range;

                // Range of character before the list
                var prevRange = listRange.Previous(WdUnits.wdCharacter);

                // If null, the list might be located in the very beginning of the doc
                if (prevRange == null)
                {
                    // Insert new paragraph
                    listRange.InsertParagraphBefore();
                    // Insert the text
                    listRange.InsertBefore(myText);
                }
                else
                {
                    if (prevRange.Text.Any())
                    {
                        // Dont't append the list text to any lines that might already be just before the list
                        // Instead, make sure the text gets its own line
                        prevRange.InsertBefore("\r\n" + myText);
                    }
                    else
                    {
                        // Insert the list text
                        prevRange.InsertBefore(myText);
                    }
                }
            }

            // Save, quit, dones
            Console.WriteLine("Dones");
            Console.ReadLine();
            documentA.Save();
            wordApplication.Quit();
        }
    }
}

つまり、コードは、指定されたドキュメントの各リストの前に文字列を挿入します。リストの前の行にすでにテキストがある場合、実装では、リストの前と、リストの前の行にすでにあるテキストの後に、リストの説明テキストを必ず挿入します。

お役に立てれば :)

---編集された質問に答えるための更新:

ここで第2ラウンドで求めていることを達成する方法は、次のようなことです。

...
// The paragraph before the current list is also a list -> so in order to insert text, we must do "some magic"
else if(prevRange.ListParagraphs.Count > 0)
{
    // First, insert a new line -> this causes a new item to be inserted into the above list
    prevRange.InsertAfter("\r");

    // Modify current range to be on the line of the new list item
    prevRange.Start = prevRange.Start + 1;
    prevRange.End = prevRange.Start;

    // Convert the list item line into a paragraph by removing its numbers
    prevRange.ListFormat.RemoveNumbers();

    // Insert the text
    prevRange.InsertBefore(myText);
}
...

if-else上記で提供したサンプルコードのループ内のブロックにそのコードを追加するだけforeachで、準備が整います:) MS Word 2013を使用してマシンでテストしましたが、機能しているようです。

于 2012-11-10T11:24:29.340 に答える