TPdf.SetFocusedFormFieldText pakeičia sufokusuoto XFA lauko gyvą buferį, tačiau jo neįrašo į išsaugomą datasets paketą, todėl reikšmė po atidarymo dingstaTPdf.SetFocusedFormFieldTextdatasets/V
AcroForm ir XFA PDFium įrašymo kelyje yra skirtingi formos modeliai, todėl sėkmingas vienos eilutės API iškvietimas negarantuoja XFA išsaugojimoSetFocusedFormFieldTextAcroForm JavaScript straipsnis
Kaip SetFocusedFormFieldText įrašo lauko reikšmę
SetFocusedFormFieldText imituoja FORM_SelectAllText ir FORM_ReplaceSelection klaviatūros redagavimą, o FocusedFormFieldText skaito FORM_GetFocusedText rezultatąTPdf.SetFocusedFormFieldTextFORM_SelectAllTextFORM_ReplaceSelectionFocusedFormFieldTextFORM_GetFocusedTextSetFocusedFormFieldText
if Pdf.FocusedFormFieldIndex >= 0 then
begin
if Pdf.SetFocusedFormFieldText('1284.50') then
Log('Buffer now reads: ' + Pdf.FocusedFormFieldText)
else
Log('No field is focused, or it does not accept text');
end
else
Log('Focus a field first - FocusFormField or a real click');
Kodėl AcroForm išlaiko reikšmę, o XFA ją praranda
AcroForm reikšmė išlieka, nes praradus fokusą ji įrašoma į /V, o TPdf.ClearFormFieldFocus priverčia šį įrašymą prieš SaveAs/VTPdf.ClearFormFieldFocusFORM_ForceToKillFocusTPdf.SaveAs/V
Pdf.FocusFormField(FieldIndex);
Pdf.SetFocusedFormFieldText('1284.50');
Pdf.ClearFormFieldFocus; // forces the /V commit now
Pdf.SaveAs('invoice-acroform.pdf');
// Reopen and confirm - this is an AcroForm document, so it holds
Pdf.Active := False;
Pdf.FileName := 'invoice-acroform.pdf';
Pdf.Active := True;
Pdf.FocusFormField(FieldIndex);
Assert(Pdf.FocusedFormFieldValue = '1284.50'); // passes
Kur iš tikrųjų gyvena XFA lauko pakeitimas
XFA reikšmė lieka CPWL_Edit buferyje ir neperkeliama į PDF datasets paketą, todėl TPdf.GetXfaDatasets prieš ir po redagavimo grąžina tuos pačius baitusCPWL_EditdatasetsTPdf.GetXfaDatasets
var
Before, After: TBytes;
begin
Before := Pdf.GetXfaDatasets;
Pdf.FocusFormField(FieldIndex);
Pdf.SetFocusedFormFieldText('1284.50');
After := Pdf.GetXfaDatasets;
// Before and After are byte-for-byte identical on an XFA document -
// the edit never touched the packet GetXfaDatasets reads from
end;
Ar tai PDFium Component klaida, ar PDFium ribojimas
Viešoji PDFium API neturi FPDF_SetXFAPacket ar FPDF_SaveAsXFA, o FPDF_SaveAsCopy neturi kablio gyvai XFA būsenai išplautiFPDF_SetXFAPacketFPDF_SaveAsXFAdatasetsFPDF_SaveAsCopyTPdf.SaveAs
v2.13.2 auditas parodė šį apribojimą kartu su SetFocusedFormFieldText, nors atskira AcroForm JavaScript spraga buvo pataisytaSetFocusedFormFieldTextFORM_ReplaceSelectionapp.alertAcroForm JavaScript vykdymą su PDFium Component
Ką daryti Delphi programoje
AcroForm atveju prieš SaveAs iškvieskite ClearFormFieldFocus, o mišriam dokumentui patikrinkite FormType arba XFA būsenąClearFormFieldFocusSaveAsFormTypeXFAXFA formų aptikimą ir XFA paketų išskleidimą/V
Dinaminei XFA formai GetXfaDatasets naudokite kaip pradinį XML, atskirai saugokite naudotojo pakeitimus ir patys pataisykite XMLGetXfaDatasetsCPWL_Edit
function ExportEditedXfaValue(Pdf: TPdf; const FieldPath,
NewValue: string): TBytes;
var
DatasetsXml: string;
begin
// GetXfaDatasets ships with PDFium Component; PatchXmlNode below is
// your own helper over your own XML library, nothing PDFium provides
DatasetsXml := TEncoding.UTF8.GetString(Pdf.GetXfaDatasets);
DatasetsXml := PatchXmlNode(DatasetsXml, FieldPath, NewValue);
Result := TEncoding.UTF8.GetBytes(DatasetsXml);
end;
Kaip pastebėti spragą anksčiau nei klientas
TPdf.SaveAs gali grąžinti True, nors XFA reikšmė neišliko, todėl regresijos testas turi iš naujo atverti failą ir palyginti reikšmęTPdf.SaveAsTrueGetXfaDatasets
Tai PDFium riba, kurią reikia įvertinti projektuojant, o ne įprasta PDFium Component Delphi susiejimo klaidaSetFocusedFormFieldTextPDFium Component