PDF文書にフォームフィールドを追加し、内容を入力します。
フォームフィールドは、PDF文書への入力データ用のプレースホルダです。入力データの例としては、名前、日付、複数の項目からの選択などがあります。
フォームフィールドに記載されたデータはPDF文書を閲覧しているユーザーによって変更できます(変更が許可されている場合)。
Toolbox add-onは以下のタイプのフォームフィールドをサポートします。
General textComb textCheck boxRadio buttonCombo boxList box特殊なタイプSubFormを使ったフォーム フィールドの論理グループ作成もできます。
Toolbox Add-onのAPIリファレンスはこちらです。(すべて英文)
C#のサンプルプロジェクトではPdftools SDK(Toolbox Add-on)ライブラリ(DLL)をNuGetから自動でダウンロードします。
CのサンプルプロジェクトにはPdftools SDK(Toolbox Add-on)ライブラリ(DLL)が含まれています。
License Agreement(利用許諾契約書)が含まれていますので必ず確認してください。
入力PDFの内容を出力PDFにコピーして、コピーされた出力PDFにフォームフィールドを追加します。
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// 出力PDF
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// PDF全体のデータをコピー
CopyDocumentData(inDoc, outDoc);
// すべてのフォームフィールドをコピー
FieldNodeMap inFormFields = inDoc.FormFields;
FieldNodeMap outFormFields = outDoc.FormFields;
foreach (KeyValuePair<string, FieldNode> inPair in inFormFields)
{
FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inPair.Value);
outFormFields.Add(inPair.Key, outFormFieldNode);
}
// ページのコピーオプションを定義
PageCopyOptions copyOptions = new PageCopyOptions
{
FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
UnsignedSignatures = CopyStrategy.Remove,
};
// 先頭ページをコピー
Page inPage = inDoc.Pages[0];
Page outPage = Page.Copy(outDoc, inPage, copyOptions);
// 出力ページにさまざまな種類のフォームフィールドを追加
AddCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle { Left = 50, Bottom = 300, Right = 70, Top = 320 });
AddComboBox(outDoc, "Combo Box ID", new string[] { "item 1", "item 2" }, "item 1", outPage, new Rectangle { Left = 50, Bottom = 260, Right = 210, Top = 280 });
AddListBox(outDoc, "List Box ID", new string[] { "item 1", "item 2", "item 3" }, new string[] { "item 1", "item 3" }, outPage, new Rectangle { Left = 50, Bottom = 160, Right = 210, Top = 240 });
AddRadioButtonGroup(outDoc, "Radio Button ID", new string[] { "A", "B", "C" }, 0, outPage, new Rectangle { Left = 50, Bottom = 120, Right = 210, Top = 140 });
AddGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle { Left = 50, Bottom = 80, Right = 210, Top = 100 });
// 出力PDFにページを追加
outDoc.Pages.Add(outPage);
// 残りのページを出力PDFにコピー追加
PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// ドキュメント全体のデータをコピー
// 出力色特性設定
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
// メタデータ
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
// ビューア設定
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
// 関連ファイル(PDF/A-3およびPDF2.0のみ)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
// プレーンな埋め込みファイル
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void AddCheckBox(Document doc, string id, bool isChecked, Page page, Rectangle rectangle)
{
// Check boxを生成
CheckBox checkBox = CheckBox.Create(doc);
// PDFにCheck boxを追加
doc.FormFields.Add(id, checkBox);
// Check boxの状態を設定
checkBox.Checked = isChecked;
// ウィジェットを作成し、ページに追加
page.Widgets.Add(checkBox.AddNewWidget(rectangle));
}
private static void AddComboBox(Document doc, string id, string[] itemNames, string value, Page page, Rectangle rectangle)
{
// Combo boxを生成
ComboBox comboBox = ComboBox.Create(doc);
// PDFにCombo boxを追加
doc.FormFields.Add(id, comboBox);
// 全アイテムを名前でループ処理
foreach (string itemName in itemNames)
{
// 選択項目を作成する
ChoiceItem item = comboBox.AddNewItem(itemName);
// 選択したアイテム名であるかどうかを確認
if (value.Equals(itemName))
comboBox.ChosenItem = item;
}
if (comboBox.ChosenItem == null && !string.IsNullOrEmpty(value))
{
// 項目が選択されていない場合は、編集可能な項目を設定する
comboBox.CanEdit = true;
comboBox.EditableItemName = value;
}
// ウィジェットを作成し、ページに追加
page.Widgets.Add(comboBox.AddNewWidget(rectangle));
}
private static void AddListBox(Document doc, string id, string[] itemNames, string[] chosenNames, Page page, Rectangle rectangle)
{
// list box生成
ListBox listBox = ListBox.Create(doc);
// PDFにList Boxを追加
doc.FormFields.Add(id, listBox);
// 複数選択を許可
listBox.AllowMultiSelect = true;
ChoiceItemList chosenItems = listBox.ChosenItems;
// 全アイテムを名前でループ処理
foreach (string itemName in itemNames)
{
// 選択項目を生成
ChoiceItem item = listBox.AddNewItem(itemName);
// 選択したアイテムに追加するかどうかを確認
if (chosenNames.Contains(itemName))
chosenItems.Add(item);
}
// ウィジェットを作成しページに追加
page.Widgets.Add(listBox.AddNewWidget(rectangle));
}
private static void AddRadioButtonGroup(Document doc, string id, string[] buttonNames, int chosen, Page page, Rectangle rectangle)
{
// Radio Buttonグループを生成
RadioButtonGroup group = RadioButtonGroup.Create(doc);
// ページのウィジェットを取得
WidgetList widgets = page.Widgets;
// Radio Buttonグループをページに追加
doc.FormFields.Add(id, group);
// 各ボタン用に矩形を水平方向に並べて配置します
// 矩形の幅を計算します
double buttonWidth = (rectangle.Right - rectangle.Left) / buttonNames.Length;
// 全ボタンを名前ごとに繰り返します
for (int i = 0; i < buttonNames.Length; i++)
{
// ボタンの矩形
Rectangle buttonRectangle = new Rectangle()
{
Left = rectangle.Left + i * buttonWidth,
Bottom = rectangle.Bottom,
Right = rectangle.Left + (i + 1) * buttonWidth,
Top = rectangle.Top
};
// ボタンと関連ウィジェットを作成
RadioButton button = group.AddNewButton(buttonNames[i]);
Widget widget = button.AddNewWidget(buttonRectangle);
// 選択されたボタンかどうかを確認します
if (i == chosen)
group.ChosenButton = button;
// ページのウィジェットに追加
widgets.Add(widget);
}
}
private static void AddGeneralTextField(Document doc, string id, string value, Page page, Rectangle rectangle)
{
// General textフィールド生成
GeneralTextField field = GeneralTextField.Create(doc);
// PDFにフィールドを追加
doc.FormFields.Add(id, field);
// 文字列をセット
field.Text = value;
// 新規ウィジェットを作成し文字を追加してからページに追加
page.Widgets.Add(field.AddNewWidget(rectangle));
}
def copy_document_data(in_doc: Document, out_doc: Document):
# ドキュメント全体のデータをコピー
# 出力色特性設定
if in_doc.output_intent is not None:
in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
# メタデータ
out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
# ビューア設定
out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
# 関連ファイル(PDF/A-3およびPDF2.0のみ)
outAssociatedFiles = out_doc.associated_files
for in_file_ref in in_doc.associated_files:
outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
# プレーンな埋め込みファイル
out_embedded_files = out_doc.plain_embedded_files
for in_file_ref in in_doc.plain_embedded_files:
out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
def add_check_box(doc: Document, field_id: str, is_checked: bool, page: Page, rectangle: Rectangle):
# Check boxを生成
check_box = CheckBox.create(doc)
# PDFにCheck boxを追加
doc.form_fields[field_id] = check_box
# Check boxの状態を設定
check_box.checked = is_checked
# ウィジェットを作成し、ページに追加
page.widgets.append(check_box.add_new_widget(rectangle))
def add_combo_box(doc: Document, field_id: str, item_names: list[str], value: str, page: Page, rectangle: Rectangle):
# Combo boxを生成
combo_box = ComboBox.create(doc)
# PDFにCombo boxを追加
doc.form_fields[field_id] = combo_box
# 全アイテムを名前でループ処理
for item_name in item_names:
# 選択項目を作成する
item = combo_box.add_new_item(item_name)
# 選択したアイテム名であるかどうかを確認
if value == item_name:
combo_box.chosen_item = item
if combo_box.chosen_item is None and value:
# 項目が選択されていない場合は、編集可能な項目を設定する
combo_box.can_edit = True
combo_box.editable_item_name = value
# ウィジェットを作成し、ページに追加
page.widgets.append(combo_box.add_new_widget(rectangle))
def add_list_box(doc: Document, field_id: str, item_names: list[str], chosen_names: list[str], page: Page, rectangle: Rectangle):
# list box生成
list_box = ListBox.create(doc)
# PDFにList Boxを追加
doc.form_fields[field_id] = list_box
# 複数選択を許可
list_box.allow_multi_select = True
chosen_items = list_box.chosen_items
# 全アイテムを名前でループ処理
for item_name in item_names:
# 選択項目を生成
item = list_box.add_new_item(item_name)
# 選択したアイテムに追加するかどうかを確認
if item_name in chosen_names:
chosen_items.append(item)
# ウィジェットを作成しページに追加
page.widgets.append(list_box.add_new_widget(rectangle))
def add_radio_button_group(doc: Document, field_id: str, button_names: list[str], chosen: int, page: Page, rectangle: Rectangle):
# Radio Buttonグループを生成
group = RadioButtonGroup.create(doc)
# ページのウィジェットを取得
widgets = page.widgets
# Radio Buttonグループをページに追加
doc.form_fields[field_id] = group
# We partition the given rectangle horizontally into sub-rectangles, one for each button与えられた長方形を水平に分割し、ボタンごとに1つずつ長方形を作成
# 分割された長方形の幅を計算
button_width = (rectangle.right - rectangle.left) / len(button_names)
# すべてのボタンを名前でループ
for i, button_name in enumerate(button_names):
# このボタンの分割された長方形を計算
button_rectangle = Rectangle(
left = rectangle.left + i * button_width,
bottom = rectangle.bottom,
right = rectangle.left + (i + 1) * button_width,
top = rectangle.top
)
# ボタンと関連するウィジェットを作成
button = group.add_new_button(button_name)
widget = button.add_new_widget(button_rectangle)
# 選択されたボタンかどうかを確認
if i == chosen:
group.chosen_button = button
# ページのウィジェットに作成されたウィジェットを追加
widgets.append(widget)
def add_general_text_field(doc: Document, field_id: str, value: str, page: Page, rectangle: Rectangle):
# General text フィールド生成
text_field = GeneralTextField.create(doc)
# PDFにフィールドを追加
doc.form_fields[field_id] = text_field
# 文字列をセット
text_field.text = value
# 新規ウィジェットを作成し文字を追加してからページに追加
page.widgets.append(text_field.add_new_widget(rectangle))
# 入力PDFを開く
with io.FileIO(input_file_path, 'rb') as in_stream:
with Document.open(in_stream, None) as in_doc:
# 出力ファイルを作成
with io.FileIO(output_file_path, 'wb+') as output_stream:
with Document.create(output_stream, in_doc.conformance, None) as out_doc:
# PDF全体のデータをコピー
copy_document_data(in_doc, out_doc)
# すべてのフォームフィールドをコピー
in_form_fields = in_doc.form_fields
out_form_fields = out_doc.form_fields
for in_pair_key, in_pair_node in in_form_fields.items():
out_form_field_node = FieldNode.copy(out_doc, in_pair_node)
out_form_fields[in_pair_key] = out_form_field_node
# ページのコピーオプションを定義
copy_options = PageCopyOptions()
copy_options.form_fields = FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS
copy_options.unsigned_signatures = CopyStrategy.REMOVE
# 先頭ページをコピー
out_page = Page.copy(out_doc, in_doc.pages[0], copy_options)
# 出力ページにさまざまな種類のフォームフィールドを追加
add_check_box(out_doc, "Check Box ID", True, out_page, Rectangle(left=50.0, bottom=300.0, right=70.0, top=320.0))
add_combo_box(out_doc, "Combo Box ID", ["item 1", "item 2"], "item 1", out_page, Rectangle(left=50.0, bottom=260.0, right=210.0, top=280.0))
add_list_box(out_doc, "List Box ID", ["item 1", "item 2", "item 3"], ["item 1", "item 3"], out_page, Rectangle(left=50.0, bottom=160.0, right=210.0, top=240.0))
add_radio_button_group(out_doc, "Radio Button ID", ["A", "B", "C"], 0, out_page, Rectangle(left=50.0, bottom=120.0, right=210.0, top=140.0))
add_general_text_field(out_doc, "Text ID", "Text", out_page, Rectangle(left=50.0, bottom=80.0, right=210.0, top=100.0))
# 出力PDFにページを追加
out_doc.pages.append(out_page)
# 残りのページを出力PDFにコピー追加
in_page_range = in_doc.pages[1:]
copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
out_doc.pages.extend(copied_pages)
入力PDFの内容を出力PDFにコピーして、コピーされた出力PDFのフォームフィールドに値を入力します。
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// 解放・クローズの必要なオブジェクト
TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
TPtxPdf_Metadata* pInMetadata = NULL;
TPtxPdf_Metadata* pOutMetadata = NULL;
TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
TPtxPdf_FileReferenceList* pInFileRefList = NULL;
TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
TPtxPdf_FileReference* pInFileRef = NULL;
TPtxPdf_FileReference* pOutFileRef = NULL;
iReturnValue = 0;
// 出力PDFの色特性設定
pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
if (pInOutputIntent != NULL)
{
pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
_T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
_T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// メタデータ
pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
if (pInMetadata != NULL)
{
pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
_T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// ビューア設定
pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
if (pInViewerSettings != NULL)
{
pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
_T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
_T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
Ptx_GetLastError());
// 関連ファイル(PDF/A-3およびPDF2.0のみ)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}
Ptx_Release(pInFileRefList);
pInFileRefList = NULL;
Ptx_Release(pOutFileRefList);
pOutFileRefList = NULL;
// プレーンな埋め込みファイル
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}
cleanup:
if (pInOutputIntent != NULL)
Ptx_Release(pInOutputIntent);
if (pOutOutputIntent != NULL)
Ptx_Release(pOutOutputIntent);
if (pInMetadata != NULL)
Ptx_Release(pInMetadata);
if (pOutMetadata != NULL)
Ptx_Release(pOutMetadata);
if (pInViewerSettings != NULL)
Ptx_Release(pInViewerSettings);
if (pOutViewerSettings != NULL)
Ptx_Release(pOutViewerSettings);
if (pInFileRefList != NULL)
Ptx_Release(pInFileRefList);
if (pOutFileRefList != NULL)
Ptx_Release(pOutFileRefList);
if (pInFileRef != NULL)
Ptx_Release(pInFileRef);
if (pOutFileRef != NULL)
Ptx_Release(pOutFileRef);
return iReturnValue;
}
int copyFields(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// 解放または閉じる必要があるオブジェクト
TPtxPdfForms_FieldNodeMap* pInFields = NULL;
TPtxPdfForms_FieldNodeMap* pOutFields = NULL;
TCHAR* szFieldKey = NULL;
TPtxPdfForms_FieldNode* pInFieldNode = NULL;
TPtxPdfForms_FieldNode* pOutFieldNode = NULL;
iReturnValue = 0;
pInFields = PtxPdf_Document_GetFormFields(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFields,
_T("Failed to get form fields of the input document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
pOutFields = PtxPdf_Document_GetFormFields(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFields,
_T("Failed to get form fields of the output document. %s (ErrorCode: 0x%08x).\n"),
szErrorBuff, Ptx_GetLastError());
for (int iField = PtxPdfForms_FieldNodeMap_GetBegin(pInFields);
iField != PtxPdfForms_FieldNodeMap_GetEnd(pInFields);
iField = PtxPdfForms_FieldNodeMap_GetNext(pInFields, iField))
{
if (iField == 0)
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// キーを取得
size_t nKey = PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, 0);
GOTO_CLEANUP_IF_ZERO(nKey, _T("Failed to get form field key\n"));
szFieldKey = (TCHAR*)malloc(nKey * sizeof(TCHAR*));
GOTO_CLEANUP_IF_NULL(szFieldKey, _T("Failed to allocate memory for field key\n"));
if (PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, nKey) != nKey)
{
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field key. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
// 入力フィールドノードを取得
pInFieldNode = PtxPdfForms_FieldNodeMap_GetValue(pInFields, iField);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFieldNode, _T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// フィールドノードを出力ドキュメントにコピー
pOutFieldNode = PtxPdfForms_FieldNode_Copy(pOutDoc, pInFieldNode);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFieldNode, _T("Failed to copy form field. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// コピーしたフィールドノードを出力フィールドに追加
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_FieldNodeMap_Set(pOutFields, szFieldKey, pOutFieldNode),
_T("Failed to add form field \"%s\". %s (ErrorCode: 0x%08x)\n"), szFieldKey,
szErrorBuff, Ptx_GetLastError());
// 次の反復のためのクリーンアップ
free(szFieldKey);
szFieldKey = NULL;
Ptx_Release(pOutFieldNode);
pOutFieldNode = NULL;
Ptx_Release(pInFieldNode);
pInFieldNode = NULL;
}
cleanup:
if (pOutFieldNode != NULL)
Ptx_Release(pOutFieldNode);
if (pInFieldNode != NULL)
Ptx_Release(pInFieldNode);
if (szFieldKey != NULL)
free(szFieldKey);
if (pOutFields != NULL)
Ptx_Release(pOutFields);
if (pInFields != NULL)
Ptx_Release(pInFields);
return iReturnValue;
}
int fillFormField(TPtxPdfForms_Field* pField, const TCHAR* szValue)
{
// 解放または閉じる必要があるオブジェクト
TPtxPdfForms_RadioButtonList* pButtonList = NULL;
TPtxPdfForms_RadioButton* pButton = NULL;
TPtxPdfForms_ChoiceItemList* pChoiceItemList = NULL;
TPtxPdfForms_ChoiceItem* pItem = NULL;
TCHAR* szName = NULL;
// その他の変数
TPtxPdfForms_FieldType iType = 0;
TPtxPdfForms_CheckBox* pCheckBox = NULL;
TPtxPdfForms_RadioButtonGroup* pRadioButtonGroup = NULL;
iReturnValue = 0;
iType = PtxPdfForms_Field_GetType(pField);
if (iType == ePtxPdfForms_FieldType_GeneralTextField || iType == ePtxPdfForms_FieldType_CombTextField)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_TextField_SetText((TPtxPdfForms_TextField*)pField, szValue),
_T("Failed to set text field value. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else if (iType == ePtxPdfForms_FieldType_CheckBox)
{
pCheckBox = (TPtxPdfForms_CheckBox*)pField;
if (_tcscmp(szValue, _T("on")) == 0)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, TRUE),
_T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, FALSE),
_T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
}
else if (iType == ePtxPdfForms_FieldType_RadioButtonGroup)
{
pRadioButtonGroup = (TPtxPdfForms_RadioButtonGroup*)pField;
pButtonList = PtxPdfForms_RadioButtonGroup_GetButtons(pRadioButtonGroup);
for (int iButton = 0; iButton < PtxPdfForms_RadioButtonList_GetCount(pButtonList); iButton++)
{
pButton = PtxPdfForms_RadioButtonList_Get(pButtonList, iButton);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pButton, _T("Failed to get radio button. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError())
size_t nName = PtxPdfForms_RadioButton_GetExportName(pButton, szName, 0);
GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get radio button name\n"));
szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for radio button name\n"));
if (PtxPdfForms_RadioButton_GetExportName(pButton, szName, nName) != nName)
{
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get radio button name. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
}
if (_tcscmp(szValue, szName) == 0)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_RadioButtonGroup_SetChosenButton(pRadioButtonGroup, pButton),
_T("Failed to set radio button. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
}
free(szName);
szName = NULL;
Ptx_Release(pButton);
pButton = NULL;
}
}
else if (iType == ePtxPdfForms_FieldType_ComboBox || iType == ePtxPdfForms_FieldType_ListBox)
{
pChoiceItemList = PtxPdfForms_ChoiceField_GetItems((TPtxPdfForms_ChoiceField*)pField);
for (int iItem = 0; iItem < PtxPdfForms_ChoiceItemList_GetCount(pChoiceItemList); iItem++)
{
pItem = PtxPdfForms_ChoiceItemList_Get(pChoiceItemList, iItem);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pItem,
_T("Failed to get item from choice field. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
size_t nName = PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, 0);
GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get choice item name\n"));
szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for choice item name\n"));
if (PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, nName) != nName)
{
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get choice item name. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
}
if (_tcscmp(szValue, szName) == 0)
{
break;
}
free(szName);
szName = NULL;
Ptx_Release(pItem);
pItem = NULL;
}
if (pItem != NULL)
{
free(szName);
szName = NULL;
if (iType == ePtxPdfForms_FieldType_ComboBox)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_ComboBox_SetChosenItem((TPtxPdfForms_ComboBox*)pField, pItem),
_T("Failed to set choice item for combo box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else // iType == ePtxPdfForms_FieldType_ListBox
{
Ptx_Release(pChoiceItemList);
pChoiceItemList = PtxPdfForms_ListBox_GetChosenItems((TPtxPdfForms_ListBox*)pField);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pChoiceItemList, _T("Failed to get list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_ChoiceItemList_Clear(pChoiceItemList),
_T("Failed to clear list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfForms_ChoiceItemList_Add(pChoiceItemList, pItem),
_T("Failed to add item to list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
}
}
}
cleanup:
if (szName != NULL)
free(szName);
if (pItem == NULL)
Ptx_Release(pItem);
if (pChoiceItemList == NULL)
Ptx_Release(pChoiceItemList);
if (pButton != NULL)
Ptx_Release(pButton);
if (pButtonList != NULL)
Ptx_Release(pButton);
return iReturnValue;
}
// 入力ドキュメントを開く
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// 出力PDF
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// PDF全体のデータをコピー
CopyDocumentData(inDoc, outDoc);
FieldNodeMap outFields = outDoc.FormFields;
// すべてのフォームフィールドをコピー
FieldNodeMap inFields = inDoc.FormFields;
foreach (var inPair in inFields)
{
FieldNode inFieldNode = inPair.Value;
FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inFieldNode);
outFields.Add(inPair.Key, outFormFieldNode);
}
// 指定されたフィールドを検索
// 見つからない場合は例外をスロー
var selectedNode = outFields.Lookup(fieldIdentifier);
if (selectedNode is Field selectedField)
FillFormField(selectedField, fieldValue);
// 既存のウィジェットを更新し、署名フィールドを削除するためのコピーオプションを構成
PageCopyOptions copyOptions = new PageCopyOptions
{
FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
UnsignedSignatures = CopyStrategy.Remove,
};
// すべてのページをコピーして出力ドキュメントに追加
PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
outDoc.Pages.AddRange(copiedPages);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// ドキュメント全体のデータをコピー
// 出力PDF色特性設定
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
// メタデータ
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
// ビュワー設定
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
// 関連ファイル(PDF/A-3およびPDF2.0のみ)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
// プレーンな埋め込みファイル
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
static void FillFormField(Field formField, string value)
{
// フィールドタイプに応じて値を適用
if (formField is TextField textField)
{
// テキストを設定
textField.Text = value;
}
else if (formField is CheckBox checkBox)
{
// チェックまたはチェックを外す
checkBox.Checked = "on".Equals(value, StringComparison.CurrentCultureIgnoreCase);
}
else if (formField is RadioButtonGroup group)
{
// 指定された名前のボタンを検索
foreach (var button in group.Buttons)
{
if (value.Equals(button.ExportName))
{
// 見つかったので、このボタンを選択
group.ChosenButton = button;
break;
}
}
}
else if (formField is ComboBox comboBox)
{
// 指定されたアイテムを検索
foreach (var item in comboBox.Items)
{
if (value.Equals(item.DisplayName))
{
// 見つかったので、このアイテムを選択
comboBox.ChosenItem = item;
break;
}
}
}
else if (formField is ListBox listBox)
{
// 指定されたアイテムを検索
foreach (var item in listBox.Items)
{
if (value.Equals(item.DisplayName))
{
// 見つかったので、この項目を唯一の選択項目として設定
var itemList = listBox.ChosenItems;
itemList.Clear();
itemList.Add(item);
break;
}
}
}
}
def copy_document_data(in_doc: Document, out_doc: Document):
# ドキュメント全体のデータをコピー
# 出力PDF色特性設定
if in_doc.output_intent is not None:
in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
# メタデータ
out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
# ビュワー設定
out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
# 関連ファイル(PDF/A-3およびPDF2.0のみ)
outAssociatedFiles = out_doc.associated_files
for in_file_ref in in_doc.associated_files:
outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
# プレーンな埋め込みファイル
out_embedded_files = out_doc.plain_embedded_files
for in_file_ref in in_doc.plain_embedded_files:
out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
def fill_form_field(form_field: Field, value: str):
"""Set the value of a form field based on its type."""
if isinstance(form_field, TextField):
form_field.text = value
elif isinstance(form_field, CheckBox):
form_field.checked = value.lower() == "on"
elif isinstance(form_field, RadioButtonGroup):
for button in form_field.buttons:
if button.export_name == value:
form_field.chosen_button = button
break
elif isinstance(form_field, ComboBox):
for item in form_field.items:
if item.display_name == value:
form_field.chosen_item = item
break
elif isinstance(form_field, ListBox):
for item in form_field.items:
if item.display_name == value:
form_field.chosen_items.clear()
form_field.chosen_items.append(item)
break
# 入力ドキュメントを開く
with io.FileIO(input_file_path, "rb") as in_stream:
with Document.open(in_stream, None) as in_doc:
# 出力PDF作成
with io.FileIO(output_file_path, "wb+") as out_stream:
with Document.create(out_stream, in_doc.conformance, None) as out_doc:
# PDF全体のデータをコピー
copy_document_data(in_doc, out_doc)
# すべてのフォームフィールドをコピー
in_fields = in_doc.form_fields
out_fields = out_doc.form_fields
for key, in_field_node in in_fields.items():
out_fields[key] = FieldNode.copy(out_doc, in_field_node)
# 指定されたフィールドを検索し、指定された値で更新
selected_field = out_fields.lookup(field_identifier)
if selected_field:
fill_form_field(selected_field, field_value)
# コピーオプション設定
copy_options = PageCopyOptions()
copy_options.form_fields = FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS
copy_options.unsigned_signatures = CopyStrategy.REMOVE
# すべてのページをコピー
copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
out_doc.pages.extend(copied_pages)
他の機能サンプルを参照してください。
質問のページからお送りいただくようお願いします。
または、メールでsupport@trustss.co.jpあてにお送りください。
ご購入前の技術的質問も無償で対応します。サポート受付ページからお願いします。