- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
I want to macrotize the following code that works. It doesn't produce an error or log, it just does not terminate.
data public.want;
set public.have;
length batch_id_dt1 batch_id1 varchar(*);
batch_id_dt1=strip(batch_id_dt);
drop batch_id_dt;
rename batch_id_dt1=batch_id_dt;
batch_id1=strip(batch_id);
drop batch_id;
rename batch_id1=batch_id;
run;
I'm trying to plug-in the text from a macro function. Here is my failed attempt.
%macro varcharer(name=);
&name.1=strip(&name);
drop &name;
rename &name.1=&name;
%mend;
data public.want;
set public.have(where=(datepart(timestamp)='28mar2025'd));
length batch_id1 varchar(*);
array temp batch_id;
do i=1 to dim(temp);
/* call execute('%varcharer(name=' ||vnamex(temp(i)) || ');'); */
call execute('%varcharer(name=batch_id);');
end;
run;
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
This should work:
data public.want;
set public.have;
length batch_id_dt1 batch_id1 varchar(*);
%varcharer(name=batch_id);
%varcharer(name=batch_id_dt);
run;
You could use proc sql to create a variable containing all the variables that need to be converted, assuming it is named "var_list":
%macro convert(); data public.want; set public.have; length batch_id_dt1 batch_id1 varchar(*); %do i = 1 %to %sysfunc(countw(&var_list, %str( ))); %let var = %scan(&var_list, &i, %str( )); %varcharer(name= &var); %end; run; %mend convert; %convert();
Code is untested.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
You macro resolves to data step code. It cannot run outside of a data step. CALL EXECUTE queues SAS code to run after the data step finishes, and so is incompatible with the macro.
In addition, the content of your macro will fail as you can't rename a variable like that.
In order to write good macro code, you first (this is MANDATORY not optional) have to write code that works without macros and without macro variables for one case, such as for variable named batch_id. You clearly haven't done that because if you had done this you would know you can't rename variables like this.
Finally, I don't see why a macro is needed inside an array in this situation.
Here is my solution. Of course this is untested as you haven't provided data for me to work with.
data public.want;
set public.have(where=(datepart(timestamp)='28mar2025'd));
array temp batch_id;
do i=1 to dim(temp);
temp(i)=strip(temp(i));
end;
run;
So please, next time, you need to do all of these steps
- Describe in words the problem you are trying to solve, so we don't have to guess or figure it out ourselves
- Show us code that works without macros and without macro variables for at least one iteration (in this case variable named batch_id)
- Provide sample data
Do not skip any of these steps
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
My code works without error, now I want to put it with a macro.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Why do you need a macro? I wrote code that does what you want without a macro. Macros seem to be an unnecessary complication.
Please state in words what you are trying to do.
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@PaigeMiller I can easily have many variables that need conversion from char to varchar format.
This works:
data public.want;
set public.have;
length batch_id_dt1 batch_id1 varchar(*);
batch_id_dt1=strip(batch_id_dt);
drop batch_id_dt;
rename batch_id_dt1=batch_id_dt;
batch_id1=strip(batch_id);
drop batch_id;
rename batch_id1=batch_id;
run;
But for 30 variables I would like to use a macro function. Therefore I've thought about an array for the variables I want to change to varchar.
And looping over the array elements to plug-in the varnames for the maco function.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@acordes wrote:
@PaigeMiller I can easily have many variables that need conversion from char to varchar format.
This should have been clearly stated in your original post. We shouldn't have to guess why you are going through these gyrations with CALL EXECUTE and Macros and arrays. Please provide sample data set for us to work with.
As far as I can see, the reason you might want VARCHAR is for CAS data sets, this also should have been clearly stated.
But I saw the usage of macro functions within data steps and cas actions. And I want to learn it and add it to my tool kit.
One of the things you should learn about macros is when NOT to use them. This is such a case. If the code can be easily written without macros, then macros are not necessary. Examples from me and @yabwon show you don't need a macro here.
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Listen to @PaigeMiller , there is no need for macro here.
You have a list of variables (batch_id_dt and batch_id) you want to strip leading and trailing spaces, just do it with a loop:
data public.want;
set public.have(where=(datepart(timestamp)='28mar2025'd));
array temp batch_id_dt batch_id;
do over temp;
temp=strip(temp);
end;
run;
Bart
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug
"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings
SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@yabwon I'm not with you. I need to change the batch_id (and x variables more) from char format to varchar format.
I could produce the text with a proc sql select into, no problem, I can do it.
But I saw the usage of macro functions within data steps and cas actions. And I want to learn it and add it to my tool kit.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
OK, since now it's clear what you want to do, try this:
data public.have;
a=" A";
b=" A";
c=" A";
d=" A";
run;
%macro char2varchar(list);
%local V i;
%let i=1;
%let v = %scan(&list., &i., %str( ));
%do %while (&v. NE );
length &v.1 varchar(*);
&v.1=strip(&v.);
drop &v.;
rename &v.1=&v.;
%let i= %eval(&i. + 1);
%let v = %scan(&list., &i., %str( ));
%end;
%mend char2varchar;
options NOmprint;
options mprint;
data public.want;
set public.have;
%char2varchar(A B C D)
run;
[EDIT:]
Just to be clear if "public" is not a CAS library, then conversion to varchar is pointless:
Log:
1 options mprint;
2 data public.want;
3 set public.have;
4
5 %char2varchar(A B C D)
MPRINT(CHAR2VARCHAR): length A1 varchar(*);
MPRINT(CHAR2VARCHAR): A1=strip(A);
MPRINT(CHAR2VARCHAR): drop A;
MPRINT(CHAR2VARCHAR): rename A1=A;
MPRINT(CHAR2VARCHAR): length B1 varchar(*);
MPRINT(CHAR2VARCHAR): B1=strip(B);
MPRINT(CHAR2VARCHAR): drop B;
MPRINT(CHAR2VARCHAR): rename B1=B;
MPRINT(CHAR2VARCHAR): length C1 varchar(*);
MPRINT(CHAR2VARCHAR): C1=strip(C);
MPRINT(CHAR2VARCHAR): drop C;
MPRINT(CHAR2VARCHAR): rename C1=C;
MPRINT(CHAR2VARCHAR): length D1 varchar(*);
MPRINT(CHAR2VARCHAR): D1=strip(D);
MPRINT(CHAR2VARCHAR): drop D;
MPRINT(CHAR2VARCHAR): rename D1=D;
6 run;
NOTE: VARCHAR data type is not supported by the V9 engine. Variable A has been converted to CHAR data type.
NOTE: VARCHAR data type is not supported by the V9 engine. Variable B has been converted to CHAR data type.
NOTE: VARCHAR data type is not supported by the V9 engine. Variable C has been converted to CHAR data type.
NOTE: VARCHAR data type is not supported by the V9 engine. Variable D has been converted to CHAR data type.
NOTE: There were 1 observations read from the data set PUBLIC.HAVE.
NOTE: The data set PUBLIC.WANT has 1 observations and 4 variables.
NOTE: DATA statement used (Total process time):
real time 0.04 seconds
user cpu time 0.03 seconds
system cpu time 0.03 seconds
memory 714.18k
OS Memory 21764.00k
Bart
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug
"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings
SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Bart, I'll test later.
And for sure you're right @PaigeMiller to call me on stating well the problem. If I use public as library for me it's always a caslib, but yes, I should have said clearly.
And to generate test data here in this case I've found it to complicated or time-consuming.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
data public.have;
a=" A";
b=" A";
c=" A";
d=" A";
run;
Not "that" time consuming 😉 🙂
Bart
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug
"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings
SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
This should work:
data public.want;
set public.have;
length batch_id_dt1 batch_id1 varchar(*);
%varcharer(name=batch_id);
%varcharer(name=batch_id_dt);
run;
You could use proc sql to create a variable containing all the variables that need to be converted, assuming it is named "var_list":
%macro convert(); data public.want; set public.have; length batch_id_dt1 batch_id1 varchar(*); %do i = 1 %to %sysfunc(countw(&var_list, %str( ))); %let var = %scan(&var_list, &i, %str( )); %varcharer(name= &var); %end; run; %mend convert; %convert();
Code is untested.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Can I use the these lines within an array loop???
batch_id_dt1=strip(batch_id_dt);
drop batch_id_dt;
rename batch_id_dt1=batch_id_dt;