/* Generously contributed by Tom Abernathy */ /* (Tom.Abernathy@pfizer.com) */ %macro pageofpp /*------------------------------------------------------------------------------ Post-processor to handle internal pagination of SAS output ------------------------------------------------------------------------------*/ (infile= /* Input file (fileref or quoted filespec) (REQ) */ ,outfile= /* Output file (fileref or quoted filespec) (REQ) */ /* Input and output must be two different files. */ ,text= /* String to find and replace in input file (REQ) */ [Page_00000_of_99999] ,type=TXT /* File format type (TXT LIS LST PS PDF RTF). */ ,justify=L /* Justification of generated text. Ignored when type=RTF. */ /* L=Left R=Right C=Center. */ ); /*------------------------------------------------------------------------------ Read in an output file and replace place holder text with actual text for Page X of Y internal pagination of SAS output. Place the TEXT value on the page where you want the generated Page X of Y string to be placed. This would normally be in a TITLE or FOOTNOTE statement. The special text must occur only once per page and all on one line. The length of the special text must be long enough to hold the generated Page X of Y text. Does not apply to RTF files because the internal pagination is not generated. Instead RTF commands to display page number and number of document pages are used. Use values for TEXT that do not include spaces. This will help insure that they are not split into separate lines in RTF or PDF files by SAS. * Example 1 - Left Justified in a PDF file ; %let pagnumt=[Page_00000_of_99999]; footnote1 j=l "&pagenumt"; ... %pageofpp(infile="test1.pdf",outfile="test2.pdf",text=&pagnumt,type=pdf) * Example 2 - Centered in a TXT file ; %let pagnumt=[Page_00000_of_99999]; footnote1 "%sysfunc(repeat(%str( ),50))&pagenumt"; ... %pageofpp(infile="t1.txt",outfile="t2.txt",text=&pagnumt,type=txt,justify=c) ------------------------------------------------------------------------------*/ %local parmerr infilen outfilen numpages numpagel slength rtfcommand lpageof ; %*---------------------------------------------------------------------- Validate parameters -----------------------------------------------------------------------; %let parmerr=0; %if (^%length(&infile)) %then %do; %put ERROR: INFILE not specified.; %let parmerr=1; %end; %if (^%length(&outfile)) %then %do; %put ERROR: OUTFILE not specified.; %let parmerr=1; %end; %else %if ("&infile" = "&outfile") %then %do; %put ERROR: OUTFILE same file as INFILE.; %let parmerr=1; %end; %if (^%length(&text)) %then %do; %put ERROR: TEXT not specified; %let parmerr=1; %end; %*------------------------------------------------------------------------------ Recode TYPE because some are treated exactly the same way. -------------------------------------------------------------------------------; %let type=%upcase(&type); %if (&type = LIS) or (&type = LST) %then %let type=TXT; %else %if (&type = PS) %then %let type=PDF; %if (^%index(%str( TXT RTF PDF ),%str( &type ))) %then %do; %put ERROR: TYPE=&type not valid.; %let parmerr=1; %end; %let justify=%substr(%upcase(&justify%str( )),1,1); %if (^%index(LCR,&justify)) %then %do; %put ERROR: JUSTIFY=&justify value not valid.; %let parmerr=1; %end; %if (&parmerr) %then %goto quit; %*----------------------------------------------------------------------------- Start body of macro -------------------------------------------------------------------------------; %*------------------------------------------------------------------------------ RTFCOMMAND = Command string in RTF that tells WORD to display Page X of Y. -------------------------------------------------------------------------------; %let rtfcommand={Page }{\field{\*\fldinst {PAGE }}}{ of }; %let rtfcommand=&rtfcommand.{\field{\*\fldinst {NUMPAGES }}}; %*------------------------------------------------------------------------------ SLENGTH = length of search string to use in later calculations. LPAGENO = length of variable to hold generated Page X of Y string. -------------------------------------------------------------------------------; %let slength=%length(&text); %if (&type = RTF) %then %let lpageof=%length(&rtfcommand); %else %let lpageof=&slength; %if (&type ^= RTF) %then %do; *------------------------------------------------------------------------------; * Scan file to determine the number of pages ; *------------------------------------------------------------------------------; data _null_; infile &infile lrecl=32767 end=_eof; input; if index(_infile_,"&text") then pageno + 1; if _eof then call symput('NUMPAGES',compress(put(pageno,14.))); run; %*------------------------------------------------------------------------------ Get length of numpages string to set format for generating page numbers. Check that generated text will fit without space reserved by placeholder text. Note: 9=length(PAGE__OF_). -------------------------------------------------------------------------------; %let numpagel=%length(&numpages); %if (%length(&text) < %eval(9 + 2*&numpagel)) %then %do; %let parmerr=1; %put ERROR: NUMPAGES=&numpages will generate text longer than search text; %goto quit; %end; %end; *------------------------------------------------------------------------------; * Process file and replace place holder text with actual pagination ; *------------------------------------------------------------------------------; data _null_; infile &infile lrecl=32767 end=_eof; length pageof $ &lpageof; input ; if index(_infile_,"&text") then do; %if (&type = RTF) %then %do; *------------------------------------------------------------------------------; * Type = RTF. Set pageof string to rtf command. ; *------------------------------------------------------------------------------; pageof = "&rtfcommand"; %end; %else %do; *------------------------------------------------------------------------------; * Type ^= RTF. Count pages and generate Page x of y string. ; *------------------------------------------------------------------------------; pageno + 1; pageof = 'Page ' || put(pageno,&numpagel..) || " of &numpages"; %if (&type = PDF) %then %do; *------------------------------------------------------------------------------; * Type = PDF. Compress out multiple blanks in generated text.; *------------------------------------------------------------------------------; pageof = compbl(pageof); %end; %if (&justify = R) %then %do; *------------------------------------------------------------------------------; * Justify = R. Push generated text to right of field.; *------------------------------------------------------------------------------; pageof = right(pageof); %end; %else %if (&justify = C) %then %do; *------------------------------------------------------------------------------; * Justify = C. Shift right by half of difference in lengths. ; *------------------------------------------------------------------------------; len = length(pageof); if ( (len+1) < &slength ) then do; pageof = repeat(' ',int((&slength - len)/2) -1) || pageof; end; %end; %*------------------------------------------------------------------------------ Justify = L. Do nothing as generated text is already on left. -------------------------------------------------------------------------------; %end; *------------------------------------------------------------------------------; * Replace the placeholder text with the generated text ; *------------------------------------------------------------------------------; _infile_ = tranwrd(_infile_,"&text",pageof); end; file &outfile noprint lrecl=32767; put _infile_; run; %quit: %if (&parmerr) %then %put ERROR: Macro PAGEOFPP stopped because of error. ; %mend pageofpp;