BookmarkSubscribeRSS Feed
Steff
Calcite | Level 5
Hi

I'm using a truetype font with ODS PDF using multiple PROC REPORT. I want to fit as many reports onto each page, running each PROC REPORT without bylines and creating my own column headers and bylines as needed.
I'd like to know exactly how much text will fit on a line so that I can keep track of the number of lines used.
My output dataset is pre-processed to put markers on the observations that should start new pages. The compute blocks execute before these markers to print the column headers.

Do I need to emulate the ODS PDF kerning algorithm to find the line breaks for each variable of each observation?

My current method estimates where the line breaks will be by counting the lengths as the number of characters in the output values. This doesn't always give the correct estimate for the number of lines needed per observation. The output can run over to the next page before I've run the header compute block for a new page.

Any other ideas?

Thanks
Steff
4 REPLIES 4
Cynthia_sas
SAS Super FREQ
Hi:
You asked:

Do I need to emulate the ODS PDF kerning algorithm to find the line breaks for each variable of each observation?


ODS PDF is designed to produce TABULAR output -- output in tables, even from a DATA step report and certainly from PROC REPORT. While you can simulate BYLINES with ODS TEXT= or with the LINE statement in a COMPUTE block, I fear that you will find it almost impossible to write your own column headers or to attempt "kerning".

In the LISTING destination (where you could be sure that the letter 'i' took up the same amount of space as the letter 'w') it might have been possible to determine "line length" by knowing what letters were on each line. However, in ODS destinations, the LINESIZE option is totally ignored. ODS PDF uses such factors as margin options, table width, cell width, cell padding, border width, font size and font face together with the variable values to determing how much of an observation will fit on one "line".

To fit as many "reports" onto a physical page as possible, look at the previous forum posting on dealing with very wide reports. There is a program there that shows how changes in font-size, cell padding and page orientation will impact ODS PDF (and ODS RTF) output.

And, of course, if you have multiple PROC REPORT steps or PROC REPORT with the PAGE option on the BREAK or RBREAK statement or BY group processing, you will want to look at the STARTPAGE=NO option in order to suppress normal page breaks that are inserted when a procedure issues a page break command.

Hopefully, the previous forum posting will get you started and the use of STARTPAGE=NO along with some of those suggestions will help you worry less about doing the kerming yourself and more about just tailoring the style characteristics to get the report you want.

cynthia
Steff
Calcite | Level 5
Thanks Cynthia

I'm following a 'house style' for this output. The code for manually creating the by-lines and column headers is already there and works pretty well using compute blocks. The main difference with the standard report output is that the column headers are only ever printed once per page.

The new piece that I'm doing is to put consecutive reports on the same page, if they'll fit, controlling page breaks with the STARTPAGE=NO option and the PAGE option on the BREAK statement. What I've done works OK, except that it sometimes wrongly estimates how many lines remain on a page.

The key calculation comes from:
nFlowLines = max(ceil(length(cValue) / nColWidth),nFlowLines);
where nFlowLines is the number of lines needed to print an observation,
cValue is the text to be printed (or formatted text of a numeric value), and
nColWidth is the column width assigned for the column. This loops around for every cell of the table being printed.

This sometimes underestimates the actual number of rows that ODS PDF will use with the result that the output spills over the page.
Can you suggest a better way of estimating the number of lines that ODS PDF will use?

Regards
Steff
Cynthia_sas
SAS Super FREQ
Steff:
No, I really can't think of any way to second guess ODS PDF. Too much goes into building a report row and too much goes into assembling those report rows into a "page image". The only time I ever had any success with calculating number of lines per page was when I used the LISTING destination and only the LISTING destination.

ODS PDF is not creating a report in a vacuum...First, PROC REPORT is building the output object, then that output object is sent forward to the destination, at which point style and/or customizing information is added as appropriate to the destination. So for example, the SAME PROC REPORT step could generate different results when sent to 2 different destinations, because the style/ font/ cellpadding/ etc information was different for the 2 destinations. An HTML report generated from PROC REPORT can be as wide as it needs to be, so as the output object is sent to the HTML destination, width controls have little impact, except for the explicit OUTPUTWIDTH or CELLWIDTH style attributes.

On the other hand, the PDF file is bound by physical margin limits (which are different from number of lines) -- a PDF file that has bigger margins will get fewer report lines per page than a PDF file that has smaller margins. Similarly, a PDF file using in a smaller font will be able to get more report lines per physical page than a PDF file which uses a larger font.

It sounds like your "house style" wants LISTING-like control in the world of ODS. The only way I know to get that kind of control -- and even then, I don't know that you have "line per page" type of control -- would be to look at the DATA step object interface (experiemental) to ODS.
http://support.sas.com/rnd/base/datastep/dsobject/

Or, you could work with Tech Support to see whether there's a way that more conventional techniques could be used to replicate your house style.

cynthia
Steff
Calcite | Level 5
Hi Cynthia

Thanks for the advice. The data step object interface is interesting.

I think I'll try tweak the line counting algorithm to overestimate when a new line is needed. It might not fill the last few lines on a page, but that looks better than running over onto a new page.

Your help is much appreciated.

Regards
Steffen

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 1906 views
  • 0 likes
  • 2 in conversation