In row 42 below I'm trying to select a numeric format name that I stored in a macro variable, but SAS seems to read it as character (see "NOTE 484-185" below). What can be done to tell SAS it is numeric?
27 /*Store variable names*/
28 %let varvals=Partictype RecPmtRcvd;
29 /*Store their associated format names*/
30 %let formval=partictype yesno;
31 options mprint;
32 data temp1(keep=CJRorig Var_name Var_value);
33 length var_name var_value $20;
34 set CJR_Combine;
35 if CJRorig=1 then do;
36 /*Create an observation for each variable*/
37 %macro selval;
38 %do i=1 %to 2;
39 /*Assign the variable name to Var_name*/
40 Var_name="%scan(&varvals,&i)";
41 /*Assign its formatted value to Var_value*/
42 Var_value=put(Var_name,%scan(&formval,&i).);
43 %end;
44 %mend;
45 %selval
MPRINT(SELVAL): Var_name="Partictype";
NOTE: Line generated by the macro function "SCAN".
45 partictype
__________
484
MPRINT(SELVAL): Var_value=put(Var_name,partictype.);
MPRINT(SELVAL): Var_name="RecPmtRcvd";
NOTE 484-185: Format $PARTICTYPE was not found or could not be loaded.
NOTE: Line generated by the macro function "SCAN".
45 yesno
_____
2 The SAS System 09:50 Tuesday, June 12, 2018
484
MPRINT(SELVAL): Var_value=put(Var_name,yesno.);
NOTE 484-185: Format $YESNO was not found or could not be loaded.
46 output;
47 end;
48 run;
NOTE: There were 3316 observations read from the data set WORK.CJR_COMBINE.
NOTE: The data set WORK.TEMP1 has 793 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.04 seconds
cpu time 0.04 seconds
It is a poor idea to define a macro in the middle of a data step.
When you do this:
if CJRorig=1 then do; 36 /*Create an observation for each variable*/ 37 %macro selval;
The behavior can be very problematic.
Note that MACROS do not access data step variables without a lot of extra work.
In
40 Var_name="%scan(&varvals,&i)"; 41 /*Assign its formatted value to Var_value*/ 42 Var_value=put(Var_name,%scan(&formval,&I).);
The data step variable VAR_NAME will always be character. So if you attempt to put the value with a numeric format you get that error.
You might try
Var_value=put(%scan(&varvals,&i),%scan(&formval,&i).);
But that will require having the variable referenced in your macro variable in the data set.
Note that if you have a format that uses decimals such as F8.2 your code will also yield unexpected resultsas it attempts to use format "F8." due to the . you have to terminate the scanned formval AND that . is a default delimiter to %scan. Which then means the value following the . is the next format to use.
To output multiple records from one you also need an OUTPUT statement inside the DO loop.
PUT does not take a format without the dot and/or $, try PUTC or PUTN instead depending on the type. It also looks like you're missing the $ for a character format.
I can't quite decipher your code but it also looks like you have a macro definition embedded in a data step. I would highly suggest not doing that. I also think you want some array logic here, and use the macro count but not necessarily a macro here.
@Batman wrote:
In row 42 below I'm trying to select a numeric format name that I stored in a macro variable, but SAS seems to read it as character (see "NOTE 484-185" below). What can be done to tell SAS it is numeric?
27 /*Store variable names*/
28 %let varvals=Partictype RecPmtRcvd;
29 /*Store their associated format names*/
30 %let formval=partictype yesno;
31 options mprint;
32 data temp1(keep=CJRorig Var_name Var_value);
33 length var_name var_value $20;
34 set CJR_Combine;
35 if CJRorig=1 then do;
36 /*Create an observation for each variable*/
37 %macro selval;
38 %do i=1 %to 2;
39 /*Assign the variable name to Var_name*/
40 Var_name="%scan(&varvals,&i)";
41 /*Assign its formatted value to Var_value*/
42 Var_value=put(Var_name,%scan(&formval,&i).);
43 %end;
44 %mend;
45 %selval
MPRINT(SELVAL): Var_name="Partictype";
NOTE: Line generated by the macro function "SCAN".
45 partictype
__________
484
MPRINT(SELVAL): Var_value=put(Var_name,partictype.);
MPRINT(SELVAL): Var_name="RecPmtRcvd";
NOTE 484-185: Format $PARTICTYPE was not found or could not be loaded.
NOTE: Line generated by the macro function "SCAN".
45 yesno
_____
2 The SAS System 09:50 Tuesday, June 12, 2018
484
MPRINT(SELVAL): Var_value=put(Var_name,yesno.);
NOTE 484-185: Format $YESNO was not found or could not be loaded.
46 output;
47 end;
48 run;
NOTE: There were 3316 observations read from the data set WORK.CJR_COMBINE.
NOTE: The data set WORK.TEMP1 has 793 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.04 seconds
cpu time 0.04 seconds
Thanks Reeza, I would prefer to use arrays, but run into trouble when I try to reference a format name using an array.
27 data _null_;
28 length var_name var_value $20;
29 array varvals{2} Partictype RecPmtRcvd;
30 array formvals{2} $ ('partictype.' 'yesno.');
31 set CJR_Combine(obs=1);
32 Var_name=varvals(1);
33 Var_value=put(varvals(1),formvals(1));
________
85
76
ERROR 85-322: Expecting a format name.
ERROR 76-322: Syntax error, statement will be ignored.
34 put Var_name= Var_value=;
35 run;
To use an expression to contain the format specification you need to use PUTN() or PUTC() functions instead of the PUT() function. So you need to know whether the variable is numeric (PUTN) or character (PUTC).
data want;
set CJR_Combine(obs=1);
array varvals(2) 8 Partictype RecPmtRcvd;
array formvals(2) $20 _temporary_ ('partictype.' 'yesno.');
length var_name var_value $32;
do i=1 to dim(varvals);
Var_name=varvals(1);
Var_value=putn(varvals(1),formvals(1));
output;
end;
run;
@Batman wrote:
Thanks Reeza, I would prefer to use arrays, but run into trouble when I try to reference a format name using an array.
27 data _null_;
28 length var_name var_value $20;
29 array varvals{2} Partictype RecPmtRcvd;
30 array formvals{2} $ ('partictype.' 'yesno.');
31 set CJR_Combine(obs=1);
32 Var_name=varvals(1);
33 Var_value=put(varvals(1),formvals(1));
________
85
76
ERROR 85-322: Expecting a format name.
ERROR 76-322: Syntax error, statement will be ignored.
34 put Var_name= Var_value=;
35 run;
PUTC in this case instead.
Don't define a macro in the middle of data step (or for that matter in the middle of program). Define the macro first and then use it where you want it to run.
From the comments in your code you need to have an OUTPUT statement generated by the macro for each variable name.
%macro selval;
%do i=1 %to 2;
/*Assign the variable name to Var_name*/
Var_name="%scan(&varvals,&i)";
/*Assign its formatted value to Var_value*/
Var_value=put(Var_name,%scan(&formval,&i).);
/*Create an observation for each variable*/
output;
%end;
%mend;
Now you can call it in the middle of a data step to generate the assignment and output statements.
/*Store variable names*/
%let varvals=Partictype RecPmtRcvd;
/*Store their associated format names*/
%let formval=partictype yesno;
data temp1(keep=CJRorig Var_name Var_value);
length var_name var_value $20;
set CJR_Combine;
if CJRorig=1 then do;
%selval
end;
run;
The error messages are complaining that the formats have not been defined. Make sure you create the YESNO and other formats before trying to use them in a PUT() function call.
It is a poor idea to define a macro in the middle of a data step.
When you do this:
if CJRorig=1 then do; 36 /*Create an observation for each variable*/ 37 %macro selval;
The behavior can be very problematic.
Note that MACROS do not access data step variables without a lot of extra work.
In
40 Var_name="%scan(&varvals,&i)"; 41 /*Assign its formatted value to Var_value*/ 42 Var_value=put(Var_name,%scan(&formval,&I).);
The data step variable VAR_NAME will always be character. So if you attempt to put the value with a numeric format you get that error.
You might try
Var_value=put(%scan(&varvals,&i),%scan(&formval,&i).);
But that will require having the variable referenced in your macro variable in the data set.
Note that if you have a format that uses decimals such as F8.2 your code will also yield unexpected resultsas it attempts to use format "F8." due to the . you have to terminate the scanned formval AND that . is a default delimiter to %scan. Which then means the value following the . is the next format to use.
To output multiple records from one you also need an OUTPUT statement inside the DO loop.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.