カーソルが段落の先頭にあると正しい段落インデックスが取得できない(Word)

カーソルが段落の先頭にあると正しい段落インデックスが取得できない

[Range].Startプロパティと[Range].[Paragraphs].Countプロパティを用いる方法

Rangeオブジェクトの終端がある段落インデックスを取得する方法は、かつて

akashi-keirin.hatenablog.com

で紹介したことがある。

簡単に言うと、

RangeオブジェクトのStartプロパティを強引に「0」にすることにより、Rangeオブジェクトの始端をドキュメントの先頭にしてRangeオブジェクトを拡張。その中のParagraphsコレクションの数(Countプロパティで取得可能)を勘定する

というやり方である。

当時は、脳天気に「最初にこのアイディアを考えついたやつは天才だと思う。」などと喜んでいたものだ。

落とし穴があった!

ところが、「上手の手から水が漏る」のことば通り、先の方法には落とし穴があったのである!

落とし穴をお目にかけよう。

f:id:akashi_keirin:20220219091242p:plain

この通り、どう見てもカーソルは第4段落の先頭にある。したがって、Selection.Rangeが返すRangeオブジェクトは、第4段落の先頭を指し示すのである。

しかし!

リスト1
Public Function GetParagraphIndex( _
            ByVal a_Target As Range) As Long
  Dim ret As Long
  a_Target.Start = 0
  ret = a_Target.Paragraphs.Count
  GetParagraphIndex = ret
End Function

このGetParagraphIndexメソッドに、Selection.Rangeを渡して実行すると、

f:id:akashi_keirin:20220219091246p:plain

この通り、「3」が返る〔*〕のである!

これでは全然だめである!

GetParagraphIndexメソッドは、Normal.dotmプロジェクトの標準モジュールParagraphUtilに書いてあるので、このような呼び出し方になっている。

検証:なんでこうなるのか

先のリスト1に、次の1行を付け加える。

スト2
Public Function GetParagraphIndex( _
            ByVal a_Target As Range) As Long
  Dim ret As Long
  a_Target.Start = 0
  Call a_Target.Select '……(*)'
  ret = a_Target.Paragraphs.Count
  GetParagraphIndex = ret
End Function

a_TargetStartプロパティを「0」にした直後、つまりa_Targetの始端をドキュメントの先頭まで拡張した直後に、Selectメソッドを実行して止めてみる。

f:id:akashi_keirin:20220219091249p:plain

確かに、第3段落目までしか選択されていない。

道理で「3」が返るわけである。

検証終わり。

おわりに

というわけで、カーソルが段落の先頭にある場合にも正しい段落インデックスを返すように、改修する必要があります。

いちおう、改修自体はしているのですが、なんとも不細工なやり方で、もっとスマートな方法はないものか、と思っています。

〈カーソルが段落先頭にあることを判定するスマートな方法〉を知っていたら教えろえてください。