x cd /pub/data/sf32000/Tools; %let pgm=gen_sf3pros; filename pgm "&pgm..sas"; /* ---This is an MCDC-edited version of MainSF3.sas, the main program of the SDC profiles application. The original code upon which this is based is stored in the sf32000/sdcprofiles/MainSF3.sas module. View at http://mcdc2.missouri.edu/data/sf32000/sdcprofiles/MainSF3.sas We edited that module to create this one as follows: -Added this new "top matter" and removed some (a lot, actually) of the original. -Edited the credline parm to reference mcdc. -Edited all occurrences of SASCode to Codelib. (Because we already used sascode to point to another lib here). -Edited path pointed to by SASCode/Codelib. -Edited the SF3 libname statement. Added access=readonly in addition to pointing to our path-; -Removed all code related to defining SAS format codes. We already have these. Not using geocompbrief. -Added the psfile global parm and edited the ods ps file= statement to reference this parm as the filename. -Moved %let stab parm assignment up near top because that is what we usually change. Right next to psfile. -Added the filter macro and added invocation during DATA step. Allows getting this crucial filtering entered into code at same time as other run parameters. -Added stmt to include sascode(notify) -- an mcdc-only thing. -Commented out proc template step after running once interactively to stored in my sasuser lib. -Had to edit the %include statements. Had to add the .sas extension (bug!!) and also had to fix the names so that filenames were correct in terms of case. (e.g. SecProf.sas was really secprof.sas). -Edited the Disprof.sas module to get rid of long source lines. See setup edit_disprof.sas in sdcprofiles. -Tried adding an extra line to the page to make our pages align when converted to pdf. */ %let temp=%str(/temp); *<---for embargoed data. Set to null for public data-; /*----- "MainSF3.SAS", SDC 2000 SF3 Profiles Main Routine which reads a SAS data set and generates individual profile pages as specified by user parameters. Part of the joint SF3 Profiles project of the national State Data Center network, Spring, 2002. Based on the similar routine for SF1 profiles coded by John Blodgett, OSEDA/U. of Missouri, & Roy Williams, MISER/UMass (413)545-3460 ..... 8/14/02: added explicit PROC FORMAT LIBRARY=LIBRARY run & some more comments ------*/ %LET stab=mo; * <== which state's files to access (<== edit as needed) ; %let psfile=04029all; *<=====Output reports go to a file with this name, extension ps in the sdcprofiles directory; * which profiles--leave blank or null to select all (can't use "ALL" --that would get only Ancestry & Language!) See IF(INDEX(... statements below for meaning of the 1-char mnemonics; %LET profiles= ; * (same as saying %LET profiles='12ADEFHIJLMPT') ; * <== edit each time ; *LET profiles=1; * requests Primary only--; %macro filter; %*--inserted into program to subset the sf3 data--; WHERE LogRecNo = 1 ; * first record (state) only ; %mend filter; OPTIONS LINESIZE=149 PAGESIZE=64 PAGENO=1 NODATE NONUMBER ORIENTATION=LANDSCAPE ; %GLOBAL stab profiles pages1 pages2 pagesA pagesD pagesE pagesF pagesH pagesI pagesJ pagesL pagesM pagesP pagesT geocomps CumulPaging ; %* credit line becomes bottom line on every page (<==customize for your state) ; %LET credline=%STR(Profile prepared by the Missouri Census Data Center (MCDC), http://mcdc.missouri.edu) ; %LET CumulPaging=1 ; %* <== turns on cumulative paging for this run (your preference) ; * where the page module code is stored-- ; FILENAME Codelib "/pub/data/sf32000/sdcprofiles"; *<== probably edit only once ; LIBNAME sf3 "/pub/data/sf32000&temp" access=readonly; ***INCLUDE Codelib(SF3Template.sas) ; * runs Proc Template: creates the ODS style "SF3style" to allow direct output to the ODS PostScript Destination. Selecting PostScript instead of pdf gets around an indentation/alignment bug in the SAS Version 8.2 ODS PDF implementation, but it means the user must run Adobe Distiller to "distill" the resulting file from ps to pdf. Distiller automatically saves "name.pdf" in the same location as "name.ps". Turning on the "pdfmark" option will allow adding pdf bookmarks later, or so I'm told. Haven't tried it yet. Proc Template actually needs to be run only once, since the style will automatically get saved in a SASUSER location. SAS Version 8.2 doesn't allow for hard page breaks in ODS "batch" print output, but these margins cause appropriate breaks every 64 lines, at least on my Windows2000 machine here at MISER with Adobe Acrobat 5.0 ; TITLE ; * Blanks out "The SAS System" title in ODS output ; ODS ps file="/pub/webrepts/sdcprofiles3/&stab/&psfile..ps" pdfmark style=SF3style ; * <== edit psfile parm, above; * selecting pages--leave blank or null or use "ALL" to select all (use A for page10 & B for page11 of the Primary module) The ones you don't mention are null by default ; * examples of how to select fewer than all pages of a module-- ; %*LET pagesI=1234 ; * page 1 to 4 of Income ; * (<== edit as needed) ; %*LET pages1=89ab ; * pages 8, 9, 10 & 11 of Primary ; %* Note for interactive mode users: Global macro vars automatically retain a value across data steps during an interactive session. You generally will need to reset "profiles" and "pagesX" before your next run. For example if you had pages1=89AB in your last run and now you want them all, you have to explicitly reset pages1 by setting it to null as shown (commented out) ; *%LET pages1= ; %LET geocomps=00 ; *<===specify additional geocomp codes (2-digit, separated by blanks) in the unlikely event that you want profiles for geog components other than the default "00" (which means "NOT a geographic component")--; %* Macro which PUTs centered title & a brief mnemonic on line 1 of every page ; %Macro PutTitle ( Title, Mnemonic) ; %* gets invoked by every page ; _Ltitle=LENGTH("&Title" ) ; %*--calculate column for centering title in 149-char line--; _TitleCol=FLOOR( (149 -_Ltitle)/2 ); %*--calculate column for right-justifying mnemonic in 149-char line--; _MnemCol = 150 -LENGTH("&Mnemonic" ) ; PUT #1 @_TitleCol "&Title" @_MnemCol "&Mnemonic" ; %MEnd ; DATA _NULL_ ; * Merging takes time--you may want to do it once and save extract files grouped by county or by SumLev or whatever. Remember BG's only have P & H tables ; MERGE sf3.&stab.ph sf3.&stab.phct sf3.&stab.phctR ; BY LogRecNo ; * SET sf3.Tracts ; * for example, if you made a tract-level extract with all vars ; * Area selection here--; * WHERE AreaName =: 'Vermont' ; * WHERE SumLev =: '2' ; * all Native American SumLevs ; %filter * to Display Manager window or its batch-mode equivalent--commenting this out caused problems ; FILE PRINT LINESIZE=149 PAGESIZE=65 N=PAGESIZE NOTITLES; LENGTH _PAGES $11 profiles $13; %LET profiles=%UPCASE(&profiles) ; %* now people can use lower-case letters above ; RETAIN profiles "&profiles" ; AreaCount+1; * comment out the stopping criterion if you don't know how many to expect! ; IF AreaCount>2 THEN STOP ; *------------------------------------------------------------------------------------------- Probably nothing needs to be edited after this point, but look it over once to get an idea what's going on. You may want to tweak something to make it work the way YOU want it.! ------------------------------------------------------------------------------------------- ; IF AreaCount LE 199 OR MOD(AreaCount,50)=0 THEN DO ; FILE LOG; PUT Pop100= GeoCode= AreaName= ; FILE PRINT; END ; RETAIN strtline 6 RunPage 0 ; * if cumulative page numbering is set to false, each area will start with page 1 ; IF (&CumulPaging=0) THEN RunPage=0 ; LENGTH Underline DoubleLine SingleLine $149 ; RETAIN Underline DoubleLine SingleLine VBAR '|' PLUS '+' _first 1; IF _first THEN DO; RunDate="&sysdate"; RETAIN RunDate; UnderLine= REPEAT('_',147) ; DoubleLine=REPEAT('=',147) ; SingleLine=REPEAT('-',147) ; profiles=SYMGET('PROFILES'); IF profiles=' ' THEN profiles='12ADEFHIJLMPT'; * can't use ALL ; _first=0 ; * (i.e. false) ; END; * IF (TOC>1 or (TOC=1 AND AreaCount=1)) THEN LINK PageTOC ; * no Table of Contents yet ; *Note that _pages gets a value intended (!) to be local to each routine ; IF INDEX(PROFILES,'1')THEN DO; ProfID='Primary'; _PAGES="&pages1"; LINK PrimeProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'2')THEN DO; ProfID='2ndary'; _PAGES="&pages2"; LINK secprof; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'A')THEN DO; ProfID='Ancestry'; _PAGES="&pagesA"; LINK AncyProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'D')THEN DO; ProfID='Disability'; _PAGES="&pagesD"; LINK DisProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'E')THEN DO; ProfID='Educ'; _PAGES="&pagesE"; LINK EducProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'F')THEN DO; ProfID='Family'; _PAGES="&pagesF"; LINK familyprof; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'H')THEN DO; ProfID='Housing'; _PAGES="&pagesH"; LINK HousProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'I')THEN DO; ProfID='Income'; _PAGES="&pagesI"; LINK IncProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'J')THEN DO; ProfID='Jobs'; _PAGES="&pagesJ"; LINK JobsProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'L')THEN DO; ProfID='Language'; _PAGES="&pagesL"; LINK LangProf; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'M')THEN DO; ProfID='Migration'; _PAGES="&pagesM"; LINK migrprof; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'P')THEN DO; ProfID='Poverty'; _PAGES="&pagesP"; LINK povprof; IF _ERROR_ THEN LINK err; END; IF INDEX(PROFILES,'T')THEN DO; ProfID='Transport'; _PAGES="&pagesT"; LINK tranprof; IF _ERROR_ THEN LINK err; END; RETURN; *---end main routine. Now come the linked-to routines---; err: *---Handles errors encountered while generating profiles---; FILE LOG; _nerr+1; IF _nerr LE 20 THEN PUT '** Error detected (probably division by zero) ' 'during processing of profile ' ProfID ' for ' AREANAME; _ERROR_=0; ** turn off flag, avoid dump **; IF _nerr EQ 20 THEN DO; PUT // '** NO MORE OF THESE MESSAGES WILL BE PRINTED **'; END; FILE PRINT; RETURN; *<---main program loop ends with above return stmt. The following include statements reference the Codelib library where the links to generate the profiles reside--; OPTIONS NOSOURCE2 NOMPRINT ; *<====can flip switches for debugging----; *%INCLUDE Codelib(TOC)/SOURCE2 ; *--Roy Williams, Massachusetts (not yet)--; %INCLUDE Codelib(PrimeProf.sas) ; *--Julie Hoang, California (with help from Jeff & Xan)--; %INCLUDE Codelib(secprof.sas) ; *--Xan Stevens, Kansas--; %INCLUDE Codelib(AncyProf.sas) ; *--Roy Williams, Massachusetts; %INCLUDE Codelib(Disprof.sas) ; *--Phyllis Smith, Amrut K., et al, Arkansas--; *---mcdc-Edited version!--; %INCLUDE Codelib(EducProf.sas) ; *--Jeff Wallace, Oklahoma--; %INCLUDE Codelib(familyprof.sas) ; *--Amy Chen, Maryland--; %INCLUDE Codelib(HousProf.sas) ; *--Julie Hoang, California (with help from Jeff)--; %INCLUDE Codelib(IncProf.sas) ; *--Annette Boyer, Colorado--; %INCLUDE Codelib(JobsProf.sas) ; *--Roy Williams, Massachusetts--; %INCLUDE Codelib(LangProf.sas) ; *--Annette Boyer, Colorado--; %INCLUDE Codelib(migrprof.sas) ; *--Jeff Wallace, Oklahoma--; %INCLUDE Codelib(Povprof.sas) ; *--Phyllis Smith, Amrut K., et al, Arkansas--; %INCLUDE Codelib(tranprof.sas) ; *--Jeff Wallace, Oklahoma--; %* That's a lot of %INCLUDE's! May add macro that builds the %INCLUDE list selectively based on &profiles value. It was in the 1990 STF3 package ; HeadFoot: /* This routine is invoked after the body of each profile page is complete. Puts the headers, footers and the big outer box. Centered TITLE & brief mnemonic already PUT in line #1 by above routines. */ PUT #1 'Census 2000, Summary File 3' ; IF geocomp EQ '00' THEN PUT #2 'Area Name: ' AreaName ; ELSE PUT #2 'Area: ' AreaName 'Geo. Component:' geocomp $geocomp. ; LENGTH TypeString $ 60 ; * Minimal list of summary levels--John Blodgett's cnvtsf3 package has a much fuller $SumLev. list, but the strings would first need to be abbreviated substantially. ; TypeString='Area Type: '||TRIM(PUT(SumLev,$SumLev.))|| ' (Summary Level '||SumLev||')' ; PUT #2 @(150 - LENGTH(TypeString)) TypeString ; LENGTH GeoString $149 ; GeoString=' ' ; IF (StAb NE ' ') THEN GeoString='State: '||UPCASE(StAb) ; IF (cnty NE ' ') THEN DO ; GeoString=TRIM(GeoString)||' County: '||cnty ; IF (SumLev NE '050' ) THEN geostring= TRIM(geostring)||' ('||TRIM(PUT(county,$county.))||')'; END ; IF (CouSubFP NE ' ') THEN GeoString=TRIM(GeoString)||' CouSub: '||CouSubFP ; IF (PlaceFP NE ' ') THEN GeoString=TRIM(GeoString)||' Place: '||PlaceFP ; IF (Tract NE ' ') THEN GeoString=TRIM(GeoString)||' Tract: '||Tract ; IF (BG NE ' ') THEN GeoString=TRIM(GeoString)||' BG: '||BG ; IF (MSACMSA NOT IN (' ','####','9999')) THEN DO ; IF (CMSA2 = '99') THEN GeoString=TRIM(GeoString)||' MSA: '||MSACMSA ; ELSE DO ; GeoString=TRIM(GeoString)||' CMSA: '||MSACMSA ; IF (PMSA NE ' ') THEN GeoString=TRIM(GeoString)||' PMSA: '||PMSA ; END ; END ; IF (UA NOT IN (' ','9999')) THEN GeoString=TRIM(GeoString)||' UA: '||UA ; IF (CD106 NE ' ') THEN GeoString=TRIM(GeoString)||' CD: '||CD106 ; IF (UrbanRur NE ' ') THEN GeoString=TRIM(GeoString)||' Urban/Rural: '||UrbanRur ; * There is plenty of room to display additional geocodes as needed-- just concatenate them onto GeoString as above ; PUT #3 GeoString ; *---Draw the box around the tabular area incl left and right vertical lines--; PUT #5 @1 PLUS $1. DoubleLine $147. PLUS $1. ; DO _I_=6 TO 61; PUT #_I_ @1 VBAR $1. @149 VBAR $1. @; END ; *----Footers including bottom of box--------; RunPage + 1 ; * Cumulative paging for this run: (# of areas) x (# of profiles) ; LENGTH credline $148 ; RETAIN credline "&credline"; PUT #62 @1 PLUS $1. DoubleLine $147. PLUS $1. / @1 "Source: Census 2000 Summary File 3 [machine-readable data file]/prepared" " by the U.S.Census Bureau, 2002 (www.census.gov)" @123 RunDate +(-1) ': Area ' AreaCount : 3.0 +(-1) ', Page ' RunPage 3.0-L / @1 credline / @5 "Report generated on &sysdate at &systime"; *---Try putting an extra line to get around our problem with being off by 1 on pagination--; RETURN; *************end HeadFoot routine**************; RUN; ODS ps close ; %PUT state=&stab geocomps=&geocomps profiles=&profiles pages: 1=&pages1 2=&pages2 A=&pagesA D=&pagesD E=&pagesE F=&pagesF H=&pagesH I=&pagesI J=&pagesJ L=&pagesL M=&pagesM P=&pagesP T=&pagesT ; %include sascode(notify);