インストールレスプログラミング( ´ー`)

VBA , JavaScript , HTAなど 365アプリはインストール必要ですが、仕事に無いケースはほぼないから(・_・;)

WordをExcel VBAから使う,まとめ。

今までこれがうまくできなかったのは,一連の作業に今一理解が及ばないからだったんですが,クラスやコレクションを使うようになって,似たようなものなので,以前よりはしっくりくるようになりました。

本当にWordの文書にExcelのデータを流し込むというのは,便利極まりなかったので,そこは記憶から消えないうちに再度きちんとまとめたいと思います。

まずは,自分のパソコンでしか使わないのであれば,参照設定は最強だと思われるので,参照設定を入れましょう。

データを流し込むという意味では,Excel上のVBAから他のアプリを操作するという設定で考えます。

f:id:chemiphys:20170211010934p:plain
VisualBasicEditorの ツール→参照 から
Microsoft Powerpoint ●.● Object Library やMicrosoft Word ●.● Object Library
を登録します。インテリセンスが効いてくれるので,便利です。
組み終わった後,汎用性を高めるなら,参照設定なしでも動くように作れるので,まずは組みやすさを優先するといいと思います。

さて,ExcelもWordもPowerpointもかなり巨大なクラスモジュールみたいなものだと考えられます。

なので,使い始めは同じような感じになる。それらを放り込むオブジェクト変数を作り,そこに各アプリケーションを参照渡しで入れます。

そして,アクセスしやすいように,
ExcelならWorkbook,WordならDocument,PowerpointならPresentationを入れるオブジェクト変数を作り,これまた参照渡しで入れてあげます。

ExcelからWord文書を開くテストです。ファイルは同じパスにあると仮定して,Excelのパスをthisworkbook.pathで取得して使っています。
ファイル名は直接書き込むのもいいんですが,書き換えやすいように最初あたりで変数に放り込むようにすると,変更部分を最初あたりにかためることができます。

Word.Applicationで宣言して,Newでメモリ上に確保して上げます。この時点でWordはメモリ上にもういるんですが,隠れているのでVisible=Trueで表に出す。
Applicationからいちいち目的のオブジェクトまでいくのはひどく面倒なので,Documentオブジェクトも変数に入れています。

Sub testWord()
    Dim FileName As String: FileName = ThisWorkbook.Path & "\test.docx"
    
    Dim WordApp As Word.Application: Set WordApp = New Word.Application
    WordApp.Visible = True
    Dim WordDoc As Word.Document: Set WordDoc = WordApp.Documents.Open(FileName)
    
    Stop
End Sub

Powerpointの例だと次の感じですね。

Sub testPowerpoint()
    Dim FileName As String: FileName = ThisWorkbook.Path & "\test.pptx"
    
    Dim PowerpointApp As PowerPoint.Application: Set PowerpointApp = New PowerPoint.Application
    PowerpointApp.Visible = True
    Dim PptPresen As PowerPoint.Presentation: Set PptPresen = PowerpointApp.Presentations.Open(FileName)
    
    Stop
End Sub

無駄に,Excelから同じ作法でExcelブックを開いてみると,次の感じ。

Sub testExcel()
    Dim FileName As String: FileName = ThisWorkbook.Path & "\test2.xlsx"
    
    Dim ExcelApp As Excel.Application: Set ExcelApp = New Excel.Application
    ExcelApp.Visible = True
    Dim ExcelBook As Excel.Workbook: Set ExcelBook = ExcelApp.Workbooks.Open(FileName)
    
    Stop
End Sub

Applicationに対して作業を行いたいときと,ファイルにあたるプレゼンやドキュメントに対して作業を行いたいときの両方があるので,
わたしは,いつもこんな感じで他のオフィスアプリを制御するときは2つのオブジェクト変数を必ず使用しています。

ほぼクラスと同じ書き方ですよね。クラスを扱うようになって,ずいぶんしっくりくるようになりました。


ここからは,今回はWordが主の相手なので,Wordに焦点を置きます。

何回かの記事に書いたように,差し込み印刷的な動きを実現するには, 表,テキストボックス,文字置換 の3つの手段を手に入れることで,ほぼ実現可能です。
実際私はそれで今日仕事が成立しました。もっと扱いたいオブジェクトを増やすには,上記のようにStopで止めてローカルウィンドウを見たり,Wordにも記録マクロがありますので,それを利用すればおそらく解決の方法は見つかると思います。

各オブジェクトへのアクセスは以前にも書きましたが,次のような感じでどうでしょう。

    '表を制御 表が複数あるならインデックスの数字を変える。
    WordDoc.Tables(1).Cell.Range.Text = " ~ "
    'テキストボックスを制御
    WordDoc.Shapes("シェイプの名前").TextFrame.TextRange.Text = " ~ "
    '文字置換
    WordDoc.Content.Find.Execute findtext:="置換元", ReplaceWith:="置換先"
    
    'ループの使用例
    i = 1
    Dim SourceString1 As String, SourceString2 As String
    Dim SourceSht As Worksheet: Set SourceSht = ThisWorkbook.Worksheets("Sheet1")
    Do
        SourceString1 = SourceSht.Cells(i, 1)
        SourceString2 = SourceSht.Cells(i, 2)
        
        WordDoc.Content.Find.Execute findtext:="【フィールド1】", ReplaceWith:=SourceString1
        WordDoc.Content.Find.Execute findtext:="【フィールド2】", ReplaceWith:=SourceString2
        '印刷する
        WordDoc.PrintOut
        '元に戻して次の置換に備える。
        WordDoc.Content.Find.Execute findtext:=SourceString1, ReplaceWith:="【フィールド1】"
        WordDoc.Content.Find.Execute findtext:=SourceString2, ReplaceWith:="【フィールド2】"
        
        i = i + 1
    Loop Until SourceSht.Cells(i, 1) = ""

本日私はこんな感じのループで仕事をしたのですが,
もちろんうまく戻せるように文字を配慮できた場合の使い方になります。簡便さを求めた単純な書き方ですので。

Wordオブジェクトを作ったり開いたりするところにもさっと時間がかかるので,一度開いたらその文書を開いたままどう編集作業を繰り返すかで勝負をしています。
Excelから二つの数値を読み取って, 【フィールド1】等をその文字に置換して, 印刷したら ,次のループで変えれるように 【フィールド1】等に戻しておく。
これをデータがなくなるまで繰り返す,と書いています。

差し込みって基本こんな感じですから,これで私はできました。

Wordを使い倒したら,ドキュメントを閉じて,メモリを解放します。

WordDoc.Close
WordApp.Quit

サヨナラ(゚▽゚*)

今この記事を書くために,実際使ってみてたんですが,インテリセンスもきちんと動きますし,とても制御しやすい感じです。参照設定はすばらしい。

ただ,参照設定をしているパソコンでしか動かない状態なので,組み終わったら,汎用性のために,次のように変えてあげる。

    'Dim WordApp As Word.Application: Set WordApp = New Word.Application
    Dim WordApp As Object: Set WordApp = CreateObject("Word.Application")
    WordApp.Visible = True
    'Dim WordDoc As Word.Document: Set WordDoc = WordApp.Documents.Open(FileName)
    Dim WordDoc As Object: Set WordDoc = WordApp.Documents.Open(FileName)

こうしてあげておけば,参照設定が無くても動きます。

自分のためのメモでもありますが,いかがでしょうか。他のオフィスアプリを制御できるととってもタノシイデスヨ(゚▽゚*)
VBA仲間探索のため,ブログ村に参加しています。
にほんブログ村 IT技術ブログ VBAへ
にほんブログ村