PDFの自動印刷のためにAPIのkernel32を利用してみた

今回の記事の2つ前に以下のような過去記事を書いています。今回は以下の過去記事の続きです。

SendKeysメソッドとFolderfilelistでPDFを自動印刷できないか

 

エクセルのVBAでSendkeysメソッドとフリーソフトのFolderfilelistでPDFを自動で印刷できるマクロをつくろうと試みたのですが、思うように動作せずに失敗したといった内容です。

 

考えられる理由として、エクセルからPDFへSendkeysメソッドで指示を送れるようにしていたが、指示が速すぎてPDFが表示される前に送ってしまっていたのではないかということでした。

 

その解決策として、VBAのコードにAPIのkernel32を利用してみました。今回のこの部分で試行錯誤した内容について書いていってみます。

VBAにおけるAPIとは、kernel32とは

過去記事の課題をなんとかするために、何か良い方法はないかとインターネットを使って調べていたら、「これはいけるんじゃないか?」と感じられたものがありました。

 

それは「APIのkernel32」です

 

冒頭の過去記事で書いたコードに、今回はAPIのkernel32というコードを利用してみました。ではAPIのkernel32とはどんなコードなのでしょうか。自分の勉強という意味でも備忘録という意味でもちょっと引用してみます。

 

『VBAエキスパート公式テキスト Excel VBA スタンダード』には次のように書かれています。

p.191

APIとはApplication Programming Interfaceの略称です。APIは、Windowsなどが持っている機能のうち、外部に公開している関数などで、VBAなど他のプログラムから利用できます。

 

一般的に、APIとはWindowsのAPIを差しますが、機能をAPIとして公開できるのはWindowsに限りません。そのほかのプログラムでも、機能の一部をAPIとして公開しているものがあります。そのように外部に公開している機能や関数などを「ライブラリ」と呼びます。

 

プログラム自身を操作するOLEオートメーションとは異なり、APIは公開されている機能や関数だけを呼び出して実行します。両者は、Excel VBAによるプログラミングの中でも、高度な部類に入ります。しかし適切に使いこなせれば、VBAだけでは難しい機能を実現できます。

 

同様に本書においてkernel32は次のように書かれています。

p.191

「Declare Function GetTickCount Lib “kernel32″()As Long」は、kernel32というライブラリが公開しているGetTickCountという関数を使用するための宣言です。

APIとは、要はVBAで使えるいろんなコードの種類の中のひとつといったところでしょうか。Kernel32というのは「Kernel32というライブラリ」とあるので、そういった種類のコードがまとめられている所があるということでしょう。

 

ちなみにAPIを使用するには、どのライブラリの、どの関数を使うかを予め宣言しなければならず、そのためには宣言セクションでDeclareステートメントを使う必要があります。変数の宣言に似ています。

 

今回はこのコードを使って、前回の課題だった読み込み時間中にエクセルに待機させるという指示が出せるか試してみます。

Sleep関数を利用して自動で印刷できるようにしたコード

冒頭部分の過去記事で書いたコードにAPIのkernel32のコードを利用してつくったのが以下のコードになります。

Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub 印刷()
Dim time As Long
time = 1500
Dim i As Long
Dim buf As String
On Error Resume Next
Range("F7").Select
Range("F7").Value = "=VLOOKUP(RC[-4],パス!C[-5]:C[3],9,0)"
Selection.AutoFill Destination:=Range("F7:F100"), Type:=xlFillDefault
For i = 7 To 100
If Cells(i, 2) <> "" Then
Cells(i, 6).Hyperlinks.Add Anchor:=Cells(i, 6), Address:=Cells(i, 6).Value
Cells(i, 6).Hyperlinks(1).Follow
Sleep time
SendKeys "^{p}"
Sleep time
SendKeys "{enter}"
Sleep time
SendKeys "%{F4}"
End If
Next i
Range("F7:F100").Delete
End Sub

上のDeclareステートメント内とコード中には「Sleep関数」というものを使っています。Sleep関数とは指定した時間(ミリ秒間)だけ処理を中断できる関数です。例えばコードに中に「1000」と入れれば1000ミリ秒、つまり1秒間、「待ち」の時間をつくるということです。

 

このSleep関数を

  • PDFが開かれる前
  • PDFが開かれて「Ctrl+P」で印刷ダイアログボックスが開かれる前
  • 印刷ダイアログボックスが開かれてenterが押された後

に「待機」の時間をつくることで、エクセルからの指示を対応できるようにしました。

結果と感想

とりあえず形にはなったかな、という感じです。過去記事ではPDFファイルが開かれるまでに若干のタイムラグがあり、その間にエクセルがSendkeysメソッドで指示を送ってPDFが開かれていないので対応できない、という課題がありました。

 

しかし、今回見つけたコードを入れることで「待ち」の時間をつくることができ、PDFが開いてから指示を送れるようになりました。

 

それによってある程度は理想的な動きをしてくれるようにはなったのですが、問題は「ちょっと時間がかかってしまう」ことだと感じています。

 

VBAでマクロをつくるんだから、一瞬で作業を終わらせてしまう、とは言わないまでももうちょっと何とかならないかなぁと思いました。

 

特に数が印刷する数が増えれば増えるほどより時間がかかってしまいます。自分はVBA初心者なのでまだこういったコードしか書けませんが、たぶんもっと汎用性があって便利なコードはあるはずです。

 

実際インターネットでいろんなコードを見てみると、難しそうなコードをたくさん目にしますし。そのようなコードが理解できるように、自分は今後も勉強が必要だと感じました。

あわせて読みたい

こんな記事も読まれています

コメント