Hi,
I am trying to round multiple variables from below dataset B. Dataset A is my reference dataset with rounding requirements for decimal places. Below in this dummy data I have less number of variables but in real data there are many variables, the following code works as expected for less variables but for lot of variables I am getting the below error:
ERROR: The length of the value of the macro variable LGT_MACRO (65540) exceeds the maximum length (65534). The value has been
truncated to 65534 characters.
Can someone please help me fixing the above error.
Example datasets are below
/*Dataset A:*/
/*If not an integer then round to number of decimal places from Var1 column*/
data a;
informat var1 $50. length $10. var2 $200.;
infile datalines delimiter=',';
input var1 length var2 ;
datalines;
NotAvailable,8,Subject
NotAvailable,8,Site
NotAvailable,$200,Visit
integer,8,Age
0.0001,8,Score1
integer,8,Score2
NotAvailable,$200,Date
0.00001,8,Score_3
NotAvailable,$200,I_am_the_longest_variable_Test_3
;
run;
/*dataset B:*/
data b;
informat Visit $200. Date $200. I_am_the_longest_variable_Test_3 $200.;
infile datalines delimiter=',';
input Subject Site Visit Age Score1 Score2 Date Score_3 I_am_the_longest_variable_Test_3 ;
datalines;
1234,001,Day1,55,344.70452025162167,4,2023-06-08 15:37,4.5707963267948966,ABCD
2456,002,Day5,45,100.12342025162167,3,2023-06-09 15:37,3.1234907586284892,WXYZ
3456,003,Day1,60,94.38627492995121,2,2023-06-10 15:37,5.7398282916662683,ABCD
7890,001,Day5,52,92.28219778353588,1,2023-06-08 15:37,3.749207747474,WXYZ
1111,002,Day1,70,124.6789456782671,3,2023-06-09 15:37,4.172819191919191,ABCD
1567,003,Day1,59,125.4796290763492,5,2023-06-10 15:37,1.272383939999,WXYZ
;
run;
data a1;
set a;
if index(length,'$')>0 or UPCASE(var1)='NOTAVAILABLE' then ;
else if UPCASE(var1)='INTEGER' then Rnd_var=0;
else If UPCASE(var1)='0.0001' then Rnd_var=0.0001;
else If UPCASE(var1)='0.00001' then Rnd_var=0.00001;
else If UPCASE(var1)='NOTAVAILABLE' then Rnd_var=.;
run;
data sample_formats;
set a1;
format length_macr0 $100. ;
if index(length,'$')> 0 or UPCASE(var1) in ('NOTAVAILABLE') then length_macr0='';
else length_macr0=cat(compress(var2),'=','round(',compress(var2),',',compress(rnd_var),')') ;
run;
proc sql;
select length_macr0 into :lgt_macro separated by ";"
from sample_formats
where length_macr0 is not missing
;
%put length_macr0;
data test;
set b;
&lgt_macro. ;
run;
If the goal is to generate CODE from the metadata in the dataset A then it might be easier to do that by just writing the code directly from the dataset and skipping the macro variable.
filename code temp;
data _null_;
file code ;
set a;
where not (index(length,'$') or upcase(var1)='NOTAVAILABLE');
if upcase(var1)='INTEGER' then var1=1;
put var2 '=round(' var2 ',' var1 ');' ;
run;
data test;
set b;
%include code / source2 ;
run;
1940 data test; 1941 set b; 1942 %include code / source2 ; NOTE: %INCLUDE (level 1) file CODE is (system-specific pathname). 1943 +Age =round(Age ,1 ); 1944 +Score1 =round(Score1 ,0.0001 ); 1945 +Score2 =round(Score2 ,1 ); 1946 +Score_3 =round(Score_3 ,0.00001 ); NOTE: %INCLUDE (level 1) ending. 1947 run; NOTE: The data set WORK.TEST has 6 observations and 9 variables.
PS You seem to be trying to use INFORMAT and FORMAT as if they were designed to DEFINE variables. That is not what those statements are for. The only reason they work in your code is because it is the first place the variable is mentioned so the data step compiler is forced to GUESS that you wanted the LENGTH of the variable to be defined to match the WIDTH of the informat or format that you wanted to attach to it.
this part:
proc sql;
select length_macr0 into :lgt_macro separated by ";"
from sample_formats
where length_macr0 is not missing
;
causes the problem, the data extracted in the length_macr0
variable is bigger than possible macrovariable length.
you can do 2 things:
1) make it: select STRIP(length_macr0) into :lgt_macro separated by ";"
or
2) create a macrovariable list: select length_macr0 into :lgt_macro1-
and when the list is created call to its elements like: &&lgt_macro%i
where the "i" is macro %do-loop iterator.
Bart
If the goal is to generate CODE from the metadata in the dataset A then it might be easier to do that by just writing the code directly from the dataset and skipping the macro variable.
filename code temp;
data _null_;
file code ;
set a;
where not (index(length,'$') or upcase(var1)='NOTAVAILABLE');
if upcase(var1)='INTEGER' then var1=1;
put var2 '=round(' var2 ',' var1 ');' ;
run;
data test;
set b;
%include code / source2 ;
run;
1940 data test; 1941 set b; 1942 %include code / source2 ; NOTE: %INCLUDE (level 1) file CODE is (system-specific pathname). 1943 +Age =round(Age ,1 ); 1944 +Score1 =round(Score1 ,0.0001 ); 1945 +Score2 =round(Score2 ,1 ); 1946 +Score_3 =round(Score_3 ,0.00001 ); NOTE: %INCLUDE (level 1) ending. 1947 run; NOTE: The data set WORK.TEST has 6 observations and 9 variables.
PS You seem to be trying to use INFORMAT and FORMAT as if they were designed to DEFINE variables. That is not what those statements are for. The only reason they work in your code is because it is the first place the variable is mentioned so the data step compiler is forced to GUESS that you wanted the LENGTH of the variable to be defined to match the WIDTH of the informat or format that you wanted to attach to it.
Thanks Tom...this worked.
More than a little concerned about reading any DATE type value as $200 to begin with. SAS dates should generally be date, time or datetime valued with an appropriate format though the values should be integer unless dealing with fractional seconds.
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!What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.
Select SAS Training centers are offering in-person courses. View upcoming courses for: