PDFをAdobe ReaderのOLEオートメーション経由でExcelのワークシートに自動貼り付けするようにしてみたところ、「画像の解像度が低くて使い物にならない」とクレームを貰ったので。
準備
.NET Framework 4.0環境
Excel-DNA一式
ExcelDna.xllは作成するdnaファイル名に合わせてPdfRender.xllにリネームしておく。PDFLibNet.dll
流通してるのは2.0用ですが、幸いなことにCubePDF Utilityに4.0でコンパイルされたdllが含まれているので、CubePDF Utilityのインストールフォルダから拝借。
※Adobe AcrobatもVisual Studioもなしで使えるのがポイント
呪文
以下をテキストエディタで作成して、上記のxllと同じフォルダに置いておくこと。
PdfRender.dna
<DnaLibrary RuntimeVersion="v4.0" Name="PdfLibNet" Description="PdfRender" Language="CS">
<Reference Path="System.Drawing.dll"/>
<Reference Path="System.Windows.Forms.dll"/>
<Reference Path="PDFLibNet.dll" />
<![CDATA[
using System;
using System.Drawing;
using System.Windows.Forms;
using PDFLibNet;
using ExcelDna.Integration;
public class PdfTest
{
[ExcelCommand(MenuName = "PdfRender", MenuText = "Paste PDF to selection")]
public static void PdfRender(string fname, int page, int dpi)
{
dynamic Excel = ExcelDnaUtil.Application;
var doc = new PDFLibNet.PDFWrapper();
doc.LoadPDF(fname);
System.Drawing.Image img = RenderPage(doc, page, dpi);
Clipboard.SetImage(img);
img.Dispose();
doc.Dispose();
}
private static System.Drawing.Image RenderPage(PDFLibNet.PDFWrapper doc, int page, int dpi)
{
doc.CurrentPage = page;
doc.CurrentX = 0;
doc.CurrentY = 0;
doc.RenderDPI = dpi;
using (var box = new PictureBox())
{
doc.RenderPage(box.Handle);
var buffer = new Bitmap(doc.PageWidth, doc.PageHeight);
doc.ClientBounds = new Rectangle(0, 0, doc.PageWidth, doc.PageHeight);
using (var g = Graphics.FromImage(buffer))
{
var hdc = g.GetHdc();
try
{
doc.DrawPageHDC(hdc);
}
finally
{
g.ReleaseHdc();
}
}
return buffer;
}
}
}
]]>
</DnaLibrary>
詠唱
ワークブックにPdfRender.xllをドラッグ&ドロップし、「このアドインをこのセッションに限り有効にする」を選択しておく。
Excel VBAからの呼び出し
' filename: PDFをフルパスで指定
' page: 表示したいページ
' dpi: DPIを指定
Application.Run "PdfRender", filename, page, dpi
ActiveSheet.Paste ' クリップボード経由で貼り付け
ペーストした直後はセレクトされたShapeなので、Selectionを使ってサイズ変更などのオペレーションも容易です。
クリップボード経由の貼り付けなので、メモリ不足には注意されたし。