PDF-Reuse-Tutorial

 view release on metacpan or  search on metacpan

Tutorial.pm  view on Meta::CPAN

       prText($x1, $y, "Check No $str");
    }
   
    sub pageTop
    {  $pageNo++;
       prFont('Times-Roman');
       prFontSize(18);
   
       prText(230, 702, "$now  Page: $pageNo");
   
       prFontSize(14);
       prText(180, 665, $customer);
       prText(180, 649, $address);
       prText(180, 633, $city);
       prText(180, 617, $phone);
       prText(386, 665, $seller);
       prText(386, 649, $cashier);
    }

=for end

When I run this program with the template of 4,84 kB the final file was 6,95 kB.  
In this special case the log was 2,07 kB and compressed 1,00 kB. It would have had
practically the same size if you had used the template of 46 kB.

Note the sentence

     prTouchUp(0);

It more or less "disables" the TouchUp tool in Acrobat. It makes it difficult to change
the document by mistake. Still you can save the document as postscript, distill it
and change whatever you want. But now you have had to put some effort in to it, and 
hopefully you have not had access to my log and you should not know how the check 
numbers are calculated, so it would anyway be difficult to falsify. (Also
the barcodes change from a font to pure graphics if you redistill the page.)

This is the way the check number is calculated

       my $str2 = prGetLogBuffer() . '436';
       prLog('<S1>');
       $str = Digest::MD5::md5_hex($str2);
       prText($x1, $y, "Check No $str");

prGetLogBuffer() returns what has been logged for the current page. This could be
an alternative to accumulating all variables.(The log buffer is 
written to the disc and undefined after every page break. Also you need to have a 
log. It is only activated when you have given a log directory with the function
prLogDir.)  The program concatenates the string from the buffer with a fixed
string, '436', which someone has decided should be used in this check number method.
After that, prLog puts a tag, <S1>, in the log. Now a hexadecimal digest is produced
and printed.  With this check number method you need the log to verify that a document
is consistent. If that is good or not depends on your needs.

=head2 Replacing placeholders with form fields

A common need is to have a nicely designed PDF template with placeholder areas that
get filled in with data from your program. For example, you might have an invoice PDF
with fields for customer name, address, and line items; or a certificate with a name
and date field.

The previous examples showed how to overlay text at specific coordinates using prForm()
and prText(). That works well, but you have to know the exact x,y position for every
piece of text. An alternative approach is to use B<interactive form fields> (AcroForm
fields) as named placeholders. You design your template with named fields, and then use
prField() to fill them in by name.

B<Step 1: Create a PDF template with named form fields.>

Use a tool like LibreOffice Writer, LibreOffice Draw, or Adobe Acrobat to create your
PDF template. Add text form fields where you want dynamic content to appear. Give each
field a meaningful name like "Name", "Address", "Date", etc. Export or save as PDF with
the form fields intact.

In LibreOffice Writer, you can insert form fields via View > Toolbars > Form Controls,
then use the Text Box tool. Right-click each field and set its Name property. When done,
export to PDF and check "Create PDF Form" in the export options.

B<Step 2: Fill in the fields with prField() and prDocForm().>

=for placeholderFields.pl begin

    use PDF::Reuse;
    use strict;

    prFile('filled_form.pdf');

    # Assign values to the named form fields
    prField('Name',    'Jane Smith');
    prField('Address', '123 Main Street');
    prField('City',    'Springfield');
    prField('Date',    '2026-01-22');
    prField('Amount',  '$1,250.00');

    # Load the template - fields get filled automatically
    prDocForm('invoice_template.pdf');

    prEnd();

=for end

The field names passed to prField() must match exactly the names you gave the fields
in your template. The values are assigned via JavaScript when the PDF is opened, so
the resulting PDF needs a viewer that supports JavaScript (Adobe Reader, most modern
viewers).

B<Step 3: Data-driven production.>

Just like the mail merge example in "Starting to reuse", you can combine this with a
data source to mass-produce filled forms:

=for placeholderBatch.pl begin

    use PDF::Reuse;
    use strict;

    prFile('all_certificates.pdf');

    my @recipients = (
        { name => 'Alice Johnson',  course => 'Advanced Perl',  date => '2026-01-15' },
        { name => 'Bob Williams',   course => 'PDF Processing', date => '2026-01-16' },
        { name => 'Carol Martinez', course => 'Advanced Perl',  date => '2026-01-17' },



( run in 1.068 second using v1.01-cache-2.11-cpan-39bf76dae61 )