BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
defaz
Fluorite | Level 6

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

1 ACCEPTED SOLUTION

Accepted Solutions
gamotte
Rhodochrosite | Level 12

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.

View solution in original post

12 REPLIES 12
RW9
Diamond | Level 26 RW9
Diamond | Level 26

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.

defaz
Fluorite | Level 6

@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.

 

 

 

 

RW9
Diamond | Level 26 RW9
Diamond | Level 26

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.

 

 

defaz
Fluorite | Level 6

@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.

 

gamotte
Rhodochrosite | Level 12

Hello,

 

The macrovariables generated by %qscan contain spaces. You can remove them with %trim.

 

gamotte
Rhodochrosite | Level 12
My explanation is wrong but the solution works.
Using %scan instead of %qscan also avoids getting this error message.
gamotte
Rhodochrosite | Level 12

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.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

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.

Kurt_Bremser
Super User

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.

Kurt_Bremser
Super User

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.

 

 

 

ballardw
Super User

@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.

Shmuel
Garnet | Level 18

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 ?

 

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 12 replies
  • 9676 views
  • 4 likes
  • 6 in conversation