このコードでは:
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を使用してマシンでテストしましたが、機能しているようです。