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?
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');
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!
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');
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
Thank you @Tom
This solved my problem.
%let varname=FONTE&mon01. ;
....
&varname = tranwrd(&varname,'D','1');
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;
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.