カーソルを任意の位置に置く(Word)

f:id:akashi_keirin:20180610173412j:plain

カーソルを任意の位置に置く

たぶんWord2010のバグだと思うのだけれど、均等割付を施したところに差込フィールドがあると、差し込まれた後に字幅がおかしくなる。

職場のPCでしか遭遇しない症状なので、画像でお見せできないんだけれど、データが差し込まれた瞬間、字幅が異様に縮まってそのままになってしまう。

特に困るのは、

akashi-keirin.hatenablog.com

これを使ってレコードごとにドキュメントを作成したとき。

差し込むデータの文字数によって、字幅が広がったり狭まったりして、ガタガタになってしまう。

できあがったものを開いて、均等割付部分にカーソルを当てると元に戻るのだが、いちいち開いてはクリック、とかやっていたのでは、何のために自動化したのか分からない。

そこで、作成する文書に応じてRangeプロパティを使って

targetDocument.Range(1,1).Select

みたいなのを書いていた。

ところが、均等割付を施す場所なんて文書によってまちまちだから、テンプレートになる文書の均等割付の場所に応じてその都度指定するRangeプロパティの引数を調整する、という実にアホなことになっている。

Selection.GoToメソッド

「○ページ目の○行目の○文字目にカーソルを置く」ようなメソッドを作れば、少しは指定しやすくなると思って調べてみると、Selection.GoToメソッドというものを見つけた。

例によってMSDNのSelection.GoToメソッドのページによると、

指定した項目の直前の文字位置にカーソルを移動します。

という実に素っ気ない記述。引数が4種類あるけれど、それらは、

パラメータ
What

省略可能です。オブジェクト型 (Object) の値を指定します。選択範囲の移動先の項目の種類を指定します。使用できる定数は、WdGoToItem 列挙型の定数のいずれかです。

Which

省略可能です。オブジェクト型 (Object) の値を指定します。選択範囲の移動先を指定します。使用できる定数は、WdGoToDirection 列挙型の定数のいずれかです。

Count

省略可能です。オブジェクト型 (Object) の値を指定します。文書内の項目の番号を指定します。既定値は 1 です。

正の値のみ有効です。指定範囲または選択範囲より前にある項目を指定するには、引数 Which として wdGoToPrevious を使用し、Count の値を指定します。

Name

省略可能です。オブジェクト型 (Object) の値を指定します。引数 What に wdGoToBookmark、wdGoToComment、wdGoToField、wdGoToObject のいずれかを指定した場合、この引数は名前を指定します。

とのこと。

ちなみに、WdGoToItem列挙体については、同じくMSDNのWdGoToItem列挙体のページを、WdGoToDirection列挙体については、MSDNのWdGoToDirection列挙体のページをご覧ください。

○ページ○行目○文字目にカーソルを置くFunction

とりあえず、次のようなFunctionを作ってみた。

リスト1 標準モジュール
Public Function setCursor(ByVal targetPage As Long, _
                          ByVal targetLine As Long, _
                          ByVal targetCharacter As Long) As Boolean    '……(1)'
  If targetPage <= 0 Then GoTo Finalizer
  If targetLine <= 0 Then GoTo Finalizer
  If targetCharacter <= 0 Then GoTo Finalizer
On Error GoTo Finalizer
  Call Selection.GoTo(What:=wdGoToPage, _
                      Which:=wdGoToAbsolute, _
                      Count:=targetPage)    '……(2)'
  If targetLine = 1 Then    '……(3)'
  Else
    Call Selection.GoTo(What:=wdGoToLine, _
                        Which:=wdGoToRelative, _
                        Count:=targetLine - 1)
  End If
  Call Selection.MoveRight(Unit:=wdCharacter, _
                           Count:=targetCharacter - 1, _
                           Extend:=wdMove)    '……(4)'
  setCursor = True
  Exit Function
Finalizer:
  setCursor = False
End Function

まず、(1)の

Public Function setCursor(ByVal targetPage As Long, _
                          ByVal targetLine As Long, _
                          ByVal targetCharacter As Long) As Boolean

で引数と返り値の設定。

第1引数targetPageでページ数、

第2引数targetLineで何行目か、

第3引数targetCharacterで何文字目かを渡す。

返り値はBoolean型。成功したらTrue、失敗したらFalseを返す。

(2)の

Call Selection.GoTo(What:=wdGoToPage, _
                    Which:=wdGoToAbsolute, _
                    Count:=targetPage)

では、Selection.GoToメソッドを用いてまずはページ移動。

引数WhatwdGoToPageを指定しているのでページ単位の移動、引数WhichwdGoToAbsoluteを指定しているので、文書全体の引数Countページ目に移動することになる(と思う)。

次は行移動。

(3)の

If targetLine = 1 Then
Else
  Call Selection.GoTo(What:=wdGoToLine, _
                      Which:=wdGoToRelative, _
                      Count:=targetLine - 1)
End If

では、同じようにSelection.GoToメソッドを用いているが、今度はIfを用いている。

実は、にもあるように、Countの既定値が1で、ここが0になると、1と見なされるっぽいのだ。

従って、引数targetLine1(つまり○ページ目の1行目というとき)は、何もしない、ということになる。何もしない、ということを明示するためにあえてこのような書き方にした次第。

(2)実行直後にカーソルは引数targetPage目の先頭にあるので、引数WhichwdGoToRelativeにした。

このとき、Count1だと2行目先頭にカーソルが移動するようなので、targetLine - 1としている。

あとは(4)の

Call Selection.MoveRight(Unit:=wdCharacter, _
                         Count:=targetCharacter - 1, _
                         Extend:=wdMove)

Selection.MoveRightメソッドでtargetCharacter字目にカーソルを移動する。

Selection.MoveRightメソッドについては、MSDNのSelection.MoveRightメソッドのページをどうぞ。

おわりに

実は、未だにWordのSelectionというオブジェクトがよく分かっていない。っていうか、Wordのオブジェクトモデルそのものがよく分かっていない。きちんと勉強したいのだけれど、現状本業の勉強が忙しくて、Wordのオブジェクトモデルの勉強に手が回っていない。

もどかしいなあ。

コチラもどうぞ

akashi-keirin.hatenablog.com