Вот пример кода, который использует COM-объекты Acrobat для заполнения форм для заполнения полей Acrobat из данных XML, проанализированных с использованием библиотеки XML Partner от Turbopower. Он не компилируется как есть из-за некоторых внешних зависимостей и нуждается в небольшом рефакторинге, но он должен дать вам общее представление. Процедура Calibrate
добавляет некоторые метки для облегчения размещения поля.
unit AcrobatXMLu;
interface
uses
[...]
Acrobat_tlb, // main Acrobat COM wrapper
AFORMAUTLib_TLB; // Acrobat Forms COM objects
type
TGenerateFlag = (gfShowAcrobat, gfUseDefaultValues, gfGenerateTestData, gfAddCalibration, gfAlwaysFillCheckboxes);
TGenerateFlags = set of TGenerateFlag;
function CreateAcrobatFieldsInner(eStartNode: TxpElement;
const Path: String; Flags : TGenerateFlags; const OutputFile : String): Boolean;
implementation
function CreateAcrobatFieldsInner(eStartNode: TxpElement;
const Path: String; Flags : TGenerateFlags; const OutputFile : String): Boolean;
var
List : TxpNodeList;
X : TxpNode;
N,
Max : Integer;
E : TxpElement;
Align,
S : String;
AddedFields : TStringlist;
procedure CreateField(E : TxpElement);
var
FieldName,
FieldType,
MappedFieldType : String;
PageNo : Integer;
ALeft,
ARight,
ATop,
ABottom,
AWidth,
AHeight : Single;
S : String;
Field : IField; // Acrobat form field
IsMultiLine : Boolean;
begin
FieldName := E.GetAttribute('Name');
if CompareText(FieldName, 'Name1') = 0 then
NoOp;
FieldType := LowerCase(E.GetAttribute('PdfFieldType'));
MappedFieldType := FieldType;
if CompareText(MappedFieldType, 'checkbox') = 0 then
MappedFieldType := 'text';
IsMultiLine := CompareText(MappedFieldType, 'memo') = 0;
if (CompareText(MappedFieldType, 'Text') = 0) or (CompareText(MappedFieldType, 'Memo') = 0) then
MappedFieldType := 'text';
Align := LowerCase(E.GetAttribute('Align'));
S := E.GetAttribute('Page');
if S = '' then
S := TxpElement(E.ParentNode).GetAttribute('Page');
if S <> '' then
PageNo := StrToInt(S) - 1
else
PageNo := 0;
S := GetHeritableAttribute(E, 'XPos', 'FieldXPos');
ALeft := StrToInt(S);
ATop := E.GetAttributeInt('YPos');
S := GetHeritableAttribute(E, 'Width', 'FieldWidth');
if S <> '' then
AWidth := StrToInt(S)
else
AWidth := 60;
S := GetHeritableAttribute(E, 'Height', 'FieldHeight');
if S <> '' then
AHeight := StrToInt(S)
else
AHeight := 20;
ARight := ALeft + AWidth;
ABottom := ATop - AHeight;
try
Field := Acrobat.Fields.Add(FieldName, MappedFieldType, PageNo, ALeft, ATop, ARight, ABottom) as IField;
if True or (AddedFields.IndexOf(FieldName) < 0) then begin
if CompareText(MappedFieldType, 'text') = 0 then begin
S := GetHeritableAttribute(E, 'TextFont', 'FieldTextFont');
if S <> '' then
Field.Set_TextFont(S);
S := GetHeritableAttribute(E, 'TextSize', 'FieldTextSize');
if S <> '' then
if not (CompareText(S, 'Auto') = 0) then
Field.Set_TextSize(StrToInt(S));
if IsMultiLine then
Field.Set_IsMultiline(True);
S := E.GetAttribute('DefaultValue');
S := StringReplace(S, #10, #10#13, [rfReplaceAll]);
if S <> '' then begin
Field.Set_Value(S);
end
else begin
if CompareText(FieldType, 'checkbox') = 0 then begin
if gfAlwaysFillCheckboxes in Flags then
Field.Set_Value('X')
end
else begin
if gfGenerateTestData in Flags then
Field.Set_Value(Format('(%s)', [FieldName]));
end;
end;
if Align <> '' then
Field.Set_Alignment(Align);
end
else begin
if CompareText(MappedFieldType, 'checkbox') = 0 then begin
end;
end;
end;
if AddedFields.IndexOf(FieldName) < 0 then
AddedFields.Add(FieldName)
except
ShowMessage('Error adding field ' + FieldName);
end;
end;
procedure Calibrate;
var
X,
Y,
N,
M,
Page : Integer;
Field : IField; // Acrobat form field
procedure AddField(X, Y : Integer);
var
S : String;
FieldName : String;
begin
if X < 40 then
S := Format('Y:%d', [Y])
else
S := Format('X:%d', [X]);
FieldName := Format('X%dY%d', [X, Y]);
Field := Acrobat.Fields.Add(FieldName, 'text', Page, X, Y, X + 40, Y - 15) as IField;
Field.Set_TextFont('Courier');
Field.Set_TextSize(10);
Field.Set_Value(S);
end;
begin
for Page := 0 to ((Acrobat.AcroApp.GetActiveDoc as CAcroAVDoc).GetPDDoc as CAcroPDDoc).GetNumPages - 1 do begin
for N := 1 to 15 do
AddField(40 * N, 0);
N := 15;
for M := 0 to 60 do
AddField(0, N * M);
end;
end;
begin
AddedFields := TStringlist.Create;
AddedFields.Sorted := True;
Result := False;
try
List := eStartNode.SelectNodes(Path);
try
Max := List.Length - 1;
for N := 0 to Max do begin
X := List.Item(N);
if not (X is TxpElement) then Continue;
E := TxpElement(X);
S := E.GetAttribute('YPos');
if S <> '' then
CreateField(E);
end;
Result := True;
finally
List.Free;
end;
if gfAddCalibration in Flags then
Calibrate;
Acrobat.DocV.GetPDDoc.Save(PDSaveFull, OutputFile);
finally
AddedFields.Free;
end;
end;
end.
Как написано, этот код добавляет поля, определенные в XML, и заполняет их по мере продвижения. Очевидно, что заполнение существующих полей является тривиальной задачей.
Некоторые из сторонних библиотек PDF для Delphi также могут заполнять поля Acrobat. Кроме того, библиотека командной строки PDFtk также может заполнять поля Acrobat и делать другие вещи, которые COM-объекты Acrobat не могут, например «выравнивание» PDF-формы, что эффективно объединяет текст в полях с основным документом и, таким образом, больше не редактируется как форма. См. https://www.pdflabs.com/docs/pdftk-man-page/ для получения дополнительной информации.
person
MartynA
schedule
08.11.2017