Jump to content

OnRecordStart - applying to multiple pages


NAFPRm

Recommended Posts

I have a 12-page project (a booklet) where many of the VDP fields we use are repeated on multiple pages.

 

We have the OnRecordStart code below in place. The second part is a code that basically says "show the company name as text unless a logo is available in which case hide the text and show the logo". It works perfectly for the first such appearance of this code, but in all other appearances it doesn't work and displays the logo and text simultaneously.

 

How can I make it apply to the whole project?

 

var Name = Field("REA_FirstName")
var Headshot = Field("REA_Headshot")
var Logo = Field("REA_Logo")

if(Name =="" || Headshot =="")
{
FindTextFrame("REA..TXT..Data").suppress=true;
FindTextFrame("REA..TXT..Message").suppress=true;
FindGraphicFrame("REA..IMG..Headshot").suppress=true;
FindGraphicFrame("REA..IMG..CompanyLogo").suppress=true;
FindTextFrame("REA..TXT..CompanyName").suppress=true;
}

if(Logo !="")
{
FindTextFrame("REA..TXT..CompanyName").suppress=true;
}

Link to comment
Share on other sites

I have a 12-page project (a booklet) where many of the VDP fields we use are repeated on multiple pages.

 

We have the OnRecordStart code below in place. The second part is a code that basically says "show the company name as text unless a logo is available in which case hide the text and show the logo". It works perfectly for the first such appearance of this code, but in all other appearances it doesn't work and displays the logo and text simultaneously.

 

How can I make it apply to the whole project?

You can't have multiple frames with the same name, even on different Body pages. Well, you can, but the FindTextFrame and FindGraphicFrame functions are only going to find one of the frames with the given name.

 

I think you need a different approach to this template. There are several options, though which one is best for your template is hard to say without knowing more about it.

 

One thing you can do is to give all of the frames different names on different pages, in some kind of pattern, like with the page name, so that you have frames named "REA..TXT..Data_1", "REA..TXT..Data_2", "REA..TXT..Data_3", etc., and so on for all the other frames. Then you can suppress all of them in a loop, like so:

var Name = Field("REA_FirstName");
var Headshot = Field("REA_Headshot");
var Logo = Field("REA_Logo");

for (var i = 1; i <= 12; i++)
{
   if (Name == "" || Headshot == "")
   {
       FindTextFrame("REA..TXT..Data_" + i).suppress=true;
       FindTextFrame("REA..TXT..Message_" + i).suppress=true;
       FindGraphicFrame("REA..IMG..Headshot_" + i).suppress=true;
       FindGraphicFrame("REA..IMG..CompanyLogo_" + i).suppress=true;
       FindTextFrame("REA..TXT..CompanyName_" + i).suppress=true;
   }

   if (Logo != "")
   {
       FindTextFrame("REA..TXT..CompanyName_" + i).suppress=true;
   }
}

 

Another option is to simply insert a rule into each of the frames which returns either empty text or some other content (for a text frame) or a graphic or NullResource() (for a graphic frame). In other words, instead of suppressing the frames, you can just set them to have no content. A rule might look something like this:

// Graphic rule "Headshot"
var Name = Field("REA_FirstName")
var Headshot = Field("REA_Headshot");

if (Name == "" || Headshot == "")
  return NullResource();
//else
// ...whatever else your rule for the "REA..IMG..Headshot" frame was doing...

 

However, you still need to make multiple rules, and then modify every copy of the frame on every page any time to do that. And you may need to modify every copy of every frame again later if you need to change anything else. That makes the whole template hard to maintain. A general rule of thumb I like to follow is that, if you are manually/painstakingly adding/modifying the same frames on multiple pages, then there's almost always a way to accomplish what you need without so much manual, repetitive work. After all, the whole reason you have a computer is to automate repetitive tasks, right?

 

One way to reduce the number of repetitive tasks and make the template more maintainable is to place all of the frames that are common into a Repeatable Component, or Template Page, or actually, into two or more Template pages, one for each variation of the layout, so that instead of suppressing particular frames, you call out the version of the Template page which has just the frames you want. You'll just have a single text frame on each Body page, which will call out a rule which instantiates and returns one of the Repeatable Components, something like this:

var Name = Field("REA_FirstName");
var Headshot = Field("REA_Headshot");
var Logo = Field("REA_Logo");

var rc = new FPRepeatableComponent("All");
if(Name == "" || Headshot == "")
{
 rc = new FPRepeatableComponent("NoHeadshot");
}
else if (Logo != "")
{
 rc = new FPRepeatableComponent("NoCompany");
}
return rc;

Another option may be simply to repeat the entire record, which will effectively repeat each page the same number of times. All you need is this in OnRecordStart:

FusionPro.Composition.repeatRecordCount = 12;

If you need to do something else specific to each repeat (like in all the other frames that don't have the same content on all 12 pages), you can use the FusionPro.Composition.repeatRecordNumber property.

 

There may be other ways to approach the template and reduce both the number of pages and frames and the number of lines of code. But again, I would have to see the template, or at least know a bit more about it, to be able to make a more specific suggestion.

Link to comment
Share on other sites

I think the first solution would work, but I get an error that says:

 


  • In FindFrame(), no frame named "REA..TXT..CompanyName_1"

 

I'm guessing this has to do with how I named the fields on each page. Because the same field can appear on a page I had to add identifiers to, so the naming system looks like this

 

"REA..TXT..CompanyName..P01a"

 

where "P01" represents "page 1" and "a" distinguishes it from others on the same page (for example the next one would be "REA..TXT..CompanyName..P01b", etc.)

 

using this system, is there a way to use your first code and make it work?

Link to comment
Share on other sites

I think the first solution would work, but I get an error that says:

 


  • In FindFrame(), no frame named "REA..TXT..CompanyName_1"

 

I'm guessing this has to do with how I named the fields on each page.

Well, yes, if you don't have a frame with that name, then you'll get that error.

Because the same field can appear on a page I had to add identifiers to, so the naming system looks like this

 

"REA..TXT..CompanyName..P01a"

 

where "P01" represents "page 1" and "a" distinguishes it from others on the same page (for example the next one would be "REA..TXT..CompanyName..P01b", etc.)

 

using this system, is there a way to use your first code and make it work?

So you have multiple copies of each frame on each of multiple pages? In other words, there's "REA..TXT..CompanyName..P01a", "REA..TXT..CompanyName..P01b" etc. on one page, and then "REA..TXT..CompanyName..P02a", "REA..TXT..CompanyName..P02b" on another page, and so on? This sounds like even more of a complicated set of manually-created frames than I originally thought. It also sounds like a nightmare to maintain. I'd really like to be able to take a look at the job and see if there's a better way to approach it.

 

Anyway, if you really want to go with that model, then sure, you could iterate over the frames on each page. One way would be to name them something like "REA..TXT..CompanyName..P01_1", "REA..TXT..CompanyName..P01_2", etc. But if you have the letters, you can do something like this:

var Name = Field("REA_FirstName");
var Headshot = Field("REA_Headshot");
var Logo = Field("REA_Logo");

for (var i = 1; i <= 12; i++)
{
   for (var k = Asc('a'); k <= Asc('d'); k++) // <- change 'd' to however many you need to iterate
   {
       var suffix = "..P" + FormatNumber("00", i) + Chr(k);
       if (Name == "" || Headshot == "")
       {
           FindTextFrame("REA..TXT..Data" + suffix).suppress=true;
           FindTextFrame("REA..TXT..Message" + suffix).suppress=true;
           FindGraphicFrame("REA..IMG..Headshot" + suffix).suppress=true;
           FindGraphicFrame("REA..IMG..CompanyLogo" + suffix).suppress=true;
           FindTextFrame("REA..TXT..CompanyName" + suffix).suppress=true;
       }

       if (Logo != "")
       {
           FindTextFrame("REA..TXT..CompanyName" + suffix).suppress=true;
       }
   }
}

Again, though, it's difficult to try to code this blind, without the template files.

Link to comment
Share on other sites

This sounds like even more of a complicated set of manually-created frames than I originally thought. It also sounds like a nightmare to maintain.

 

haha, it is.

 

Yea, there are pages in the booklet where the same field - headshot for instance - will appear multiple times, however it isn't consistent. Some pages have several, some have no VDP fields at all.

 

I'm not committed to any solution. Whatever works, really. I tried the one you most recently provided and it didn't work. Same issue: solved the first appearance of the text/logo issue, but didn't work on any others.

Link to comment
Share on other sites

haha, it is.

 

Yea, there are pages in the booklet where the same field - headshot for instance - will appear multiple times, however it isn't consistent. Some pages have several, some have no VDP fields at all.

 

I'm not committed to any solution. Whatever works, really. I tried the one you most recently provided and it didn't work. Same issue: solved the first appearance of the text/logo issue, but didn't work on any others.

Well, feel free to post the job files here and take me up on my offer to look at them and try to come up with a better approach. Or not. You might also consider some custom template-building from our excellent Services team.

Link to comment
Share on other sites

Please see attached...

Thanks for posting the template. But I said to post the job fileS, plural. At an absolute minimum, I obviously also need a data file in order to try it out (run the rules, compose, etc.). An example of what you want the output to look like would be helpful as well.

 

That said, I noticed a few important details in the template:

 

For one thing, your naming convention is inconsistent. You have some of the frames with names like "REA..IMG..CompanyLogo..P01a", with a "P" before the page number and the letter, and others with names like "REA..IMG..CompanyLogo..09c", without the "P", and then others which don't match either pattern, such as "LO..IMG..Headshot..P01F1". In order to handle all of these in a loop like we're trying to do, the names absolutely need to be consistent, and follow the pattern exactly.

 

Mostly, though, I never intended that what I posted would just fit into your template and immediately work without any modification. For one thing, the comment at the end of this line was meant to tell you to do something:

    for (var k = Asc('a'); k <= Asc('d'); k++) // <- change 'd' to however many you need to iterate

Because, since I hadn't seen the template, I had no way of knowing how many repeats you had. (My ESP is not working well today.)

 

But it's more complicated than that: The number of repeats can be different for each page, and it also seems that, for some reason, you don't always want to start with 'a', which I don't get, but the rule can account for that:

var Name = Field("REA_FirstName");
var Headshot = Field("REA_Headshot");
var Logo = Field("REA_Logo");

for (var i = 1; i <= 12; i++)
{
   for (var k = Asc('a'); k <= Asc('d'); k++)
   {
       var suffix = "..P" + FormatNumber("00", i) + Chr(k);
       if (Name == "" || Headshot == "")
       {
           SuppressFrame("REA..TXT..Data" + suffix);
           SuppressFrame("REA..TXT..Message" + suffix);
           SuppressFrame("REA..IMG..Headshot" + suffix, true);
           SuppressFrame("REA..IMG..CompanyLogo" + suffix, true);
           SuppressFrame("REA..TXT..CompanyName" + suffix);
       }

       if (Logo != "")
       {
           SuppressFrame("REA..TXT..CompanyName" + suffix);
       }
   }
}

function SuppressFrame(name, graphic)
{
   try
   {
       var frame = graphic ? FindGraphicFrame(name) : FindTextFrame(name);
       frame.suppress = true;
   }
   catch (e)
   {
   }
}

If you name all of the frames consistently, with the "P" and the two-digit page number and another letter, I think that will work, or at least not throw any errors. But I can't really test it without the data file.

 

Having gone through that exercise, though, I still think it would have been easier to set this job up with repeatable components. But since you have already laid everything out this way, it might be better to stay the course now. But I can't really try another approach without the data anyway.

Edited by Dan Korn
Link to comment
Share on other sites

Sorry about the wrong field names. It's not that way on my end. Maybe I uploaded the wrong file somehow.

 

I tried to upload the source file, but it said "invalid file".

 

I tried the code you provided though and it appears to have worked. Thank you!

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...