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

Hi,

I'm trying to get the code below to work, but I can't seem to figure out what I'm doing wrong. It's probably the Call Symput step. Basically, the user needs to enter in a percent for each color, in whole numbers (so 5 would be 5%). I would like to take the number that is entered and turn it into decimal form and create another macro variable for it. When I test to see if it worked (in the data step test), I get the "Syntax Error" "Apparent symbolic reference DEC_BLUE_A not resolve."

Am I missing an ampersand somewhere, or something? I've tried making a few changes here and there, but I haven't been successful yet.

Thank you for your help.

%WINDOW INPUTS

     #3  @35 "Inputs" COLOR = BLUE

     #6  @10 "Percents" COLOR = RED //

               @15 "Red" COLOR = BLACK +2 RED_1 4 COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE /

               @15 "Black" COLOR = BLACK +2 BLACK_1 4 COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE /

               @15 "Blue" COLOR = BLACK +2 BLUE_1 4 COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE

;

%DISPLAY INPUTS;

%MACRO DECIMAL2(COLOR);

DATA DECIMAL;

     &COLOR._1 = &&&COLOR/100;

    CALL SYMPUT ("DEC_&COLOR",&COLOR._1);

RUN;

%MEND;

%DECIMAL2(RED_A); %DECIMAL2(BLACK_A); %DECIMAL2(BLUE_A);

DATA TEST; X = &DEC_RED_A; Y = &DEC_BLUE_A; Z = &DEC_BLACK_A; RUN;

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

When creating macro variables in a macro (your macro is using CALL SYMPUT) that you want to use after the macro has finished you need to be careful to make sure that the macro variable is not local to that macro.

You could slap in a %GLOBAL statement to force the macro variable to defined in the global scope.

%MACRO DECIMAL2(COLOR);

%global DEC_&COLOR ;

DATA DECIMAL;

     &COLOR._1 = &&&COLOR/100;

    CALL SYMPUT ("DEC_&COLOR",&COLOR._1);

RUN;

%MEND;

But it would be better to create it conditionally to prevent error messages if the macro variable already exist in an outer executing macro scope.

%macro decimal2(color);

%if not %symexist(dec_&color) %then %global dec_&color ;

data decimal;

   &color._1 = &&&color/100;

   call symputx("dec_&color",&color._1);

run;

%mend decimal2 ;

%let red=200 ;

%symdel dec_red /nowarn;

%decimal2(red);

%put red=&red dec_red=&dec_red ;

Also, do you really need the DATA step?

%macro decimal2(color);

%if not %symexist(dec_&color) %then %global dec_&color ;

%let dec_&color = %sysevalf(&&&color/100) ;

%mend decimal2 ;

View solution in original post

6 REPLIES 6
Haikuo
Onyx | Level 15

'%global DEC_RED_A DEC_BLUE_A DEC_BLACK_A' will help?

Haikuo

ballardw
Super User

I suspect that part of your problem is the value of &&&Color is supposed to resolve to the numeric value in Red_1, Blue_1 or Black_1. However since you are calling with COLOR=RED_A the resolution will never be one of those values entered in the window.

Your calculation line is resolving as:

RED_A_1 = &RED_A/ 100;

You might try using two parameters in your macro Color and suffix.

and

&color.&suffix = &color._1 / 100;

call symput("Dec_&Color.&suffix",&color.&suffix);

ArtC
Rhodochrosite | Level 12

If you need macro variables, I would suggest not using the DATA step.

%* Macro window;
%WINDOW INPUTS
     #3  @35 "Inputs" COLOR = BLUE
     #6  @10 "Percents" COLOR = RED //
               @15 "Red" COLOR = BLACK +2 RED_1 4 COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE /
               @15 "Black" COLOR = BLACK +2 BLACK_1 4 COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE /
               @15 "Blue" COLOR = BLACK +2 BLUE_1 4 COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE;
%DISPLAY INPUTS;
%let dec_red = %sysevalf(&red_1/100);
%let dec_black = %sysevalf(&black_1/100);
%let dec_blue = %sysevalf(&blue_1/100);
%put &red_1 &dec_red;
%put &black_1 &dec_black;
%put &blue_1 &dec_blue;

OTOH if you are going to use these values in a DATA step then use the WINDOW statement and avoid the use of the macro language altogether.

***************************
* DATA step window;
data colors;
WINDOW INPUTS
     #3  @35 "Inputs" COLOR = BLUE
     #6  @10 "Percents" COLOR = RED //
               @15 "Red" COLOR = BLACK +2 RED_1 4. COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE /
               @15 "Black" COLOR = BLACK +2 BLACK_1 4. COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE /
               @15 "Blue" COLOR = BLACK +2 BLUE_1 4. COLOR = GREEN REQUIRED = NO ATTR = UNDERLINE;
DISPLAY INPUTS;
dec_red = red_1/100;
dec_black = black_1/100;
dec_blue = blue_1/100;
put red_1 dec_red;
put black_1 dec_black;
put blue_1 dec_blue;
stop;
run;

kranikai_2
Calcite | Level 5

Hello,

I had somewhat similar a problem; it seemed call symput inside a parametrized macro doesn't work. I found this article helpful: http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#tw3514-symput.htm

So it's a variable scope problem: When there is that "run;" after the data step, the scope of the variables you define in the data step will be the enclosing macro only. I just removed the "run;" and my code started to work. However, I do not know if that's the best way to handle the problem.

Ksharp
Super User

Or use call symputx to assign it to a global macro variable .

call symputx('x',x,'G');

Tom
Super User Tom
Super User

When creating macro variables in a macro (your macro is using CALL SYMPUT) that you want to use after the macro has finished you need to be careful to make sure that the macro variable is not local to that macro.

You could slap in a %GLOBAL statement to force the macro variable to defined in the global scope.

%MACRO DECIMAL2(COLOR);

%global DEC_&COLOR ;

DATA DECIMAL;

     &COLOR._1 = &&&COLOR/100;

    CALL SYMPUT ("DEC_&COLOR",&COLOR._1);

RUN;

%MEND;

But it would be better to create it conditionally to prevent error messages if the macro variable already exist in an outer executing macro scope.

%macro decimal2(color);

%if not %symexist(dec_&color) %then %global dec_&color ;

data decimal;

   &color._1 = &&&color/100;

   call symputx("dec_&color",&color._1);

run;

%mend decimal2 ;

%let red=200 ;

%symdel dec_red /nowarn;

%decimal2(red);

%put red=&red dec_red=&dec_red ;

Also, do you really need the DATA step?

%macro decimal2(color);

%if not %symexist(dec_&color) %then %global dec_&color ;

%let dec_&color = %sysevalf(&&&color/100) ;

%mend decimal2 ;

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 6 replies
  • 5628 views
  • 6 likes
  • 7 in conversation