2017年12月6日水曜日

ワードマクロ、クリップボードのデータの取得


仕事中に文書の整形がしたくなって、ワードのマクロを調べてみたのでその備忘録
やりたかったのは、特定の文字列を一気に削除すること
文字列をコピーして、置換のダイアログでターゲットにペーストして、一気に置換を実行するだけなんだけど、この作業を簡素化したかった

マクロを記録すれば自動でコードは書いてくれる、しかしコードを見たらターゲットの文字列は記録したときのものに固定されてしまっていた
そこでこの文字列を都度クリップボードから取得するようにしたくてちょっと調べてみたら、方法は2種類あった

① DataObjectを使用

Dim buf2 As String, CB As New DataObject
With CB
    .GetFromClipboard   ''クリップボードからDataObjectにデータを取得する
    buf2 = .GetText     ''DataObjectのデータを変数に取得する
End With
' MsgBox buf2

結構簡単、DataObjectってのを使うだけ
ただ私のワード環境ではこれがエラーになってしまい、DataObjectを使用するためには Microsoft Forms 2.0 Object Libralyを標準モジュールに追加しなくてはいけないことがわかった
VisualBasic を開いて「ツール」「参照設定」
しかしこれでも見つからず、そういう場合は直接これを参照すれば良い
system32\\FM20.dll

② win32apiを直接使う

VisualBasic を開いて左のツリーから「標準モジュール」を右クリ →「挿入」→「標準モジュール」として以下をコピペ

Declare Function OpenClipboard Lib "User32" (ByVal hwnd As Long) _  As Long
Declare Function CloseClipboard Lib "User32" () As Long
Declare Function GetClipboardData Lib "User32" (ByVal wFormat As _ Long) As Long
Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags&, ByVal _ dwBytes As Long) As Long
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) _  As Long
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) _  As Long
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) _  As Long
Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _   ByVal lpString2 As Any) As Long

Public Const GHND = &H42
Public Const CF_TEXT = 1
Public Const MAXSIZE = 4096

Function ClipBoard_GetData()
   Dim hClipMemory As Long
   Dim lpClipMemory As Long
   Dim MyString As String
   Dim RetVal As Long

   If OpenClipboard(0&) = 0 Then
      MsgBox "Cannot open Clipboard. Another app. may have it open"
      Exit Function
   End If

   ' Obtain the handle to the global memory
   ' block that is referencing the text.
   hClipMemory = GetClipboardData(CF_TEXT)
   If IsNull(hClipMemory) Then
      MsgBox "Could not allocate memory"
      GoTo OutOfHere
   End If

   ' Lock Clipboard memory so we can reference
   ' the actual data string.
   lpClipMemory = GlobalLock(hClipMemory)

   If Not IsNull(lpClipMemory) Then
      MyString = Space$(MAXSIZE)
      RetVal = lstrcpy(MyString, lpClipMemory)
      RetVal = GlobalUnlock(hClipMemory)

      ' Peel off the null terminating character.
      MyString = Mid(MyString, 1, InStr(1, MyString, Chr$(0), 0) - 1)
   Else
      MsgBox "Could not lock memory to copy string from."
   End If

OutOfHere:

   RetVal = CloseClipboard()
   ClipBoard_GetData = MyString

End Function

あとは自分のマクロで ClipBoard_GetData() を実行すれば文字列が帰ってくる

③ 考察
DataObjectってのは多分VBのwin32ラッパーです
それよりも②の書き方が参考になります
これでwin32のapiが自由に使えるって事だと思う
使いたい関数を冒頭でDeclare Functionするだけなんだね
これを標準モジュールの中で書いておくってあたりは良く仕組みがわかんないけど、応用が利きそうでうれしい
ワードマクロについてはエクセルとほとんど変わりませんな
いずれもVBだから当たり前なのか?

0 件のコメント:

コメントを投稿