Selection.Collapseメソッドの挙動に注意
前回
紹介した、次のハイライト箇所を取得するgetNextHighLightメソッド。
検索箇所を取得した後、Selection.Collapseメソッドを用いて、選択箇所を後方に向けて潰すようにしている。
こうしないと、同じところを取得し続けてしまうからだ。
しかし、カーソルの位置によっては、Selection.Collapseメソッドはちょっと困った動きをする。
カーソルが最後尾にあるとき
たとえば、

こんなふうに、テキストボックスに「ダボ」というテキストが入力されていて、全体がハイライトされているとする。
このとき、テキストボックスの先頭にカーソルを置いて、次のコードを実行してみる。
リスト1
Private Sub test02() Dim tmp As Range Set tmp = getNextHighLight(Selection.Range) Debug.Print tmp.Text End Sub
当然、結果は、

こうなって、カーソル位置は

こうなる。
問題はこの次。
カーソルは、テキストボックスの末尾にある。
この状態で、
Call Selection.Find.Execute
を実行するとどうなるか。

なんと、こうなるのである。
で、この状態で、
Call Selection.Collapse(wdCollapseEnd)
を実行するとどうなるのか。
悲しいことに、

こうなってしまうのである。
最末尾であるがゆえに、引数にwdCollapseStartを指定したのと同じ結果になってしまうのである。
これは実にまずい。
なぜなら、この状態で再び
Call Selection.Find.Execute
を実行すると、

またしてもこうなってしまうからである。
つまり、たとえば
リスト2
Private Sub test03()
Dim tmp As Range
Do
Set tmp = getNextHighLight(Selection.Range)
If tmp Is Nothing Then Exit Do
Call someCollection.Add(tmp)
Loop
End Sub
このようなコードで、終了判定にgetNextHighLightがNothingを返すかどうかを用いてDo ~ Loopを使おうとすると、無限ループになってしまうのだ。
しかも、恐ろしいことに、この形で無限ループになってしまった場合、派手にWordがクラッシュしてしまう。(←経験者。)
どういう理屈でそうなるのかはわからないが、たとえば私が経験したパターンだと、
- 無限ループに陥る
- 「応答なし」になる
- 画面をクリックすると画面が白っぽくなる
- ウインドウの×をクリックするとWordが終了する
- 再び同じドキュメントを開こうとすると、「セーフモード」で起動することを勧められる
- 言われた通りにセーフモードで開くと、中身のないWordだけが開く
- 仕方がないのでWordを終了する
- もう一度ドキュメントを開こうと試みる
- 別のユーザが開いているので開けない旨通知がある
- タスク マネージャーを開くと、確かにMicrosoft Wordが実行中で、しかもすっげーメモリを食っている
- タスクを終了させる
- 再度ドキュメントを開こうと試みる
- 「セーフモード」起動を促されるが、拒否して普通に開く
- 開くには開くが、クラスモジュールとか標準モジュールが消え去っている
長くなってしまったが、ざっとこれぐらいのわけのわからないことが起こった。
おわりに
気をつけましょう。