Jump to content

Count instances of variable in job?


MeeshKB

Recommended Posts

This is bit a of a "creative" use of FP (at least it is for me). So please bear with me.

 

I am wondering if there is a way to return a count of the number of instances of a variable within a job. For reference and context, a composed copy of my form is attached. This is essentially what it looks like (except that there are a total of 12 available items - I cropped the image to make it easier to view). It is a form to allow our client to order double sided posters.

 

http://i141.photobucket.com/albums/r42/Turtlegirl203/Public/Professional/MS-TOPPERDS-Output-1_zpsf9207355.jpg

 

Basically, the user will choose artwork for each side, for each "topper" poster. They will also indicate a quantity. This form will not return the print ready artwork - rather, it will create a form suitable for them to review and confirm, and for our customer service reps to create the job.

 

I would like to include, on the second page of the output, a summary of each art file required (resources, in my form) as well as how many total prints of each are require to fulfill the job (ie, how many occurrences of the resource within the job). I know I will need to work in some additional math for the quantities, but I wasn't sure if there is a function to count the occurrences.

 

If anyone is still with me, could you kindly point me in the right direction or divest me of my grand illusions?

MS-TOPPERDS-Output.pdf

Link to comment
Share on other sites

I'm not sure I understand what it is that we're trying to count. The PDF just has a bunch of entries with "Qty. 1." Is that "Qty" number going to vary? Also, is this imposed output, or are these all separate frames on a single Body page? Furthermore, it's not clear to me what this "form" is that you mention: Is it a web form, and if so, in what web application?

 

I assume that the web form is generating an input data file for FusionPro, with some kind of quantity field. If so, why can't you just grab that field value?

 

Maybe posting the collected job would clarify things a bit.

Link to comment
Share on other sites

Sorry - I didn't explain myself particularly well. I forget how many different applications FP has.

 

This is a web form which I am loading to Avanti eAccess. Our client will use the form to choose art and indicate quantities for each double-sided poster. The composed file will look similar to the image in my previous post (except with varying pieces of art and quantities in each category). These items are set up as a bunch of frames on a single body page.

 

The composed file is not final art but rather a "key" which will allow our CSRs to see which art needs to be retrieved and printed, as well as for production to understand which items need to be partnered for laminating back to back.

 

I would like to include a second page in the output which lists all the art files required, and a tally of how many of each we need to print. Based on the collected job I'm attaching, it might look something like this:

 

Antacids and Laxitives - 1

First Aid - 1

Men's Health - 1

Women's Health - 1

Skin Care - 2

Pain & Discomfort - 2

 

I hope this, along with the collected job, makes some sense. Thanks for whatever insight you can provide.

MS-TOPPERDS.zip

Link to comment
Share on other sites

Okay, so looking at this job, it seems to be in the category I like to call "mowing your lawn with tweezers." That is, you're quite painstakingly creating a whole series of frames and rules numbered from 1 to n, laying them out just so, and linking everything up. That's a lot more work than you need to do. There are several ways in which the complexity of this job, and the work needed to do to set it up and maintain it, can be greatly simplified. Many of these optimizations will also result in faster composition times, and smaller file sizes. And they will also make it much easier to program in the concept of repeating an element.

 

One approach that comes to mind right away is to use a table or a repeatable component, or perhaps imposition, to lay out multiple instances of that same basic set of frames in an automated way. A table might be tricky with the graphic frames, although I think you could actually do everything here with text and inline graphics, without a table. A repeatable component would also work: Basically, you would recreate that same basic set of three frames on a page of type Template, and then use the FPRepeatableComponent object in a rule to create instances of the repeatable component in a text frame (probably a two-column frame). As an imposed job, the entire PDF template would be a single body page with those three frames, which would be imposed multi-up onto a finished 8.5x11" sheet.

 

With any of these strategies, you also don't need to have 12 sets of rules. Actually, even with the layout the way it is with all of those multiple frames, you still don't need all those rules. They can be reduced in several ways: variable injection, frame assignment, or per-flow rules. In all of these cases, you can use a loop based on something like "for (var i = 1; i <= 12; i++)" and then assign the values in the loop, in one bit of code, not 12 separate copied-and-pasted bits of code.

 

Without naming all of the frames, you can use variable injection. Believe it or not, you can delete all those rules you have now, and instead, simply have one rule, OnRecordStart, like so:

for (var i = 1; i <= 12; i++)
{
   var baseName = "Topper " + i;
   var text = (Field(baseName + " Side 1") == "None" ? "" : baseName + " - Qty. " + TaggedDataField(baseName + " Qty"));
   FusionPro.Composition.AddVariable(baseName + " Text", text, true); // true to treat as tagged

   for (var side = 1; side <= 2; side++)
   {
       var sideName = baseName + " Side " + side;
       var r = NullResource();
       try { r = Resource(Field(sideName)); } catch (e) {}
       FusionPro.Composition.AddGraphicVariable(sideName + " Fill", r);
   }
}

You can do something very similar in a loop if you name all of the frames the same as their variable names. (You don't even need to assign variables to the frames with this approach; it's all about the frame names). Then the OnRecordStart logic becomes this:

for (var i = 1; i <= 12; i++)
{
   var baseName = "Topper " + i;
   var text = (Field(baseName + " Side 1") == "None" ? "" : baseName + " - Qty. " + TaggedDataField(baseName + " Qty"));
   FindTextFrame(baseName + " Text").content = text;

   for (var side = 1; side <= 2; side++)
   {
       var sideName = baseName + " Side " + side;
       var r = NullResource();
       try { r = Resource(Field(sideName)); } catch (e) {}
       FindGraphicFrame(sideName + " Fill").SetGraphic(r);
   }
}

Or, with the named frames, you could have three separate rules, one for each of the three frames in the set, and check the "Re-evaluate this rule for every text flow/graphic frame" box, grab the name of the flow with FusionPro.Composition.CurrentFlow.name, parse that out to get the index number (1 to 12), and then return the associated indexed text or resources.

 

But these strategies all still require you to lay out 12 separate sets of frames. Remember how I said that you could actually do everything here with text and inline graphics? You can actually do this with just a single text frame on the page, with two columns, and get rid of all those other frames. Again, you just need a single rule (this time a regular Text rule, not OnRecordStart). If you name that single text frame and check the "Re-evaluate this rule for every text flow" box for the rule, the single rule can look like this:

var result = [];

for (var i = 1; i <= 12; i++)
{
   var baseName = "Topper " + i;
   var text = (Field(baseName + " Side 1") == "None" ? "" : baseName + " - Qty. " + TaggedDataField(baseName + " Qty"));
   result.push(text);

   for (var side = 1; side <= 2; side++)
   {
       var sideName = baseName + " Side " + side;
       var r = null;
       try { r = Resource(Field(sideName)); } catch (e) {}
       if (r)
       {
           var width = 24000;
           if (!FusionPro.inValidation)
               width = FindTextFrame(FusionPro.Composition.CurrentFlow.name).GetSettableTextWidth();
           var tag = '<graphic resource="' + Field(sideName) + '" width="' + width + '">';
           result.push(tag);
       }
       else
           result.push("<br><br>");
   }
}
return result.join("<p>\n\n");

You may need to play around a bit with the size and position of the text frame, and the gutter width, and possibly inter-paragraph spacing, to get the layout just so, but that should be a lot easier than laying out all those multiple frames. (A repeatable component could give you a bit more fine-grained control over the layout, although the JavaScript code for that is just a bit more complicated; I'll leave that as an exercise for later, or for someone else to tackle.)

 

Now, we still haven't done anything here to handle the repeat quantities. It's also still not exactly clear to me what you want to do with those. But, assuming that you want to actually repeat the set of frames that number of times, now we have an easy way to do that:

var result = [];

for (var i = 1; i <= 12; i++)
{
   var baseName = "Topper " + i;
   var repeatCount = Int(Field(baseName + " Qty")) || 1;
   for (var repeat = 1; repeat <= repeatCount; repeat++)
   {
       var text = (Field(baseName + " Side 1") == "None" ? "" : baseName + " - " + repeat + " of " + repeatCount);
       result.push(text);

       for (var side = 1; side <= 2; side++)
       {
           var sideName = baseName + " Side " + side;
           var r = null;
           try { r = Resource(Field(sideName)); } catch (e) {}
           if (r)
           {
               var width = 24000;
               if (!FusionPro.inValidation)
                   width = FindTextFrame(FusionPro.Composition.CurrentFlow.name).GetSettableTextWidth();
               var tag = '<graphic resource="' + Field(sideName) + '" width="' + width + '">';
               result.push(tag);
           }
           else
               result.push("<br><br>");
       }
   }
}
return result.join("<p>\n\n");

But now that we're repeating those, what happens when we fill more than those 12 frames (or 12 spaces on the page where there used to be separate frames)? Easy! Just add an Overflow page, with the same-sized frame on it, and overflow to that.

 

I've attached a modified version of your PDF template to demonstrate both of these approaches (multi-frame with variable injection and single-frame with inline graphics).

MS-TOPPERDS-dan.pdf

Edited by Dan Korn
Added a note about using a repeatable component.
Link to comment
Share on other sites

Thank you so much for this, Dan.

 

I can definitely see that my approach was...what is the polar opposite of succinct? That. I was definitely "mowing my lawn with tweezers". In my defense, I hadn't yet learned how to use the lawnmower and was afraid of cutting my feet off.

 

Anyway, I sincerely appreciate the guidance. I would like to explore this further even though - and I apologize for this - I learned this morning that my multi-up solution isn't suitable for this application. Because pricing is attached to these jobs on a "per layout" basis, I need a simple form which only includes one layout. That's up and running now.

 

Regardless of that, I do want to understand this approach. Unfortunately, I am unable to work with your PDF. A version compatibility issue, perhaps? Although, I am on 9.1.0. I can open and view the PDF, but my FP menus are greyed out. I can access the Text Editor by double-clicking, but all else is inaccessible.

Link to comment
Share on other sites

I can definitely see that my approach was...what is the polar opposite of succinct? That. I was definitely "mowing my lawn with tweezers". In my defense, I hadn't yet learned how to use the lawnmower and was afraid of cutting my feet off.

Understood. This stuff isn't necessarily obvious; that's why I wanted to lay it all out.

Anyway, I sincerely appreciate the guidance. I would like to explore this further even though - and I apologize for this - I learned this morning that my multi-up solution isn't suitable for this application. Because pricing is attached to these jobs on a "per layout" basis, I need a simple form which only includes one layout. That's up and running now.

Okay. I'm no stranger to having to completely restart a project due to poorly communicated customer requirements.

Regardless of that, I do want to understand this approach. Unfortunately, I am unable to work with your PDF. A version compatibility issue, perhaps? Although, I am on 9.1.0. I can open and view the PDF, but my FP menus are greyed out. I can access the Text Editor by double-clicking, but all else is inaccessible.

Sorry about that; I'm using FusionPro 9.3, and templates created with 9.2 or later aren't readable by older versions (9.1 and earlier) due to everything being double-byte Unicode. But we're adding a new feature to 9.3 to collect the job in 9.1 compatibility mode. I've utilized that and re-attached the PDF here. This should work for you.

MS-TOPPERDS-dan.pdf

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