LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (October 2006, week 3)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Mon, 16 Oct 2006 11:58:19 -0400
Reply-To:     Peter Crawford <peter.crawford@BLUEYONDER.CO.UK>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Peter Crawford <peter.crawford@BLUEYONDER.CO.UK>
Subject:      Re: Macro with keyword parameters and PARMBUFF
Comments: To: Jim Groeneveld <jim2stat@YAHOO.CO.UK>

Jim

since you have only one keyword parameter, and do no statements (other than debugging options), keep maintainability in sight by turning it into a macro function, called like

Counter = %COUNT ( a b c, 3 5 7 _sysmis_, b a, 1 9);

or

%put count is %COUNT ( a b c, 3 5 7 _sysmis_, b a, 1 9);

If you really want just to demonstrate the ParmBuff feature, try counting the commas in &sysPbuff .

Good Luck

Peter

On Mon, 16 Oct 2006 11:03:20 -0400, Jim Groeneveld <jim2stat@YAHOO.CO.UK> wrote:

>Hi friends, > >I am developing an advanced macro %COUNT, counting specified values for >variables within records, similar to SPSS's COUNT command. So far no >problem. But I want the macro to contain both one or more keyword parameters >and subsequent positional parameters to analyze from the macro variable >&SYSPBUFF: > > %MACRO Count (CountVar=) / PARMBUFF; %* Macro definition; > %COUNT (CountVar=Counter, a b c, 3 5 7 _sysmis_, b a, 1 9); * Macro call; > >This (of course!?) does not work: > ERROR: All positional parameters must precede keyword parameters. > >That is too bad. I get it to work with: > > %MACRO Count (CountVar) / PARMBUFF; %* Macro definition; > %COUNT (Counter, a b c, 3 5 7 _sysmis_, b a, 1 9); * Macro call; > >or with > > %MACRO Count (CountVar=) / PARMBUFF; %* Macro definition; > %COUNT (CountVar=Counter, V=a b c, N=3 5 7 _sysmis_, V=b a, N=1 9); > * Macro call; > >where I (of course) have to account for the dummy keywords (V= and N=) in >the SYSPBUFF variable list. I do not at all like these two solutions. > >How can I define and assign the named parameters by keyword and the unnamed >ones as positional ones? Or is this a bug or limitation in SAS? >Or should I revert to a command or statement style invocation? How? > >I finally can get it to work correctly with: > %MACRO Count / PARMBUFF; %* Macro definition; > %COUNT (CountVar=Counter, a b c, 3 5 7 _sysmis_, b a, 1 9); >while processing the first argument explicitly inside the macro. >Is there a better or more elegant solution with defined keyword arguments? >I would like to define more optional keyword parameters and I don't want to >recognize optional keyword parameters as such by my macro code, but by SAS, >because the presence of an '=' character may not be exclusive. > >The whole preliminary macro (and test) code for the time being is: > >%*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; >%* Macro Count counts value lists for dataset variables ; >%*______________________________________________________; > >%* (C) Jim Groeneveld, 16 October 2006; > >%MACRO Count / PARMBUFF; > %LOCAL CountVar H VarList ValList I Var J Val Debug; > > %LET Debug=0; > %IF (&Debug EQ 1 OR &Debug GT 11) %THEN %DO; > OPTIONS MPRINT MERROR SERROR MLOGIC SYMBOLGEN MACROGEN; > %END; > > %LET SYSPBUFF = %Disclose (Enclosed=&SYSPBUFF); %* remove enclosing parens; >%put syspbuff=&SYSPBUFF; > %LET CountVar = %SCAN(&SYSPBUFF,1,%STR(,)); >%put A: CountVar=&CountVar; > %IF (%QUPCASE(%SCAN(%QUOTE(&CountVar),1,=)) EQ COUNTVAR AND > %SCAN(%QUOTE(&CountVar),2,=) NE) %THEN > %LET CountVar=%SCAN(%QUOTE(&CountVar),2,=); >%put B: CountVar=&CountVar; > > &CountVar = 0; > %LET H = 2; > %LET VarList=%QSCAN(&SYSPBUFF,&H,%STR(,)); > %LET ValList=%QSCAN(&SYSPBUFF,%EVAL(&H+1),%STR(,)); > %DO %WHILE (%QUOTE(&VarList) NE); >%put VarList=&VarList; >%put ValList=&ValList; > %IF (%QUOTE(&ValList) EQ) %THEN %DO; > %PUT Empty value list, VarList=&VarList; > %END; > %ELSE %DO; > > %LET I = 1; > %LET Var = %QSCAN ( &VarList, &I, %STR( ) ); > %DO %WHILE (%QUOTE(&Var) NE); > %LET J = 1; > %LET Val = %QSCAN ( &ValList, &J, %STR( ) ); > %DO %WHILE (%QUOTE(&Val) NE); > %IF (%UPCASE(&Val) EQ _SYSMIS_) %THEN > %DO; > IF (&Var LE .z) THEN &CountVar = &CountVar + 1; >* (all 28 SAS missing values are checked here); > %END; > %ELSE > %DO; > IF (&Var EQ &Val) THEN DO; > &CountVar = &CountVar + 1; >*put &Var= "Var=&Var Val=&Val " &CountVar=; > END; >* (no sum statement to avoid implicit RETAIN); > %END; > %LET J = %EVAL (&J + 1); > %LET Val = %SCAN ( &ValList, &J, %STR( ) ); > %END; > %LET I = %EVAL (&I + 1); > %LET Var = %SCAN ( &VarList, &I, %STR( ) ); > %END; > > %END; > %LET H = %EVAL (&H + 2); > %LET VarList=%QSCAN(&SYSPBUFF,&H,%STR(,)); > %LET ValList=%QSCAN(&SYSPBUFF,%EVAL(&H+1),%STR(,)); > %END; >%MEND Count; > >%*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; >%* Auxiliary Macro Disclose removes enclosing parentheses ; >%*________________________________________________________; > >%MACRO Disclose (Enclosed=); > %IF (%QUOTE(&Enclosed) EQ %STR(%(%))) %THEN; %* if () then return nothing; > %* to prevent warning message; > %ELSE %IF (%QSUBSTR(&Enclosed,1,1) EQ %STR(%() > AND %QSUBSTR(&Enclosed,%LENGTH(&Enclosed),1) EQ %STR(%))) %THEN > %QSUBSTR(&Enclosed, 2, %LENGTH(&Enclosed)-2); %* return disclosed value; > %ELSE &Enclosed; %* return original value; >%MEND; > >DATA _NULL_; > INPUT a b c; > %COUNT (CountVar=Counter, a b c, 3 5 7 _sysmis_, b a, 1 9); > PUT (_ALL_)(=); > CARDS; >1 2 3 >4 5 6 >7 8 9 >. .z ._ >; >RUN; > >I already have contributed a draft paper about (a basic version of) this >macro for SGF 2007. >I am currently improving the basic macro %COUNT that I already have >available on my website. It eventually will also allow value range >specifications, like in SPSS. > >Regards - Jim. >-- >Jim Groeneveld, Netherlands >Statistician, SAS consultant >home.hccnet.nl/jim.groeneveld


Back to: Top of message | Previous page | Main SAS-L page