Jump to content

Body page usage, multiple fields, external data, ouput separate pdf


JeremyT

Recommended Posts

I am working on a whopper of a merge job. I am setting up a job for imprinting calendars. I am given a list of branches and it tells me how many addresses will be on the imprint. Most of the branches have just one address so I am able to pull the address using an external data file.

 

I have a total of 10 different body pages, depending on how many addresses will be on the imprint.

 

Merge needs to first select correct body page, based on number of addresses required.

 

Then each address gets it's own variable text box.

 

For example, my data file says that branch 080 has 3 addresses- 80, 102, 324. FusionPro first needs to grab body page "3 Address". Then get address for branch 80 from external data file. Then put branch 80 address in variable data box 1. Then get address for 102 and put in variable data box 2. Then get address for 324 and put in variable data box 324.

 

After that, it needs to output a separate PDF for branch 80, labelled as such.

 

Then continue on to next branch, which most likely will have a different number of addresses and need a different body page.

 

- How do I get FusionPro to select the correct body page?

 

- How do I get FusionPro to fill each variable data box with the correct address?

 

I've got the output rules set up from last year, so I don't need help with that.

 

 

Thanks,

Jeremy

Calendar Imprint T.zip

Link to comment
Share on other sites

- How do I get FusionPro to select the correct body page?

The way I would do this is to loop through your address fields (which I've made an assumption that they are the IB## fields), and check to see if they contain data. If they contain data, push their value into a global array:

addresses = []; // Global array of addresses
var pg = 0; // Count of pages

for (var i in FusionPro.Fields) {
   if (/IB\d+/.test(i) && Field(i))
       addresses[pg++] = Field(i);
}

FusionPro.Composition.composeThisRecord = !!pg;
FusionPro.Composition.SetBodyPageUsage(pg + 'Address', true);

Note that if pg remains zero (aka no address records were found), the record will not be composed.

 

- How do I get FusionPro to fill each variable data box with the correct address?

 

Now we need to link to your external data file that you're going to use as an address map (in OnJobStart):

addressMap = new ExternalDataFileEx('2014 er 2015 October Branch Master List - Calendars.txt','\t');

 

Then, I would set up one text rule that is set to "Re-evaluate for every text flow" and "treat returned strings as tagged text" that will return the first element in the global 'addresses' array and then splice it from the array. Then you can apply that same rule to every text frame in your template and it will return unique addresses:

var [key] = addresses || '';
// If no branch found, return nothing
if (!key)
   return ''
// Remove leading zeros from Branchkey
key = String(Int(key)); 
var address = ExternalField("Address");
var CSZ = [ExternalField("City"),ExternalField("St"),ExternalField("Zip")].filter(String).join(' ');
address = [address,CSZ].filter(String).join('<br>');
// Remove the current address from the array
addresses.splice(0,1); 

return address;

//====================================
// Short hand for returning the external data values
//====================================
function ExternalField(name) {
  return addressMap.GetFieldValue(addressMap.FindRecord('BR #', key),name);
}

Link to comment
Share on other sites

Step,

 

Thank you for your help.

 

I am still having trouble getting this to work. I followed your instructions and now I get 10 blank pages for each record when I compose.

 

You are correct, IB## fields are the address fields. So, IB1 would be address Imprint 1, IB2 would be address Imprint 2, etc.

 

Here is what I did:

 

I put the following code into JavaScript Globals

 

addresses = []; // Global array of addresses
var pg = 0; // Count of pages

for (var i in FusionPro.Fields) {
   if (/IB\d+/.test(i) && Field(i))
       addresses[pg++] = Field(i);
}

FusionPro.Composition.composeThisRecord = !!pg;
FusionPro.Composition.SetBodyPageUsage(pg + 'Address', true);

In OnJobStart I put

 

addressMap = new ExternalDataFileEx('2014 er 2015 October Branch Master List - Calendars.txt','\t');

In the Return Address Phone Numbers from Branch Master List Rule I put

 

var [key] = addresses || '';
// If no branch found, return nothing
if (!key)
   return ''
// Remove leading zeros from Branchkey
key = String(Int(key)); 
var address = ExternalField("Address");
var CSZ = [ExternalField("City"),ExternalField("St"),ExternalField("Zip")].filter(String).join(' ');
address = [address,CSZ].filter(String).join('<br>');
// Remove the current address from the array
addresses.splice(0,1); 

return address;

//====================================
// Short hand for returning the external data values
//====================================
function ExternalField(name) {
  return addressMap.GetFieldValue(addressMap.FindRecord('BR #', key),name);
}

I am attaching the newest PDF I am composing from.

 

Thanks!

Imprints 2015.pdf

Link to comment
Share on other sites

Sorry, I should have specified – none of the code should go in JavaScript Globals. I meant that the "addresses" array was global (notice it doesn't have 'var' in front of it). JavaScript Globals.

 

This needs to be put in an OnRecordStart callback rule:

addresses = []; // Global array of addresses
var pg = 0; // Count of pages

for (var i in FusionPro.Fields) {
   if (/IB\d+/.test(i) && Field(i))
       addresses[pg++] = Field(i);
}

FusionPro.Composition.composeThisRecord = !!pg;
FusionPro.Composition.SetBodyPageUsage(pg + 'Address', true);

Link to comment
Share on other sites

Progress!

 

I added a comma between City and State. I added Phone number. I added "Fax: " and the fax number.

 

I put the "address" array into an OnRecordStart callback rule.

 

It now pulls address and puts them into an array.

 

Addresses are called from an array, but the SetBodyPageUsage isn't working correctly.

 

I attached 341 Imprint 2015.pdf which has 12 address imprints.

 

It puts Address 1 into text frame on 1Address page, then Address 2 and Address 3 go into text frames on 2Address page, then Address 4, Address 5, Address 6 go into text frames on 3Address page.

 

Merge should put all 12 addresses on 12Address page.

 

Thanks again!

Imprints 2015.pdf

341 Imprint 2015.pdf

Link to comment
Share on other sites

I can't open your file because I have an older version of FusionPro than you do but the "address" array does not belong in the OnRecordStart rule. It also sounds like maybe you don't have all of your pages set to unused by default. Just to clear up any lingering confusion:

 

This goes in OnJobStart:

addressMap = new ExternalDataFileEx('2014\ er\ 2015\ October\ Branch\ Master\ List\ -\ Calendars.txt', '\t');

 

This goes in JavaScript Globals:

addressMap = {};
addresses = [];

 

This goes in OnRecordStart:

addresses = []; // Global array of addresses
var pg = 0; // Count of pages

for (var i in FusionPro.Fields) {
   var key = Int(addressMap.FindRecord('BR #', Field(i)));
   if (/IB\d+/.test(i) && (key+1))
       addresses[pg++] = key;
}

FusionPro.Composition.composeThisRecord = !!pg;
FusionPro.Composition.SetBodyPageUsage(pg + "Address", true);

(Notice that I've changed the code above to check that there's a record that matches the branch key before deciding on which page to use. Just in case there are some records that aren't in the external data file.)

 

This goes in the your text rule (there are just a few changes to match the edits I made above):

key = addresses.shift();

var address = ExternalField("Address");
var CSZ = [ExternalField("City"),ExternalField("St"),ExternalField("Zip")].filter(String).join(' ');
address = [address,CSZ].filter(String).join('<br>');

return address || '';

//==================================================
// Short hand for returning the external data values
//==================================================
function ExternalField(name) {
  return addressMap.GetFieldValue(key,name);
}

Link to comment
Share on other sites

Merge works correctly now that I've got the code in the right spots.

 

I adjusted the code for returning the addresses. I added a comma after City. I also added phone and fax numbers.

 

key = addresses.shift();

var address = ExternalField("Address");
var CityComma =[ExternalField("City"),","].filter(String).join('');
var CSZ = [CityComma,ExternalField("St"),ExternalField("Zip")].filter(String).join(' ');
var phone = ExternalField("Phone");
var fax = ["Fax:",ExternalField("Fax")].filter(String).join(' ');
address = [address,CSZ,phone,fax].filter(String).join('<br>');
return address || '';

//==================================================
// Short hand for returning the external data values
//==================================================
function ExternalField(name) {
  return addressMap.GetFieldValue(key,name);
}

Two minor adjustments:

 

1. I had a couple of instances where the address was missing, so nothing was returned and the incorrect BodyPage was used.

 

Can a line be added to the composition log saying that it was not able to find an address for a specific branch?

 

2. Now that I've added phone and fax numbers, how do I suppress "Fax: " if a branch doesn't have a fax number?

 

Thanks again for all your help!!

Link to comment
Share on other sites

Two minor adjustments:

 

1. I had a couple of instances where the address was missing, so nothing was returned and the incorrect BodyPage was used.

Can a line be added to the composition log saying that it was not able to find an address for a specific branch?

Yes. You can do that a number of ways (Print, ReportError, etc) and they are all detailed on page 79 of the RuleSystemsGuide.pdf documentation (under the "FusionPro Functions" table heading).

2. Now that I've added phone and fax numbers, how do I suppress "Fax: " if a branch doesn't have a fax number?

Here are some posts that relate to your question:

http://forums.pti.com/showthread.php?t=33.

http://forums.pti.com/showthread.php?t=3711.

http://forums.pti.com/showthread.php?t=2885.

 

But on a related note, what you've written here doesn't make sense:

var CityComma =[ExternalField("City"),","].filter(String).join('');
var CSZ = [CityComma,ExternalField("St"),ExternalField("Zip")].filter(String).join(' ');

Basically, you've created an array ("CityComma") of two values:

1. a "City" variable (which may or may not contain a value)

2. a static comma (,) which will always be there because it's static

Then you apply the filter method to it. In this case, the filter method is checking each position of the "CityComma" array to determine if it's empty and if it is that position will be removed from the array. Finally you join the two positions (if there are still two positions) with a space. The problem being: if the "City" variable is empty, it will be removed and the resulting "CityComma" string will be: "," – which will then be inserted into the CSZ array to have the exact same thing done to it.

 

It would make more sense to write it as:

var CityComma = ExternalField("City") ? ExternalField("City") + ', ' : '';
var CSZ = [CityComma,ExternalField("St"),ExternalField("Zip")].filter(String).join(' ');

 

Or simply:

var CSZ = [ExternalField("City"),ExternalField("St"),ExternalField("Zip")].filter(String).join(' ').replace(ExternalField("City") + ' ', ExternalField("City") + ', ');

Link to comment
Share on other sites

Yes. You can do that a number of ways (Print, ReportError, etc) and they are all detailed on page 79 of the RuleSystemsGuide.pdf documentation (under the "FusionPro Functions" table heading).

 

Here are some posts that relate to your question:

http://forums.pti.com/showthread.php?t=33.

http://forums.pti.com/showthread.php?t=3711.

http://forums.pti.com/showthread.php?t=2885.

 

 

I've worked with rules like the posts you suggested show.

 

I am unfamiliar how those rules would work with an array.

Link to comment
Share on other sites

  • 1 year later...

New year, additional job requirements.

 

So this job is for making calendar imprints. Most branches have a single address, but some have multiple addresses. FusionPro looks at my data file and chooses which template page to use depending on how many addresses. Then outputs a pdf for that branch that is labelled and put in a folder. This part of the job is for proofing, it is a smaller page size that shows the imprint in the imprint area.

 

I need to have another page that is the "imposed" part. It takes the smaller page size pdf created above and positions it on a larger page. I need to have this be its own pdf when completed.

 

So I need to get 2 pdfs out of this job.

1. a smaller page size for proofing

2. a larger page size for printing.

 

 

What do I need to add to get the imposed pdf?

 

Code in OnRecord Start.

addresses = []; // Global array of addresses
var pg = 0; // Count of pages

for (var i in FusionPro.Fields) {
   var key = Int(addressMap.FindRecord('BR #', Field(i)));
   if (/IB\d+/.test(i) && (key+1))
       addresses[pg++] = key;
}

FusionPro.Composition.composeThisRecord = !!pg;
FusionPro.Composition.SetBodyPageUsage(pg + "Address", true);

Code in OnNewOutputFile

var outputName = Field("Branchkey") + "-AB Imprint 2017." + FusionPro.Composition.outputFormatExtension;
FusionPro.Composition.outputFileFullPathName = "//Volumes/Imprints/" + outputName;
Print("Changing to output file: " + outputName);}

Link to comment
Share on other sites

In order to get separate imposed and non-imposed outputs, you need to run two separate compositions. This is easy to automate with FusionPro Server, but not so much with Creator or Producer.

 

I hadn't considered using the FP Imposer. I'm trying to simplify this job so using FP Imposer won't work.

 

Ideally I'd like to do this all in one step within FusionPro.

Link to comment
Share on other sites

I hadn't considered using the FP Imposer. I'm trying to simplify this job so using FP Imposer won't work.

Well, you mentioned imposed output, so that immediately makes me think of FP Imposer. Also, I'm not sure I agree with your assessment that trying to emulate imposition without FP Imposer is a way to "simplify" the job. I definitely disagree that using Imposer "won't work."

 

That said, if all you're trying to do is to output a larger, single page 1-up, it should be possible to to do that without FP Imposer.

Ideally I'd like to do this all in one step within FusionPro.

I think the simplest way to accomplish this in FP Creator is to move all of the content of your Body page to a Template (repeatable component) page. Then you can call out (repeat) that repeatable component on both a smaller Body page and on a larger Body page. (The rule for that can be just the "Repeatable Component Rule" XML Template.) You can have logic in OnRecordStart to output repeat the record twice, and output the first repeat on the smaller page and the second repeat on the larger page; something like this:

FusionPro.Composition.repeatRecordCount = 2;
FusionPro.Composition.SetBodyPageUsage("small", FusionPro.Composition.repeatRecordNumber == 1);
FusionPro.Composition.SetBodyPageUsage("large", FusionPro.Composition.repeatRecordNumber == 2);

Your code in OnNewOutputFile can also use theFusionPro.Composition.repeatRecordNumber property to determine which file name to use for each output file.

 

P.S. A new question should be in a new thread.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...