%Let Pgm=utl_DemSho; /*---------------------------------------------*\ | | | A Demo table in less lines of code | | than most stadardized macros | | ( when foreign data and/or formats and | | transformations are required) | | | | I was discouraged when I found that it took | | more time and code to prep data for a | | 'standardized' demographics macro then | | to write this program. The standardized macro| | did not line up the decimal, do pagination | | or make the Title and footnotes | | part of the table. The macro did not allow | | for bold or italic fonts. The macro was | | obviously less flexible then this code. | | | | Note this code lines up decimal points in | | four lines of code,and creates the (N=XX) | | header in one line of SQL. | | | | For a more complete solution with | | | | Page N of M and | | More statistics Mean, Std Min and Max | | | | go to members.aol.com/xlr82sas/utl.html | | | | or just put xlr82sas into ant search engine | | | | Pehaps code like this could be used as a | | template for Tables and listings instead of | | standardized macros. | | | | | | This is an oversimplified example, a more | | complete solution would not requre much more | | code. | | | \*---------------------------------------------*/ Data MkeDat(Label="Create Test Data"); Do Trt= 'Placebo', 'Potion7', 'Potion8', 'Potion9'; Do PatNum=1 to 90; If normal(-1) < .5 then Rce='White'; Else Rce='Black'; If normal(-1) < .4 then Sex='Female'; Else Sex='Male'; If normal(-1) < .7 then output; End; End; Stop; Run; /*---------------------------------------------*\ | | | What MkeDat looks like | | | | | | Pat | | Trt Num Rce Sex | | | | 1 Placebo 1 White Female | | 2 Placebo 2 Black Female | | 3 Placebo 3 White Female | | 4 Placebo 4 White Female | | 5 Placebo 5 White Female | | 6 Placebo 6 White Female | | 7 Placebo 7 Black Male | | 8 Placebo 8 Black Female | | 9 Placebo 9 Black Male | |10 Placebo 10 White Female | |11 Placebo 11 White Female | | | \*---------------------------------------------*/ /*---------------------------------------------*\ | | | Create Statistics and Header | | | | Note the resolve funtion in Sql | | | | When used witht the rtf destination we get | | | | The header | | | | Placebo Potion#7 Potion#8 Potion#9 | | (N=31) (N=33) (N=37) (N=32) | | | | | \*---------------------------------------------*/ Proc sql; Create Table MkeStaTisTic(drop=Nul) as Select /* Header into mac vars */ resolve('%let '!! Trt !!'='!!Trt!!'\-2n(N='!!put( Count(*),2.)!!');') as Nul, %Macro FrqPct(var,cat1,cat2); Put(Sum(&Var.="&cat1."),5.2)!!'('!!put(100*Sum(&Var.="&cat1.")/Count(*),5.1)!!'%)' as %substr(&cat1.,1,3)Pct, Put(Sum(&Var.="&cat2."),5.2)!!'('!!put(100*Sum(&Var.="&cat2.")/Count(*),5.1)!!'%)' as %substr(&cat2.,1,3)Pct, %Mend FrqPct; %FrqPct(Sex,Male,Female) %FrqPct(Rce,Black,White) Trt From MkeDat Group By Trt ; quit; run; %Put Placebo= &Placebo. Potion7= &Potion7. Potion8= &Potion8. Potion9= &Potion9.; /*------------------------------------------------------------------------------*\ | | | Macro vars output from above | | | | Placebo= Placebo\-2n(N=71) Note \-2n is the rtf wrap character | | Potion7= Potion7\-2n(N=64) | | Potion8= Potion8\-2n(N=73) | | Potion9= Potion9\-2n(N=66) | | | | | | MkeStaTisTic Table | | | | MalPct FemPct BlaPct WhiPct Trt | | | | 26.00( 36.6%) 45.00( 63.4%) 23.00( 32.4%) 48.00( 67.6%) Placebo | | 19.00( 29.7%) 45.00( 70.3%) 24.00( 37.5%) 40.00( 62.5%) Potion7 | | 24.00( 32.9%) 49.00( 67.1%) 27.00( 37.0%) 46.00( 63.0%) Potion8 | | 26.00( 39.4%) 40.00( 60.6%) 22.00( 33.3%) 44.00( 66.7%) Potion9 | | | \*------------------------------------------------------------------------------*/ /*---------------------------------------------*\ | | | | | Line up on the last decimal and normalize | | the data structure ( long and skinny ) | | | \*---------------------------------------------*/ Data MkeRow(Keep=Pge Trt Typ Val); Retain Pge 1; Length Typ $3 Cat $3 Val $32 spa $8; Set MkeStaTisTic; /* Allign the last Decimal point as the 4th position from the end of string */ /* use the Ods char \~ as a digit space - note a 'space' is not as wide as a digit */ /* note this code is really not needed for this example see my site for realistic */ /* example */ %Macro FixDecPos; CurDecPos=Index(Left(Reverse(Val)),'.'); If CurDecPos ne 4 Then Do; NumSpa = 4-CurDecPos; Spa=Repeat('\~',NumSpa+1); Val=Compress(Trim(Left(Val))!!"\R/RTF"!!"'"!!Compress(Spa)!!"'"); End; %Mend FixDecPos; Typ="Fem";Val=FemPct ;%FixDecPos; OutPut ; Typ="Mal";Val=MalPct ;%FixDecPos; OutPut ; Typ="Bla";Val=BlaPct ;%FixDecPos; OutPut ; Typ="Whi";Val=WhiPct ;%FixDecPos; OutPut ; run; /*-------------------------------------*\ | | | Output from above | | | | Typ Val Trt | | | | Fem 45.00( 63.4%) Placebo | | Mal 26.00( 36.6%) Placebo | | Bla 23.00( 32.4%) Placebo | | Whi 48.00( 67.6%) Placebo | | Fem 45.00( 70.3%) Potion7 | | Mal 19.00( 29.7%) Potion7 | | Bla 24.00( 37.5%) Potion7 | | Whi 40.00( 62.5%) Potion7 | | Fem 49.00( 67.1%) Potion8 | | Mal 24.00( 32.9%) Potion8 | | Bla 27.00( 37.0%) Potion8 | | Whi 46.00( 63.0%) Potion8 | | Fem 40.00( 60.6%) Potion9 | | Mal 26.00( 39.4%) Potion9 | | Bla 22.00( 33.3%) Potion9 | | Whi 44.00( 66.7%) Potion9 | | | \*-------------------------------------*/ /*---------------------------------------------*\ | | | Sort and transpose for proc report | | | \*---------------------------------------------*/ Proc Sort Data=MkeRow Out=MkeRowSrt; By Typ Trt; Run; Proc Transpose Data=MkeRowSrt Out=MkeFin(Drop=_Name_ Where=(Placebo ne ' ')); By Typ; Var Val; Id Trt; Copy Pge; Run; /*----------------------------------------------------------------------*\ | | | Output from above | | | | Typ Placebo Potion7 Potion8 Potion9 | | | | Bla 23.00( 32.4%) 24.00( 37.5%) 27.00( 37.0%) 22.00( 33.3%) | | Fem 45.00( 63.4%) 45.00( 70.3%) 49.00( 67.1%) 40.00( 60.6%) | | Mal 26.00( 36.6%) 19.00( 29.7%) 24.00( 32.9%) 26.00( 39.4%) | | Whi 48.00( 67.6%) 40.00( 62.5%) 46.00( 63.0%) 44.00( 66.7%) | | | \*----------------------------------------------------------------------*/ /*---------------------------------------------*\ | | | Put out the report | | | | Note how the column headings are done | | | \*---------------------------------------------*/ Options orientation=landscape;run; Ods rtf file="c:\demtbl.rtf"; Ods EscapeChar='\'; Title; Footnote;run; Proc Report Nowd Data=MkeFin ; Cols Pge Typ Placebo Potion7 Potion8 Potion9 ; %let hdr= %str(\S={font_weight=bold font_size=11pt cellwidth=1in}); %let hdr1=%str(\S={font_weight=bold font_size=8pt font_style=italic}); define pge / Order noprint; define typ / Order "&Hdr.Parameter" Style={Just=r} Noprint Order=Data; define Placebo / display "&Hdr.&Placebo." Style={Just=r}; define Potion7 / display "&Hdr.&Potion7." Style={Just=r}; define Potion8 / display "&Hdr.&Potion8." Style={Just=r}; define Potion9 / display "&Hdr.&Potion9." Style={Just=r}; Break before Pge / Suppress Page; Compute Before _page_; MaxPge=1; /* see mu url for setting this value */ PgeNofM="&Hdr1.Page "!!put(Pge,1.)!!" of "!!put(MaxPge,1.); Line @1 PgeNofM $64.; Line "&hdr.Table 1.1 Oversimplified Demographics Table for Demostartion Purposes\{super 1}"; Line "&hdr.Culmination of many posts on SAS-L"; EndComp; Compute Before Typ; Length Txt $64; Dum='09'x; Line @1 Dum $1.; Txt="&Hdr."!!Typ; Line @1 Txt $64.; EndComp; Break after Pge / Suppress Page; Compute after Pge; Dum='09'x; Line @1 Dum $1.; line "&Hdr1.\{super 1}For a more realistic example see /members/aol.com/xlr82sas/utl.html"; EndComp; run; quit; run; ods rtf close; run;