BookmarkSubscribeRSS Feed
thanikondharish
Calcite | Level 5
proc sql ;
select count(distinct origin) into: count from sashelp.cars ;
select distinct(strip(origin)) into:or1-:or%left(&count) from sashelp.cars ;
quit;

%put &or1 &count ;

 

%macro test ;
proc sql ;
%do i=1 %to 1 ;
%global co make%left(&co) ;
select count(distinct make) into:co from sashelp.cars 
where strip(origin)="&&or&i" ;
select distinct make into:make1-:make%left(&co) from sashelp.cars 
where strip(origin)="&&or&i" ;
%end; 
quit; 
%mend ;
options mprint symbolgen ;
%test ;
%put &make1 ;

when I want to see value of make1 macro variable it is showing not resolved.

 

How  to convert local to global macro variable?

10 REPLIES 10
PaigeMiller
Diamond | Level 26

Please paste your code into a text box (running man icon) from now on so we don't see smiley faces in your code.

 

If you really need &MAKE1 outside of the macro, you put a %GLOBAL statement before the macro, or inside the macro, or you change your logic so that you don't need &MAKE1 outside of the macro (which in this simple case, it is not needed outside of the macro).

--
Paige Miller
thanikondharish
Calcite | Level 5
total 14 global macro variables should be formed
Kurt_Bremser
Super User

PLEASE

use the "little running man" icon for posting code. It is not rocket science, and it prevents the appearance of smileys and other funnies that make it hard to impossible to run your code.

 

You use the %global statement to declare a macro variable global. You have to do this for ALL variables you create, and since you use a variable series of macro variables, you have to do this declaration in the same manner.

 

But this all just shows the UTTER STUPIDITY of storing values in macro lists. Keep data where it belongs, in DATASETS, and use the usual SAS means to create dynamic code where necessary, but most of the time you just use lookups (join, format, hash) from the dataset anyway.

Tom
Super User Tom
Super User

Your %DO loop is running only once since you are starting at one and stopping at one.  Did you mean to use a different upper bound?

 

You are over complicating things.  Your first step can just be:

proc sql NOPRINT;
select distinct strip(origin) into :or1- from sashelp.cars ;
%let count=&sqlobs;
quit;

Inside your macro why not just use CALL SYMPUTX() instead?  It is not clear why you switched from putting the ORIGIN variable into the macro variables to putting the MAKE variable into the macro variables. 

 

So in this example I will just show how to replicate what the SQL code above does.

%macro test ;
proc sql ;
  create table origins as select distinct left(origin) as origin 
  from sashelp.cars;
quit;
data _null_;
  if eof then call symputx('count',_n_-1,'g');
  set origins end=eof;
  call symputx(cats('or',_n_),origin,'g');
run;
%mend ;

UPDATE

Note that if your source dataset is already sorted there is no need for an extra step to find or count the distinct values.  By group processing will do that for you.

%let or1=Asia;
%let j=1;

data _null_;
  set cars end=eof;
  by make ;
  where origin = "&&or&J" ;
  if first.make then do;
    make_count + 1;
    call symputx(cats('make',make_count),make,'g');
  end;
  if eof then call symputx('make_count',make_count,'g');
run;

%put _user_;
GLOBAL J 1
GLOBAL MAKE1 Acura
GLOBAL MAKE10 Nissan
GLOBAL MAKE11 Scion
GLOBAL MAKE12 Subaru
GLOBAL MAKE13 Suzuki
GLOBAL MAKE14 Toyota
GLOBAL MAKE2 Honda
GLOBAL MAKE3 Hyundai
GLOBAL MAKE4 Infiniti
GLOBAL MAKE5 Isuzu
GLOBAL MAKE6 Kia
GLOBAL MAKE7 Lexus
GLOBAL MAKE8 Mazda
GLOBAL MAKE9 Mitsubishi
GLOBAL MAKE_COUNT 14
GLOBAL OR1 Asia
Cynthia_sas
SAS Super FREQ
Hi:
It's not clear to me what you want to do. Why does your %DO loop only go from 1 to 1? Can you clarify what it is you need to do? I think your problem is not how to convert a local to a global macro variable. I think the issue is starting with what your 2 programs are doing versus what they need to do.
Cynthia
Kurt_Bremser
Super User

Your whole issue is solved by this:

proc sort data=sashelp.cars out=lookup nodupkey;
by origin make;
run;

Now you have a dataset from which you can create lookups, where conditions, whatever. No macro stuff needed. AT ALL.

thanikondharish
Calcite | Level 5
We have to keep in macros not dataset
s_lassen
Meteorite | Level 14

Two problems with your code:

  1. The CO macro variable is used in your %GLOBAL statement before it has been assigned a value
  2. Even if you had assigned to it before trying to declare the MAKE variables %GLOBAL, you would only be declaring the last MAKE value %GLOBAL

Other than that, what are you trying to do? Your %TEST macro tries to assign values to macro variables for a specific ORIGIN value (the first). If you want to do that, you should give your %TEST macro a parameter, so that you can specify the ORIGIN value that you want, e.g.:

%macro test(origin) ;
%local i;
proc sql ;
  %global co;
   select count(distinct make) into:co trimmed from sashelp.cars 
     where strip(origin)="&origin" ;
  %do i=1 %to &co;
      %global make&i ;
      %end;
  select distinct make into:make1-:make&co trimmed from sashelp.cars 
  where strip(origin)="&origin" ;
quit; 
%mend ;

Then you can call the macro with the ORIGIN value that you want to get the MAKE values for. Note the use of TRIMMED in the INTO clause, that removes trailing blanks from the assigned macro variables.

 

But generally, I would advise against putting everything into %GLOBAL values. What exactly is it you are trying to accomplish? 

Astounding
PROC Star
You have received lots of good advice here. If you intend to follow your original path, you can correct the mistake with a small change to your %GLOBAL statement:

%global co make&i;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 10 replies
  • 3125 views
  • 1 like
  • 7 in conversation