HotPDF — нативная VCL PDF-библиотека для приложений Delphi и C++Builder, которым нужны прямое создание и редактирование PDF, формы, аннотации, шифрование, цифровые подписи, Unicode-шрифты, вывод с учетом стандартов и preflight-отчеты без внешнего PDF-runtime.
Эта статья предназначена для developers replacing hand-edited PDF forms with deterministic Delphi form generation. Она рассматривает AcroForm fields and action logic как промышленную инженерию документов, а не как одиночный вызов компонента.
Практический риск состоит в том, что field widgets can look correct while shared names, export values, JavaScript actions, tab order, or flattening rules break the receiving workflow. Поэтому процессу нужны письменный контракт, наблюдаемая диагностика и реалистичные регрессионные файлы.
Архитектурные решения
Treat the field map as an application contract. field naming rules for repeated widgets and grouped business values / allowed trigger actions, submit targets, and viewer-side script policy
- field naming rules for repeated widgets and grouped business values
- allowed trigger actions, submit targets, and viewer-side script policy
- required flags, default values, calculation order, and validation messages
- whether the output remains interactive or is flattened for archive delivery
Порядок реализации
Build the form layer before assigning values. The order below keeps the workflow reviewable for Delphi and C++Builder teams.
- inventory the template fields and normalize names before binding application data
- apply values only after the allowed action profile has been selected
- refresh widget appearances with the same font and color policy used at design time
- validate exported values and tab order in the same viewer family used by customers
- flatten only after all required-field and calculation checks have passed
Доказательства проверки
Evidence that proves the form is usable. Keep these fields with the output or support record.
- field name, widget bounds, page number, required state, and exported value
- action type, trigger event, destination, and whether the profile allowed it
- appearance stream status, font fallback decision, and calculated-field result
- remaining interactive fields after flattening and warnings for unsupported actions
Appearance streams, actions, and flattening order
A production form workflow separates field creation, value assignment, appearance refresh, action binding, and final flattening. Keeping those phases visible makes it possible to explain why a required field failed or why a submit action was suppressed.
Decision table for AcroForm fields and action logic
A decision table keeps product ownership visible when the same workflow is reused by a desktop tool, service job, and support utility.
| Decision | Engineering reason | Evidence |
|---|---|---|
| field naming rules for repeated widgets and grouped business values | inventory the template fields and normalize names before binding application data | field name, widget bounds, page number, required state, and exported value |
| allowed trigger actions, submit targets, and viewer-side script policy | apply values only after the allowed action profile has been selected | action type, trigger event, destination, and whether the profile allowed it |
| required flags, default values, calculation order, and validation messages | refresh widget appearances with the same font and color policy used at design time | appearance stream status, font fallback decision, and calculated-field result |
Замечания для инженерного ревью по AcroForm fields and action logic
Используйте эти замечания, чтобы убедиться, что функция вышла за рамки демо и может быть обоснована на релизе, в поддержке и при эскалации клиента
- Решение: field naming rules for repeated widgets and grouped business values. Точка приложения при реализации: apply values only after the allowed action profile has been selected. Доказательство приемки: appearance stream status, font fallback decision, and calculated-field result. Триггер регрессии: flattening before validation can permanently hide incomplete or inconsistent data
- Решение: allowed trigger actions, submit targets, and viewer-side script policy. Точка приложения при реализации: refresh widget appearances with the same font and color policy used at design time. Доказательство приемки: remaining interactive fields after flattening and warnings for unsupported actions. Триггер регрессии: checkbox captions do not always match the export values consumed by external systems
Пограничные случаи
- checkbox captions do not always match the export values consumed by external systems
- identically named fields may intentionally share one value across several pages
- viewer security settings can block actions that worked during development
- flattening before validation can permanently hide incomplete or inconsistent data
Примечания по Delphi / C++Builder
HotPDF Component should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. Важные термины включают AcroForm, widget, field action, appearance stream, submit action, flattening.
Пример кода Delphi
Следующий эскиз Delphi показывает практическую границу сервиса для этой темы. Оставляйте проверки политики, журналирование и валидацию вне узкого блока вызова продукта, чтобы сценарий было проще тестировать.
procedure BuildAcroFormPackage(const OutputFile: string; const Profile: TFormProfile);
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := OutputFile;
Pdf.BeginDoc;
AddCustomerFields(Pdf, Profile);
WireSubmitActions(Pdf, Profile.ActionMap);
ValidateRequiredFields(Profile.RequiredFields);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Производственный чек-лист
- Запускайте сценарий на пустом файле, обычном клиентском файле и файле худшего случая
- Открывайте сгенерированный PDF в целевом просмотрщике, валидаторе, принтере или downstream-приложении
- Записывайте версию продукта, версию профиля, хэш входа, путь вывода, затраченное время и число предупреждений
- Храните пароли, сертификаты, временные файлы и данные клиентов по явным правилам хранения
- Добавляйте регрессионные документы, когда клиентский файл выявляет новый граничный случай
Документация по продукту
Дополнительные примеры кода
// Open a help page in the system browser
Pdf.CurrentPage.AddPushButtonWithAction('btnHelp', 'Help',
'https://www.example.com/claims-help', Rect(320, 700, 420, 730), baURI);
// Run viewer-side JavaScript
Pdf.CurrentPage.AddPushButtonWithAction('btnRecalc', 'Recalculate',
'app.alert("Totals updated.");', Rect(320, 660, 420, 690), baJavaScript);
// Submit as XFDF and keep empty fields in the payload
Pdf.CurrentPage.AddPushButtonWithSubmitAction('btnSubmit', 'Submit claim',
'https://api.example.com/claims', Rect(320, 620, 420, 650),
[sffXFDF, sffIncludeNoValueFields]);// Reject committed values that are not plausible email addresses
Pdf.AttachFieldKeyStrokeAction('applicant.email',
'if (event.willCommit && !/^[\w.-]+@[\w.-]+\.\w+$/.test(event.value)) event.rc = false;');
// Display US phone numbers as (NNN) NNN-NNNN
Pdf.AttachFieldFormatAction('applicant.phone',
'event.value = event.value.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");');
// Refuse applicants under 18 at commit time
Pdf.AttachFieldValidateAction('applicant.age',
'if (parseInt(event.value) < 18) event.rc = false;');