I use Proc Report to create a listing for the destination tagsets.rtf. I have numeric columns with formats. There is a repetative ID column with subcategories. I want to only print each category once at first appearance and repeat them after a page break, so the reader always knows the ID and respective subgroups. For this I use the "spanrows" option in my Proc Report statement.
To enhance readability I added an empty line for each new ID-variable and after each new subcategory (only for the first subcategory) by using a compute block with a line statement:
compute after <ID-variable> / style={font_size=4pt};
line@1 "";
endcomp;
Displaying the results in "ods listing" works fine, but the output with "tagsets.rtf" does not work as I want, because after such a line break of the subcategory the ID-variable will no longer show up on following pages.
I know this is an issue addressed by SAS providing a workaraound. I tried to use this workaround, but somehow it doesn't work.
For reproducing my issue I created the following dataset:
proc format;
value originf 1="Asia" 2="Europe" 3="USA";
value makef 1="Acura" 2="Audi" 3="BMW" 4="Buick" 5="Cadillac" 6="Chevrolet" 7="Chrysler" 8="Dodge" 9="Ford" 10="GMC"
11="Honda" 12="Hummer" 13="Hyundai" 14="Infiniti" 15="Isuzu" 16="Jaguar" 17="Jeep" 18="Kia" 19="Land Rover" 20="Lexus"
21="Lincoln" 22="MINI" 23="Mazda" 24="Mercedes-Benz" 25="Mercury" 26="Mitsubishi" 27="Nissan" 28="Oldsmobile" 29="Pontiac" 30="Porsche"
31="Saab" 32="Saturn" 33="Scion" 34="Subaru" 35="Suzuki" 36="Toyota" 37="Volkswagen" 38="Volvo";
value typef 1="Hybrid" 2="SUV" 3="Sedan" 4="Sports" 5="Truck" 6="Wagon";
run;
data tst;
retain or mk typ model weight;
set sashelp.cars;
select(origin);
when("Asia") or=1;
when("Europe") or=2;
when("USA") or=3;
otherwise or=.;
end;
select(make);
when("Acura") mk=1; when("Audi") mk=2; when("BMW") mk=3; when("Buick") mk=4; when("Cadillac") mk=5;
when("Chevrolet") mk=6; when("Chrysler") mk=7; when("Dodge") mk=8; when("Ford") mk=9; when("GMC") mk=10;
when("Honda") mk=11; when("Hummer") mk=12; when("Hyundai") mk=13; when("Infiniti") mk=14; when("Isuzu") mk=15;
when("Jaguar") mk=16; when("Jeep") mk=17; when("Kia") mk=18; when("Land Rover") mk=19; when("Lexus") mk=20;
when("Lincoln") mk=21; when("MINI") mk=22; when("Mazda") mk=23; when("Mercedes-Benz") mk=24; when("Mercury") mk=25;
when("Mitsubishi") mk=26; when("Nissan") mk=27; when("Oldsmobile") mk=28; when("Pontiac") mk=29; when("Porsche") mk=30;
when("Saab") mk=31; when("Saturn") mk=32; when("Scion") mk=33; when("Subaru") mk=34; when("Suzuki") mk=35;
when("Toyota") mk=36; when("Volkswagen") mk=37; when("Volvo") mk=38;
otherwise mk=.;
end;
select(type);
when("Hybrid") typ=1; when("SUV") typ=2; when("Sedan") typ=3;
when("Sports") typ=4; when("Truck") typ=5; when("Wagon") typ=6;
otherwise typ=.;
end;
format or originf.
mk makef.
typ typef.;
keep or mk typ model weight;
run;
proc sort data=tst;
by or mk typ;
run;
Then the desired output is created by:
%let filename=&path.\Listings\Proc-Report_spanrows_rtf-tagsets_issue_&sysdate9..doc;
ods listing close;
options nofontembedding orientation=landscape nodate nonumber center ls=150 ps=70;
ods tagsets.rtf style=styles.listings_journal file="&filename." uniform;
ods noproctitle;
ods escapechar = "^";
ods tagsets.rtf startpage=yes;
proc report data=tst center split='*' nowd headline headskip spacing=2 spanrows
style(report) = [cellspacing=0 cellpadding=6] out=tst
/*style(lines) = {font_size=10pt}*/;
columns (or hold_or mk typ model weight);
define or / order left width=10 "Origin";
define hold_or / computed noprint;
define mk / order left width=10 "Make";
define typ / order left width=10 "Type";
define model / order left width=10 "Model";
define weight / left width=14 "Weight (in kg)" f=comma7.0;
compute before or;
hold=or; * Assign new variable "hold", that keeps the value of "or";
endcomp;
compute hold_or;
hold_or=hold; * Pass value of "or" (earlier saved as "hold") to computed variable "hold_or";
if or=. then or=hold;
endcomp;
* Empty line after "make";
compute after mk / style={font_size=4pt};
line@1 "";
endcomp;
* Empty line after "origin";
compute after or / style={font_size=8pt};
line@1 '';
endcomp;
run;
ods tagsets.rtf close;
ods listing;
The resulting Output is attached.
Hi:
Making a first pass reading your program I note a lot of inconsistency that I would clean up first:
That's all I've found so far that I would change. I haven't actually had a chance to run anything yet. Thanks for posting your program that makes the data although it is annoying that you are using a custom style -- I'm not sure how it is different from regular JOURNAL style.
Cynthia
Dear Cynthia,
thank you for your quick reply and helpful comments on my code! I corrected the inconsistencies:
%let filename=&path.\Listings\Proc-Report_spanrows_rtf-tagsets_issue_v2_&sysdate9..rtf;
ods listing close;
options nofontembedding orientation=landscape nodate nonumber center;
ods tagsets.rtf style=styles.journal file="&filename." uniform;
ods noproctitle;
ods escapechar = "^";
ods tagsets.rtf startpage=yes;
proc report data=tst center split='*' nowd spanrows
style(report) = [cellspacing=0 cellpadding=6]
/*out=tst_out style(lines) = {font_size=10pt}*/;
columns (or hold_or mk typ model weight);
define or / order left style(column)=[cellwidth=1.5cm] "Origin";
define hold_or / computed noprint;
define mk / order left style(column)=[cellwidth=1.5cm] "Make";
define typ / order left style(column)=[cellwidth=1.5cm] "Type";
define model / order left style(column)=[cellwidth=1.5cm] "Model";
define weight / left style(column)=[cellwidth=2.0cm] "Weight (in kg)" f=comma7.0;
compute before or;
hold=or; * Assign new variable "hold", that keeps the value of "or";
endcomp;
compute hold_or;
hold_or=hold; * Pass value of "or" (earlier saved as "hold") to computed variable "hold_or";
if or=. then or=hold;
endcomp;
* Empty line after "make";
compute after mk / style={font_size=4pt};
line@1 "";
endcomp;
* Empty line after "origin";
compute after or / style={font_size=8pt};
line@1 '';
endcomp;
run;
ods tagsets.rtf close;
ods listing;
Regarding the custom journal-style: I made some changes on the page definitions (e.g. size of page, fontsize). For the sake of this example I can go with the default journal style.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.