BookmarkSubscribeRSS Feed
deleted_user
Not applicable
Hi all,

I need to display headers in one of my SAS ods pdf. I have created macro values for all the tiles that i need( provider_name, provider_id, exp value, Observed value)

the problem is i need to display all headings (name of the headers) in one line and then their value below these names. I can display these using two title commands in proc report. But as the length of the value is variable how can i set the esact location. Here is one example.

Pvdr name .............pvdr id..........................obs................exp
xyzabs ................123456..........................1.................... 0.5

I have used dots here to show spacing

when the value changes its length also changes. thus the spacing between two value also changes. How can i fix it??
11 REPLIES 11
Peter_C
Rhodochrosite | Level 12
proc print has an option LABEL , which requests the label of the variable (or its name when there is no label) should appear as column heading.

What code are you using to create your report?
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
You cannot influence the exact location of a PROC PRINT column header label value, relative to the column-position of your detail report "body" contents.

However, if you use a DATA step approach to generate your report/output, then, yes, you have full-control of the position of your column header label as it related to the report content, however you then must contend with variances in maximum data-width each execution, as compared to SAS PROC PRINT, when your SAS data variable values change in maximum length, from run to run.

Also, you may have some additional flexibility with PROC REPORT.

It would be most helpful to share your SAS code, fully expanded, in an embedded post-reply (COPY/PASTE from your SAS session log).

Scott Barry
SBBWorks, Inc.
Cynthia_sas
SAS Super FREQ
Hi:
Because ODS PDF uses a proportional spaced font, you will have issues "lining up" text strings when you try to control the whole report. For example, compare the 2 sets of lines below:
** Proportional Font:
wwwwwwwwwwwwwwwwwwww (20 letter 'w')
iiiiiiiiiiiiiiiiiiii (20 letter 'i')

** Compared to fixed pitch font:
[pre]
wwwwwwwwwwwwwwwwwwww (20 letter 'w')
iiiiiiiiiiiiiiiiiiii (20 letter 'i')
[/pre]


Note how only in the "fixed pitch" font, does anything line up. In a fixed pitch font, the letter 'i' takes up the same amount of horizontal space as the letter 'w'. On the other hand, in a proportional font (the first example), the letter 'i' takes up less horizonal space on the line compared to the letter 'w'. Therefore, when you try to write a report the way you describe, you will see "wavy-ness" or the space between 2 values changing.

PROC PRINT, PROC REPORT and other SAS procedures use a TABLE layout with proportional fonts to keep columns lined up when ODS PDF (or ODS HTML or ODS RTF) is used to create reports. I still don't understand your report requirements well enough to understand what you are trying to do. And, since you have only shown 1 observation's worth of output, I have no clear picture on how the report should look if you have multiple providers.

Also, you do not need to put ...... as spacers to show your output. There is a way to display "preformatted" output, such as you want to show. In order to preserve code and output indention, refer to this previous forum posting.
http://support.sas.com/forums/thread.jspa?messageID=27609毙
It talks about how to surround code snippets with [pre] and [/pre] in order to show "lined up" output without resorting to ...... to control spacing.

Seeing the code that you are currently using and a small subset of the data would be useful. If you feel that you cannot post your data, then using some fake data is perfectly acceptable -- but do show more than 1 observation, so we have a sense of how the data looks (more than 1 obs for each ID, for example) and how the final report output needs to be transformed from the input data.

cynthia
deleted_user
Not applicable
The part shown is used in title command not in the data anywhere. here is the code

ods listing close;
ods pdf file = "/data27/xcelqm_N/Aex2012_&mkt._&spc._&ru._&msr_grp_name._0110.pdf" notoc dpi=150 ;
options nodate leftmargin = 0.75in nocenter ;
ods escapechar = "^";
title1 h=8pt f= century j=r bold italic "Confidential";
title2 j=l "^S={preimage = '/data27/xcelqm_N/Logo.jpg' }"; /*image also not showing*/
title3 h=16pt f = arial j=c bold italic "Aexcel - %sysfunc(propcase(&measure_name))";
title4 j = l "_________________________________________________________________________________________________________";
title5 " ";
title6 h=8pt f= arial j=l bold italic "Provider: Market: Speciality: Observed: Expected: ";
title7 h=10pt f= arial j=l bold italic "&space1.&space2.&space3. &space4. &Expected_value.";
title8 j = l "_________________________________________________________________________________________________________";
footnote1 j = l "_________________________________________________________________________________________________________ ";
footnote2 h=8pt f= arial j=c bold italic "Please refer to the letter accompanying this report for your Aexcel disignation status";
footnote3 h=8pt f=Arial j=r italic " Report Date: %sysfunc(today(),mmddyy10.)"
j=c italic "Page ^{thispage} of Page ^{lastpage}";
proc report data = detail3_adv headline headskip nowindows

style(report)=[bordercolor = black background=_undef_ rules=rows frame = void]
style(header)=[just =left font_face = century font_weight = Bold font_size = 8pt font_style = italic background = white]
style(column)=[just =left font_face = arial font_style = Italic font_size = 8pt]
ls =200;
;
column measure_id_key
rollup_id...........;
define........;
run;
ods odf close;

what i am doing is printing some titles in header6 and then their correponding values in header 7. I want to display the values just below the headings. As you said about fixed pitch and proportional font, i think fixed pitch (which i cant have) is the required one. do you have any suggestion so as to line up the headings and values?
deleted_user
Not applicable
I am so sorry but i could not find anything on this link..

http://support.sas.com/forums/thread.jspa?messageID=27609毙
Cynthia_sas
SAS Super FREQ
Hi:
Basically, the note says about the use of [pre ] and [/pre ] (quoted here for clarification purposes about making posts to the forum -- especially of code that you want to have "line up"):
[quote]
It doesn't come up very often, but you can use & for &.

To make text bold surround it with [b ] and [/b ]. For example bold
To make text italic surround it with [i ] and [/i ]. For example italic
To underscore text surround it with [u ] and [/u ]. For example underscore

Surround code snippets with [pre ] and [/pre ] This changes to a typewriter font and retains spaces and line breaks. So

[pre ]
proc print data=sashelp.class;
run;
[/pre ]

becomes

[pre]
proc print data=sashelp.class;
run;
[/pre]

[endquote]

(Note how the indention on the 'run;' was maintained in the "pre-formatted" text, but "disappears" in the regular forum posting font.)

cynthia
Ksharp
Super User
Hi.Cynthia
Can you ask the administrator of this forum to how to make code colorful .

Ksharp
Cynthia_sas
SAS Super FREQ
Hi:
In a proportional spaced font, you would not be able to guarantee that the macro variable for "Expected" value would line up under the string on the line above it.

Depending on what you want to do, however, let's say that you want this:
[pre]
ONE TWO THREE
111 222 333
[/pre]

Or you want the string '111' under the ONE and the string '333' under the THREE, but you don't want anything under 'TWO' -- you can accomplish the variable spacing with the use of multiple options on a TITLE statement, like this (and as shown in the program below):
[pre]
title j=l 'Left' j=c 'Center' j=r 'Right';
[/pre]

And ODS PDF will appropriately left, right and center justify the 3 text strings based on the margin settings, font, etc. Then, a second title statement, also with j=l, j=c and j=r for the text strings would "line up" the new strings under the previous title statement. But within this scheme, you only have 3 positions in which to put text strings. Also, you might not be happy with a long line of underscores -- instead you might want to investigate using the TEXTDECORATION=UNDERLINE style attribute.

Is this a multi page report??? Do you need for this information to appear on the first page or on EVERY page???? You may need to redesign your titles, since absolute placement is not possible within a title statement, the way you want.

Or, investigate ODS LAYOUT with ODS PDF, which may allow you more control. (However, ODS LAYOUT is still pre-production in SAS 9.2 -- so you -might- have to revisit your code when you upgrade to SAS 9.3, IF the syntax changes between now and when ODS LAYOUT becomes production.

If this information only needs to appear on the first page of your output, then you might place this "extra" information into a separate table and use STARTPAGE=NO to put the information on the same page as the main table. (see example #2).

cynthia
[pre]
** Example 1 -- use the j=l, j=c, j=r capabilities of the TITLE statement;
%let one = 111;
%let two = ^{nbspace};
%let expect = 333;

ods listing close;
options nodate nonumber center
topmargin=.5in bottommargin=.5in leftmargin=.5in rightmargin=.5in;
ods pdf file='c:\temp\output\title_stringxx.pdf';
ods escapechar='^';

** with ods escapechar the {nbspace} escapechar function inserts a non-breaking space;
title j=l 'ONE' j=c 'TWO' j=r 'Expected:';
title2 j=l "&one" j=c "&two" j=r "^{style[textdecoration=underline]&expect}";

proc print data=sashelp.class;
run;

ods _all_ close;


** Example 2 -- put the "extra" headers into a separate table;
data smalltable;
ONE = 111;
TWO = ' ';
THREE = '333';
FOUR = '444';
Expected = 'something';
label ONE = 'One:'
TWO = 'Two:'
THREE = 'Three:'
FOUR = 'Four:'
Expected = 'Expected:';
run;

title; footnote;
ods listing close;
options nodate nonumber center
topmargin=.5in bottommargin=.5in leftmargin=.5in rightmargin=.5in;
ods pdf file='c:\temp\output\extra_table.pdf' startpage=no;
ods escapechar='^';

title j=c '#2 Different Approach';

proc report data=smalltable nowd
style(report)={rules=none frame=void cellspacing=0}
style(header)={background=white foreground=black font_weight=bold just=left width=20%}
style(column)={background=white foreground=black font_weight=bold textdecoration=underline just=left};
column one two three four expected;
run;

** note how page 2 only has the TITLE, not the first table;
proc print data=sashelp.shoes (obs=60);
run;

ods _all_ close;
[/pre]
deleted_user
Not applicable
Thanks a ton Cynthia...I am printing it in two rows not using distinct justification for all as suggested by you.

Thanks again.

I have another question though. I want to underline the data only after third observation each time( first after 3rd line then after 6th and then after 9th..so on).
do i need to print "__" using a comput block? or is there any such option?
deleted_user
Not applicable
sorry for type...NOW using the justification 🙂
Cynthia_sas
SAS Super FREQ
Hi:
glad you got the justification working. As you see in my previous code, there is a style attribute called TEXTDECORATION -- that can use to underline or you could use the BORDERBOTTOM--- style attributes (BORDERBOTTOMSTYLE, BORDERBOTTOMCOLOR, BORDERBOTTOMWIDTH, etc) or you could put a fake "break" and do a skipped line (but make the line black or gray). It really depends on what you are trying to achieve.

Each result has ups and downs. Personally, I don't think that the TEXTDECORATION underline looks like a "divider". I think the other two methods give a better divider. But you'll have to judge for yourself. Do note that the COMPUTE AFTER FAKEGRP method does give a line at the bottom of the table, no matter how many "rows" are in the last fake group, because the end of the report is essentially a break point for the last group (which is why you will see a divider line after William for report #1 and #2).

cynthia
[pre]
data class;
set sashelp.class;
retain fakegrp 0;
fakegrp = ceil(_n_/3);
myorder = _n_;
run;

ods listing;
proc print data=class;
var fakegrp myorder name sex age height weight;
run;

ods listing close;
ods pdf file='c:\temp\output\use_border_attr.pdf';

proc report data=class nowd
style(report)={rules=none cellspacing=0 frame=void cellpadding=1px};
title '1) Use BORDERBOTTOMxxxx= style attributes';
column fakegrp name age sex age height weight;
define fakegrp / order noprint;
compute after fakegrp / style={borderbottomstyle=solid borderbottomcolor=black
borderbottomwidth=1px font_size=.01pt};
line ' ';
endcomp;
run;

ods pdf close;


ods pdf file='c:\temp\output\use_blank_color2.pdf';

proc report data=class nowd
style(report)={rules=none cellspacing=0 frame=void cellpadding=1px};
title '2) use background/foreground color of dark gray, but height may be too thick';
column fakegrp name age sex age height weight;
define fakegrp / order noprint;
compute after fakegrp / style={background=cx999999 foreground=cx999999
height=.01pt font_size=.01pt};
line ' ';
endcomp;
run;

ods pdf close;

** use "MYORDER" variable -- which is just a row number;
** this assumes that you already have data in the order you want before;
** you create the MYORDER variable;
ods pdf file='c:\temp\output\use_textdec_attr3.pdf';

proc report data=class nowd
style(report)={rules=none cellspacing=0 frame=void };
title '3) Use TextDecoration -- but underline will only be under values';
column myorder name age sex age height weight;
define myorder / order ;
compute weight;
if mod(myorder,3) = 0 then do;
call define(_row_,'STYLE', 'style={textdecoration=underline}');
end;
endcomp;
run;

ods pdf close;
[/pre]

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 11 replies
  • 1226 views
  • 0 likes
  • 5 in conversation