Jump to content

Word does not fit error and Table cell


mcmahand

Recommended Posts

I am setting up a template for a client that requires me to pull in a list of information from an external file and place in a table for each letter. There are several pieces of information that go into each cell and some columns are rather narrow.

 

Unfortunately, one of the columns requires placing names but only leaves about 7/8" width for them. Some of the names (and all of my test data names) can be too long to fit on one line. The result is I get errors like:

 

Word <Testexample_Name_1> does not fit in frame after line 0.

 

The composed results will usually show an arbitrary line break (which is OK), but I know from a similar job last year that if a "word" requires more than 2 lines, the entire cell content will be blank. There could be hundreds (if not thousands) of errors like this in the .msg file. Last year, I had to manually edit the data to force breaks myself. This year, the job is too big to do that.

 

Is there some way to force arbitrary line breaks (and not give errors and not give up at just 2 lines)? Or any ideas for how to make a function that efficiently creates forced line breaks?

 

This would be OK result

--------------
|Testexamp   |
|le_Name_1   |
|            |
|RecordID    |
--------------

 

I do not need copy fitting or other sizing changes. I don't need it to look pretty--it is far more important to include all of the information. I need to keep breaking to new lines as needed.

Link to comment
Share on other sites

The way I would do it is: find out how many lines your field is going to require (using TextMeasure) and if it requires more than 1 line, insert line breaks into your string in order to give you the resulting number of lines.

 

For example: if your field is 30 characters long and takes up 3 lines, insert a line break every 10th character.

function breakText(input,cellWidth){
   var tm = new FusionProTextMeasure;
   tm.pointSize = "12 pt";
   tm.font = "Helvetica";
   tm.maxWidth = cellWidth;
   tm.CalculateTextExtent(input);
   var breaks = tm.textLines-1;
   if (!breaks)
   	return input;

   return input.replace(new RegExp('(.{' + input.length/breaks + '})','g'),'$1<br>');
}

var w = 6300; // 7/8"
var field = 'asdqwertyuiopasdfghjasdqwertyuiopasdfghj'; // Your field

var table = new FPTable();
table.AddColumn(w);
var row = table.AddRow();
var cell = row.Cells[0];
cell.Margins = {Top:0, Bottom:0, Left:0, Right:0};
cell.SetBorders('Thin','Black','Left','Right','Top','Bottom');
row.SetContents( breakText(field,w) );

return table.MakeTags();

Edited by step
Link to comment
Share on other sites

Thanks Ste.

 

Unfortunately, I still have issues using your function with my test data placed in a table cell. I had to set the width to less than half my column width--there are margins but not that much--to break the test names at all. And I still have a real name that errors for some reason when I compose. (I adjusted the code for my font and size, so it's not that either).

 

Not sure what's going on. It seems like your code should work.

 

For the particular job I'm working on, I may use a more "crude" solution. I'm thinking along the lines of figuring out a safe character count for each line and breaking the text at the character count.

Link to comment
Share on other sites

If you've got margins (specifically left and right) those will need to be accounted for in the width. Keeping in mind that left and right margins are measured in 100th's of a point while top and bottom are measured in 10th's of a point. Also, if you're setting your top and bottom margin to 0 like I was, try setting them to something like 10. I don't think tables honor horizontal margins that are set to 0. Can you post an example of the code that's building your table and a sample name that doesn't fit?

 

The other thing I would recommend would be turning off "legacy line leading" if you don't need it. That seems to have some kind of odd affect on table margins especially in tighter cells.

 

I noticed that my original code was adding a break tag to the end of the line as well which may have had yielded some non-desirable results. I've made a few changes that might work better (in red):

function breakText(input,cellWidth){
   var tm = new FusionProTextMeasure;
   tm.pointSize = "12 pt";
   tm.font = "Helvetica";
   tm.maxWidth = cellWidth;
   tm.CalculateTextExtent(input);
   var breaks = tm.textLines-1;
   if (!breaks)
   	return input;

   [color="Red"]input = input.match(new RegExp('(.{' + Math.floor(input.length/breaks) + '})','g')) || [];
   return input.join('<br>');[/color]
}

// Example Table:

var w = 6300; // 7/8"
var field = 'asdqwertyuiopasdfghjasdqwertyuiopasdfghj'; // Your field

var table = new FPTable();
table.AddColumn(w);
var row = table.AddRow();
var cell = row.Cells[0];
[color="red"]cell.Margins = {Top:10, Bottom:10, Left: 100,Right: 100};[/color]
cell.SetBorders('Thin','Black','Left','Right','Top','Bottom');
[color="red"]var margins = 0;
if (cell.Margins) {
   margins += cell.Margins.Left || 0;
   margins += cell.Margins.Right || 0;
}[/color]
row.SetContents( breakText(field, [color="red"]w-margins[/color]) );

return table.MakeTags();

Link to comment
Share on other sites

Actually, I am not setting the margins but am leaving defaults. This table has to overflow to multiple pages, and I found in the past that setting margins does not work well with that.

 

Below is a stripped-down version of my code. The cell width is actually less than 7/8", and the font size is 8pt, but that is accounted for in the code.

 


function breakText(input,cellWidth){
   var tm = new FusionProTextMeasure;
   tm.pointSize = "8 pt";
   tm.font = "Helvetica";
   tm.maxWidth = cellWidth;
   tm.CalculateTextExtent(input);
   var breaks = tm.textLines-1;
   if (!breaks)
   	return input;

   input = input.match(new RegExp('(.{' + Math.floor(input.length/breaks) + '})','g')) || [];
   return input.join('<br>');
}

FPTable.prototype.NewRow = function()
{
   table.AddRows(1);
   return table.Rows[table.Rows.length-1];
}

//Setup column widths for table
var Column00Width = 0.8125 * 7200;
var Column01Width = 0.5 * 7200;

//Start table
var table = new FPTable;
table.AddColumns(Column00Width,Column01Width);

// Add rows as we go...
// Row 1 -------------------------------------------
var row = table.NewRow();
var cell = row.Cells[0];
var margins = 0;
if (cell.Margins) {
   margins += cell.Margins.Left || 0;
   margins += cell.Margins.Right || 0;
}

row.Cells[0].Content = breakText('Subject_Name_1', Column00Width-margins)
   + '<br><br>[Record ID]';

row.Cells[1].Content = '[DOB]';

// Row 2 -------------------------------------------
row = table.NewRow();

row.Cells[0].Content = breakText('Jane Neverendinglastname', Column00Width-margins)
   + '<br><br>[Record ID]';

row.Cells[1].Content = '[DOB]';

// Apply formatting to all the rows.
for (var a = 0; a < table.Rows.length; a++)
{
   for (var b = 0; b < table.Columns.length; b++)
   {
       table.Rows[a].Cells[b].SetBorders("Thin", "Black", "Left", "Right");
       table.Rows[a].Cells[b].SetBorders("Thick", "Black", "Top", "Bottom");
   }
} 

return table.MakeTags();

 

The result is that FP lists an error for each name in the log and does its own wrapping (or lack thereof) that happens without the function. The second row shows that the entire cell content disappears if a word requires more than 2 lines.

textbreakattempt1.png.6c924cbc80e4bd5e6ec6430a748e8b6a.png

 

If I hardcode a value like 3000 for the parameter, the function does work and the errors go away. But I had an idea in mind for this project to just set a character limit instead. While I have the green light for arbitrary breaks, I still wanted to try to break lines at spaces where possible. I found almost exactly what I was thinking of in a post at stack overflow, so I used that instead for the breakText function.

 

I am getting good results, so I will probably stick with the character limit option (as shown below).

 

// Found at
// http://stackoverflow.com/questions/14484787/wrap-text-in-javascript
function testWhite(x) {
   var white = new RegExp(/^\s$/);
   return white.test(x.charAt(0));
};

function breakText(str, maxChars) {
   var newLineStr = '<br>'; done = false; res = '';
   do {                    
       found = false;
       // Inserts new line at first whitespace of the line
       for (z = maxChars - 1; z >= 0; z--) {
           if (testWhite(str.charAt(z))) {
               res = res + [str.slice(0, z), newLineStr].join('');
               str = str.slice(z + 1);
               found = true;
               break;
           }
       }
       // Inserts new line at maxWidth position, the word is too long to wrap
       if (!found) {
           res += [str.slice(0, maxChars), newLineStr].join('');
           str = str.slice(maxChars);
       }

       if (str.length < maxChars)
           done = true;
   } while (!done);

   return res + str;
}

FPTable.prototype.NewRow = function()
{
   table.AddRows(1);
   return table.Rows[table.Rows.length-1];
}

//Setup column widths for table
var Column00Width = 0.8125 * 7200;
var Column01Width = 0.5 * 7200;

//Start table
var table = new FPTable;
table.AddColumns(Column00Width,Column01Width);

// Add rows as we go...
// Row 1 -------------------------------------------
var row = table.NewRow();
var cell = row.Cells[0];
var margins = 0;
if (cell.Margins) {
   margins += cell.Margins.Left || 0;
   margins += cell.Margins.Right || 0;
}

row.Cells[0].Content = breakText('Subject_Name_1', 10)
   + '<br><br>[Record ID]';

row.Cells[1].Content = '[DOB]';

// Row 2 -------------------------------------------
row = table.NewRow();

row.Cells[0].Content = breakText('Jane Neverendinglastname', 10)
   + '<br><br>[Record ID]';

row.Cells[1].Content = '[DOB]';

// Apply formatting to all the rows.
for (var a = 0; a < table.Rows.length; a++)
{  
   for (var b = 0; b < table.Columns.length; b++)
   {
       table.Rows[a].Cells[b].SetBorders("Thin", "Black", "Left", "Right");
       table.Rows[a].Cells[b].SetBorders("Thick", "Black", "Top", "Bottom");
   }
} 
return table.MakeTags();

textbreakattempt2.png.532745bd64bd3a3ba7c59b36bdcc4d8d.png

 

Thanks for your help on this. I like to see different code options--and especially want to understand RegEx better.

Link to comment
Share on other sites

Actually, I am not setting the margins but am leaving defaults. This table has to overflow to multiple pages, and I found in the past that setting margins does not work well with that.

That's part of the issue with passing the width as a parameter to the function that I wrote. If you don't actually specify margins, there aren't any defaults. I mean there are clearly margins in the table cells that we can see but there is not a default value in the FPTable object that we can access and account for. Which means that this value will always be 0 and the width being passed as a parameter to the 'breakText' function will always be the exact width of the cell (because cell.Margins isn't defined):

var margins = 0;
if (cell.Margins) {
   margins += cell.Margins.Left || 0;
   margins += cell.Margins.Right || 0;
}

As far as margins not working well with Overflow pages, I think that ties into to legacy line leading but I know what you're saying.

 

If I hardcode a value like 3000 for the parameter, the function does work and the errors go away.

This goes back to what I was saying. You're esscentially estimating that the margins take up about 28.5 pts of the entire width and passing the difference to the function.

 

But I had an idea in mind for this project to just set a character limit instead. While I have the green light for arbitrary breaks, I still wanted to try to break lines at spaces where possible. I found almost exactly what I was thinking of in a post at stack overflow, so I used that instead for the breakText function.

 

I am getting good results, so I will probably stick with the character limit option (as shown below).

I'm glad you found something that's working! One word of caution though about that approach: calling that function on a per row basis (and as a result running though that for loop and while loop) could increase your composition time.

Link to comment
Share on other sites

Yeah, I had some concerns about composition time with any of the approaches. Testing so far is promising with the text measure and RegEx taking the same amount of time as looping through strings. Another approach of using a RegEx to split at n characters and no other operations saved about a minute in my test run.

 

Then again, for this job, even double composition time would still be a savings compared to hand editing the data files.

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