Hi all,
I would like to add a new value in an existing Macro-Variable. The new value should only be added if is not already part of the Macro-Variable.
Adding a value works fine:
%let parameter_macrovariable = ¶meter_macrovariable. ¶meter_value.;
To do the check I would like to use a Macro (if there is not a better way to do it). I haven't find a solution to work inside the Macro with the literal name of Inputparamter in the macro (parameter_macrovariable 😃 The assignment inside a macro is different. This is in SAS not allowed: %let %parameter_macrovariable. = ...
Thank you for your help. Here my not working macro:
%global macrovariable
%let macrovariable = Value1
%macro check_and_add(parameter_macrovariable =, parameter_value =);
%let found = %sysfunc(findw(¶meter_macrovariable., ¶meter_value., %str( )));
%if &found. = 0 %then %do;
%let parameter_macrovariable = ¶meter_macrovariable. ¶meter_value.;
%put Updated list: ¶meter_macrovariable., new added value: ¶meter_value.;
%end;
%mend;
%check_and_add(parameter_macrovariable = macrovariable, parameter_value = Value2)
%put parameter_macrovariable: parameter_macrovariable; /* Result: empty */
@obvisou wrote:
This Code gives this ERROR: Invalid Macro-Variable is already used by chkvaluelist_Add. ERROR 180-322: Statement is not valid or it is used out of proper order:
%global parameter_macrovariable; %let parameter_macrovariable =; %MACRO ChkValueList_Add(p_list =, p_value =); %if %sysfunc(findw(&p_list., %p_value.,,s)) %then %do; &p_list.; %end; %else %do; &p_list. &p_value.; %end; %MEND; ChkValueList_Add(p_list = ¶meter_macrovariable . ,p_value = Value1);
Remove the extra semicolons from these line:
...
&p_list.;
..
&p_list. &p_value.;
You do NOT want those to be part of the text that the macro emits.
Make sure to use the % when calling the macro. Without that CHKVALUELIST_ADD is ignored by the macro processor and so will cause a syntax error by SAS itself.
Finally call the macro in a place where a single string is expected by SAS.
Such as in an %LET macro statement.
%let parameter_macrovariable = %ChkValueList_Add(p_list = ¶meter_macrovariable . ,p_value = Value1);
So if you set
%let parameter_macrovariable = ABC ;
And then run :
%let parameter_macrovariable = %ChkValueList_Add(p_list = ¶meter_macrovariable . ,p_value = Value1);
You will get
ABC Value1
Assigned to parameter_macrovariable .
when you use a variable in as a parameter in a macro it is definled in the local macro variable table and is not availble outside the macro. You need do define it before.
%let macrovariable = Value1;
%let parameter_macrovariable = ¯ovariable;
%macro check_and_add( parameter_value =);
%let found = %sysfunc(findw(¶meter_macrovariable., ¶meter_value.));
%if &found. = 0 %then %do;
%let parameter_macrovariable = ¶meter_macrovariable. ¶meter_value.;
%put Updated list: ¶meter_macrovariable., new added value: ¶meter_value.;
%end;
%put &=parameter_macrovariable;
%mend;
%check_and_add(parameter_value = Value2)
%put &=parameter_macrovariable;
Thank you. But this is not want I want. The Macro should be dynamic and be used also for other Macro-Variables, so it is necessary to have two Input-Parameters. One for the Macro-Variable (List) to be updated and second for the Value who must be added or not (parameter_macrovariable =, parameter_value 😃
Try this:
%global myMacrovariable;
%let myMacrovariable = A;
%put &=myMacrovariable.;
%macro add_value(val,mvName=myMacrovariable)/minoperator mindelimiter=' ';
%if NOT (&val. in (&&&mvName.)) %then
%let &mvName. = &&&mvName. &val.;
%mend add_value;
%add_value(A)
%put &=myMacrovariable.;
%add_value(B)
%put &=myMacrovariable.;
%add_value(C)
%put &=myMacrovariable.;
%add_value(C)
%put &=myMacrovariable.;
%add_value(A)
%put &=myMacrovariable.;
Of course the assumption is that values you're adding don't have spaces in them.
Bart
An alternative could be to add everything as it goes to the variable value, and when it's done, to use the %dedupListS() macro from the BasePlus package:
%let list = 4 5 6 1 2 3 1 2 3 4 5 6;
%let list = %dedupListS(&list.);
Bart
Thanks Bard.
Had to change the if statement to:
%let pos_found = %sysfunc(findw(&mvName., &val.));
%if &pos_found = 0 %then % do:
But this is still not allowed:
%let &mvName. = &&&mvName. &val.;
ERROR: Expecting a variable name after %let.
ERROR: The macro variable name is either all blank or missing.
Full log please...
"ERROR: The macro variable name is either all blank or missing." - did you defined your macro variable BEFORE running the macro ?
%MACRO ChkValueList_Add(p_list =
,p_value =
)/minoperator mindelimiter = ' ';
/*----------------------------------------------------------------
Parameter
----------------------------------------------------------------*/
%put @_&sysmacroname._500_p_list: &p_list.;
%put @_&sysmacroname._502_p_value: &p_value.;
/*----------------------------------------------------------------
Check
----------------------------------------------------------------*/
%if %length(&p_value.) = 0 %then %do;
%put ERROR: Parameter 'p_value' ist leer. (ku-508);
%return;
%end;
/*----------------------------------------------------------------
----------------------------------------------------------------*/
%let pos_found = %sysfunc(findw(&p_list., &p_value.)); /* */
/*%if NOT (&p_value. IN (&&&p_list.)) %then %do; /* */
%put @_&sysmacroname._517_Position_Found: &pos_found.;
%if &pos_found. = 0 %then %do;
%let &p_list. = &&&p_list. &p_value.;
%put @_&sysmacroname._522: Wert (&p_value.) wurde in Liste hinzugefügt (&p_list.).;
%end;
%else %do;
%put @_&sysmacroname._525: Wert (&p_value.) ist bereits in Liste enthalten (&p_list.).; /* nicht möglich Name der Liste anzuzeigen!!!)
%end;
%put;
%put #---------------------------------------------------#;
%put # &sysmacroname._End;
%put #---------------------------------------------------#;
%MEND ChkValueList_Add;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
%global list_epi list_add;
%let list_epi =;
%let list_add =;
/* */
%include "/......_ChkVariableExist.sas";
%ChkValueList_Add(p_list= &list_epi., p_value= Hallo);
%put ----list_epi: &list_epi.;
------------------------------------------------------------------------------
Log
------------------------------------------------------------------------------
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Config';
4 %LET _CLIENTPROCESSFLOWNAME='Manual';
5 %LET _CLIENTPROJECTPATH='/SAS/......egp';
6 %LET _CLIENTPROJECTPATHHOST='........';
7 %LET _CLIENTPROJECTNAME='.......egp';
8 %LET _SASPROGRAMFILE='';
9 %LET _SASPROGRAMFILEHOST='';
10
11 ODS _ALL_ CLOSE;
12 OPTIONS DEV=SVG;
13 GOPTIONS XPIXELS=0 YPIXELS=0;
14 %macro HTML5AccessibleGraphSupported;
15 %if %_SAS_VERCOMP_FV(9,4,4, 0,0,0) >= 0 %then ACCESSIBLE_GRAPH;
16 %mend;
17 FILENAME EGHTML TEMP;
18 ODS HTML5(ID=EGHTML) FILE=EGHTML
19 OPTIONS(BITMAP_MODE='INLINE')
20 %HTML5AccessibleGraphSupported
MPRINT(HTML5ACCESSIBLEGRAPHSUPPORTED): ACCESSIBLE_GRAPH
21 ENCODING='utf-8'
22 STYLE=HTMLBlue
23 NOGTITLE
24 NOGFOOTNOTE
25 GPATH=&sasworklocation
26 ;
27
28
29 %include "/SAS/................sas";
574 %ChkValueList_Add(p_list= &list_epi., p_value= Hallo);
#---------------------------------------------------#
# ChkValueList_Add_Start
#---------------------------------------------------#
@_ChkValueList_Add_500_p_list:
ERROR: Expecting a variable name after %LET.
ERROR: The macro variable name is either all blank or missing.
ERROR: The macro ChkValueList_Add will stop executing.
575
576
578
579 %put ----list_epi: &list_epi.;
----list_epi:
580 %put &=list_epi;
LIST_EPI=
581 /* */
582
583
584 %LET _CLIENTTASKLABEL=;
585 %LET _CLIENTPROCESSFLOWNAME=;
586 %LET _CLIENTPROJECTPATH=;
587 %LET _CLIENTPROJECTPATHHOST=;
588 %LET _CLIENTPROJECTNAME=;
589 %LET _SASPROGRAMFILE=;
2 The SAS System 09:26 Monday, March 18, 2024
590 %LET _SASPROGRAMFILEHOST=;
591
592 ;*';*";*/;quit;run;
593 ODS _ALL_ CLOSE;
594
595
596 QUIT; RUN;
597
Great, but where is your log with the code I proposed ?
Bart
This comment seems to be not closed:
/* nicht möglich Name der Liste anzuzeigen!!!)
Bart
This line is badly commented out too:
/*%if NOT (&p_value. IN (&&&p_list.)) %then %do; /* */
Bart
Is here something wrong? It was your suggestion. I don't need it. just deleted.
yes sorry, but this is not the mistake.
Take the code I posted, copy it to your session, run it, and share the results, ok ?
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.