**************************************************************************************************** * PROGRAM OVERVIEW **************************************************************************************************** * * PROGRAM: output_report.sas * Created (mm/dd/yyyy): 02/24/2021 * *-------------------------------------------------------------------------------------------------- * PURPOSE: This macro drives the calling of each macro to produce a report * * Program inputs: * * * Program outputs: * - qrp_report.pdf * - qrp_report.xlsx * * PARAMETERS: * - destination: ODS destination. Valid values: excel or pdf * - font: font * - fontsize = font size * - footfontsize = font size for footnotes, typically set as 1 pt smaller than fontsize * - bordersize = line thickness for top/bottom report lines * * Programming Notes: * * *-------------------------------------------------------------------------------------------------- * CONTACT INFO: * Sentinel Coordinating Center * info@sentinelsystem.org * ***************************************************************************************************; %macro output_report(destination = , font=, fontsize=, footfontsize=, bordersize=); %put =====> MACRO CALLED: output_report; ***************************************************************************************************; * Set up and initialize report template ***************************************************************************************************; /*report template*/ %report_template(outputtype = &destination., fontsize = &fontsize., font = &font.); ods listing close; ods select all; ods noresults; %if &destination. = excel %then %do; ods excel file="&output.qrp_report.xlsx" NOGTITLE style = qrp_report_excel options(embedded_titles="yes" sheet_interval="proc" gridlines="off" embedded_footnotes= "yes" flow="tables"); %end; %if &destination. = pdf %then %do; /* Prevent path from being written to log */ proc printto log=log; run; ods pdf file="&output.qrp_report&reportid..pdf" NOGTITLE dpi=300 pdftoc=1 style = qrp_report_pdf; /* Resume writing to log */ proc printto log="&OUTPUT.qrp_report_log&reportid..log"; run; %end; ods noproctitle; options nodate nonumber orientation=portrait; ods escapechar="^"; title; /* Counter for figure number */ %let figurenum=1; /* Counter for table number */ %let tablenum=1; /*leavebehindreport logo*/ %if &leavebehindreport. = Y %then %do; %if %str("&logofile") ne %str("") & &destination. = pdf %then %do; title j=L "^{style[preimage='&input./&logofile.']}" ' '; %end; %end; ***************************************************************************************************; * Table of Contents ***************************************************************************************************; %if &destination. = excel %then %do; ods excel options(sheet_name="Table of Contents" tab_color = "orange"); %end; ods proclabel = "Table of Contents"; proc report data = tableofcontents nofs nowd headline headskip split="*" style(report) = {rules = none frame = box borderwidth =1pt bordercolor = black cellpadding=1.75pt}; columns ( "Table of Contents" tabnum caption); define tabnum / order=data ' ' style(column)=[just=R width=1.1in fontweight=bold textdecoration=underline]; define caption / order=data ' ' style(column)=[just=L]; run; %if &produceappendixfileonly. = Y %then %goto appendix; ***************************************************************************************************; * Baseline tables ***************************************************************************************************; %baseline_output(); ***************************************************************************************************; * Covariate profile tables ***************************************************************************************************; %if &numprofilecovarstoinclude > 0 %then %do; %baseline_profile_output; %let tablenum = %eval(&tablenum + 1); %end; ***************************************************************************************************; * Effect estimate tables ***************************************************************************************************; %if %index(&reporttype,L2) and %sysfunc(exist(input.&treeaggfile.)) eq 0 %then %do; /* Need to set to landscape so PDF tables don't wrap */ options orientation = landscape; %l2_effect_estimate_output; options orientation = portrait; %end; /*********************************************************************************************/ /* Type 1 and 2 summary tables */ /*********************************************************************************************/ %if %sysfunc(prxmatch(m/T1|T2L1/i,&reporttype.)) %then %do; %if %sysfunc(prxmatch(m/t1cida|t2cida|t2conc/i,&tdatasetlist.)) %then %do; /* Set options to missing to prevent dot from printing in row */ options orientation = landscape; options missing = ' '; %do td = 1 %to &tdatasetlistnum.; %let reporttable = %scan(&tdatasetlist, &td.); %if ^%sysfunc(prxmatch(m/t1cida|t2cida|t2conc/i,&reporttable.)) %then %goto leavet1t2conc; %let tablecount=1; proc sql noprint; select cats(columnname,'_char') ,cats(columnwidth,'in') ,smallcellyn into :outvarlist separated by ' ', :outwidths separated by ' ', :outsmallcells separated by ' ' from tablecolumns where table="&reporttable" order by order; %let tableobs = 0; select max(stratificationorder) into :tableobs trimmed from tablefile where dataset="&reporttable"; quit; %do z = 1 %to &tableobs; %if &stratifybydp = Y %then %let tablecount=1; %else %let tablecount=0; data _null_; set tablefile(where=(dataset="&reporttable" and stratificationorder=&z)); call symputx('tabletitle', tabletitle); call symputx('strataid',levelid1); call symputx('strataname',tablesub); run; %tableletter(); %t1t2conc_output(dataset=final_&reporttable(where=(level="&strataid")), varlist = &outvarlist, stratavar = %quote(&strataname), varwidths = %bquote(&outwidths.), varsmallcells = &outsmallcells, title=%bquote(Summary of &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.)); %if &stratifybydp = Y %then %do; %do dps = 1 %to %eval(&num_dp.); %let maskedID = %scan(&masked_dplist,&dps); %tableletter(); %t1t2conc_output(dataset=final_dps_&reporttable(where=(level="&strataid" and dpidsiteid="&maskedID")), varlist = &outvarlist, stratavar = %quote(&strataname), varwidths = %bquote(&outwidths.), varsmallcells = &outsmallcells, title = %bquote(Summary of &reporttitle. in the &database. for &maskedID from &startdateformatted. to &enddateformatted.&tabletitle.)); %end; %end; %let tablenum = %eval(&tablenum + 1); %end; /* z */ %leavet1t2conc: %end; /* td */ options missing = '.'; options orientation = portrait; %end; /* %sysfunc(prxmatch(m/t1cida|t2cida|t2conc/i,&tdatasetlist.)) */ /*****************************************************************************************/ /* Type 1 and 2 censor tables */ /*****************************************************************************************/ %if %sysfunc(prxmatch(m/t1censor|t2censor|t2followuptime/i,&tdatasetlist.)) > 0 %then %do; options orientation = landscape; %macro t1t2censoroutput(tablename=, tablenametitle=, cattableheader=, conttableheader=); %let tableidlist=; proc sql noprint; select distinct table into: tableidlist separated by ' ' from tablefile(where=(dataset in ("&tablename."))); quit; %isdata(dataset=&tablename.); %if %eval(&nobs.>0) %then %do; %if %str("&tableidlist") ne %str("") %then %do; %do t = 1 %to %sysfunc(countw(&tableidlist.)); %let tableid = %scan(&tableidlist., &t.); %let stratificationorder = 0; proc sql noprint; select max(stratificationorder) into: stratificationorder from tablefile(where=(dataset in ("&tablename.") and table = "&tableid")); quit; /*counter for determining table letter*/ %if %eval(&stratificationorder. = 1) & &stratifybydp. ne Y %then %let tablecount = 0; %else %let tablecount = 1; %do st = 1 %to &stratificationorder.; data _null_; set tablefile(where=(dataset in ("&tablename.") and table = "&tableid" and stratificationorder = &st.)); call symputx('tabletitle', tabletitle); if tablesub = 'overall' then call symputx('strat', 'overall'); else call symputx('strat', tablesub); /*table T1/T3 - determine if continuous metrics should be printed*/ if missing(levelid2) = 0 and tablesub = 'overall' then call symputx('continuousmetrics', 'Y'); else call symputx('continuousmetrics', 'N'); /*table T2 - censor reasons*/ %if &tableid. = T2 %then %do; call symputx('t2censorreasons', censorreason); %end; run; %tableletter(); %if &tableid. = T1 %then %do; %censortable_output_table13(tablename=&tablename., tablenum=&tablenum.&tableletter., title=%quote(Summary of Time to End of &tablenametitle. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.), where=%str(dpidsiteid = 'ALL' and table_name = 'overall' and strat = "&strat."), tablesub=&strat., continuousmetrics=&continuousmetrics., cattableheader=by &cattableheader., conttableheader=%str(&conttableheader. in Days, by Episode), episodesorpatients=Episodes, censorreason=); %if &stratifybydp. = Y & %eval(&st.=1) %then %do; %tableletter(); %censortable_output_table13(tablename=&tablename., tablenum=&tablenum.&tableletter., title=%quote(Summary of Time to End of &tablenametitle. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner), where=%str(dpidsiteid ne 'ALL' and table_name = 'overall' and strat = 'overall'), tablesub=dpidsiteid, continuousmetrics=N, cattableheader=by &cattableheader., conttableheader=%str(&conttableheader. in Days, by Episode), episodesorpatients=Episodes, censorreason=); %end; %end; %else %if &tableid. = T2 %then %do; %censortable_output_table2(tablename=&tablename., title=%quote(Summary of Reasons for End of &tablenametitle. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.), where=%str(dpidsiteid = 'ALL' and table_name = 'overall' and strat = "&strat." and censorcat_sort = 1), reasonlist= &t2censorreasons., tablesub=&strat., tablenum=&tablenum.&tableletter., episodesorpatients=Episodes); %if &stratifybydp. = Y & %eval(&st.=1) %then %do; %tableletter(); %censortable_output_table2(tablename=&tablename., title=%quote(Summary of Reasons for End of &tablenametitle. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner), where=%str(dpidsiteid ne 'ALL' and table_name = 'overall' and strat = "&strat." and censorcat_sort = 1), reasonlist= &t2censorreasons., tablesub=dpidsiteid, tablenum=&tablenum.&tableletter., episodesorpatients=Episodes); %end; %end; %else %if &tableid. = T3 & %eval(&st.=1) %then %do; /*loop through each reason for censoring and within that - loop through stratificationorder*/ %do c = 1 %to %sysfunc(countw(&defaultcensororder., ' ')); %let reason = %scan(&defaultcensororder., &c.); /*check if rows exist in table (censorreason parameter has already been applied in %censortables_createdata*/ data chktable; set &tablename.(where=(table_name="&reason.")); run; %isdata(dataset=chktable); %if %eval(&nobs.>0) %then %do; /*set table letter counter - need to check # of stratifications requested for censor reason*/ proc sql noprint; select count(distinct stratificationorder) into: reasonstratificationorder from tablefile where dataset in ("&tablename.") and table = "&tableid" and findw(censorreason, "&reason.")>0; quit; %if %eval(&reasonstratificationorder. = 1) %then %let tablecount = 0; %else %let tablecount = 1; /*loop through each stratification*/ %do t3st = 1 %to &stratificationorder.; %let censorreasontable = N; data _null_; set tablefile(where=(dataset in ("&tablename.") and table = "T3" and stratificationorder = &t3st.)); call symputx('tabletitle', tabletitle); if tablesub = 'overall' then call symputx('strat', 'overall'); else call symputx('strat', tablesub); /*table T1/T3 - determine if continuous metrics should be printed*/ if missing(levelid2) = 0 and tablesub = 'overall' then call symputx('continuousmetrics', 'Y'); else call symputx('continuousmetrics', 'N'); /*check if censoring reason requested*/ if findw(censorreason, "&reason.")>0 then call symputx('censorreasontable', 'Y'); run; %if &censorreasontable. = Y %then %do; %tableletter(); %censortable_output_table13(tablename=&tablename., tablenum=&tablenum.&tableletter., title=%quote(Summary of Time to End of &tablenametitle. due to %bquote(&&&reason._label) for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.), where=%str(dpidsiteid = 'ALL' and table_name = "&reason" and strat = "&strat."), tablesub=&strat., continuousmetrics=&continuousmetrics., cattableheader=%quote(Censored due to %bquote(&&&reason._label) by &cattableheader.), conttableheader=%str(&conttableheader. in Days, by Episode), episodesorpatients=Episodes, censorreason=&reason.); %end; /*censor reason requested*/ %end; /*loop through stratification*/ proc datasets nowarn noprint lib=work; delete chktable; quit; /*after each censor reason upnumber table*/ %let tablenum = %eval(&tablenum + 1); %end; /*dataset exists*/ %end; /*censor reason loop*/ %end; /*T3*/ %end; /*loop through stratifications*/ /*if table = T1 or T2 - upnumber table*/ %if %sysfunc(prxmatch(m/T1|T2/i,&tableid.)) > 0 %then %do; %let tablenum = %eval(&tablenum + 1); %end; %end; /*underlying data exists*/ %end; /*loop through each table*/ %end; /*table requested*/ %mend; %t1t2censoroutput(tablename=t2followuptime, tablenametitle=At-Risk Period, cattableheader=Episode Length, conttableheader=At-Risk Time); %t1t2censoroutput(tablename=t&typenum.censor, tablenametitle=Observable Data, cattableheader=Observable Time, conttableheader=Observable Time); options orientation = portrait; %end; %end; /*ReportType = T1 and T2L1 summary tables*/ /*********************************************************************************************/ /* Type 4 summary tables */ /*********************************************************************************************/ %if %str("&reporttype") = %str("T4L1") & %str("&tablelist") ne %str("") %then %do; options orientation = landscape; %do tb = 1 %to %sysfunc(countw(&tablelist.)); %let table = %scan(&tablelist., &tb); /*determine if table includes non-pregnant section*/; %let nonpreglabel = %str( ); %let nonpreg = N; %let s=; /*table specific information*/ %let datasuffix=; %let spanningheader=; /*column order*/ %let gestwkorder = ; data _null_; set tablefile(where=(table="&table")); if table in ('T1', 'T2', 'T3', 'T4') then call symputx('datasuffix','moi'); if table in ('T5', 'T6') then do; call symputx('datasuffix','gestwk'); call symputx('gestwkorder','gestwkorder,'); end; if tablesubstrat in ("t4nopreg", "t4nopreggestwk") then do; call symput('nonpreglabel', " and Matched Non-Pregnant Episodes "); call symputx('s', "s"); call symputx('nonpreg', 'Y'); end; run; /* Output dataset only with superscript flags */ proc contents data = final_t4&datasuffix out=_t4vars_ss(keep=name where=(index(name,'_ss'))) noprint; run; proc sql noprint; select name into :superscript_vars separated by ' ' from _t4vars_ss; quit; /* Get number of non-missing observations for each superscript column */ proc univariate data=final_t4&datasuffix outtable=_miss_ss&datasuffix(keep=_var_ _nobs_) noprint; var &superscript_vars; run; /* Only keep non-missing flag values */ %let non_missing_vars=; proc sql noprint; select _var_ into :non_missing_vars separated by ' ' from _miss_ss&datasuffix where _nobs_>0; quit; /* flag each column to determine whether it gets a superscript */ data tablecolumns; set tablecolumns; columnsuperscript = 'N'; %if %str(&non_missing_vars) ne %str() %then %do; %do i = 1 %to %sysfunc(countw(&non_missing_vars)); %let non_missing_var = %scan(&non_missing_vars,&i); if columnname = "%scan(&non_missing_var,1,%str(_))" then columnsuperscript = 'Y'; %end; %end; run; proc sql noprint; select cats(columnname,'_char') ,cats(columnwidth,'in') ,smallcellyn ,columnlabel ,columnheader ,columnsuperscript into :outvarlist separated by ' ', :outwidths separated by ' ', :outsmallcells separated by ' ', :columnlabels separated by '|||', :columnheaders separated by '|||', :columnsuperscripts separated by '|||' from tablecolumns where table="&table" order by &gestwkorder. order; %if &table. = T5 | &table. = T6 %then %do; select distinct spanningheader into: spanningheader trimmed from tablecolumns where table="&table"; %end; quit; %if &stratifybydp = Y %then %let tablecount=1; %else %let tablecount=0; %tableletter(); /*Overall*/ %t4tables_output(table=&table., dataset=final_t4&datasuffix., %if &nonpreg. = N %then %do; where=pregflg = 'Y', %end; %else %do; where=1, %end; tabnum=&tablenum.&tableletter., %if &table. = T1 %then %do; title=%quote(Pregnant Episodes&nonpreglabel.with &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.), %end; %if &table. = T2 %then %do; title=%quote(&reporttitle. Episodes Among Pregnant&nonpreglabel.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted.), %end; %if &table. = T3 %then %do; title=%quote(&reporttitle. Codes Among Pregnant&nonpreglabel.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted., without Adjusting for Same-Day Dispensings), %end; %if &table. = T4 %then %do; title=%quote(&reporttitle. Codes Among Pregnant&nonpreglabel.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted., Adjusting for Same-Day Dispensings), %end; %if &table. = T5 %then %do; title=%quote(Pregnant Episodes&nonpreglabel.with &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Gestational Week), %end; %if &table. = T6 %then %do; title=%quote(&reporttitle. Episodes Among Pregnant&nonpreglabel.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted., by Gestational Week), %end; nonpreg = &nonpreg., varlist = &outvarlist, varwidths = %bquote(&outwidths.), varsmallcells = &outsmallcells, varsuperscripts = &columnsuperscripts, columnstatementlabels = %quote(&columnlabels.), definestatementlabels = %quote(&columnheaders.), spanningheader = %quote(&spanningheader.)); /*By DP*/ %if &stratifybydp. = Y %then %do; %do dps = 1 %to %eval(&num_dp.); %let maskedID = %scan(&masked_dplist,&dps); %tableletter(); %t4tables_output(table=&table., dataset=final_dps_t4&datasuffix., where=dpidsiteid="&maskedID" %if &nonpreg. = N %then %do; and pregflg = 'Y' %end;, tabnum=&tablenum.&tableletter., %if &table. = T1 %then %do; title=%quote(Pregnant Episodes&nonpreglabel.with &reporttitle. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted.), %end; %if &table. = T2 %then %do; title=%quote(&reporttitle. Episodes Among Pregnant&nonpreglabel.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted.), %end; %if &table. = T3 %then %do; title=%quote(&reporttitle. Codes Among Pregnant&nonpreglabel.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., without Adjusting for Same-Day Dispensings), %end; %if &table. = T4 %then %do; title=%quote(&reporttitle. Codes Among Pregnant&nonpreglabel.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., Adjusting for Same-Day Dispensings), %end; %if &table. = T5 %then %do; title=%quote(Pregnant Episodes&nonpreglabel.with &reporttitle. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., by Gestational Week), %end; %if &table. = T6 %then %do; title=%quote(&reporttitle. Episodes Among Pregnant&nonpreglabel.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., by Gestational Week), %end; nonpreg = &nonpreg., varlist = &outvarlist, varwidths = %bquote(&outwidths.), varsmallcells = &outsmallcells, varsuperscripts = &columnsuperscripts, columnstatementlabels = %quote(&columnlabels.), definestatementlabels = %quote(&columnheaders.), spanningheader = %quote(&spanningheader.)); %end; %end; %let tablenum = %eval(&tablenum + 1); %end; /*loop through each table*/ options orientation = portrait; %end; /*ReportType = T4L1 summary tables*/ /*********************************************************************************************/ /* Type 5 summary tables */ /*********************************************************************************************/ %if %str("&reporttype") = %str("T5") %then %do; options orientation = landscape; /*****************************************************************************************/ /* Type 5 Tables T1-T13, T18-T22 */ /*****************************************************************************************/ /*Loop through each tablesub, determine whether to output categorical and/or continuous table*/ %isdata(dataset=t5_tempmap); %if %eval(&nobs.>0) %then %do; %let t5tableobs = &nobs.; %do st = 1 %to %eval(&t5tableobs.); %let cattabledataset = ; %let distabledataset = ; %let tableorder=0; data _null_; set t5_tempmap; if _n_ = &st. then do; call symputx('numtables', numtables); call symputx('tableorder', tableorder); %if %varexist(t5_tempmap,cattable) = 1 %then %do; if missing(cattable)=0 then call symputx('cattabledataset', catx('_',cattable,put(catstratificationorder,best.))); %end; %if %varexist(t5_tempmap,disttable) = 1 %then %do; if missing(disttable)=0 then call symputx('distabledataset', catx('_',disttable,put(diststratificationorder,best.))); %end; end; run; /*Increment the table number and reset the table letter counter*/ %if %eval(&tableorder.=1) %then %do; %if %eval(&st. ^=1) %then %let tablenum = %eval(&tablenum + 1); %let tablecount=1; %end; /*reset table letter counter if only 1 table*/ %if %eval(&numtables.=1) %then %let tablecount=0; %if %str("&cattabledataset.") ne %str("") %then %do; %tableletter(); %t5tables_output(dataset=&cattabledataset.,reporttype=cat); %end; %if %str("&distabledataset.") ne %str("") %then %do; %tableletter(); %t5tables_output(dataset=&distabledataset.,reporttype=dist); %end; %end; %let tablenum = %eval(&tablenum + 1); proc datasets nowarn noprint lib=work; delete _temp_t5_tempmap; quit; %end; /*****************************************************************************************/ /* Type 5 censor tables */ /*****************************************************************************************/ %macro t5censoroutput(tableid = , tablename=, first=, episodesorpatients=); %if %sysfunc(prxmatch(m/T14\b|T16\b/i,&tableid.)) > 0 %then %do; data _null_; set tablefile(where=(dataset in ("t5censor") and table = "&tableid")); /*censor reasons*/ call symputx('t5censorreasons', censorreason); run; /*counter for determining table letter*/ %if &stratifybydp. = Y %then %let tablecount = 1; %else %let tablecount = 0; %tableletter(); %censortable_output_table2(tablename=&tablename., title=%quote(Summary of Reasons &first.Treatment Episodes Ended for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.), where=%str(dpidsiteid = 'ALL' and table_name = 'overall' and strat = "overall" and censorcat_sort = 1), reasonlist= &t5censorreasons., tablenum=&tablenum.&tableletter., tablesub= overall, episodesorpatients=&episodesorpatients.); %if &stratifybydp. = Y %then %do; %tableletter(); %censortable_output_table2(tablename=&tablename., title=%quote(Summary of Reasons &first.Treatment Episodes Ended for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner), where=%str(dpidsiteid ne 'ALL' and table_name = 'overall' and strat = "overall" and censorcat_sort = 1), reasonlist= &t5censorreasons., tablesub=dpidsiteid, tablenum=&tablenum.&tableletter., episodesorpatients=&episodesorpatients.); %end; %let tablenum = %eval(&tablenum + 1); %end; %if %sysfunc(prxmatch(m/T15\b|T17\b/i,&tableid.)) > 0 %then %do; /*loop through each reason for censoring*/ %do c = 1 %to %sysfunc(countw(&defaultcensororder., ' ')); %let reason = %scan(&defaultcensororder., &c.); %let censorreasontable = N; data _null_; set tablefile(where=(dataset in ("t5censor") and table = "&tableid.")); /*check if censoring reason requested*/ if findw(censorreason, "&reason.")>0 then call symputx('censorreasontable', 'Y'); run; %if &censorreasontable. = Y %then %do; /*check if rows exist in table (censorreason parameter has already been applied in %censortables_createdata*/ data chktable; set &tablename.(where=(table_name="&reason.")); run; %isdata(dataset=chktable); %if %eval(&nobs.>0) %then %do; /*note - table is not stratified by DP*/ %censortable_output_table13(tablename=&tablename., tablenum=&tablenum., title=%quote(Summary of Episode Duration for &first.Treatment Episodes Ended due to %bquote(&&&reason._label) for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.), where=%str(dpidsiteid = 'ALL' and table_name = "&reason" and strat = "overall" and not missing(censdays_value_cat_format)), tablesub=overall, continuousmetrics=Y, /*continuous metrics always returned*/ cattableheader=%quote(Censored due to %bquote(&&&reason._label) by Episode Length), conttableheader=%str(Treatment Episode Length, in Days), episodesorpatients=&episodesorpatients., censorreason=&reason.); %let tablenum = %eval(&tablenum + 1); %end; proc datasets nowarn noprint lib=work; delete chktable; quit; %end; %end; %end; %mend; %if %sysfunc(prxmatch(m/T14\b/i,&tablelist.)) > 0 %then %do; %t5censoroutput(tableid=T14, tablename = t5censor_first, first=%str(First ), episodesorpatients=Patients); %end; %if %sysfunc(prxmatch(m/T15\b/i,&tablelist.)) > 0 %then %do; %t5censoroutput(tableid=T15, tablename = t5censor_first, first=%str(First ), episodesorpatients=Patients); %end; %if %sysfunc(prxmatch(m/T16\b/i,&tablelist.)) > 0 %then %do; %t5censoroutput(tableid=T16, tablename = t5censor, first=, episodesorpatients=Episodes); %end; %if %sysfunc(prxmatch(m/T17\b/i,&tablelist.)) > 0 %then %do; %t5censoroutput(tableid=T17, tablename = t5censor, first=, episodesorpatients=Episodes); %end; options orientation = portrait; %end; /*type 5 tables*/ /*********************************************************************************************/ /* Type 6 summary tables */ /*********************************************************************************************/ %if %str("&reporttype") = %str("T6") %then %do; /*****************************************************************************************/ /* Type 6 censor tables */ /*****************************************************************************************/ %if %sysfunc(prxmatch(m/t6censor|t6plota|t6plotb/i,&tdatasetlist.)) > 0 %then %do; options orientation = landscape; %macro t6censor(tableid=); %isdata(dataset=table&tableid.); %if %eval(&nobs.>0) %then %do; /*counter for determining table letter*/ %if &stratifybydp. ne Y %then %let tablecount = 0; %else %let tablecount = 1; %if &tableid = T8 %then %let t6reporttitle=Summary of Episode Duration by Reason Episodes Ended for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.; %if &tableid = T9 %then %let t6reporttitle=Summary of Time to First Switch or Episode End for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.; %if &tableid = T10 %then %let t6reporttitle=Summary of Time to Second Switch or Episode End for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.; data _null_; set tablefile(where=(table = "&tableid")); censorreason=tranwrd(censorreason,"endenrollmentcount","cens_elig"); censorreason=tranwrd(censorreason,"deathcount","cens_dth"); censorreason=tranwrd(censorreason,"endavaildatacount","cens_dpend"); censorreason=tranwrd(censorreason,"endquerycount","cens_qryend"); censorreason=tranwrd(censorreason,"endproductdiscontinuationcount","cens_episend"); censorreason=tranwrd(censorreason,"productdiscontinuationcount","cens_episend"); censorreason=tranwrd(censorreason,"switchedcount","cens_switch"); call symputx('t6censorreasons', censorreason); run; %tableletter(); %t6censor_output(tablenum=&tablenum.&tableletter, dataset=table&tableid, title=%quote(&t6reporttitle), reasonlist=&t6censorreasons, where=%str(dpidsiteid = 'ALL')); %if &stratifybydp. = Y %then %do; %tableletter(); %t6censor_output(tablenum=&tablenum.&tableletter, dataset=table&tableid, title=%quote(&t6reporttitle., by Data Partner), reasonlist=&t6censorreasons, where=%str(dpidsiteid ^= 'ALL'), dptable=Y); %end; %let tablenum = %eval(&tablenum + 1); %end; /*underlying data exists*/ %mend t6censor; %if %sysfunc(prxmatch(m/\bT8\b/i,&tablelist.)) > 0 %then %do; %t6censor(tableid=T8); %end; %if %sysfunc(prxmatch(m/\bT9\b/i,&tablelist.)) > 0 %then %do; %t6censor(tableid=T9); %end; %if %sysfunc(prxmatch(m/\bT10\b/i,&tablelist.)) > 0 %then %do; %t6censor(tableid=T10); %end; options orientation = portrait; %end; %end; /*type 6*/ ***************************************************************************************************; * Code distribution tables ***************************************************************************************************; %if &output_code_distribution. eq Y %then %do; %codedistribution_output; %let tablenum = %eval(&tablenum + 1); %end; ***************************************************************************************************; * Attrition tables ***************************************************************************************************; %if %sysfunc(prxmatch(m/T1|T2L1|T2L2|T4L1|T4L2|T5|T6/i,&reporttype.)) %then %do; /* reset counter to reset table letter */ %let tablecount=1; %do j = %eval(&look_start) %to %eval(&look_end); %if %index(&reporttype,L2) %then %let attrperiodid=_&j; /* Check to see if either dataset exists */ %isdata(dataset=agg_patient_attrition&attrperiodid); %let attrition_patient = &nobs; %isdata(dataset=agg_episode_attrition&attrperiodid); %let attrition_episode = &nobs; %if &attrition_patient > 0 or &attrition_episode > 0 %then %do; %if (&attrition_patient > 0 and &attrition_episode = 0) or (&attrition_patient = 0 and &attrition_episode > 0) %then %do; %let tablecount = 0; %end; options orientation = landscape; %attrition_output(tabletype=episode); %attrition_output(tabletype=patient); options orientation = portrait; %let tablenum = %eval(&tablenum + 1); %end; %end;/*periodid */ %end; ***************************************************************************************************; * Figures ***************************************************************************************************; *********************************************; * L2 Reports: PS Histograms and Forest Plots *********************************************; %if %index(&reporttype,L2) %then %do; %if %index(&figurelist,F1) %then %do; %l2_psdistribution_output; %end; %if %index(&figurelist,F2) and %sysfunc(exist(input.&treeaggfile.)) eq 0 %then %do; %l2_forestplot_driver; %end; %end; ************************************************; * Type 5 Figures ************************************************; options orientation = landscape; %if %sysfunc(prxmatch(m/T5/i,&reporttype.)) %then %do; /* Figures F1, F2, and F3 */ %if %sysfunc(prxmatch(m/F1|F2|F3/i,&figurelist.)) > 0 %then %do; %do figure_count = 1 %to %sysfunc(countw(&figurelist.)); %let current_figure = %scan(&figurelist, &figure_count, ' '); %if ¤t_figure = F1 or ¤t_figure = F2 or ¤t_figure = F3 %then %do; /*set up titles for F123 figures */ %if "¤t_figure" = "F1" %then %do; %let title_f123 = Patient Entry into Study by Month; %let y1label = Monthly number of patients; %let y2label = Cumulative number of patients in study; %let yvarF123 = npts; %end; %if "¤t_figure" = "F2" %then %do; %let title_f123 = Number of Prescription Dispensings in Patients%str(%') First Episodes by Month Patient Entered into Study; %let y1label = Monthly number of prescription dispensings; %let y2label = Cumulative number of prescription dispensings; %let yvarF123 = adjustedcodecount; %end; %if "¤t_figure" = "F3" %then %do; %let title_f123 = Total Days Supply in Patients%str(%') First Episodes by Month Patient Entered into Study; %let y1label = Monthly total days supply; %let y2label = Cumulative days supply; %let yvarF123 = daysupp; %end; /*loop through the figuresubs to create ¤t_figuresub*/ proc sql noprint; select max(stratificationorder) into: max_order from figurefile(where=(figure = "¤t_figure")); quit; %do g = 1 %to %sysfunc(countw(&requestedfigs)); %let figorder = %scan(&requestedfigs,&g); %do t = 1 %to &max_order; %let figuretitle = ""; data _null_; set figurefile(where=(figure = "¤t_figure" and stratificationorder = &t)); call symputx('current_figuresub',figuresub); call symputx('figuretitle', figuretitle); run; data _null_; set figure123(where=(order=&figorder)); if _n_ = 1 then do; call symputx('t5grouplabel',grouplabel); end; run; %tableletter(); %if %sysfunc(countw(&requestedfigs)) = 1 and &max_order = 1 %then %let tableletter = ; %figure_t5_output(figure=¤t_figure, figurenum=&figurenum, figureletter=&tableletter., title=%quote(&title_f123. for &t5grouplabel. in the &database. from &startdateformatted. to &enddateformatted.&figuretitle.), where=figuresub = "¤t_figuresub" and order=&figorder, figuresub=¤t_figuresub., yaxislabel1= &y1label, yaxislabel2= &y2label, yvar=&yvarF123.); %end; %end; %end; %let figurenum = %eval(&figurenum +1); %let tablecount = 1; %end; %end; %end; /*end type 5 plots*/ ************************************************; * Survival plots for L1 and L2 reports - Kaplan-Meier - 1-CDF - CIF ************************************************; %if %sysfunc(exist(input.&treeaggfile.)) eq 0 %then %do; %figure_survivalcurves_output; %end; options orientation = portrait; ***************************************************************************************************; * Appendices ***************************************************************************************************; %appendix: %appendix_output(); ***************************************************************************************************; * Clean up ***************************************************************************************************; /*reset title*/ %let title = ; /* Prevent path from being written to log */ proc printto log=log; run; ods _all_ close; /* Resume writing to log */ proc printto log="&OUTPUT.qrp_report_log&reportid..log"; run; ods listing; ods results; %put =====> END MACRO: output_report ; %mend output_report;