I am having issues adjusting the frame=hsdies and rules=groups options for my PDF output when using proc template. When I output to RTF I have no issues changing the thickness of the borders using the borderwidth option and when I INCREASE the borderwidth it increases, but when i try to make it thinner, it stays too thick. Unfortunately this table will be part of a CSR that was done externally from my company and our standard macros cannot support a table of its type so I need to solve this isse of simply getting the border to be less thick.
Here is my code:
1) The proc template I am using: (I underlined, bolded, and italicized the option that when i increase the value it gets bigger in the PDF but when I decrease it stays too thick...)
%let bottommargin= 0.8in;
%let topmargin= 1in;
%let rightmargin= 1in;
%let leftmargin= 1in;
%let frame=hsides;
%let rules=groups;
proc Template;
define style Landscape_8pt;
parent=styles.printer;
replace fonts /
'docFont' =("Courier",8pt)
'FixedFont' =("Courier",8pt)
'BatchFixedFont' =("Courier",8pt)
'FixedStrongFont' =("Courier",8pt)
'FixedHeadingFont' =("Courier",8pt)
'FixedEmphasisFont' =("Courier",8pt)
'EmphasisFont' =("Courier",8pt)
'HeadingEmphasisFont'=("Courier",8pt)
'StrongFont' =("Courier",8pt)
'HeadingFont' =("Courier",8pt)
'TitleFont' =("Courier",8pt)
'TitleFont2' =("Courier",8pt)
'TitleFont3' =("Courier",8pt) ;
style table /
protectspecialchars=off
frame=&frame
width=9in
rules=&rules
font=fonts('docFont')
borderwidth=0.05pt
cellpadding = 1pt
cellspacing = 1pt;
style parskip from parskip /
font=("Courier", 2pt);
replace HeadersAndFooters from Cell /
font = fonts('TitleFont')
foreground=colors('datafg')
background=colors('databg')
protectspecialchars= off;
replace SystemFooter from TitlesAndFooters /
font=fonts('TitleFont3')
protectspecialchars= off
just=c;
replace body from Document /
bottommargin=&bottommargin
topmargin =&topmargin
rightmargin =&rightmargin
leftmargin =&leftmargin
protectspecialchars= off
;
end;
run;
quit;
2) The proc reports (i have taken out and identifying information)
options orientation=landscape linesize=142 nodate nonumber;
ods escapechar='^';
ods pdf file="&outloc./test.pdf" style=Landscape_8pt;
%let LineSize=142;
TItle4 j=center "Table 14.3.1.22.1";
TItle5 j=center "Symptoms and Findings of Differentiation Syndrome from eCRF IDH-DS";
Title6 j=center "(Safety Population)";
PROC REPORT DATA=final_out nowd missing headline headskip spacing=1 split='~' ;
compute after parcat1n;
line'';
endcomp;
COLUMN ( pagen parcat1n paramn _col_1 _col_2 _col_3 _col_4);
DEFINE PAGEN / WIDTH=8 ORDER order noprint " ";
DEFINE PARAMN / WIDTH=8 order noprint " ";
DEFINE PARCAT1N / WIDTH=8 ORDER order noprint " ";
DEFINE _COL_1 / WIDTH=134 id width=80 left flow style=[asis=on]" ";
DEFINE _COL_2 / WIDTH=20 width=17 center "Study~ (N=&n2)";
DEFINE _COL_3 / WIDTH=20 width=17 center "Placebo ~ (N=&n3)";
DEFINE _COL_4 / WIDTH=20 order width=17 center "Total ~ (N=&n4)";
BREAK AFTER pagen / page skip;
BREAK AFTER parcat1n /skip;
run;
PROC REPORT DATA=final_out nowd missing headline headskip spacing=1 split='~';
compute before _page_;
line '^S={just=left} Pre-Selected to WWW';
endcomp;
compute after parcat1n;
line'';
endcomp;
COLUMN ( pagen parcat1n paramn _col_1 _col_5 _col_6 _col_7);
DEFINE PAGEN / WIDTH=8 ORDER order noprint " ";
DEFINE PARAMN / WIDTH=8 order noprint " ";
DEFINE PARCAT1N / WIDTH=8 ORDER order noprint " ";
DEFINE _COL_1 / WIDTH=134 id width=80 left flow style=[asis=on]" ";
DEFINE _COL_5 / WIDTH=20 width=17 center "Study ~ (N=&n5)";
DEFINE _COL_6 / WIDTH=20 width=17 center "Placebo ~ (N=&n6)";
DEFINE _COL_7 / WIDTH=20 width=17 center "Total ~ (N=&n7)";
BREAK AFTER pagen / page skip;
BREAK AFTER parcat1n /skip;
run;
PROC REPORT DATA=final_out nowd missing headline headskip spacing=1 split='~';
compute before _page_;
line '^S={just=left} Pre-Selected to XXX';
endcomp;
compute after parcat1n;
line'';
endcomp;
COLUMN ( pagen parcat1n paramn _col_1 _col_8 _col_9 _col_10);
DEFINE PAGEN / WIDTH=8 ORDER order noprint " ";
DEFINE PARAMN / WIDTH=8 order noprint " ";
DEFINE PARCAT1N / WIDTH=8 ORDER order noprint " ";
DEFINE _COL_1 / WIDTH=134 id width=80 left flow style=[asis=on]" ";
DEFINE _COL_8 / WIDTH=20 width=17 center "Study ~ (N=&n8)";
DEFINE _COL_9 / WIDTH=20 width=17 center "Placebo ~ (N=&n9)";
DEFINE _COL_10 / WIDTH=20 width=17 center "Total ~ (N=&n10)";
BREAK AFTER pagen / page skip;
BREAK AFTER parcat1n /skip;
run;
PROC REPORT DATA=final_out nowd missing headline headskip spacing=1 split='~';
compute before _page_;
line '^S={just=left} Pre-Selected to YYYY';
endcomp;
compute after parcat1n;
line'';
endcomp;
COLUMN ( pagen parcat1n paramn _col_1 _col_11 _col_12 _col_13);
DEFINE PAGEN / WIDTH=8 ORDER order noprint " ";
DEFINE PARAMN / WIDTH=8 order noprint " ";
DEFINE PARCAT1N / WIDTH=8 ORDER order noprint " ";
DEFINE _COL_1 / WIDTH=134 id width=80 left flow style=[asis=on]" ";
DEFINE _COL_11 / WIDTH=20 width=17 center "Study ~ (N=&n11)";
DEFINE _COL_12 / WIDTH=20 width=17 center "Placebo ~ (N=&n12)";
DEFINE _COL_13 / WIDTH=20 width=17 center "Total ~ (N=&n13)";
BREAK AFTER pagen / page skip;
BREAK AFTER parcat1n /skip;
run;
PROC REPORT DATA=final_out nowd missing headline headskip spacing=1 split='~';
compute before _page_;
line '^S={just=left} Pre-Selected to ZZZZ';
endcomp;
compute after parcat1n;
line'';
endcomp;
COLUMN ( pagen parcat1n paramn _col_1 _col_14 _col_15 _col_16);
DEFINE PAGEN / WIDTH=8 ORDER order noprint " ";
DEFINE PARAMN / WIDTH=8 order noprint " ";
DEFINE PARCAT1N / WIDTH=8 ORDER order noprint " ";
DEFINE _COL_1 / WIDTH=134 id width=80 left flow style=[asis=on]" ";
DEFINE _COL_14 / WIDTH=20 width=17 center "Study ~ (N=&n14)";
DEFINE _COL_15 / WIDTH=20 width=17 center "Placebo ~ (N=&n15)";
DEFINE _COL_16 / WIDTH=20 width=17 center "Total ~ (N=&n16)";
BREAK AFTER pagen / page skip;
BREAK AFTER parcat1n /skip;
RUN;
ods pdf close;
Without data it is extremely hard to test Proc Report output.
Instructions here: https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-dat... will show how to turn an existing SAS data set into data step code that can be pasted into a forum code box using the </> icon or attached as text to show exactly what you have and that we can test code against.
Hi:
Unfortunately, I'm in class this week and not able to run code. However, the first thing I would do is clean up your PROC REPORT and your Template code. Unless you are still running in SAS 9.1, you should not be using the REPLACE statement in your template code. That statement was deprecated starting in SAS 9.2 and I think the only reason they didn't get rid of it was that they didn't want to yank it away from users, but my experience with REPLACE after 9.2 was that it was far better to stick with STYLE or CLASS instead of REPLACE.
System Options like LINESIZE and PAGESIZE are LISTING only options and are ignored by ODS PDF. You should try to set your ODS PDF margins using the regular system option margins (instead of in the template) because as long as you set the options BEFORE ODS PDF starts, they should be respected by PDF. PROC REPORT options like HEADLINE, HEADSKIP, FLOW, WIDTH= are also LISTING only options and will not be respected or even used by ODS PDF. In addition, you have WIDTH= repeated multiple times in one define statement -- which will not work at all, even in LISTING. I've highlighted a few places where these statements should be revised for use with ODS PDF.
If I have a chance when class is over, I will try to run your code. What I know about PDF and borders and line widths is that if you specify a value that is incompatible with the PDF construction of a document or table, then PDF will basically ignore your setting. For example, an attempt to set margins too small or fonts too small will simply result in your settings being ignored. If you need immediate help with this, you should consider opening a track with Tech Support.
Cynthia
Try this quick fix to the proc report line
PROC REPORT DATA=final_out nowd missing headline headskip spacing=1 split='~' style(column)=[borderwidth=0.05pt];
Hi:
Now that class is over I had a chance to work with your code a bit. I changed your template to use Journal style because I wanted to illustrate the border issue without any distraction from changing the borders. Consider this:
Journal style removes the interior table lines and puts a line around the headers and at the bottom of the table. In the multi-page view, the bottom line looks darker than the other lines. However, Adobe Reader has a Loupe tool that you can use to zoom in on a part of the page and if you look at the 2 lines under the tool, you can see that they are the same size, even though they may not look the same when viewed on a screen.
I tweaked your template a bit to remove all the default attributes, to change REPLACE to CLASS and to use Courier New instead of just Courier as the font name. Here's an example of Page 1 zoomed to 125%:
As you can see, when zoomed to 125% the lines are all the same width. When printed they look the same width. Sorry, can't post a printed image here.
I adjusted your _COL_1 variable to have more text and you can see that it do NOT have FLOW in the DEFINE for that column, but the text flows anyway to the column width. I see the width to 9 inches for the whole report and then allowed PROC REPORT to fit the columns in that width. Your WIDTH= option was a LISTING only option and was ignored by ODS PDF and specified incorrectly (some of your statements had 2 WIDTH= for LISTING. I also cleaned up the BREAK statements and put all the COMPUTE blocks and BREAK statements together because conceptually, PROC REPORT has a pre-processing phase that it goes through and it "collects" all the COMPUTE blocks and BREAK statements and executes them as it needs to. Putting the COMPUTE block first was just distracting to me. I also cleaned up your STYLE overrides to refer to STYLE(HEADER) and STYLE(COLUMN) in the DEFINE Statement, as PROC REPORT expects.
I also added a second row with a different PAGEN value in the fake data, to test the BREAK processing on PAGEN. I only did 3 PROC REPORT steps instead of your original number of steps. Here's the code I tested:
ods path work.tmp(update) sasuser.templat(update) sashelp.tmplmst(read);
proc Template;
define style styles.new8;
parent=styles.journal;
class fonts /
'docFont' =("Courier New, Courier",8pt)
'FixedFont' =("Courier New, Courier",8pt)
'BatchFixedFont' =("Courier New, Courier",8pt)
'FixedStrongFont' =("Courier New, Courier",8pt)
'FixedHeadingFont' =("Courier New, Courier",8pt)
'FixedEmphasisFont' =("Courier New, Courier",8pt)
'EmphasisFont' =("Courier New, Courier",8pt)
'HeadingEmphasisFont'=("Courier New, Courier",8pt)
'StrongFont' =("Courier New, Courier",8pt)
'HeadingFont' =("Courier New, Courier",8pt)
'TitleFont' =("Courier New, Courier",8pt)
'TitleFont2' =("Courier New, Courier",8pt)
'TitleFont3' =("Courier New, Courier",8pt) ;
class table /
protectspecialchars=off
font=fonts('docFont')
cellpadding = 1pt;
class parskip /
font=("Courier New, Courier",2pt);
class HeadersAndFooters /
font = ("Courier New, Courier",8pt)
protectspecialchars= off;
class SystemTitle /
font=("Courier New, Courier",8pt)
protectspecialchars= off;
class SystemFooter /
font=("Courier New, Courier",8pt)
protectspecialchars= off;
class body /
protectspecialchars= off;
end;
run;
** create some macro variables;
%let bottommargin= 1in;
%let topmargin= 1in;
%let rightmargin= 1in;
%let leftmargin= 1in;
%let l1 = %str(Twas brillig and the slity toves did gyre and gimble in the wabe.);
%let l2 = %str(All mimsy were the borogroves, and the Momeraths outgrabe.);
%let l3 = %str(Beware the Jabberwock my son, the jaws that bite, the claws that snatch.);
%let l4 = %str(Beware the Jubjub bird and shun the frumious Bandersnatch.);
** set System options. ODS PDF should respect margin options/orientation here;
options orientation=landscape
bottommargin=&bottommargin topmargin=&topmargin
rightmargin =&rightmargin leftmargin=&leftmargin nodate nonumber;
ods escapechar='^';
** read in test data, make _COL_1 bigger to hold multiple lines of text;
** in order to show FLOW behavior in PDF without using FLOW LISTING option;
** added another fake data row to test break for PAGEN variable;
data final_out;
length _col_1 $500;
input pagen paramn parcat1n
_col_1$ _col_2$ _col_3$ _col_4$ _col_5$ _col_6$
_col_7$ _col_8$ _col_9$ _col_10$ _col_11$ _col_12$
_col_13$ _col_14$ _col_15$ _col_16$;
_col_1 = catx('~',pagen,"&l1. &l2. &l3. &l4");
datalines;
1 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
2 1 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
;
run;
** no values for &n macro variables n2-n16, so just used text instead of macro var;
** not sure what TITLE1-TITLE3 are supposed to be so just used placeholders;
** used new style template based on JOURNAL, not on PRINTER style. ;
ods pdf file="c:\temp\testcourier.pdf" style=styles.new8;
title1 'Title1';
title2 'Title2';
title3 'Title3';
TItle4 "Table 14.3.1.22.1";
TItle5 "Symptoms and Findings of Differentiation Syndrome from eCRF IDH-DS";
Title6 "(Safety Population)";
PROC REPORT DATA=final_out nowd missing split='~'
style(report)={width=9in};
COLUMN ( pagen parcat1n paramn _col_1 _col_2 _col_3 _col_4);
DEFINE PAGEN / ORDER order noprint " ";
DEFINE PARAMN / order noprint " ";
DEFINE PARCAT1N / ORDER order noprint " ";
DEFINE _COL_1 / id "Col1"
style(header)={just=l} style(column)=[just=l];
DEFINE _COL_2 / "Study~ (N=-n2)" style(column)=[just=c ];
DEFINE _COL_3 / "Placebo ~ (N=-n3)" style(column)=[just=c ];
DEFINE _COL_4 / "Total ~ (N=-n4)" style(column)=[just=c ];
compute after parcat1n;
line ' ';
endcomp;
BREAK AFTER pagen / page ;
run;
PROC REPORT DATA=final_out nowd missing split='~'
style(report)={width=9in};
COLUMN ( pagen parcat1n paramn _col_1 _col_5 _col_6 _col_7);
DEFINE PAGEN / ORDER order noprint " ";
DEFINE PARAMN / order noprint " ";
DEFINE PARCAT1N / ORDER order noprint " ";
DEFINE _COL_1 / id "Col1"
style(header)={just=l} style(column)=[just=l];
DEFINE _COL_5 / "Study ~ (N=-n5)" style(column)=[just=c];
DEFINE _COL_6 / "Placebo ~ (N=-n6)" style(column)=[just=c] ;
DEFINE _COL_7 / "Total ~ (N=-n7)" style(column)=[just=c];
compute before _page_ / style={just=l};
line 'Pre-Selected to WWW';
endcomp;
compute after parcat1n;
line ' ';
endcomp;
BREAK AFTER pagen / page ;
run;
PROC REPORT DATA=final_out nowd missing split='~'
style(report)={width=9in};
COLUMN ( pagen parcat1n paramn _col_1 _col_8 _col_9 _col_10);
DEFINE PAGEN / ORDER order noprint " ";
DEFINE PARAMN / order noprint " ";
DEFINE PARCAT1N /ORDER order noprint " ";
DEFINE _COL_1 / id "Col1"
style(header)={just=l} style(column)=[just=l];
DEFINE _COL_8 / "Study ~ (N=-n8)" style(column)=[just=c];
DEFINE _COL_9 / "Placebo ~ (N=-n9)" style(column)=[just=c];
DEFINE _COL_10 / "Total ~ (N=-n10)" style(column)=[just=c];
compute before _page_ / style={just=l};
line 'Pre-Selected to XXX';
endcomp;
compute after parcat1n;
line ' ';
endcomp;
BREAK AFTER pagen / page ;
run;
ods pdf close;
title; footnote;
Hope this helps,
Cynthia
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.