2014/08/10 追記:
ちゃうちゃう!がバージョンアップされました。
・テキスト比較ソフト「ちゃうちゃう!」がバージョンアップされました。
//www.ka-net.org/blog/?p=4724
2つのテキストを比較し、その違いを検出するのに役立つツールとして「ちゃうちゃう!」があります。
ドキュメントを多く扱う編集者やライター、翻訳者といった方々には有名で、非常に便利なツールです。
今回はこの”ちゃうちゃう!“をVBAで無理やり制御して、
・指定した2つの文書を比較して、その結果をrtf形式で保存する
といった操作を自動化してみようと思います。
Option Explicit
Private Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As Long, ByVal dwId As Long, riid As Any, ByRef ppvObject As IAccessible) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hParent As Long, ByVal hChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, lpiid As Any) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const OBJID_CLIENT = &HFFFFFFFC
Private Const WM_COMMAND = &H111
Private Const WM_SETTEXT = &HC
Public Sub Sample()
Dim FilePath1 As String
Dim FilePath2 As String
FilePath1 = "C:\Test\File01.txt"
FilePath2 = "C:\Test\File02.txt"
CompareDocumentChawChaw FilePath1, FilePath2
FilePath1 = "C:\Test\File03.txt"
FilePath2 = "C:\Test\File04.txt"
CompareDocumentChawChaw FilePath1, FilePath2
MsgBox "処理が終了しました。", vbInformation + vbSystemModal
End Sub
Public Sub CompareDocumentChawChaw(ByVal FilePath1 As String, ByVal FilePath2 As String)
'ちゃうちゃう!で2つの文書を比較する
Dim TimeLimit As Date
Dim SaveFilePath1 As String
Dim SaveFilePath2 As String
Dim hApp As Long
Dim hBar As Long
Dim btnState As Long
Dim IID(0 To 3) As Long
Dim acc As Office.IAccessible
Const ChawChawExePath As String = "C:\Program Files\ChawChaw\ChawChaw.exe" '[ChawChaw.exe]のパス ※ 必要に応じて変更
With CreateObject("Scripting.FileSystemObject")
If .FileExists(ChawChawExePath) = False Then
MsgBox ChawChawExePath & " が見つかりません。" & vbCrLf & "処理を中止します。", vbExclamation + vbSystemModal
Exit Sub
End If
If .FileExists(FilePath1) = False Then
MsgBox FilePath1 & " が見つかりません。" & vbCrLf & "処理を中止します。", vbExclamation + vbSystemModal
Exit Sub
End If
If .FileExists(FilePath2) = False Then
MsgBox FilePath2 & " が見つかりません。" & vbCrLf & "処理を中止します。", vbExclamation + vbSystemModal
Exit Sub
End If
SaveFilePath1 = .GetFile(FilePath1).ParentFolder.Path
If Right$(SaveFilePath1, 1) <> "\" Then SaveFilePath1 = SaveFilePath1 & "\"
SaveFilePath1 = SaveFilePath1 & "[ChawChawed]" & Left$(.GetFile(FilePath1).Name, InStrRev(.GetFile(FilePath1).Name, ".")) & "rtf"
SaveFilePath2 = .GetFile(FilePath2).ParentFolder.Path
If Right$(SaveFilePath2, 1) <> "\" Then SaveFilePath2 = SaveFilePath2 & "\"
SaveFilePath2 = SaveFilePath2 & "[ChawChawed]" & Left$(.GetFile(FilePath2).Name, InStrRev(.GetFile(FilePath2).Name, ".")) & "rtf"
End With
'事前にファイル削除
If Len(Dir$(SaveFilePath1)) > 0 Then Kill SaveFilePath1
If Len(Dir$(SaveFilePath2)) > 0 Then Kill SaveFilePath2
Shell ChawChawExePath, vbNormalFocus 'ちゃうちゃう!起動
hApp = FindChawChawWindow()
If hApp = 0& Then
MsgBox "[ちゃうちゃう!]のウィンドウが見つかりませんでした。" & vbCrLf & "処理を中止します。", vbExclamation + vbSystemModal
Exit Sub
End If
SendMessage hApp, WM_COMMAND, &HFF01, 0& '左ウィンドウ選択
SendMessage hApp, WM_COMMAND, &HE121, 0& 'すべて消去
FileContentCopy FilePath1 '対象ファイルの内容をクリップボードにコピー
SendMessage hApp, WM_COMMAND, &HE125, 0& '文字列貼り付け
SendMessage hApp, WM_COMMAND, &HFF00, 0& '右ウィンドウ選択
SendMessage hApp, WM_COMMAND, &HE121, 0& 'すべて消去
FileContentCopy FilePath2 '対象ファイルの内容をクリップボードにコピー
SendMessage hApp, WM_COMMAND, &HE125, 0& '文字列貼り付け
'全文比較
'SendMessage hApp, WM_COMMAND, &H8015, 0&
hBar = FindWindowEx(hApp, 0&, vbNullString, "Tool Bar")
hBar = FindWindowEx(hBar, 0&, vbNullString, "Tool Bar")
Set acc = Nothing '初期化
If hBar <> 0& Then
IIDFromString StrPtr("{618736E0-3C3D-11CF-810C-00AA00389B71}"), IID(0)
AccessibleObjectFromWindow hBar, OBJID_CLIENT, IID(0), acc
End If
If acc Is Nothing Then
MsgBox "処理が失敗しました。", vbExclamation + vbSystemModal
Exit Sub
End If
acc.accDoDefaultAction &H10&
Sleep 200&
OperateSeparatorDialog '不適切な区切り文字ダイアログ制御
'比較処理待ち
TimeLimit = DateAdd("n", 10, Now()) 'ループの制限時間:10分
Do
btnState = acc.accState(&H10&) '全文比較 (F5)ボタンの状態取得
If Now() > TimeLimit Then Exit Do '制限時間を過ぎたら脱ループ
Sleep 1000&
DoEvents
Loop While btnState <> 0&
Sleep 1000&
SendMessage hApp, WM_COMMAND, &HFF01, 0& '左ウィンドウ選択
'SendMessage hApp, WM_COMMAND, &HE104, 0& '名前を付けて保存
PostMessage hApp, WM_COMMAND, &HE104, 0& '名前を付けて保存
If OperateSaveAsDialog(SaveFilePath1) = 0& Then
MsgBox "ファイルの保存に失敗しました。" & vbCrLf & "処理を中止します。", vbExclamation + vbSystemModal
Exit Sub
End If
Sleep 2000& '保存処理待ち
SendMessage hApp, WM_COMMAND, &HFF00, 0& '右ウィンドウ選択
'SendMessage hApp, WM_COMMAND, &HE104, 0& '名前を付けて保存
PostMessage hApp, WM_COMMAND, &HE104, 0& '名前を付けて保存
If OperateSaveAsDialog(SaveFilePath2) = 0& Then
MsgBox "ファイルの保存に失敗しました。" & vbCrLf & "処理を中止します。", vbExclamation + vbSystemModal
Exit Sub
End If
Sleep 2000& '保存処理待ち
SendMessage hApp, WM_COMMAND, &HE141, 0& 'アプリケーションの終了
End Sub
Private Sub FileContentCopy(ByVal FilePath As String)
'文書ファイルを開いて内容をクリップボードにコピー
With Application.Documents.Open(FileName:=FilePath, ReadOnly:=True)
.Content.Copy
.Close wdDoNotSaveChanges
End With
End Sub
Private Sub OperateSeparatorDialog()
'不適切な区切り文字ダイアログ制御
Dim hDlg As Long
Dim hSta As Long
Dim hBtn As Long
Dim s As String
Dim buf As String * 255
hDlg = FindWindowEx(0&, 0&, "#32770", "ChawChaw")
'Debug.Print Hex(hDlg)
If hDlg = 0& Then Exit Sub
hSta = FindWindowEx(hDlg, 0&, "Static", vbNullString)
hSta = FindWindowEx(hDlg, hSta, "Static", vbNullString)
If hSta = 0& Then Exit Sub
GetWindowText hSta, buf, Len(buf)
s = Left$(buf, InStr(buf, vbNullChar) - 1&)
If InStr(s, "不適切な区切り文字が指定されているようです") Then
hBtn = FindWindowEx(hDlg, 0&, "Button", "はい(&Y)")
SendMessage hDlg, WM_COMMAND, &H6, hBtn 'はい(&Y)ボタンクリック
'hBtn = FindWindowEx(hDlg, 0&, "Button", "いいえ(&N)")
'SendMessage hDlg, WM_COMMAND, &H7, hBtn 'いいえ(&N)ボタンクリック
End If
End Sub
Private Function FindChawChawWindow() As Long
'ちゃうちゃう!のウィンドウハンドル取得
Dim TimeLimit As Date
Dim h As Long
h = 0& '初期化
TimeLimit = DateAdd("s", 2, Now()) 'ループの制限時間:2秒
Do
h = FindWindowEx(0&, 0&, vbNullString, "ちゃうちゃう!")
If Now() > TimeLimit Then Exit Do '制限時間を過ぎたら脱ループ
DoEvents
Loop While h = 0&
FindChawChawWindow = h
End Function
Private Function OperateSaveAsDialog(ByVal FilePath As String) As Long
'名前を付けて保存ダイアログ制御
Dim TimeLimit As Date
Dim hDlg As Long
Dim hBtn As Long
Dim ret As Long
ret = -1& '初期化
TimeLimit = DateAdd("s", 5, Now()) 'ループの制限時間:5秒
Do
hDlg = FindWindowEx(0&, 0&, "#32770", "Save As")
If Now() > TimeLimit Then Exit Do '制限時間を過ぎたら脱ループ
DoEvents
Loop While hDlg = 0&
If hDlg = 0& Then GoTo FncErr:
hBtn = FindWindowEx(hDlg, 0&, "Button", "保存(&S)")
If hBtn = 0& Then GoTo FncErr:
Sleep 500&
SendDlgItemMessage hDlg, &H47C, WM_SETTEXT, 0&, FilePath 'ファイルパスセット
'SendMessage hDlg, WM_COMMAND, &H1, hBtn '保存ボタンクリック
PostMessage hDlg, WM_COMMAND, &H1, hBtn '保存ボタンクリック
FncExit:
OperateSaveAsDialog = ret
Exit Function
FncErr:
ret = 0&
GoTo FncExit:
End Function
上記コードを動作させる条件として、事前に下記2点の作業を行っておく必要があります。
・事前にライセンス登録(無料)をし、起動時にダイアログが表示されないようにする。
・事前に”比較の設定”をしておく。
また、上記コードはあくまでも”無理やり“ちゃうちゃう!の操作を行っているもので、その動作の正確性は一切保証できませんので、予めご了承ください。
上記コードを実行すると、元のファイルと同じ場所に「[ChawChawed](元のファイル名).rtf」という形で比較結果が保存されます。
上記”Sample“のように複数のファイルの比較を連続して行う場合には、上記コードが有効に使えるかもしれません。
上記ではサンプルとしてテキストファイルを使用していますが、Wordで開ける文書であれば良いので、テキストファイルでなくても問題ありません。
実は上記コードは数年前に書いたものなのですが、今日ファイルの整理をしていたらたまたま出てきて、Windows 7で動かしてみたら問題無く動いたので、ほぼそのままブログに載せることにしました。
碌に修正や動作確認をしていませんので、結構穴があるだろうと思います。
一応コードを書いた環境であるWindows XP + Word 2003とWindows 7 + Word 2010での動作は確認しましたが、それ以外の環境では動作確認を行っていません。
また、64ビット環境ではテストしていませんので、64ビット版のWordや64ビット版のちゃうちゃう!でコードを実行する際には、必要に応じてコードを修正する必要があります。
■ 関連Webページ
・テキスト比較ソフト「ちゃうちゃう!」がバージョンアップされました。
//www.ka-net.org/blog/?p=4724
・2つの文書を比較するWordマクロ
//www.ka-net.org/blog/?p=4734
・ちゃうちゃう! 2.0を操作するWordマクロ
//www.ka-net.org/blog/?p=4931



















この記事へのコメントはありません。