Word-wrap of ACROSS values in PDF output
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.
If any questions, please contact Jack at jacobbgross@hotmail.com.