PDFlib+PDI には「テキストフィールドをコピーする」機能はありませんが、PDFlib+PDI に内蔵されている pCOS インターフェースを使って既存の PDF ファイルからフォームフィールドを取得し、PDFlib の機能で新規 PDF ファイルにフォームフィールドを作成することで、テキストフィールドのコピーを実現します。
フォームフィールドには様々な種類がありますのが、今回対象とするのはテキストを入力する textfield のみを対象とします。また下記のオプションをサポートします。
重要な点として、本サンプルではテキストフィールドのフォント情報の引き継ぎは行いません。PDFlib では入力 PDF 内のフォントデータを出力 PDF にコピーすることはできないため、これを実現する場合、あらかじめ使用される可能性のあるフォントファイルを用意しておき、入力 PDF の内容に合わせてフォントを選択する必要があります。
このサンプルではそこまでは行わず、常にシステムフォントの MS-Gothic で出力側のフォームフィールドを作成することにします 。Linux 等で実行する場合や他の任意のフォントを使用する場合、適切に変更する必要があります。
基本的な処理の流れは下記のとおりです。(今回は、Java を使用して記述しています)
/*
* テキストフィールドのコピー
*
* 2021 Copyright (c) infoTek K.K. all rights reserved.
*
* 必要な製品:PDFlib+PDI/PPS 9
*/
import com.pdflib.PDFlibException;
import com.pdflib.pdflib;
class textfields {
public static void main(String[] args) {
pdflib p = null;
String optlist;
try {
/* PDF オブジェクトを生成 */
p = new pdflib();
p.set_option("errorpolicy=return");
/* 新規 PDF 文書を開く */
if (p.begin_document("new_textfields.pdf", "") == -1) {
throw new Exception("Error: " + p.get_errmsg());
}
/* 文書情報を設定 */
p.set_info("Creator", "textfields.java");
p.set_info("Author", "infoTek");
p.set_info("Title", "テキストフィールドのコピー");
/* フォームフィールド用のフォントを読み込み
* Windows での実行を前提に MS-Gothic を使用しています。
* Linux 等で実行する場合は適切なフォントに置き換えてください。
*/
p.set_option("FontOutline={MS-Gothic={C:/Windows/Fonts/msgothic.ttc}}");
int font = p.load_font("MS-Gothic", "unicode", "");
/* 既存 PDF 文書を開く */
int doc = p.open_pdi_document("textfields.pdf", "");
if (doc == -1) {
throw new Exception("Error: " + p.get_errmsg());
}
/* 既存 PDF 文書のぺージ数を pCOS 関数で取得する */
int endpage = (int)p.pcos_get_number(doc, "length:pages");
/* 既存 PDF 文書が複数ページがある場合、必要分繰り返す */
for (int pageno = 1; pageno <= endpage; pageno++) {
/* 既存 PDF ページを開く */
int page = p.open_pdi_page(doc, pageno, "");
if (page == -1) {
throw new Exception("Error: " + p.get_errmsg());
}
/* 新規 PDF ページをダミーのページサイズで作成する。 */
p.begin_page_ext(10, 10, "");
/* 新規 PDF ページ上に既存 PDF ページをインポートし、サイズを調整する */
p.fit_pdi_page(page, 0, 0, "adjustpage");
/* ページ上のテキストフィールドをコピーする */
copy_textfields(p, doc, pageno, font);
/* 既存 PDF ページを終了する */
p.close_pdi_page(page);
/* 新規 PDF ページを終了する*/
p.end_page_ext("");
}
/* 既存 PDF 文書を終了する */
p.close_pdi_document(doc);
/* 新規 PDF 文書を終了する */
p.end_document("");
}
catch (PDFlibException e) {
System.err.println("PDFlib exception occurred:");
System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() + ": " + e.get_errmsg());
}
catch (Exception e) {
System.err.println(e);
}
finally {
if (p != null) {
p.delete();
}
}
}
public static void copy_textfields(pdflib p, int doc, int pageno, int font) throws PDFlibException, Exception {
/* pageno ページ上の「注釈」の数を pCOS 関数で取得する */
String pagepath = "pages[" + (pageno - 1) + "]";
int annotscount = (int)p.pcos_get_number(doc, "length:" + pagepath + "/annots");
if (annotscount == 0) {
return;
}
/* 既存 PDF 文書内の「注釈」分だけ繰り返す */
for (int i = 0; i < annotscount; i++) {
String path = pagepath + "/annots[" + i + "]";
/* 注釈のうち、Subtype が "Widget" かつ FT が "Tx" のもののみを対象にする */
if (!(p.pcos_get_string(doc, path + "/Subtype").equals("Widget"))) {
continue;
}
if (!(p.pcos_get_string(doc, path + "/FT").equals("Tx"))) {
continue;
}
String optlist, type;
/* 座標の取得
* テキストフィールドの座標は /Rect から取得できる
*/
double llx = p.pcos_get_number(doc, path + "/Rect[0]");
double lly = p.pcos_get_number(doc, path + "/Rect[1]");
double urx = p.pcos_get_number(doc, path + "/Rect[2]");
double ury = p.pcos_get_number(doc, path + "/Rect[3]");
/* フォント情報の取得
* フォント情報は /DA から取得できる
* このサンプルでは簡単のため、フォントを固定してフォントサイズのみを取得する
*/
String[] da = p.pcos_get_string(doc, path + "/DA").split(" ");
if(da.length < 2) {
throw new Exception("cannot get fontsize");
}
String fontsize = da[1];
optlist = "font={" + font + "} fontsize={" + fontsize + "}";
/* 名前の取得
* テキストフィールドの名前は /T から取得できる
*/
String name = "";
type = p.pcos_get_string(doc, "type:" + path + "/T");
if(type.equals("string")) {
name = p.pcos_get_string(doc, path + "/T");
}
/* 現在値の取得
* テキストフィールドの現在地は /V から取得できる
*/
type = p.pcos_get_string(doc, "type:" + path + "/V");
if(type.equals("string")) {
String value = p.pcos_get_string(doc, path + "/V");
optlist += " currentvalue={" + value + "}";
}
/* テキストフラグの取得
* テキストフィールドではいくつかのフラグをセットすることができ、
* これを PDFlib の対応するオプションに変換する必要がある
* ここでは良く使用するいくつかのフラグのみを扱う
*/
type = p.pcos_get_string(doc, "type:" + path + "/Ff");
if(type.equals("number")) {
int Ff = (int) p.pcos_get_number(doc, path + "/Ff");
if((Ff & 1) != 0) {
// ReadOnly
optlist += " readonly=true";
}
if((Ff & 2) != 0) {
// Required
optlist += " required=true";
}
if((Ff & 4096) != 0) {
// Multiline
optlist += " multiline=true";
}
}
/* 最大長の取得 (任意)
* テキストフィールドの最大長は /MaxLen から取得できる
*/
type = p.pcos_get_string(doc, "type:" + path + "/MaxLen");
if(type.equals("number")) {
int maxLen = (int) p.pcos_get_number(doc, path + "/MaxLen");
optlist += " maxchar={" + maxLen + "}";
}
/* テキストフィールドを作成する */
p.create_field(llx, lly, urx, ury, name, "textfield", optlist);
}
}
}