Perl Advent Calendar 2019 の12日目です。
昨日はcodehexさんでした。
#きっかけ
紙文化の職場のため、決裁書類や契約書類など様々な定型書類に囲まれています。
共通する内容を複数の書類に転記する必要があり、ミスの原因にもなりますし、時間が掛かっていました。
そこで、入力フォームを作成してボタン一つで作成可能にするなど、業務量の圧縮を図りました。
その際の知見を共有できたら良いなと感じましたので投稿します。
#前提等
現在、VBAを使っている人にはおすすめできると思います。
Windows7とStrawberry Perl 5.30(いずれも32bit版)で行いました。
#Win32::OLE
- 良いところ
- VBAで叩きを作っておけば、それをperlに書き直すだけ
- Officeのマクロの記録機能を使用するとVBAコードが作成されるので、時間短縮が図れる
- 定数などもVBAのイミディエイトウインドウで簡単に調べられるので良い(後述)
- 悪いところ
- 文字コードを常に意識する必要がある(CP932に変換しないとうまく動作しない)
- VBAに慣れていると引数がはまりどころになる(後述)
##Microsoft Office VBAでの定数の調べ方
イミディエイトウインドウでTrueやFalse等の定数を調べることができます。
図では、True = -1, False = 0, wdSendToNewDocument = 0 だと判ります。
##引数について
関数への引数はハッシュのリファレンスで渡します。
下図の赤枠はWordのマクロ記録で作成されたVBAです。Tドライブのサンプル文書というファイルを開いたものです。
この場合perlでは以下のようになります。
# 引数準備
my %openparam;
$openparam{"FileName"} = Encode::encode("CP932","t:\\サンプル文書.docx");
$openparam{"ReadOnly"} = 0; # False
# ファイルを開く
my $doc = $word->Documents->Open(\%openparam); # 引数のハッシュはリファレンスで渡す
もしくは
my $openparam;
$openparam->{"FileName"} = Encode::encode("CP932","t:\\サンプル文書.docx");
$openparam->{"ReadOnly"} = 0; # False
# ファイルを開く
my $doc = $word->Documents->Open($openparam);
#例)Wordファイルを開き、文書を差し込み、ファイルを保存する
例は、以下の5つを行っています。
- 〔サンプル文書.docx〕を開く
- 差込元データとして〔サンプル差込データ.xlsx〕のsheet1を指定する
- 差し込みされた新規文書を作成する
- 新規文書を印刷する
- 新規文書を〔サンプル保存.docx〕として保存する
#!perl
use strict;
use Win32::OLE;
use Encode qw(encode);
use utf8;
my $word = Win32::OLE->new("Word.Application");
$word->{Visible} = -1; # 可視状態にする (True = -1)
# documentは $word->Documents->Open で開く
# その時の引数をハッシュで準備する
my %openparam;
$openparam{"FileName"} = Encode::encode("CP932","t:\\サンプル文書.docx");
$openparam{"ReadOnly"} = -1; # True 読み取り専用で開く
# ファイルを開く
my $doc = $word->Documents->Open(\%openparam); # 引数のハッシュはリファレンスで渡す
# 差し込み印刷
my %dbparam;
$dbparam{"Name"} = encode("CP932","t:\\サンプル差込データ.xlsx"); # 差し込み印刷用のデータ
$dbparam{"SQLStatement"} = "SELECT * FROM `Sheet1\$`"; # シート名は〔`〕で囲む。また名称末尾には$
$doc->MailMerge->OpenDataSource(\%dbparam); # 差し込み印刷の設定 ハッシュをリファレンスで渡す
$doc->MailMerge->{Destination} = 0; # wdSendToNewDocument = 0
$doc->MailMerge->{SuppressBlankLines} = -1; # True = -1
$doc->MailMerge->DataSource->{FirstRecord} = 1; # wdDefaultFirstRecord = 1 レコードの最初から
$doc->MailMerge->DataSource->{LastRecord} = -16; # wdDefaultLastRecord = -16 レコードの最後まで
$doc->MailMerge->Execute(0); # 差し込み印刷実行
# 差し込み印刷された文書を印刷
my $countdoc = $word->Documents->Count; # 文書数、最後に作られた文書は 文書数-1で指定できる
my $newdoc = $word->Documents->Item($countdoc - 1);
my %printparam;
$printparam{"Copies"} = 1; # コピー枚数
$printparam{"Background"} = 0; # False = 0
$newdoc->PrintOut(\%printparam);
# 保存
$newdoc->SaveAs2(encode("CP932","t:\\サンプル保存.docx"));
# 閉じる
$newdoc->Close(0); # False = 0
$doc->Close(0);
$word->Quit(0);
undef $doc;
undef $word;
#おわりに
マクロの記録を使えばVBAコードが作成されますので、「ブックマークに移動」「表を結合」「斜線を引く」等も簡単にperlに移行できたりします。
Excelも同様にマクロを記録して出来たVBAを加工すると、少し楽が出来ます。
明日、13日目はomokawa_yasuです。
ありがとうございました。