Hi everyone,
I need to include in some listings a header for all the pages containing the name of the sponsor, protocol version, run date and so on. On the other hand the title of the listing is required to appear just once at the beggining of the document in the body. For that reason I thought on the following approach:
ods escapechar='~'; title1 j=l "Sponsor name" j=r "Page ~{thispage} of ~{lastpage}"; title2 j=l "Protocol vX.X (DDMMMYY)" j=r "Run Date: &sysdate"; ods text="~S={font_face='Arial' fontsize=8pt width=100% just=c fontstyle=italic} Listing X.X.X. This is the title of the listing"; ods text="~S={font_face='Arial' fontsize=8pt width=100% just=c fontstyle=italic} "; /* An extra line to avoid the title to be too close to the listing */ ods rtf style=customstyle path="&listings" file="Listing X.X.X. This is the title of the listing (&sysdate).doc"; proc report data=indataset split='|' nowd headline headskip missing spanrows style(report)={width=100%} style(header)={background=very light grey borderbottomcolor=black} ; column (trtarm subjid adate visit test result); define trtarm / display 'Study Arm' group flow; define subjid / display 'Subject ID' group flow; define adate / noprint order order=internal; define visit / 'Visit' order order=data flow; define test/ display 'Test name' flow; define result/ display 'Test result' flow; compute after/style=[just=L]; line ''; line 'Some text to be included as footnote'; endcomp; run; ods rtf close;
The issue started when I changed the title of the table from title3 to ods text due to sponsor request.
As the first varaible of the listing (treatment arm) is grouped, it doesn't fit in an entire page and there's an unwanted page break between the title (ods text) and the table.
I have tried with startpage=never/no but it's not working for me. I have found that there is an option (uniform) for ods pdf outputs that seems to do the trick to solve this, but I couldn't find any analogy for the ods rtf.
Any tips or suggestions?
Thank you very much in advance!
An option might be to use TAGSETS.RTF which has some options related to table spacing. ODS TEXT is placed in a table so you might want to consider the option VSPACE=OFF, possibly combined with the changes to the PARSKIP style element. Example here: https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.4/odsug/p19rpsb989jyadn1kgunyh4t8g0e.htm#p00d97...
Thank you for your suggestion @ballardw!
The issue with the unwanted page break right after the table title (ods text) is automatically solved once I define ODS TAGSETS.RTF instead of ODS RTF, but now it seems that the TAGSETS is not properly calculating the page size: I consistently have one page with the header and the maximum rows of table that the page can fit and in the next one a few extra rows will be shown before a page brake and the header is not included.
It seems that the defined paper size is not consistent to the one on which tagsets is basing the calculation of the division of the table.
Any suggestions? I've checked a thousand pages of documentation and I couldn't find any tip.
Thank you in advance!
Without data it is hard to test to be sure of anything working.
If you think you need more, or less, space on a page you can use the system option PAPERSIZE= to set dimensions used.
From the few times I've played with this setting and RTF or PDF output it seems to work more consistently if you set the option before the ODS RTF, or Tagsets.rtf statement. Don't attempt to change it in the middle of a document.
If interested you can check your current setting (so you can reset it ) with
Proc options option=papersize; run; /* which will likely show a name such as*/ PAPERSIZE=LETTER Specifies the paper size to use for printing.
You can set to to specific names or dimensions.
Dimension is done with an options statement such as:
options papersize=(width , height) ;
To set the size to 10 inches wide and 15 inches high: options papersize=(10in, 15in);
you can use pixels, mm, cm.
The Orientation option will honor Papersize, so landscape with the above would use 15in wide and 10in high.
Read the documentation if you want to see all the options.
Hello again @ballardw ,
Quick update! I've been able to get the proper page size changing the columns width in the proc report. Apparently if this procedure has cells that are too crowded causing several line breaks, then the number of lines to be fitted in one page is overestimated causing an unwanted page break or let say "table overflow" over the next page.
Now that this is solved (along with some other minor issues that appeared too), I'm having a different issue. I've defined frame = hsides in my template to show the top and bottom border at each page but since I implemented the tagsets.rft option the bottom border is showing an erratic behaviour: is missing at some pages, OK at other ones and (that's the funny part) appears with different widths not matching with the defined columns. Here I'm showing a sample of the different kind of outcomes I get for different pages (I have blurred the image to avoid showing sensitive information but I guess is enough to ilustrate the issue).
Thank you again for any tips or suggestions!
You will need to show the code for the Template used, the code for the proc report, the ODS options and maybe provide some data to test with. The data does not have to be your actual sensitive values but should demonstrate the same behavior. Or use a SAS supplied data set from SASHELP that has enough variables of the same type you can modify the report code to work with that set.
I don't do a lot of fancy formatting in Proc Report so may @Cynthia_sas can provide some ideas.
I have seen a few cases of attempting to control too many style elements led to interference between options generating inconsistent output.
Thank you for your feedback @Cynthia_sas ,
We did as you proposed, start from scratch and start adding things step by step.
We managed to solve everything but we found that our main problem from the beginning was located in columns with very long content (e.g. System Organ Class/Preferred Term/Verbatim term for Adverse Events listings). In those cases apparently tagsets fails to calculate the proper size of the table piece shown in each page as it takes into account that those colums would take less rows per cell than they actually do. We have been tuning the width of each column to make those fields fit better and the problem was solved. However, I've found this method more manual than I would like, not sure if there is any shortcut. I'll make a summary of the issue to report to Tech Support as you suggested.
Thank you again for your help!
Long data into any cell like structure is problematic. A single variable in SAS has a maximum of 32K characters. Once upon a time when typewriters were actually used a page was typically 60 to 80 characters wide and depending on spacing 30 to 60 rows for about 4800 characters max on a page. So if you have long text a single variable could be considered as approaching 8 pages of data, 7 full and a partial. Which means something is going to "break" across pages. Smaller fonts will reduce the physical space but there are limits as to what is readable.
So, what exactly is the length of the longest value you going to display in the report? If you have much difference between lengths you may need to do some preprocessing and add a variable based to your data creating a page variable that is not printed but used to control pages. But you still have a potential issue if a single variable has some values longer than will fit on a page by itself.
If the result is never actually printed on a physical piece of paper you can increase the display area of tables using the PAPERSIZE system option in SAS but if you intend to print on any paper the limits of the paper and font size are going to break pages.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.