Selection.Collapseメソッドの挙動に注意(Word)
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が実行中で、しかもすっげーメモリを食っている
- タスクを終了させる
- 再度ドキュメントを開こうと試みる
- 「セーフモード」起動を促されるが、拒否して普通に開く
- 開くには開くが、クラスモジュールとか標準モジュールが消え去っている
長くなってしまったが、ざっとこれぐらいのわけのわからないことが起こった。
おわりに
気をつけましょう。