hi to all,
my code:
%let L_cnt=%sysfunc(countw(%quote(&PROG_KW_LIST)));
%put &=L_cnt;
%put &=PROG_KW_LIST;
%do i1 = 1 %to &L_cnt;
%let PROG_KW=%qscan(%quote(&PROG_KW_LIST.),&i1.,%str(,));
%put &=PROG_KW;
%put before global;
%global PE1_&PROG_KW PE2_&PROG_KW PE3_&PROG_KW;
%put after global;
.....
%end;
I expect global variables PE1_201701, PE2_201702 and PE_201703 for first iteration.
correction:
I expect global variables PE1_201701, PE2_201701 and PE3_201701 for first iteration.
Result:
L_CNT=11
PROG_KW_LIST=201701,201702,201703,201704,201705,201706,201707,201708,201709,201710,201711
PROG_KW=201701
before global
ERROR: Invalid symbolic variable name 201701.
ERROR: Invalid symbolic variable name 201701.
ERROR: Invalid symbolic variable name 201701.
after global
Why is this?
thank you very much,
defaz
https://support.sas.com/resources/papers/proceedings10/147-2010.pdf
"A macro-quoting function uses
hexadecimal delta characters to mask special characters in the value of a macro variable. These delta characters
can often cause syntax errors in code that appears to be completely acceptable in the log."
321 %let a=%quote(10);
322 %global b&a.;
SYMBOLGEN: Macro variable A resolves to 10
SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been
unquoted for printing.
Sorry, this doesn't answer your question, but what on earth are you doing? Macro lists and variables all over the place, far overcomplicated messy code?
If you really need - and I would strongly advise there are far better methods - a list of macro variables called PE1/2/3 date then do it in a datastep:
%let prog_kw=201701,201702,201703,201704,201705,201706,201707,201708,201709,201710,201711; data a; do i=1 to countw("&prog_kw.",",") by 3; call symputx(cats('pe1_',scan("&prog_kw.",i,',')),"","g"); call symputx(cats('pe2_',scan("&prog_kw.",i+1,',')),"","g"); call symputx(cats('pe3_',scan("&prog_kw.",i+2,',')),"","g"); end; run;
Also note, "I expect global variables PE1_201701, PE2_201702 and PE_201703 for first iteration." - you will not get this, all the assignments are within the loop, so all area assigned scan(1), then next loop scan(2) etc.
Again, this really isn't the best method of achieving whatever it is your doing, if this came cross my desk I would delete it without even looking at it.
@RW9 wrote:...
Also note, "I expect global variables PE1_201701, PE2_201702 and PE_201703 for first iteration." - you will not get this, all the assignments are within the loop, so all area assigned scan(1), then next loop scan(2) etc.
...
sorry, typo:
I expect global variables PE1_201701, PE2_201701 and PE3_201701 for first iteration.
BTW the is a lot of more code in the loop, e.g. some PROC SQL....
I hope it's clear now.
Then slight update:
%let prog_kw=201701,201702,201703,201704,201705,201706,201707,201708,201709,201710,201711; data a; do i=1 to countw("&prog_kw.",",") ; call symputx(cats('pe1_',scan("&prog_kw.",i,',')),"","g "); call symputx(cats('pe2_',scan("&prog_kw.",i,',')),"", "g"); call symputx(cats('pe3_',scan("&prog_kw.",i,',')),"", "g"); end; run;
Also note, on "BTW the is a lot of more code in the loop, e.g. some PROC SQL...." - it doesn't matter if there is a million lines of code, and it directs a space shuttle to the moon, this really is not the way to go. Why do you need those dates as macro variable names, that sounds bad. Why do you need all those macro varaibles, that also sounds bad. It sounds very much like you have not heard of by group processing and data modelling and are trying to fix this lack of understanding with macro code. It will fail, and you will be forever trying to maintain it. Trust me, there are far better ways of doing whatever it is your tring to do.
@RW9 wrote:Then slight update:
Also note, on "BTW the is a lot of more code in the loop, e.g. some PROC SQL...." - it doesn't matter if there is a million lines of code, and it directs a space shuttle to the moon, this really is not the way to go. Why do you need those dates as macro variable names, that sounds bad. Why do you need all those macro varaibles, that also sounds bad. It sounds very much like you have not heard of by group processing and data modelling and are trying to fix this lack of understanding with macro code. It will fail, and you will be forever trying to maintain it. Trust me, there are far better ways of doing whatever it is your tring to do.
Don't judge on things you don't know about.
I have to maintain some 100K lines of SAS code written by others and prepare data for 3rd party software within a given data model.
No budget for reengeneering.
Hello,
The macrovariables generated by %qscan contain spaces. You can remove them with %trim.
https://support.sas.com/resources/papers/proceedings10/147-2010.pdf
"A macro-quoting function uses
hexadecimal delta characters to mask special characters in the value of a macro variable. These delta characters
can often cause syntax errors in code that appears to be completely acceptable in the log."
321 %let a=%quote(10);
322 %global b&a.;
SYMBOLGEN: Macro variable A resolves to 10
SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been
unquoted for printing.
The problem is, I do know about it, and have had to do this several times. Patching up badly engineered code just ends up with badly patched badly engineered code that falls over every time it is run and fails any audit. Anyways, its up to you, the code should answer your question.
defaz wrote
No budget for reengeneering.
That's the typical stupid line that keeps totally ******* code alive. That "budget" is always there, it's just payed for in the future, when the stinking mess causes problems after problems after problems. Kick that "code" into the can where it belongs and write something that is worth maintaining.
Do it much simpler:
Wrap your core code in a macro with the three parameters. Avoid any month codes or similar in the macro variable names. Just use param1,param2,param3.
In a data _null_ step, read your parameters from cards/datalines and call the macro with call execute and the parameters.
What you are doing now is like shaking cocktails with nitroglyzerine.
@defaz wrote:
@RW9 wrote:
...
Also note, "I expect global variables PE1_201701, PE2_201702 and PE_201703 for first iteration." - you will not get this, all the assignments are within the loop, so all area assigned scan(1), then next loop scan(2) etc.
...
sorry, typo:
I expect global variables PE1_201701, PE2_201701 and PE3_201701 for first iteration.
BTW the is a lot of more code in the loop, e.g. some PROC SQL....
I hope it's clear now.
Since the variable scope is supposed to be global there is little reason to have it imbedded in code that generates lots of other items. This may be an indication that the whole process could/should be broken into smaller pieces or macro modules, each of which may be easier to maintain and document.
I don't see in your code assigning values to the global macro variables:
%let L_cnt=%sysfunc(countw(%quote(&PROG_KW_LIST)));
%put &=L_cnt;
%put &=PROG_KW_LIST;
%do i1 = 1 %to &L_cnt;
%let PROG_KW=%qscan(%quote(&PROG_KW_LIST.),&i1.,%str(,));
%put &PROG_KW; /* line edited, the equal sign was droped */
%put before global;
%global PE1_&PROG_KW PE2_&PROG_KW PE3_&PROG_KW;
%put after global;..... %end;
e.g. - you defined macro variable: PE1_&PROG_KW.
Do you have somewhere code like: %LET PE1_&PROG_KW = ...; to assign its value ?
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.