Skip to main content

 

 

DealerTeam

Make Your FDF Beautiful

Goal

FDF stands for "Forms Data Format" and is a file format for representing form data and annotations that are contained in a PDF form.

The system generated FDF is functional though not pretty, making it less than ideal to work with. It places the Value on a separate line from the Key and the Value comes first. When writing the expressions to populate data in the form it is easier to work with FDF where the Key and Value are on the same line with the Key first.

A text editor that supports regular expressions can be used to manipulate the FDF to achieve this more workable format. 

Preflight

There are a couple steps you'll need to complete before jumping in to make your FDF beautiful. First you'll need to prepare your environment by acquiring a quality text editor and generate the base FDF.

Download a Quality Text Editor

When doing any job you need the right tools. To upgrade your FDF according to this article you'll need a good text editor that supports regular expressions. Regular Expressions, commonly referred to as Regex, allow for pattern matching in text strings. In this case we can use Regex to identify the repeating pattern for each key/value pair and manipulate the form based upon that. 

We use and recommend Sublime Text at DealerTeam which is free to evaluate without continued use. While there is no defined syntax highlighting for FDF we find that within Sublime Text the Go highlighting works well.

Generate FDF

Create a Form record, upload the PDF form, and get the system generated FDF according to this article.

Get FDF Pairs on a Single Line

The system generated FDF is valuable because it automatically provides a key/value pair with the key populated for each field on the PDF form. Unfortunately, each of these pairs takes up four lines in the text editor. The lines consist of:

  1. Opening Chevrons: <<
  2. Value: /V ()
  3. Text Key: /T (Form Field Name)
  4. Closing Chevrons: >>

Step 1: Move Value to same line as opening chevrons

The next steps will replace the new-line characters ( \n) with double spaces. This step will bring the entire entry on to a single line.

Find the chevrons (<<) with a new-line character ( \n), followed by the value ( /V). Replace the new-line ( \n) with two spaces.

Follow the example provided.

Find: <<\n/V
Replace: <<../V 
helpNote_icon.gif When writing regular expressions into your text editor do not copy/paste. These expressions contain some characters, such as gray dots to represent spaces, that won't translate.

Step 2: Move Text Key to same line as closing chevrons

Find a closing parentheses followed by a new-line character and closing chevrons. Replace the new-line with two spaces.

Follow the example provided. 

Find: \)\n>>.
Replace: )..>>
helpNote_icon.gif Before executing this step be sure that all the closing chevrons have a space after, in particular check the last one which may have a closing bracket.

Step 3: Move Text Key and Value to same line

Find a new-line character followed by the text key and replace the new-line with two spaces.

Find: \n/T
Replace: ../T

Step 4: Switch the Text Key and the Value

It is most convenient when manipulating FDF data to have the text key first on the line. When assembled properly, the text keys will roughly match the same order of the fields on the PDF form. It also allows for quick access to the field even if the value includes a long formula.

Explanation of the matching is provided below, which outlines there are two capture groups.

  • The first capture group is the Value
  • The second capture group is the Text Key.

In the switch, we transpose the two capture groups to display the Text Key first.

Find: ^<<..(.+)..(\/T.+)..>>$
Replace: <<..\2..\1..>>

Regex Explanation
Created at https://regex101.com/r/qhtOJN/1

What's Next

Now you're ready to manipulate your FDF for ease of use and maintenance. With your FDF ready to go it's time to add value formulas and get your forms filling with data from DealerTeam. Check out the FDF Forms Uploading article for details.

Sample FDF

Here is a sample FDF file used for the State of Connecticut Department of Revenue Services CERT-125 (CT CERT-125.pdf) both system generated and after doing the work in this article to make it beautiful.

Beautiful FDF

Each Key / Value pair is on the same line with the Key "/T" coming first. This allows easy ordering to match the PDF form as quick reference when entering expressions.  

%FDF-1.2
%âãÏÓ
1 0 obj 
<<
/FDF 
<<
/Fields [
<<  /T (Home address 2)  /V ({!IF(  isPersonAccount, deal.dealer__Buyer_City__c + ', ' + deal.dealer__Buyer_State__c + ' ' + LEFT(deal.dealer__Buyer_Postal_Code__c, 5) ,'')})  >> 
<<  /T (Daytime Telephone No)  /V ({!deal.dealer__Buyer_Mobile_Phone__c})  >> 
<<  /T (Tradein allowance)  /V ({!tradeIn1.dealer__Trade_Allowance__c})  >> 
<<  /T (Drivers License Number)  /V ({!deal.dealer__Buyer_Drivers_License__c})  >> 
<<  /T (Model)  /V ({!deal.dealer__Model__c})  >> 
<<  /T (Gross sales price)  /V ({!deal.dtmob__Chassis_Price__c})  >> 
<<  /T (Make of vehicle)  /V ({!deal.dealer__Make__c})  >> 
<<  /T (Expiration Date_2)  /V ()  >> 
<<  /T (Trade Make)  /V ({!tradeIn1.dealer__Make__c})  >> 
<<  /T (Name of Purchaser)  /V ({!buyer.FirstName} {!buyer.LastName})  >> 
<<  /T (Employer Address)  /V ()  >> 
<<  /T (Trade Model)  /V ({!tradeIn1.dealer__Model__c})  >> 
<<  /T (Business address 1)  /V ( {!IF(  isPersonAccount, '' , deal.dealer__Buyer_Address__c )} )  >> 
<<  /T (Business address 2)  /V ({!IF(  isPersonAccount, '' , deal.dealer__Buyer_City__c + ', ' + deal.dealer__Buyer_State__c + ' ' + LEFT(deal.dealer__Buyer_Postal_Code__c, 5))} )  >> 
<<  /T (State of registration and plate number)  /V ()  >> 
<<  /T (State of registration and number)  /V ()  >> 
<<  /T (Date of sale)  /V ({!deal.dealer__deal_date__c})  >> 
<<  /T (Net sales price)  /V ({!deal.dtmob__Chassis_Price__c - tradeIn1.dealer__Trade_Allowance__c})  >> 
<<  /T (Year)  /V ({!deal.dealer__Year__c})  >> 
<<  /T (Color)  /V ({!deal.dealer__Ext_Color__c})  >> 
<<  /T (Name of retailer)  /V ({!deal.dealer__Store_Location__r.dealer__Company_Contracting_Name__c})  >> 
<<  /T (City or town State ZIP Code)  /V ({!deal.dealer__Store_Location__r.dealer__City__c} {!deal.dealer__Store_Location__r.dealer__State__c} {! LEFT(deal.dealer__Store_Location__r.dealer__Postal_Code__c,5) })  >> 
<<  /T (State_2)  /V ()  >> 
<<  /T (Expiration Date)  /V ({!deal.dealer__Buyer_Drivers_License_Exp_Date__c})  >> 
<<  /T (Street address)  /V ({!deal.dealer__Store_Location__r.dealer__Address__c})  >> 
<<  /T (Telephone No)  /V ({!deal.dealer__Store_Location__r.dealer__Main_Phone__c})  >> 
<<  /T (Vehicle identification number_2)  /V ({!tradeIn1.dealer__VIN__c})  >> 
<<  /T (State)  /V ()  >> 
<<  /T (Vehicle identification number)  /V ({!deal.dealer__VIN__c})  >> 
<<  /T (employer address 3)  /V ()  >> 
<<  /T (Drivers License Number_2)  /V ()  >> 
<<  /T (Operator 4)  /V ()  >> 
<<  /T (employer address 2)  /V ()  >> 
<<  /T (Operator 3)  /V ()  >> 
<<  /T (Trade Year)  /V ({!tradeIn1.dealer__Year__c})  >> 
<<  /T (employer address 1)  /V ()  >> 
<<  /T (Operator 2)  /V ()  >> 
<<  /T (Resident State)  /V ({!deal.dealer__Buyer_State__c})  >> 
<<  /T (Buyer Name)  /V ({!buyer.Name})  >> 
<<  /T (Co-Buyer Name)  /V ({!CoBuyer.Name})  >> 
<<  /T (User Name)  /V ({!deal.dealer__Salesperson_1__r.Name})  >> 
<<  /T (Deal Date)  /V ({!deal.dealer__Deal_Date__c})  >>
<<  /T (Operator 1)  /V ()  >> 
<<  /T (CT Tax Registration No)  /V ()  >> 
<<  /T (Home address 1)  /V ({!IF(isPersonAccount,deal.dealer__Buyer_Address__c,'')})  >>]
>>
>>
endobj 
trailer

<<
/Root 1 0 R
>>
%%EOF

System Generated FDF

The system generated FDF is much longer (nearly 3x as many lines) and takes more concentration to find the Key "/T".

%FDF-1.2
%âãÏÓ
1 0 obj 
<<
/FDF 
<<
/Fields [
<<
/V ({!IF(  isPersonAccount, deal.dealer__Buyer_City__c + ', ' + deal.dealer__Buyer_State__c + ' ' + LEFT(deal.dealer__Buyer_Postal_Code__c, 5) ,'')})
/T (Home address 2)
>> 
<<
/V ({!deal.dealer__Buyer_Mobile_Phone__c})
/T (Daytime Telephone No)
>> 
<<
/V ({!tradeIn1.dealer__Trade_Allowance__c})
/T (Tradein allowance)
>> 
<<
/V ({!deal.dealer__Buyer_Drivers_License__c})
/T (Drivers License Number)
>> 
<<
/V ({!deal.dealer__Model__c})
/T (Model)
>> 
<<
/V ({!deal.dtmob__Chassis_Price__c})
/T (Gross sales price)
>> 
<<
/V ({!deal.dealer__Make__c})
/T (Make of vehicle)
>> 
<<
/V ()
/T (Expiration Date_2)
>> 
<<
/V ({!tradeIn1.dealer__Make__c})
/T (Trade Make)
>> 
<<
/V ({!buyer.FirstName} {!buyer.LastName})
/T (Name of Purchaser)
>> 
<<
/V ()
/T (Employer Address)
>> 
<<
/V ({!tradeIn1.dealer__Model__c})
/T (Trade Model)
>> 
<<
/V ( {!IF(  isPersonAccount, '' , deal.dealer__Buyer_Address__c )} )
/T (Business address 1)
>> 
<<
/V ({!IF(  isPersonAccount, '' , deal.dealer__Buyer_City__c + ', ' + deal.dealer__Buyer_State__c + ' ' + LEFT(deal.dealer__Buyer_Postal_Code__c, 5))} )
/T (Business address 2)
>> 
<<
/V ()
/T (State of registration and plate number)
>> 
<<
/V ()
/T (State of registration and number)
>> 
<<
/V ({!deal.dealer__deal_date__c})
/T (Date of sale)
>> 
<<
/V ({!deal.dtmob__Chassis_Price__c - tradeIn1.dealer__Trade_Allowance__c})
/T (Net sales price)
>> 
<<
/V ({!deal.dealer__Year__c})
/T (Year)
>> 
<<
/V ({!deal.dealer__Ext_Color__c})
/T (Color)
>> 
<<
/V ({!deal.dealer__Store_Location__r.dealer__Company_Contracting_Name__c})
/T (Name of retailer)
>> 
<<
/V ({!deal.dealer__Store_Location__r.dealer__City__c} {!deal.dealer__Store_Location__r.dealer__State__c} {! LEFT(deal.dealer__Store_Location__r.dealer__Postal_Code__c,5) })
/T (City or town State ZIP Code)
>> 
<<
/V ()
/T (State_2)
>> 
<<
/V ({!deal.dealer__Buyer_Drivers_License_Exp_Date__c})
/T (Expiration Date)
>> 
<<
/V ({!deal.dealer__Store_Location__r.dealer__Address__c})
/T (Street address)
>> 
<<
/V ({!deal.dealer__Store_Location__r.dealer__Main_Phone__c})
/T (Telephone No)
>> 
<<
/V ({!tradeIn1.dealer__VIN__c})
/T (Vehicle identification number_2)
>> 
<<
/V ()
/T (State)
>> 
<<
/V ({!deal.dealer__VIN__c})
/T (Vehicle identification number)
>> 
<<
/V ()
/T (employer address 3)
>> 
<<
/V ()
/T (Drivers License Number_2)
>> 
<<
/V ()
/T (Operator 4)
>> 
<<
/V ()
/T (employer address 2)
>> 
<<
/V ()
/T (Operator 3)
>> 
<<
/V ({!tradeIn1.dealer__Year__c})
/T (Trade Year)
>> 
<<
/V ()
/T (employer address 1)
>> 
<<
/V ()
/T (Operator 2)
>> 
<<
/V ({!deal.dealer__Buyer_State__c})
/T (Resident State)
>> 
<<
/V ({!buyer.Name})
/T (Buyer Name)
>> 
<<
/V ({!CoBuyer.Name})
/T (Co-Buyer Name)
>> 
<<
/V ({!deal.dealer__Salesperson_1__r.Name})
/T (User Name)
>> 
<<
/V ({!deal.dealer__Deal_Date__c})
/T (Deal Date)
>>
<<
/V ()
/T (Operator 1)
>> 
<<
/V ()
/T (CT Tax Registration No)
>> 
<<
/V ({!IF(isPersonAccount,deal.dealer__Buyer_Address__c,'')})
/T (Home address 1)
>>]
>>
>>
endobj 
trailer

<<
/Root 1 0 R
>>
%%EOF