Jump to content

step

Registered Users - Approved
  • Posts

    962
  • Joined

Posts posted by step

  1. That HAlign centers ALL the cells. I was wondering if it's possible to just center the header and leave the actual dates and amounts under those headers flush left?

    It's done the same way:

    for (var i = rec; i <= data.recordCount; i++) {
     function ExField(str) { return TaggedTextFromRaw(data.GetFieldValue(i, str)); }
     if (ExField('company') && i > rec) break;
    
     var row = table.AddRow();
     [color="Red"]row.Cells[0].HAlign = 'Left';
     row.CopyCells(0, 1);[/color]
     row.SetContents.apply(row, ['Date', 'Amount'].map(ExField));
    }
    

  2. The only other thing I'd like is to center just the headers (so center the words Date and Amount over the columns). There's a way to just center headers isn't there?

    Sure, just add the line in red to the existing code:

    var header = table.AddRow();
    header.Type = 'Header';
    var cell = header.Cells[0];
    cell.SetBorders('Thin', 'Black', 'Bottom');
    [color="Red"]cell.HAlign = 'Center';[/color]
    header.CopyCells(0, 1);
    header.SetContents('Date', 'Amount');
    

    Hmmm...although I just realized it's not parsing the data properly for the different companies. It did the first record group correctly but then skips records in the following companies.

    It works for me so I imagine it has something to do with multi-line records and FusionPro 10. I would make sure that you don't still have your template configured to use multi-line records.

  3. So, there's probably an easier way to do this in FusionPro 10 but here's how I would do it in FusionPro 9 (add the following to an OnRecordStart callback):

    var numOfCols = 3;
    var data = new ExternalDataFileEx(PrimaryInputFile(), FusionPro.inputFileDelimiter);
    
    FusionPro.Composition.composeThisRecord = Field('company');
    
    var rec = FusionPro.Composition.inputRecordNumber;
    
    var table = new FPTable();
    table.AddColumns(7200, 8500);
    
    var header = table.AddRow();
    header.Type = 'Header';
    var cell = header.Cells[0];
    cell.SetBorders('Thin', 'Black', 'Bottom');
    header.CopyCells(0, 1);
    header.SetContents('Date', 'Amount');
    
    
    for (var i = rec; i <= data.recordCount; i++) {
     function ExField(str) { return TaggedTextFromRaw(data.GetFieldValue(i, str)); }
     if (ExField('company') && i > rec) break;
    
     var row = table.AddRow();
     row.SetContents.apply(row, ['Date', 'Amount'].map(ExField));
    }
    
    // Number of rows needed to evenly distribute across numOfCols.
    // Minus 1 for the header row.
    var rows = Math.ceil((table.Rows.length - 1) / numOfCols);
    
    // Duplicate column 1 and 2 (and their headers) to make up numOfCols.
    for (var i = 0; i < (numOfCols - 1) * 2; i++) {
     table.Columns.push(table.Columns[i % 2]);
     table.Rows[0].Cells.push(table.Rows[0].Cells[i % 2])
    }
    
    // Concatenate the rows cells in order to reduce our total rows
    // and fill up the extra columns. 
    var rowCounter = 1;
    while ((table.Rows.length - 1) > rows) {
     var index = rowCounter % rows || rows;
     var row = table.Rows.splice(rows + 1, 1).pop();
     table.Rows[index].Cells = table.Rows[index].Cells.concat(row.Cells)
     rowCounter++
    }
    
    // Create the table tags.
    table = table.MakeTags();
    
    // Return the table.
    FusionPro.Composition.AddVariable('RUL_table', table, true);
    

  4. So, I tried both of these. The first one gives me weird results with the first record info twice and then the last and one in the middle, then Date and Time repeated a number of times.

     

    The other one just gives me a big blank with the red bar indicating not fitting. I'm not able to make my box big enough to get anything to show.

    Interesting. Maybe you could post your template with some sample data? I think it would be easier to see what you're dealing with that way because the screenshots you posted are tiny and I have bad eyes.

     

    I'm sure it's something I'm missing or maybe I don't have my data defined properly.

    For full disclosure, as my signature indicates, I'm not running FP 10 and therefore don't have access to the GetMultiLineRecords function so I just sort of guessed at that part in the code snippets I posted. But if you post your template, I think if we could get it working using the input as an external data file (the way I would do it in FP9), I think you should be able to translate that to FP10's multi-line record function.

    Also, I do have a paragraph of text below the table and then a name and signature. I was trying to set all up in one block so that the final paragraph and sig line move up or down according to the number of rows (so maybe that's contributing to things breaking or maybe something is off with my data file).

    Oh okay, I see. Well, the 3-column text frame approach won't work then.

  5. So I know it's right before Christmas and the last thing anyone is going to do is look at this board, but maybe Dan or Ste or somebody is out there?? ;-)

    You know it.

     

    What I am trying to figure out is can I make it flow the data into columns...

    My letter layout allows 6 columns (so 3 groups of Date Amount columns).

    One company may have 25 lines of dates and amounts while another has 6 or 10, etc.

     

    Can Fusion flow that info into columns, or will I have to massage the data into columns?

    It depends on how you're wanting the data to "flow." If you want the data to fill the first column, then fill the second column, then the third, you can set up a two column table with a header row, and return it in a 3 column text frame:

    var table = new FPTable();
    table.AddColumns(7200, 8500);
    var header = table.AddRow();
    header.Type = 'Header';
    var cell = header.Cells[0];
    cell.SetBorders('Thin', 'Black', 'Bottom');
    header.CopyCells(0, 1);
    header.SetContents('Date', 'Amount');
    
    var data = FusionPro.GetMultiLineRecords();
    for (var rec in data) {
     function ExField(str) { return TaggedTextFromRaw(data.GetFieldValue(data[rec], str)); }
     var [date, amt] = ['Date', 'Amount'].map(ExField);
     table.AddRow().SetContents(date, amt);
    }
    
    return table.MakeTags();
    

    If you want the data to flow across all 6 columns before moving on to the next row, that can be done too:

    var table = new FPTable();
    table.AddColumns(7200, 8500, 7200, 8500, 7200, 8500);
    
    var header = table.AddRow();
    header.Type = 'Header';
    var cell = header.Cells[0];
    cell.SetBorders('Thin', 'Black', 'Bottom')
    header.CopyCells(0, 1, 2, 3, 4, 5);
    header.SetContents('Date', 'Amount', 'Date', 'Amount', 'Date', 'Amount');
    
    var data = FusionPro.GetMultiLineRecords();
    while (data.length) {
     var row = table.AddRow();
     var contents = [];
     data.splice(0, 3).forEach(function(rec) {
       function ExField(str) { return TaggedTextFromRaw(data.GetFieldValue(data[rec], str)); }
       contents.push(ExField('Date'), ExField('Amount'))
     });
     row.SetContents.apply(row, contents);
    }
    
    return table.MakeTags();
    

  6. It seems a little excessive, but you could use FusionProTextMeasure:

    var contactName = 'Edward Hanrahanhfewfwerewr';
    var pointSize = { max: 9.5, min: 6.5 };
    contactName = '<span font="Helvetica Neue" pointsize="' + pointSize.max + '">' + contactName + '</span>';
    var limit = Int((pointSize.min / pointSize.max) * 100);
    return NoBreakCopyfit(contactName, 100, limit);
    
    function NoBreakCopyfit(str, mag, min) {
     if (FusionPro.inValidation) return str;
     try {
       var frameName = FusionPro.Composition.CurrentFlow.name;
       var width = GetSettableTextWidth(FindTextFrame(frameName));
     } catch(e) {
       ReportError('Must name text frame and set rule to "Re-evaluate this rule for every text flow"');
     }
     var tm = new FusionProTextMeasure;
     tm.useTags = true;
     tm.maxWidth = width;
     var magnified = '<magnify factor="' + mag + '" type="text">' + str + '</magnify>';
     tm.CalculateTextExtent(magnified);
     return tm.textLines > 1 && mag > min ? NoBreakCopyfit(str, --mag, min) : magnified;
    }
    

    Make sure you name your text frame and set the rule to "Re-evaluate this rule for every text flow."

  7. case "backcta.txt":
     return Field("First Name") + ", Can you believe it's been " + Field("Month") + " months already?";
    

     

    You could also take care of adding an "s" for plural months like this:

    case "backcta.txt":
     var months = Trim(Field("Month")) + " month";
     months += /^(1|one) month$/i.test(months) ? "" : "s";
     return Field("First Name")+ ", Can you believe it's been " + months + " already?";
    

  8. What I would like to add to the code is a way to limit the number of pages that are added to the new document for any given file. For example, let say that someone uploads a document with 40 pages in it. We only want to allow up to 12 pages of any document to be included in the new composed file. So we want to allow the first 12 pages of any PDF and then disregard any pages after that.

    You can limit the number of pages to 12 like this:

    var pages = Math.min(file.countPages, 12);
    

    That will set the 'pages' variable to the lower of the two values.

    The second thing that would be beneficial - if a file we are adding to the composed document has an odd number of pages, add a blank to make it even. That way the next document we add will not start on the back page of the previous document.

    Assuming you're using overflow pages, you can specify that you want the last added page to be even. But judging by your code, it looks like you may want the last page in the PDF to print in a different text frame (lastGraphic)? So, I'm also going to assume that if you have an odd number of pages, you want the content of 'lastGraphic' to be blank rather than containing the last page?

    var file = CreateResource(path + fileName, 'graphic');
    var pages = [color="red"]Math.min(file.countPages, 12)[/color];
    
    for (var i = 1; i [color="Red"]<=[/color] pages; i++)
     (file.pagenumber = i) && result.push(file.content);
    
    [color="red"]var lastPage = result.length % 2 ? '' : result.pop();[/color]
    FindTextFrame(firstGraphic).content = result.join('<p>');
    FindTextFrame(lastGraphic).content = [color="red"]lastPage[/color];
    

  9. Is there anyway of forcing the color of the crop marks in the imposition tool?

     

    Not to my knowledge. We've run into the same limitation as well and ended up using a Pitstop Pro action to convert the color of the crop marks before it got to press. You might find that you're able to map the black separation to your spot color at the Indigo, though, and you might be able to set up a hot folder/ticket template to do it for you automatically for repeat jobs.

  10. Assuming your PDFs are named the same as your fields, you could create a text rule:

    var result = [];
    for (var field in FusionPro.Fields) {
     if (!/^Store/.test(field)) {
       var count = Int(Field(field));
       while (count--)
         result.push(CreateResource('/path/to/graphics/' + field + '.pdf', 'graphic').content);
     }
    }
    return result.join('<p verticalstart="topofpage">\n');
    

    And set the text frame to use an overflow page like you mentioned.

  11. Usually we would create a rule with the code:

    Var1 = ReplaceSubstring("Title","&","&"); 
    

    This line of code isn't necessary. It is replacing every occurrence of "&" in the string "Title" with "&." Since there are no instances of "&" in "Title," you can remove that code.

     

    I'm going to assume instead that you want to replace all instances of "&" in a field named "Title" with an ampersand. I think this will do what you want:

    var title = RawTextFromTagged(Field("Title"));
    if (CaseSelection == 'allcaps')
     title = ToUpper(title);
    return title;
    

  12. If you want to print the book number on the first page of the book, then you aren't really trying to determine if the record is a multiple of 50. Record 1, 51, 101, etc aren't multiples of 50.

     

    I think you want to do this:

    var recsInBook = 50;
    var rec = CurrentRecordNumber();
    return rec % recsInBook == 1 ? 'BOOK #' + Math.ceil(rec / recsInBook) : '';
    

  13. If you wanted to, you could make a global array containing all of your codes in an OnJobStart callback and then splice off the first 6 codes in that array and print them on every 6th record:

     

    OnJobStart

    allCodes = [];
    
    var fieldName = "Codes"; // Field name containing the codes.
    var data = new ExternalDataFileEx(PrimaryInputFile(), FusionPro.inputFileDelimiter);
    for (var i=1; i<=data.recordCount; i++)
       allCodes.push(data.GetFieldValue(i, fieldName));
    

     

    Codes (text rule)

    if (FusionPro.inValidation) 
       Rule("OnJobStart");
    
    var codesPerRecord = 6;
    var codes = (FusionPro.Composition.inputRecordNumber % codesPerRecord) == 1 ?
       allCodes.splice(0, codesPerRecord) : [];
    return codes.filter(String).join("<br>");
    

     

    Using the above code, codes for records 1-6 would be printed on the first record, codes 7-12 would be printed on the second record, et cetera.

     

    Is that what you're trying to achieve?

  14. I used the margin adjustment as you can see in my code sample

    I see a line of code that contains the word "Margins" but it is commented out, incorrectly defined, and the "Top" and "Bottom" properties are set to zero (which I noted wouldn't work in my response).

     

    it gives me the ability to increase the leading between lines, but what I need to do is decrease the default line leading of 120 in order to get these lines closer. I tried setting the minimum row to 10 but it did not move the lines.

    Again, you are not setting the leading – you are setting the minimum height of the row and the margins of the cells within the row. If setting the minimum height to 10 points and the top/bottom margins to 1 resulted in no visible difference then it makes me think the content of the row requires more space than a 10 pt row. Do your cells consist of multi-line content?

     

    You can adjust the leading of cell's content just like you would any other rule, though – just adjust the leading in the text editor.

     

    If you're still having problems, it would be helpful if you'd collect your template so that I could get a better idea of what you're trying to accomplish.

  15. You can adjust the space between rows in a table by adjusting the top and bottom margins of the row's cells (must be greater than 0). Additionally, you can set a minimum height for the row itself.

     

    If you want your rows to be (at least) 15pts tall, add this to your code:

    var table = new FPTable();
    table.AddColumns(8500, 38500, 7200);
    
    var data = FusionPro.GetMultiLineRecords();
    
    for (var rec = 1; rec <= data.recordCount; rec++) {
     function ExField(str) { return TaggedTextFromRaw(data.GetFieldValue(rec, str)); }
    
     var content = ["DATE","DESCRIPTION","OPEN-AMT"].map(ExField);
     var row = table.AddRow();
     [color="Red"]var [cell] = row.Cells;
    
     cell.Margins = { 'Top': 1, 'Bottom': 1, 'Left': 0, 'Right': 0 };
     cell.VAlign = 'Bottom';
    
     row.CopyCells(0, 1, 2);
     row.minHeight = 15 * 100; // 15 pt row height.[/color]
     row.SetContents.apply(row, content);
    }
    
    return table.MakeTags();
    

  16. I don't know about MarcomCentral but in FusionPro, "SetFieldValue" is not a property of a text frame.

     

    If you're trying to override the value of the "size" field from your OnRecordStart rule, you can do that like this:

    var NumberField = function (field) { return StringToNumber(Field(field)); }
    var size = NumberField("pageHeight") * NumberField("pageWidth");
    FusionPro.Composition.AddVariable('size', size);
    

     

    Creating a text rule called "size" will also override the value of the "size" field:

    var NumberField = function (field) { return StringToNumber(Field(field)); }
    return NumberField("pageHeight") * NumberField("pageWidth");
    

     

    If you're asking how to set the content of the "SquareInches" text frame in your template, you can do that like this:

    var NumberField = function (field) { return StringToNumber(Field(field)); }
    FindTextFrame("SquareInches").content = NumberField("pageHeight") * NumberField("pageWidth");
    

  17. Any way to get this done in Version 9.3.36? I'm not seeing getting version 10 any time soon.:(

     

    This is how I would do it:

    First, you need to remove all of the content from your overflow frame ("Donations2") on page two. That frame will be populated by "Donations1" if the text doesn't fit.

     

    Since you're querying your data file for all records of the same "DonorID," once a particular donor ID has been processed, it's safe to assume all subsequent records of the same donor ID have already been composed. So, you need to tell FusionPro to only compose a record when the "DonorID" changes so that you end up with seven composed records rather than 114. You can do that by creating a "OnRecordStart" callback rule and adding this line:

    FusionPro.Composition.composeThisRecord = FieldChanged("DonorID");
    

     

    Making those two changes should give you the results that you described in your first post. That being said, you can simplify your "ListOfDonations" rule by modifying it to:

    var returnStr = '';
    var ex = new ExternalDataFileEx(PrimaryInputFile(), FusionPro.inputFileDelimiter);
    
    // Get an array of record numbers with matching donor IDs.
    var records = ex.FindRecords('DonorID', Field("DonorID"));
    
    // Only loop through the records with matching donor IDs,
    // rather than looping through every record every time.
    for (var rec in records) {
     var ExField = function(field) { return ex.GetFieldValue(records[rec], field); }
     returnStr += ['Gift Date', 'Gift Applied To', 'Gift Comment', 'Gift Method', 'Gift Amount'].map(ExField).join('<t>') + '<br>';
    }
    
    return returnStr;
    

  18. Maybe this would do the trick:

    var result = [];
    var meals = {};
    var fields = ["Guest Entree", "2nd Guest", "3rd Guest", "4th Guest", "5th Guest", "6th Guest", "7th Guest"]
                 .map(Field).filter(String).forEach(function(s){ meals[s] = meals[s] + 1 || 1 });
    
    for (var mealChoice in meals)
     result.push((count = meals[mealChoice]) + ' ' + mealChoice + (count > 1 ? 's' : ''));
    
    return result.join('<br/>\n');
    

  19. Sure, it's possible; check out the static example below. Just create the array as a JavaScript Global:

    globalArray = [];
    

    Then you can populate the array at the start of each record in OnRecordStart:

    for (var i = 1; i <=5; i++)
       globalArray.push({
           'recordNumber': i,
           'fieldData': 'Value' + i
       });
    

     

    Then your rule could walk the array:

    var result = '';
    globalArray.forEach(function(s) {
       result += 'recordNumber: ' + s.recordNumber + '. fieldData: ' + s.fieldData + '.<br/>\n';
    });
    return result;
    

     

    Then your rule would return:

    recordNumber: 1. fieldData: Value1.

    recordNumber: 2. fieldData: Value2.

    recordNumber: 3. fieldData: Value3.

    recordNumber: 4. fieldData: Value4.

    recordNumber: 5. fieldData: Value5.

×
×
  • Create New...