/*----------------------------------------------------------------------------- File: ConvertFlags.sas Author: John Sabel Washington State Education Research & Data Center Creation date: 12/28/11 Version: 0.9 Purpose Converts all flags in all character fields in a dataset from one defined set of two values to another defined set of two values. For example, you can use this macro to convert all Y/N flags to 1/0 flags with the following call: %ConvertFlags(DsnIn=In, DsnOut=Out, FlagsIn=Y N, FlagsOut=1 0) The macro does this by analyzing all the character fields in the input datatset to determine which fields have only empty strings or the values defined in the "FlagsIn" parameter. It then changes these values to the complement values defined in the "FlagsOut" parameter. The flags in the input dataset can be either upper case or lower case. In either case they would still be converted. At the bottom of this file listing is a commented out example. It contains sample data and a calls to the macro. Parameters DsnIn: The one or two-level name of the input dataset. DsnOut: The one or two-level name of the output dataset. FlagsIn: The flags to be converted in the input dataset. FlagsOut: The converted flags in the output dataset. -----------------------------------------------------------------------------*/ %macro ConvertFlags(DsnIn=, DsnOut=, FlagsIn=, FlagsOut=); %put --- Start of %upcase(&sysmacroname) macro; %local __i; %let FlagsIn=%upcase(&FlagsIn.); %let FlagIn1=%scan(&FlagsIn., 1); %let FlagIn2=%scan(&FlagsIn., 2); %let FlagOut1=%scan(&FlagsOut., 1); %let FlagOut2=%scan(&FlagsOut., 2); %let FlagsInInverted=&FlagIn2. &FlagIn1.; proc format; invalue $__XXX (JUST UPCASE) "&FlagIn1." = "&FlagOut1." "&FlagIn2." = "&FlagOut2."; run; proc contents data=&DsnIn out=__TempContents noprint; run; proc sql noprint; SELECT NAME INTO :ColumnName1 - :ColumnName999 FROM __TempContents WHERE TYPE = 2; %let TextColumnCount=&sqlobs.; quit; %do __i = 1 %to &TextColumnCount.; proc sql noprint; SELECT count(DISTINCT UPCASE(&&ColumnName&__I)) INTO :DistinctValueCount&__I. FROM &DsnIn. ; quit; %if &&DistinctValueCount&__I=1 or &&DistinctValueCount&__I=2 %then %do; proc sql noprint; SELECT DISTINCT UPCASE(&&ColumnName&__I) INTO :DistinctValues&__I. separated by ' ' FROM &DsnIn. ; quit; %put &&DistinctValues&__I; %end; %end; data &DsnOut.; set &DsnIn.; %do __i = 1 %to &TextColumnCount.; %if &&DistinctValueCount&__I=1 %then %do; %if &&DistinctValues&__I=&FlagIn1. or &&DistinctValues&__I=&FlagIn2. %then %do; &&ColumnName&__I = input(&&ColumnName&__I, $__XXX.); %end; %end; %if &&DistinctValueCount&__I = 2 %then %do; %if &&DistinctValues&__I=&FlagsIn. or &&DistinctValues&__I=&FlagsInInverted. %then %do; &&ColumnName&__I = input(&&ColumnName&__I, $__XXX.); %end; %end; %end; run; %put --- End of %upcase(&sysmacroname) macro; %mend; /* * flag2 contains lower case flags, but these can still be converted.; * fauxFlag5 contains more than two values and so it cannot be converted.; data SampleFlagData; input ID $ flag1 $ flag2 $ flag3 $ flag4 $ fauxFlag5 $; datalines; A Y n 1 0 Y B N N 0 0 N C . y . 1 Z D Y Y 1 1 . ; run; * Convert Y/N flags to 1/0 flags.; %ConvertFlags(DsnIn=SampleFlagData, DsnOut=SampleFlagData_Out10, FlagsIn=Y N, FlagsOut=1 0) * Convert 1/0 flags to Y/N flags.; %ConvertFlags(DsnIn=SampleFlagData, DsnOut=SampleFlagData_OutYN, FlagsIn=1 0, FlagsOut=Y N) * Multi-character flag example; data SampleMultiCharFlagData; input ID $ flag1 $; datalines; A1 Yes A2 No B1 . ; run; %ConvertFlags(DsnIn=SampleMultiCharFlagData, DsnOut=SampleMultiCharFlagData_Out, FlagsIn=Yes No, FlagsOut=Good Bad) */