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

Hello

 

I've created this macro variables

 

%let basemon=201601;
%let mon02=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+2),yymmn.);
%let mon01=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+1),yymmn.);

Then I created this two data statements:

 

data out.P24M&basemon.;
set out.P24M&basemon.;
FONTE201602=tranwrd(FONTE&mon01.,'D','1');
FONTE201602=tranwrd(FONTE&mon01.,'E','1');
FONTE201602=tranwrd(FONTE&mon01.,'A','1');
FONTE201603=tranwrd(FONTE&mon02.,'D','1');
FONTE201603=tranwrd(FONTE&mon02.,'E','1');
FONTE201603=tranwrd(FONTE&mon02.,'A','1');
run;

data out.P24M&basemon.;
set out.P24M&basemon.;
NFONTE201602= input(FONTE&mon01., comma10.);
run;

Bus what I want and it doesn´t work is this code:

 

data out.P24M&basemon.;
set out.P24M&basemon.;
FONTE&mon01.=tranwrd(FONTE&mon01.,'D','1');
FONTE&mon01.=tranwrd(FONTE&mon01.,'E','1');
FONTE&mon01.=tranwrd(FONTE&mon01.,'A','1');
FONTE&mon02.=tranwrd(FONTE&mon02.,'D','1');
FONTE&mon02.=tranwrd(FONTE&mon02.,'E','1');
FONTE&mon02.=tranwrd(FONTE&mon02.,'A','1');
run;

data out.P24M&basemon.;
set out.P24M&basemon.;
NFONTE&mon01.= input(FONTE&mon01., comma10.);
run;

If I write 

FONTE&mon01.=tranwrd(FONTE&mon01.,'D','1');

instead of

FONTE201601=tranwrd(FONTE&mon01.,'D','1');

SAS does not assumes the macro variable that is on the left side of the equality.

 

How can I solve this?

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Please show the SAS log with the error message.

 

Note that sometimes the macro processor can cause SAS to get confused in parsing the generated SAS code when a single token, like a variable name, is generated from multiple macro tokens.  Adding %UNQUOTE() macro function can help.

%unquote(FONTE&mon01.)=tranwrd(%unquote(FONTE&mon01.),'D','1');

But usually it is just simpler to build a new macro variable that has the compound value and then use that macro variable when generating the code. Especially if you are going to use the new name in multiple places.

%let varname=FONTE&mon01. ;
....
&varname = tranwrd(&varname,'D','1');

 

View solution in original post

5 REPLIES 5
PaigeMiller
Diamond | Level 26

When you have problems like this with macro variables, you want to turn on the macro debugging options, as follows

 

options symbolgen mlogic;

Then run your code again and look at the log to see what is happening. If you can't decipher the log, then show us the log (all of it, every single line, every single character). It is critically important that you preserve the formatting of the log by pasting it into the window that appears when you click on the </> icon. DO NOT SKIP THIS STEP!

Insert Log Icon in SAS Communities.png

--
Paige Miller
Tom
Super User Tom
Super User

Please show the SAS log with the error message.

 

Note that sometimes the macro processor can cause SAS to get confused in parsing the generated SAS code when a single token, like a variable name, is generated from multiple macro tokens.  Adding %UNQUOTE() macro function can help.

%unquote(FONTE&mon01.)=tranwrd(%unquote(FONTE&mon01.),'D','1');

But usually it is just simpler to build a new macro variable that has the compound value and then use that macro variable when generating the code. Especially if you are going to use the new name in multiple places.

%let varname=FONTE&mon01. ;
....
&varname = tranwrd(&varname,'D','1');

 

AMSAS
SAS Super FREQ

Turn on SYMBOLGEN, rerun and provide the log

 

When I run a simple example (below) it works for me

Code:

options mprint mlogic symbolgen ;
%let basemon=201601;
%let mon02=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+2),yymmn.);
%let mon01=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+1),yymmn.);
%put &mon02 &mon01 ;

/* Create sample data */
data have ;
	do i=1 to 5 ;
		fonte201602="ABC"||left(putn(i,"8.")) ;
		fonte201603="XYZ"||left(putn(i,"8.")) ;
		output ;
	end ;
run ;

data want ;
	set have ;
	fonte&mon01.=tranwrd(fonte&mon01.,"1","X") ;
	fonte&mon02.=tranwrd(fonte&mon02.,"3","X") ;
	put fonte&mon01.= fonte&mon02.= ;
run ;

Log:

859  options mprint mlogic symbolgen ;
860  %let basemon=201601;
861  %let mon02=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+2),yymmn.);
SYMBOLGEN:  Macro variable BASEMON resolves to 201601
862  %let mon01=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+1),yymmn.);
SYMBOLGEN:  Macro variable BASEMON resolves to 201601
863  %put &mon02 &mon01 ;
SYMBOLGEN:  Macro variable MON02 resolves to 201603
SYMBOLGEN:  Macro variable MON01 resolves to 201602
201603 201602
864
865  data have ;
866      do i=1 to 5 ;
867          fonte201602="ABC"||left(putn(i,"8.")) ;
868          fonte201603="XYZ"||left(putn(i,"8.")) ;
869          output ;
870      end ;
871  run ;

NOTE: The data set WORK.HAVE has 5 observations and 3 variables.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds
      cpu time            0.03 seconds


872
873  data want ;
874      set have ;
875      fonte&mon01.=tranwrd(fonte&mon01.,"1","X") ;
SYMBOLGEN:  Macro variable MON01 resolves to 201602
SYMBOLGEN:  Macro variable MON01 resolves to 201602
876      fonte&mon02.=tranwrd(fonte&mon02.,"3","X") ;
SYMBOLGEN:  Macro variable MON02 resolves to 201603
SYMBOLGEN:  Macro variable MON02 resolves to 201603
SYMBOLGEN:  Macro variable MON01 resolves to 201602
877      put fonte&mon01.= fonte&mon02.= ;
SYMBOLGEN:  Macro variable MON02 resolves to 201603
878  run ;

fonte201602=ABCX fonte201603=XYZ1
fonte201602=ABC2 fonte201603=XYZ2
fonte201602=ABC3 fonte201603=XYZX
fonte201602=ABC4 fonte201603=XYZ4
fonte201602=ABC5 fonte201603=XYZ5
NOTE: There were 5 observations read from the data set WORK.HAVE.
NOTE: The data set WORK.WANT has 5 observations and 3 variables.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds

 

ramgouveia
Obsidian | Level 7

Thank you @Tom 

 

This solved my problem.

 

%let varname=FONTE&mon01. ;
....
&varname = tranwrd(&varname,'D','1');
ErikLund_Jensen
Rhodochrosite | Level 12

Hi @ramgouveia 

Your code actually works (proved by running the code included below where only the libref is changed).

 

So my guess would be that the macro variables aren't resolved, which would be the case if they are created inside a macro and not explicitly declared global. Try to write the macro variables to the log just befor the data step: %put &=basemon etc.

 

Working code:

 

* Test data;
data work.P24M201601;
	FONTE201601 = 'D E A X'; output;
	FONTE201602 = 'D E A X'; output;
	FONTE201603 = 'D E A X'; output;
	FONTE201604 = 'D E A X'; output;
run;

%let basemon=201601;
%let mon02=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+2),yymmn.);
%let mon01=%sysfunc(intnx(month,%sysfunc(inputn(&basemon,yymmn6.)),+1),yymmn.);

data work.P24M&basemon.;
	set work.P24M&basemon.;
	FONTE&mon01.=tranwrd(FONTE&mon01.,'D','1');
	FONTE&mon01.=tranwrd(FONTE&mon01.,'E','1');
	FONTE&mon01.=tranwrd(FONTE&mon01.,'A','1');
	FONTE&mon02.=tranwrd(FONTE&mon02.,'D','1');
	FONTE&mon02.=tranwrd(FONTE&mon02.,'E','1');
	FONTE&mon02.=tranwrd(FONTE&mon02.,'A','1');
run;

 

 

SAS Innovate 2025: Call for Content

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!

Submit your idea!

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
  • 5 replies
  • 1425 views
  • 2 likes
  • 5 in conversation