Word-wrap of ACROSS values in PDF output



Word-wrap of ACROSS values in PDF output

By Jack Gross
Problem:

When using ACROSS in a report rendered in PDF format, it is often necessary to apply word-wrap to the horizontal sort values that appear over each column, in order to reduce the width of the report and avoid paneling.

But there is no WebFocus Stylesheet syntax to force word-wrap of the Across data values (WRAP=OFF suppresses word-wrap, while WRAP=ON just prevents generation of code to suppress word-wrap. Regardless, the values is rendered straight-across).

Is there a work-around that will wrap the ACROSS values, so as to reduce the width of the report?

 

Approach:

The essential idea is to split up the long “Across” field into a series of fields (part1, part2, …), and position them, one over the other, running across the page. Once we define part1, etc. we can replace the single horizontal sort:

ACROSS LongAcrossField as ’name’

With a series of sorts


ACROSS part1 AS ’name’
     ACROSS part2 AS ’’
     ACROSS part3 AS ’’

And the result will have the same appearance as a single word-wrapped field.

 

Details:

* Splitting up the text:
WebFocus has a pair of character functions that can be used in tandem to segment the text and map the successive portions to individual variables.

PARAG(inlength, intext, 'delim', tokensize, result)

GETTOK(intext, inlength, token_number, 'delim', tokenlength, result)

PARAG prepares a long string of text for display as successive lines of a “paragraph”. It splits the input value into “tokens” (to become the lines of the paragraph), inserting a “delimiter” character between the tokens. As long as the words in the text do not exceed the requested token size, the delimiter character will be inserted between words (replacing the blank immediately after the last word in the token) so there is no loss of data.

GETTOK is a companion function that returns the nth “token” of a text string that has been tokenized by PARAG.

For example, the following code splits some flowing text into tokens of length 40, and displays the first 4 tokens:

DEFINE FILE CAR
  LGA/A180 WITH COUNTRY =
'Four score and seven years ago our fathers brought forth 
on this continent, a new nation, conceived in Liberty, 
and dedicated to the proposition that all men are created equal.';
  LGA40/A180 = PARAG(180,LGA,'\',40,'A180');
  LINE1 /A40=GETTOK(LGA40,180, 1, '\',40,'A40');
  LINE2 /A40=GETTOK(LGA40,180, 2, '\',40,'A40');
  LINE3 /A40=GETTOK(LGA40,180, 3, '\',40,'A40');
  LINE4 /A40=GETTOK(LGA40,180, 4, '\',40,'A40');
  LINE5 /A40=GETTOK(LGA40,180, 5, '\',40,'A40');
  LINE6 /A40=GETTOK(LGA40,180, 6, '\',40,'A40');
  SCALE/A40='123456789*123456789*123456789*123456789*';
  NADA/A1='';
END
TABLE FILE CAR
  WRITE LGA
  OVER LGA40
  OVER NADA AS ''
  OVER LINE1  OVER LINE2  OVER LINE3
  OVER LINE4  OVER LINE5  OVER LINE6  OVER SCALE
ON TABLE PCHOLD FORMAT PDF
ON TABLE SET STYLE *
  FONT=COURIER,SIZE=6,ORIENTATION=LANDSCAPE,GRID=OFF,
$
END

Output:
LGA     Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are
LGA40 Four score and seven years ago our\fathers brought forth on this continent,\a new nation, conceived in Liberty, and\dedicated to the proposition that all\men are

LINE1  Four score and seven years ago our
LINE2  fathers brought forth on this continent,
LINE3  a new nation, conceived in Liberty, and
LINE4  dedicated to the proposition that all
SCALE 123456789*123456789*123456789*123456789*

* Formatting the report:
We will use as specimen data a Focus file, senate.foc, containing the name, state, and party of the US Senators of the states that start with “N”.

Senate.mas:

FILENAME=SENATE,SUFFIX=FOC
SEGNAME=SENATOR,SEGTYPE=S3
 FIELD=STATE,STATE,A15,$
 FIELD=LNAME,LNAME,A12,$
 FIELD=FNAME,FNAME,A15,$
 FIELD=PARTY,PARTY,A2,$

SenateLoad_N.fex:

-* SenateLoad_N.fex : load data for states starting with "N" into Senate.foc
USE
 BASEAPP/SENATE.FOC NEW
END
CHECK FILE senate
CREATE FILE senate
MODIFY FILE senate
FIXFORM STATE/15 LNAME/12 FNAME/15 PARTY/2
MATCH * KEYS
 ON NOMATCH INCLUDE
 ON MATCH REJECT
DATA
NEBRASKA       Johanns     Mike           R
NEBRASKA       Nelson      Ben            D
NEVADA         Ensign      John           R
NEVADA         Reid        Harry          D
NEW HAMPSHIRE  Gregg       Judd           R
NEW HAMPSHIRE  Shaheen     Jeanne         D
NEW JERSEY     Lautenberg  Frank R.       D
NEW JERSEY     Menendez    Robert         D
NEW MEXICO     Bingaman    Jeff           D
NEW MEXICO     Udall       Tom            D
NEW YORK       Gillibrand  Kirsten E.     D
NEW YORK       Schumer     Charles E.     D
NORTH CAROLINA Burr        Richard        R
NORTH CAROLINA Hagan       Kay R.         D
NORTH DAKOTA   Conrad      Kent           D
NORTH DAKOTA   Dorgan      Byron L.       D
END

Here is the original version of the report:

-* SenateList1.FEX
DEFINE FILE SENATE
  COUNT/I3S WITH LNAME=1;
END
TABLE FILE SENATE
HEADING
"&FOCFEXNAME : SENATORS BY PARTY ACROSS STATE"
" "
SUM COUNT
  BY PARTY
  ACROSS STATE
ON TABLE ROW-TOTAL AND COLUMN-TOTAL
ON TABLE PCHOLD FORMAT PDF
ON TABLE SET STYLE *
TYPE=REPORT,
  ORIENTATION=LANDSCAPE,
  SQUEEZE=ON,
  FONT=COURIER,SIZE=10,
  GRID=ON,
$
ENDSTYLE
END

Here is the PDF output, Senate_List1.pdf .

Note that the report goes to two panels (PAGE 1.1, PAGE 1.2), with the warning:
(FOC3218) NOTE: REPORT WILL BE PANELED; TOTAL WIDTH IS: 12.29 INCHES

In the second version, SenateList_2.fex, we use PARAG and GETTOK to split the state names.

-* SenateList2.FEX 
DEFINE FILE SENATE
  XSTATE/A14=PARAG(14,STATE,'\',9,'A14');
  STATE1/A9=GETTOK(XSTATE,14, 1,'\',9,'A9');
  STATE2/A9=GETTOK(XSTATE,14, 2,'\',9,'A9');
  COUNT/I3S WITH LNAME=1;
END
TABLE FILE SENATE
HEADING
"&FOCFEXNAME : SENATORS BY PARTY ACROSS STATE"
" "
SUM COUNT
  BY PARTY
  ACROSS STATE1 AS ‘STATE'
  ACROSS STATE2 AS ''
ON TABLE ROW-TOTAL AND COLUMN-TOTAL
ON TABLE PCHOLD FORMAT PDF
ON TABLE SET STYLE *
TYPE=REPORT,
  ORIENTATION=LANDSCAPE,
  SQUEEZE=ON,WRAP=ON,
  FONT=COURIER,SIZE=10,
  GRID=ON,
$
ENDSTYLE
END

Here is the PDF output, SenateList_2.pdf.

While splitting the Across values has narrowed the report and avoided the paneling problem, the method can have an unwanted side-effect, as the sample output illustrates:

If several of the Across values, when split by PARAG, have identical first tokens, then in the output for “ACROSS PART1 ACROSS PART2” the value for line 1 will be left blank in the report in the second and subsequent columns.

In the sample, four state names start with “NEW”, and for three of them the text wraps after the first word, so the first line for New Hampshire, New Jersey and New Mexico contains just the word “NEW”; so the first line for New Jersey and New Mexico is left blank.

Similarly, the splitting of the text and sorting across its two component lines can cause the columns to appear in the wrong order. (Thus, if Staten Island were to secede and became a separate state named New Dorp, its column would belong at the start of the list, but because of the way the names split it would appear between New Mexico and New York.)

Version three addresses this issue – but will have a different side-effect.

-* SenateList3.FEX
DEFINE FILE senate
  XSTATE/A14=PARAG(14,STATE,'\',9,'A14');
  STATE1/A9=GETTOK(XSTATE,14, 1,'\',9,'A9');
  STATE2/A9=GETTOK(XSTATE,14, 2,'\',9,'A9');
  COUNT/I3S WITH LNAME=1;
END
TABLE FILE senate
HEADING
"&FOCFEXNAME : SENATORS BY PARTY ACROSS STATE"
" "
SUM COUNT
  BY PARTY
    ACROSS STATE NOPRINT
    ACROSS STATE1 AS ''
    ACROSS STATE2 AS ''
ON TABLE ROW-TOTAL AND COLUMN-TOTAL
ON TABLE PCHOLD FORMAT PDF
ON TABLE SET STYLE *
TYPE=REPORT,
  ORIENTATION=LANDSCAPE,
  SQUEEZE=ON,
  FONT=COURIER,SIZE=10,
  GRID=ON,
$
ENDSTYLE
END

Here is the PDF output, SenateList_3.pdf.

Adding the original text field, STATE, as the highest-level horizontal sort field (with NOPRINT to keep it from displaying) ensures that the original sort order is maintained, and also forces a top-level sort break at every column, so repeated values in the next level are displayed.

But now the report reverts to paneling!

Here is what happened: WebFocus makes the columns wide enough to accommodate the widest cell – but in that process it is apparently taking the “ACROSS textfield NOPRINT” row into account, so we are back where we started.

To address this issue, we define a numeric surrogate field that has minimal width and produces the same order as sorting on the full text field.

Here is out final code:

-* SenateList4.FEX
JOIN CLEAR *
DEFINE FILE SENATE
  XSTATE/A14=PARAG(14,STATE,'\',9,'A14');
  STATE1/A9=GETTOK(XSTATE,14, 1,'\',9,'A9');
  STATE2/A9=GETTOK(XSTATE,14, 2,'\',9,'A9');
END
TABLE FILE SENATE
  WRITE COMPUTE SEQ/I3=SEQ+1;
  STATE1 STATE2
    BY STATE
ON TABLE HOLD AS TITLES FORMAT FOCUS INDEX STATE
END
JOIN STATE IN SENATE TO STATE IN TITLES
DEFINE FILE SENATE
  COUNT/I3S WITH LNAME=1;
END
TABLE FILE SENATE
HEADING
"&FOCFEXNAME : SENATORS BY PARTY ACROSS STATE"
" "
SUM COUNT
  BY PARTY
    ACROSS SEQ NOPRINT
    ACROSS STATE1 AS ''
    ACROSS STATE2 AS ''
ON TABLE ROW-TOTAL AND COLUMN-TOTAL
ON TABLE PCHOLD FORMAT PDF
ON TABLE SET STYLE *
TYPE=REPORT,
  ORIENTATION=LANDSCAPE,
  SQUEEZE=ON,
  FONT=COURIER,SIZE=10,
  GRID=ON,
$
ENDSTYLE
END

Here is the PDF output, SenateList_4.pdf.

Click here to download the zipped file, which has all the master files, fex files, and output pdf files.

If any questions, please contact Jack at jacobbgross@hotmail.com.