カーソルを任意の場所に置くFunctionの改良(Word)
似たような書類を、宛先別に大量生産するような場合に、差込印刷機能を使う場面は多いと思う。
で、差込印刷の差込レコードごとにWordドキュメントが生成されると便利(というか後々扱いやすい)なので、
こんな感じでWordドキュメントを大量生産することが多い。
摩訶不思議な不具合
差し込むデータは、相手先の名前だったり、日付だったりするのだが、場合によっては、字幅を揃えたいことがある。
そんなときに、差し込みフィールドの部分に均等割付を施す。
しかし、たまに困ったことが起こる。
データが差し込まれた瞬間とか、出来上がったWordドキュメントを開き直したときに、均等割付がめちゃくちゃになってしまうのである。
これは、職場のPCでしか今のところ起こらないので、そのものずばりをお見せできないのだけれど、擬似的に再現すると、

こんなふうにキッチリ揃えたはずなのに、

ドキュメントを開き直したら、こんなふうにガタガタになる、というイメージ。
で、これまたお見せできないのだけれど、それぞれの均等割付がなされている部分をクリックしてやると、だいたい元に戻る。なのに、その状態で上書き保存しても、開き直すとまたガタガタ……。
職場のPCでしか起きないので、Word2010のバグか何かだと思っていたのだけれど、職場のPCが2016になってからも引き続き起こる。家の2013ではまるで再現できないのに。
これの何が困るって、
自動印刷ができない
こと。
せっかく書類の量産を自動化しても、印刷したり、PDF化したりする作業が全部手作業だというのでは、非効率もはなはだしい。
そういうわけで、作ったのが
このFunctionなのであった。
Functionの改良
Excelからでも使えるように改良してみた。
リスト1 標準モジュール
Public Function setCursor(ByVal targetDoc As Document, _
ByVal targetPage As Long, _
ByVal targetLine As Long, _
ByVal targetCharacter As Long, _
Optional ByVal isToClick As Boolean = True) As Boolean
setCursor = False
On Error GoTo Finalizer
Dim wordApp As Word.Application
Set wordApp = targetDoc.Parent
Call wordApp.Selection.GoTo(What:=wdGoToPage, _
Which:=wdGoToAbsolute, _
Count:=targetPage)
If targetLine = 1 Then
'targetLineが「1」のときは移動しない。'
Else
Call wordApp.Selection.GoTo(What:=wdGoToLine, _
Which:=wdGoToRelative, _
Count:=targetLine - 1)
End If
Call wordApp.Selection.MoveRight(Unit:=wdCharacter, _
Count:=targetCharacter, _
Extend:=wdMove)
If isToClick Then Selection.Select '……(*)'
setCursor = True
Finalizer:
Set wordApp = Nothing
End Function
Selectionオブジェクトは、Word.Applicationの配下にあるので、Excelなど他アプリから操作するときは、Word.Applicationオブジェクトから指定しないと使えない。
Officeデベロッパー センターの記述によると、
ドキュメント ウィンドウ枠ごとに Selection オブジェクトは 1 つだけであり、アプリケーション全体で 1 つの Selection オブジェクトのみをアクティブにできます。 https://docs.microsoft.com/ja-jp/office/vba/api/word.selection
とのことなので、Word.Applicationオブジェクトは、対象のDocumentオブジェクトのParentプロパティから取得するのが良いと思った。
ちなみに、(*)の
If isToClick Then Selection.Select
は、カーソル位置を移動した後、その部分をクリックする動作を再現したつもり。
これでいいのかどうか、こんなのが必要なのかどうか、は不明。
使ってみる
次のコードで実験。
リスト2 標準モジュール
Public Sub test02()
Dim wordApp As New Word.Application
wordApp.Visible = True
Dim targetDoc As Word.Document
Set targetDoc = wordApp.Documents.Open(ThisWorkbook.Path & "\ち~んw.docx")
Dim i As Long
For i = 1 To 5
Call setCursor(targetDoc, 1, i, 2, True)
Call WindowsAPI.waitFor(500)
Next
Call targetDoc.Close(SaveChanges:=False)
Call wordApp.Quit
Set wordApp = Nothing
End Sub
Excelから、同じフォルダ内にある「ち~んw.docx」というドキュメントを開いて、そのドキュメントの1ページ目にある1行目~5行目までの文字列の2文字目のところをそれぞれクリック(っていうか選択)する、というもの。
一瞬で終わってしまうと何をやっているのかわからないので、1行ごとに0.5秒ウェイトするようにしている。
WindowsAPIクラスについては、
コチラをどうぞ。

ちょいわかりにくいけど、こんな動作。
おわりに
こちらの情報によると、均等割付を字数単位で指定しているのが原因なのかも知れない。
一度、職場のPCでmm単位で指定して実験してみようと思う。