***********************************************************************************************; ** Program Name : adsl_fu_d2_p3_saf.sas **; ** Date Created : 10Mar2021 **; ** Programmer Name : XIONGR03 **; ** Purpose : Create adsl_fu_d2_p3_saf **; ** Input data : adsl **; ** Output file : adsl_fu_d2_p3_saf.html **; ***********************************************************************************************; options mprint mlogic symbolgen mprint symbolgen mlogic nocenter missing=" "; ods escapechar="~"; proc datasets library=WORK kill nolist nodetails; quit; **Setup the environment**; %let prot=/Volumes/app/cdars/prod/sites/cdars4/prjC459/nda2_unblinded_esub/bla_esub_adam/saseng/cdisc3_0; libname datvprot "&prot./data_vai" access=readonly; %let outpath=&prot./analysis/esub; %let outlog=&outpath./logs/adsl_fu_d2_p3_saf.log; %let outtable=&outpath./output/adsl_fu_d2_p3_saf.html; ******************************************************************************************; * Clean *; ******************************************************************************************; options mprint mlogic symbolgen; title; footnote; proc delete data=work._all_; run; proc printto log="&outlog" new; run; data adsl; length FUP2CAT1$ 100 FUP2CAT2$ 100 FUPCAT1$ 100 FUPCAT2$ 100; set DATVPROT.ADSL; if . 0 then call symput('_trtlb'||compress(put(_trt, 4.)), trim(left(_str))); end; run; *----------------------------------------------------------------------; * Count number of patients in each treatment. ; *----------------------------------------------------------------------; proc sql noprint; select compress(put(count(*), 5.) ) into :_trt1 - :_trt3 from (select distinct USUBJID, _trt from _data1 where NEWTRTN is not missing) group by _trt; select compress(put(count(*), 5.) ) into :_trt4 from (select distinct USUBJID from _data1 where NEWTRTN is not missing); quit; *----------------------------------------------------------------------; * Generate a dataset containing all by-variables ; *----------------------------------------------------------------------; proc sort data=_data1 out=_bydat1(keep=_datasrt _dummyby) nodupkey; by _datasrt; run; data _bydat1; set _bydat1 end=eof; by _datasrt; retain _preby 0; drop _preby; _byvar1=0; if eof then do; call symput("_preby1", compress(put(_byvar1, 4.))); if 0=0 then output; end; run; data _bydat1; set _bydat1; by _datasrt; length _bycol _byindnt $50 _bylast $10; _bycol=" "; _byindnt=" "; _bylast=" "; run; proc sort data=_bydat1; by _datasrt; run; proc sort data=_data1 out=_data1; by _datasrt; run; data _null_; set _data1 end=eof; if eof then call symput('dptlab', vlabel(FUPCAT2N)); run; data _anal1; length FUPCAT2N 8; set _data1; where same and FUPCAT2N is not missing; _blcksrt=1; _cnt=1; _cat=1; if _trt <=0 then delete; output; run; proc sort data=_anal1; by _datasrt _blcksrt FUPCAT2N _trt _cat; run; *--- Counts for each by-sequence, dependant var, and treatment combination ---*; data _temp1; set _anal1; output; run; proc sort data=_temp1 out=_temp91 nodupkey; by _datasrt _blcksrt _cat FUPCAT2N _trt USUBJID; run; proc freq data=_temp91; format FUPCAT2N; tables _datasrt*_blcksrt*_cat * FUPCAT2N * _trt / sparse norow nocol nopercent out=_pct1(drop=percent); run; proc sort data=_anal1 out=_denom1(keep=_datasrt _cat) nodupkey; by _datasrt _cat; run; data _denom1; set _denom1; by _datasrt _cat; label count='count'; _trt=1; count=&_trt1; output; _trt=2; count=&_trt2; output; _trt=3; count=&_trt3; output; run; *----------------------------------------------------------------------; * Create _DENOMF a frame dataset for the denominators ; *----------------------------------------------------------------------; data _denomf1; _datasrt=1; set _bydat1(keep=); * All treatment groups ; _trt1=0; _trt2=0; _trt3=0; * _CAT is the subgroup variable ; _cat=1; output; run; *----------------------------------------------------------------------; * Transpose _DENOM into _DENOMIN to get COUNT as _TRTn columns ; *----------------------------------------------------------------------; proc sql noprint; select put(nobs - delobs, 12.) into :_nobs from dictionary.tables where (libname="WORK" and memname="_DENOM1"); select setting into :miss from dictionary.options where upcase(optname)="MISSING"; quit; proc transpose data=_denom1 out=_denomin1(drop=_name_ _label_) prefix=_trt; by _datasrt _cat; var count; id _trt; run; proc sql noprint; select put(nobs - delobs, 12.) into :_nobs from dictionary.tables where (libname="WORK" and memname="_PCT1"); select setting into :miss from dictionary.options where upcase(optname)="MISSING"; quit; proc sort data=_pct1 out=_expv1 (keep=_datasrt _blcksrt FUPCAT2N) nodupkey; by _datasrt _blcksrt FUPCAT2N; run; proc sort data=_expv1; by _datasrt _blcksrt FUPCAT2N; run; proc sort data=_anal1 out=_catlabel1 (keep=_datasrt _blcksrt FUPCAT2N FUPCAT2) nodupkey; by _datasrt _blcksrt FUPCAT2N; run; data _expv1; merge _expv1 (in=_a) _catlabel1 (in=_b); by _datasrt _blcksrt FUPCAT2N; if _a; run; proc sql noprint; select put(nobs - delobs, 12.) into :_nobs from dictionary.tables where (libname="WORK" and memname="_PCT1"); select setting into :miss from dictionary.options where upcase(optname)="MISSING"; quit; proc sort data=_expv1; by _datasrt _blcksrt FUPCAT2N; run; data _frame1; set _expv1; by _datasrt _blcksrt FUPCAT2N; length _catLabl $100; _catLabl=FUPCAT2; if first._blcksrt then _catord=0; _catord + 1; _trt=1; _cat=1; output; _trt=2; _cat=1; output; _trt=3; _cat=1; output; run; *----------------------------------------------------------------------; * Merge the _PCT dataset with its frameup dataset(_FRAME) ; *----------------------------------------------------------------------; proc sort data=_frame1; by _datasrt _blcksrt _cat FUPCAT2N _trt; run; proc sort data=_pct1; by _datasrt _blcksrt _cat FUPCAT2N _trt; run; data _pct1; merge _frame1(in=_inframe) _pct1; by _datasrt _blcksrt _cat FUPCAT2N _trt; if _inframe; if count=. then count=0; run; *----------------------------------------------------------------------; * Delete Zero filled MISSING category rows for each combination of; * _datasrt &_byvar _blcksrt; *----------------------------------------------------------------------; proc sort data=_pct1; by _datasrt _blcksrt FUPCAT2N; run; data _miss1(keep=_datasrt _blcksrt FUPCAT2N totcount); set _pct1; where FUPCAT2N=9998; retain totcount; by _datasrt _blcksrt FUPCAT2N; if first.FUPCAT2N then totcount=0; totcount=totcount+count; if last.FUPCAT2N; run; data _pct1(drop=totcount); merge _pct1 _miss1; by _datasrt _blcksrt FUPCAT2N; if totcount=0 then delete; run; *******************************************************************; *IF PCTDISP=CAT/DPTVAR then add dptvar into denomitor frame dataset; *******************************************************************; *----------------------------------------------------------------------; * Merge the _DENOMIN with its frame up dataset (_denomf) ; *----------------------------------------------------------------------; proc sort data=_denomf1; by _datasrt _cat; run; proc sort data=_denomin1; by _datasrt _cat; run; data _denomin1; merge _denomf1(in=_inframe) _denomin1; by _datasrt _cat; if _inframe; _blcksrt=1; run; *----------------------------------------------------------------------; * Merge in _PCT(counts) with the _DENOMIN(denominator for percents) ; *----------------------------------------------------------------------; proc sort data=_pct1; by _datasrt _cat; run; data _pct1; if 0 then set _basetemplate; merge _denomin1(in=_a) _pct1; by _datasrt _cat; if _a; _varname="FUPCAT2N "; _vrlabel="Original blinded placebo-controlled follow-up period "; _rwlabel=_catLabl; if FUPCAT2N=9998 then do; _rwlabel="Missing "; _catord=9998; end; else if FUPCAT2N=9999 then do; _rwlabel="Total "; _catord=9999; end; if _catord=. then _catord=9997; run; proc sort data=_pct1; by _datasrt _blcksrt _catord FUPCAT2N _trt _cat; run; *----------------------------------------------------------------------; * Create _CVALUE variable to display results. ; * Create _ROWSRT variable to order results. ; *----------------------------------------------------------------------; data _base1; length _catlabl $200; set _pct1 end=eof; by _datasrt _blcksrt _catord FUPCAT2N _trt _cat; retain _rowsrt 0 _rowmax 0; array _trtcnt(*) _trt1-_trt4; drop _rowmax _cpct; length _cpct $100; _cpct=' '; _module='mcatstat'; if count > . then _cvalue=put(count, 5.); else _cvalue=put(0, 5.); *----------------------------------------------------------------------; * Format percent to append to display value in _CVALUE ; *----------------------------------------------------------------------; if _trt ne . then do; if _trtcnt(_trt) > 0 then do; percent=count / _trtcnt(_trt) * 100; if percent > 0 then do; if round(percent, 0.1) GE 0.1 then _cpct="(*ESC*){nbspace 1}("||strip(put(percent, 5.1))||")"; else _cpct="(*ESC*){nbspace 1}(0.0)"; _cvalue=trim(_cvalue)||_cpct; end; end; end; if length(_cvalue) < 13 then do; *----------------------------------------------------------------------; * Put character A0x at right most character to pad text; *----------------------------------------------------------------------; substr(_cvalue, 13, 1)='A0'x; end; if first.FUPCAT2N then do; _rowsrt=_rowsrt + 1; _rowmax=max(_rowsrt, _rowmax); end; _datatyp='data'; _indent=0; _dptindt=0; _vorder=1; _rowjump=1; if upcase(_rwlabel)='_NONE_' then _rwlabel=' '; _indent=4; _dptindt=0; if _trt=3 +1 then _trt=9999; if eof then call symput('_rowsrt', compress(put(_rowmax, 4.))); _direct="TOP "; _p=2; run; data _base1; set _base1; _vhlabel="Subjects (%) with length of follow-up of:"; run; data _null_; set _data1 end=eof; if eof then call symput('dptlab', vlabel(FUPCAT1N)); run; data _anal2; length FUPCAT1N 8; set _data1; where same and FUPCAT1N is not missing; _blcksrt=2; _cnt=1; _cat=1; if _trt <=0 then delete; output; run; proc sort data=_anal2; by _datasrt _blcksrt FUPCAT1N _trt _cat; run; *--- Counts for each by-sequence, dependant var, and treatment combination ---*; data _temp2; set _anal2; output; run; proc sort data=_temp2 out=_temp92 nodupkey; by _datasrt _blcksrt _cat FUPCAT1N _trt USUBJID; run; proc freq data=_temp92; format FUPCAT1N; tables _datasrt*_blcksrt*_cat * FUPCAT1N* _trt / sparse norow nocol nopercent out=_pct2(drop=percent); run; proc sort data=_anal2 out=_denom2(keep=_datasrt _cat) nodupkey; by _datasrt _cat; run; data _denom2; set _denom2; by _datasrt _cat; label count='count'; _trt=1; count=&_trt1; output; _trt=2; count=&_trt2; output; _trt=3; count=&_trt3; output; run; *----------------------------------------------------------------------; * Create _DENOMF a frame dataset for the denominators ; *----------------------------------------------------------------------; data _denomf2; _datasrt=1; set _bydat1(keep=); * All treatment groups ; _trt1=0; _trt2=0; _trt3=0; * _CAT is the subgroup variable ; _cat=1; output; run; *----------------------------------------------------------------------; * Transpose _DENOM into _DENOMIN to get COUNT as _TRTn columns ; *----------------------------------------------------------------------; proc sql noprint; select put(nobs - delobs, 12.) into :_nobs from dictionary.tables where (libname="WORK" and memname="_DENOM2"); select setting into :miss from dictionary.options where upcase(optname)="MISSING"; quit; proc transpose data=_denom2 out=_denomin2(drop=_name_ _label_) prefix=_trt; by _datasrt _cat; var count; id _trt; run; proc sort data=_pct2 out=_expv2 (keep=_datasrt _blcksrt FUPCAT1N) nodupkey; by _datasrt _blcksrt FUPCAT1N; run; proc sort data=_expv2; by _datasrt _blcksrt FUPCAT1N; run; proc sort data=_anal2 out=_catlabel2 (keep=_datasrt _blcksrt FUPCAT1N FUPCAT1) nodupkey; by _datasrt _blcksrt FUPCAT1N; run; data _expv2; merge _expv2 (in=_a) _catlabel2 (in=_b); by _datasrt _blcksrt FUPCAT1N; if _a; run; proc sql noprint; select put(nobs - delobs, 12.) into :_nobs from dictionary.tables where (libname="WORK" and memname="_PCT2"); select setting into :miss from dictionary.options where upcase(optname)="MISSING"; quit; proc sort data=_expv2; by _datasrt _blcksrt FUPCAT1N; run; data _frame2; set _expv2; by _datasrt _blcksrt FUPCAT1N; length _catLabl $100; _catLabl=FUPCAT1; if first._blcksrt then _catord=0; _catord + 1; _trt=1; _cat=1; output; _trt=2; _cat=1; output; _trt=3; _cat=1; output; run; *----------------------------------------------------------------------; * Merge the _PCT dataset with its frameup dataset(_FRAME) ; *----------------------------------------------------------------------; proc sort data=_frame2; by _datasrt _blcksrt _cat FUPCAT1N _trt; run; proc sort data=_pct2; by _datasrt _blcksrt _cat FUPCAT1N _trt; run; data _pct2; merge _frame2(in=_inframe) _pct2; by _datasrt _blcksrt _cat FUPCAT1N _trt; if _inframe; if count=. then count=0; run; proc sort data=_pct2; by _datasrt _blcksrt FUPCAT1N; run; data _miss2(keep=_datasrt _blcksrt FUPCAT1N totcount); set _pct2; where FUPCAT1N=9998; retain totcount; by _datasrt _blcksrt FUPCAT1N; if first.FUPCAT1N then totcount=0; totcount=totcount+count; if last.FUPCAT1N; run; data _pct2(drop=totcount); merge _pct2 _miss2; by _datasrt _blcksrt FUPCAT1N; if totcount=0 then delete; run; *******************************************************************; *IF PCTDISP=CAT/DPTVAR then add dptvar into denomitor frame dataset; *******************************************************************; *----------------------------------------------------------------------; * Merge the _DENOMIN with its frame up dataset (_denomf) ; *----------------------------------------------------------------------; proc sort data=_denomf2; by _datasrt _cat; run; proc sort data=_denomin2; by _datasrt _cat; run; data _denomin2; merge _denomf2(in=_inframe) _denomin2; by _datasrt _cat; if _inframe; _blcksrt=2; run; *----------------------------------------------------------------------; * Merge in _PCT(counts) with the _DENOMIN(denominator for percents) ; *----------------------------------------------------------------------; proc sort data=_pct2; by _datasrt _cat; run; data _pct2; if 0 then set _basetemplate; merge _denomin2(in=_a) _pct2; by _datasrt _cat; if _a; _varname="FUPCAT1N "; _vrlabel="Total exposure from Dose 2 to cutoff date "; _rwlabel=_catLabl; if FUPCAT1N=9998 then do; _rwlabel="Missing "; _catord=9998; end; else if FUPCAT1N=9999 then do; _rwlabel="Total "; _catord=9999; end; if _catord=. then _catord=9997; run; proc sort data=_pct2; by _datasrt _blcksrt _catord FUPCAT1N _trt _cat; run; *----------------------------------------------------------------------; * Create _CVALUE variable to display results. ; * Create _ROWSRT variable to order results. ; *----------------------------------------------------------------------; data _base2; length _catlabl $200; set _pct2 end=eof; by _datasrt _blcksrt _catord FUPCAT1N _trt _cat; retain _rowsrt 0 _rowmax 0; array _trtcnt(*) _trt1-_trt4; drop _rowmax _cpct; length _cpct $100; _cpct=' '; _module='mcatstat'; if count > . then _cvalue=put(count, 5.); else _cvalue=put(0, 5.); *----------------------------------------------------------------------; * Format percent to append to display value in _CVALUE ; *----------------------------------------------------------------------; if _trt ne . then do; if _trtcnt(_trt) > 0 then do; percent=count / _trtcnt(_trt) * 100; if percent > 0 then do; if round(percent, 0.1) GE 0.1 then _cpct="(*ESC*){nbspace 1}("||strip(put(percent, 5.1))||")"; else _cpct="(*ESC*){nbspace 1}(0.0)"; _cvalue=trim(_cvalue)||_cpct; end; end; end; if length(_cvalue) < 13 then do; *----------------------------------------------------------------------; * Put character A0x at right most character to pad text; *----------------------------------------------------------------------; substr(_cvalue, 13, 1)='A0'x; end; if first.FUPCAT1N then do; _rowsrt=_rowsrt + 1; _rowmax=max(_rowsrt, _rowmax); end; _datatyp='data'; _indent=0; _dptindt=0; _vorder=1; _rowjump=1; if upcase(_rwlabel)='_NONE_' then _rwlabel=' '; _indent=4; _dptindt=0; if _trt=3 +1 then _trt=9999; if eof then call symput('_rowsrt', compress(put(_rowmax, 4.))); _direct="TOP "; _p=2; run; data _base2; set _base2; where _trt eq 1; run; data _final; set _base1 _base2; run; proc sort data=_final; by _datasrt _blcksrt _rowsrt; run; *----------------------------------------------------------------------; * At least one of TRT and STAT is vertical; *----------------------------------------------------------------------; data _final; set _final; drop __trt; if _trt=9999 then __trt=3 + 1; else __trt=_trt; if __trt=. then __trt=1; _column=_trt; if _column=9999 then _column=3 + 1; run; proc sort data=_final out=_final; by _datasrt _blcksrt _rowsrt _column; run; data _linecnt; set _final end=eof; by _datasrt _blcksrt _rowsrt _column; retain _totline _maxval _maxrow _rwlbtag _vrlbtag 0 _maxline _linecnt; keep _datasrt _blcksrt _totline _linecnt _maxrow; if _rowjump=. then _rowjump=1; if first._blcksrt then do; *----------------------------------------------------------------------; * Count words inside DATA step ; *----------------------------------------------------------------------; _token=repeat(' ', 99); _count=1; _token=scan(_vrlabel, _count, "|"); if _token=: '_' then _tag=1; else _tag=0; do while(_token ^=' '); _count=_count + 1; _token=scan(_vrlabel, _count, "|"); end; _linecnt=_count - 1 + _tag; _totline=_linecnt; if _vrlabel ne ' ' and _vrlabel ne '^' & _datatyp='data' then _vrlbtag=1; end; if first._rowsrt then do; *----------------------------------------------------------------------; * Count words inside DATA step ; *----------------------------------------------------------------------; _token=repeat(' ', 99); _count=1; _token=scan(_rwlabel, _count, "|"); if _token=: '_' then _tag=1; else _tag=0; do while(_token ^=' '); _maxrow=max(_maxrow, length(_token) + _indent); _count=_count + 1; _token=scan(_rwlabel, _count, "|"); end; _maxline=_count - 1 + _tag; if _rwlabel ne ' ' then _rwlbtag=1; _totline + _rowjump - 1; end; *----------------------------------------------------------------------; * Count words inside DATA step ; *----------------------------------------------------------------------; _token=repeat(' ', 99); _count=1; _token=scan(_cvalue, _count, "|"); if _token=: '_' then _tag=1; else _tag=0; do while(_token ^=' '); _maxval=max(_maxval, length(_token)); _count=_count + 1; _token=scan(_cvalue, _count, "|"); end; _ccnt=_count - 1 + _tag; _maxline=max(_maxline, _ccnt); if last._rowsrt then _totline=_maxline + _totline; if last._blcksrt then do; _totline=_totline - _rowjump + 1; output; end; if eof then do; call symput('_valwid', compress(put(_maxval, 3.))); call symput('_rwlbtag', put(_rwlbtag, 1.)); call symput('_vrlbtag', put(_vrlbtag, 1.)); end; run; data _final; length _direct $20; _direct=' '; merge _final _linecnt; by _datasrt _blcksrt; run; proc sql noprint; create table rspon as select distinct _trt, _column , _vrlabel as _rwlabel , _datasrt, _blcksrt, (min(_rowsrt)-0.5) as _rowsrt , _dptindt as _indent , 0 as _dptindt from _final(where=(_vrlabel^=' ')) group by _trt, _column , _datasrt, _blcksrt, _vrlabel; quit; proc sql noprint; create table hspon as select distinct _trt, _column , _vhlabel as _rwlabel , _datasrt, _blcksrt, (min(_rowsrt)-0.9) as _rowsrt , _dptindt as _indent , 0 as _dptindt from _final(where=(_vhlabel^=' ')) group by _trt, _column , _datasrt, _blcksrt, _vhlabel; quit; data ADSL_FU_D2_P3_SAF; length _rvalue $800; set _final rspon hspon end=eof; _rwindt=sum(_indent, _dptindt); if _rwindt <=0 then _rvalue=_rwlabel; else _rvalue=repeat(byte(160), _rwindt-1)||_rwlabel; _dummy=1; if _trt=. then _trt=1; run; proc sort data=ADSL_FU_D2_P3_SAF; by _datasrt _trt _blcksrt _rowsrt; run; data treat; length FMTNAME $8 start 8 label $200; fmtname='TREAT'; do start=1 to 3 + ("N"="Y"); label=symget('_TRTLB'|| compress(put(start, 4.))); label=trim(label) || "| (N~{super a}=" || compress(symget("_TRT" || compress(put(start, 4.)))) || ")" || "|n~{super b} (%)"; output; end; run; proc format cntlin=treat; run; *---------------------------------------------------------------------; * titles and footnotes ; *---------------------------------------------------------------------; ods escapechar="~"; title1 "Follow-up Time After Dose 2 (*ESC*){unicode 2013} Phase 2/3 Subjects (*ESC*){unicode 2265}16 Years of Age (*ESC*){unicode 2013} Safety Population"; footnote1 "Note: Human immunodeficiency virus (HIV)-positive subjects are included in this summary but analyzed and reported separately."; footnote2 "a.(*ESC*){nbspace 5}N = number of subjects in the specified group, or the total sample. This value is the denominator for the percentage calculations."; footnote3 "b.(*ESC*){nbspace 5}n = Number of subjects with the specified characteristic."; data outdata1; set ADSL_FU_D2_P3_SAF; if upcase(_module)='MCATSTAT' then _cvalue=transtrn(compress(_cvalue), '(', ' ('); _fixvar=1; _fix2var=1; run; proc sort data=outdata1; by _datasrt _trt _blcksrt _rowsrt; run; proc sql noprint; select distinct start, label into :start1, :_trlbl1 - :_trlbl99 from treat order by start; quit; proc sort data=outdata1 out=_pre_transposed; by _fixvar _fix2var _datasrt _blcksrt _rowsrt _rvalue _trt; run; data _pre_transposed; set _pre_transposed; if _trt=9999 then _trt=3 +1; run; proc transpose data=_pre_transposed out=_column_transposed (drop=_name_) prefix=TRT; by _fixvar _fix2var _datasrt _blcksrt _rowsrt _rvalue; var _cvalue; id _trt; run; data REPORT; set _column_transposed; _dummy=1; run; proc sort data=report; by _datasrt _blcksrt _rowsrt _dummy; run; ods html file="&prot./analysis/esub/output/adsl_fu_d2_p3_saf.html"; proc report data=report nowd list missing contents="" split="|" spanrows style(report)={} style(header)={} style(column)={}; column _fixvar _fix2var _datasrt _blcksrt _rowsrt ("" _rvalue) (("Vaccine Group (as Administered)~{line}" TRT1 TRT2) TRT3 _dummy); define _fixvar / group noprint; define _fix2var / group noprint; define _datasrt / group order=internal noprint; define _blcksrt / group order=internal noprint; define _rowsrt / group order=internal noprint; define _rvalue / group id " " order=data style(column)={just=left width=60mm rightmargin=18px} style(header)={just=left} left; define _dummy / sum noprint; define TRT1 / group nozero "&_trlbl1." spacing=2 style(column)={width=35mm leftmargin=12px} style(header)={just=center} center; define TRT2 / group nozero "&_trlbl2." spacing=2 style(column)={width=35mm leftmargin=12px} style(header)={just=center} center; define TRT3 / group nozero "&_trlbl3." spacing=2 style(column)={width=35mm leftmargin=12px} style(header)={just=center} center; break before _fixvar / contents="" page; compute before _fix2var; line @1 " ~n "; endcomp; compute after _blcksrt; line " ~n "; endcomp; run; ods HTML close; proc printto; run;