Hello,
In a macro, I want to use the label of the old variable date to create a new variable.
But for the moment, i just can't use previous label (stocked in temp var) : label = temp doesn't work. I'm not familiar with VLABEL function but it looks work for the temp var.
And after this, I would like to add character in the middle of the label. If the label is "Date of procedure", I would like it to be "Date and time of procedure". I've tried with scan or find but it doesn't work.
%macro datetime(dataset, vardate, vartime, dataname);
data &dataset.;
set &dataset.;
temp = vlabel(&vardate.); put temp=;
if temp contains
attrib &vardate. informat=datetime. format=datetime. label = temp;
&dataname. = DHMS(&vardate.,0,0,0) ;
&vartime. = TIMEPART(&vartime.) ;
&dataname. = &dataname. + &vartime.;
run;
%mend;
Thanks in advance, let me know if I wasn't clear.
The first thing you need to do before writing a macro is to get valid working SAS code for one case, without macros and without macro variables. If you can't do this, if your code doesn't work without macros and without macro variables, then it will never work with macros and with macro variables.
You haven't done this. So please take a step back and work on that part of the problem, before trying to turn this into a macro.
I will even get you started. You do the next piece, without macros and without macro variables.
data have;
date='01JAN2022'd;
label date='Date of Procedure';
run;
data intermediate;
set have;
date_label=vlabel(date);
if find(date_label,'date of procedure','i') then do;
put 'I Found It!';
end;
run;
Thanks to reply so quickly.
I'm sorry but I wasn't clear at all in my last message.
I already wrote my code without macro and it was working for everything except label :
data datasetproc;
set datasetproc;
temp = vlabel(VIS_DT);put temp;
attrib VARDATETIME informat=datetime. format=datetime. label = temp;
VARDATETIME = DHMS(VIS_DT,0,0,0);
VIS_TIME = TIMEPART(VIS_TIME);
VARDATETIME = VARDATETIME + VIS_TIME;
run;
My main problem is when I want to attrib a label based on another one, it doesn't work.
And thanks a lot to gave me the correct syntax for the find function.
Doesn't that ATTRIB statement cause an error?
849 data test; 850 attrib VARDATETIME informat=datetime. format=datetime. label = temp ; - 22 76 ERROR 22-322: Syntax error, expecting one of the following: a name, -, :, FORMAT, INFORMAT, LABEL, LABLE, LENGTH, TRANSCODE, _ALL_, _CHARACTER_, _CHAR_, _NUMERIC_. ERROR 76-322: Syntax error, statement will be ignored. 851 run;
The LABEL= option of the ATTRIB statement needs a string literal. The attributes of all of the variables need to be defined before the data step starts running. There is no way that it could even use the value of variable. The values of variables cannot be known until the step is running.
You need to do this in two steps.
You could find the label you want first and put the value into a macro variable.
%let label=xxxx ;
data ...
...
attrib VARDATETIME informat=datetime. format=datetime. label = "&label";
...
Or figure out the label and then modify the dataset to change the label.
data XXX ;
....
run;
proc datasets nolist lib=work ;
modify XXX;
label VARDATETIME = "&label";
run;
quit;
First, great big congratulations to you for trying to do this first without macros. 👏 (And I have never really said that to anyone before, it is rare to see it)
I don't think you can do this via the ATTRIB statement in the same data set. The ATTRIB statement needs a label that is a text string, and not a variable.
So ... you can do this easily with one macro variable in PROC SQL
proc sql;
select distinct name into :varname from sashelp.vcolumn where libname='WORK' and memname='HAVE'
and upcase(label)='DATE OF PROCEDURE';
alter table have modify &varname label="Date and Time of Procedure";
quit;
Thanks for your answers,
I finally find a solution : I've added a call symputx instead of defining a macrovariable with a %let and it works. I don't really understand why but now I can attrib a label with a macro variable.
Thanks a lot for your support, I'm now gonna try to split this label to add "and time" just after "date".
@Mathis91 wrote:
Thanks for your answers,
I finally find a solution : I've added a call symputx instead of defining a macrovariable with a %let and it works. I don't really understand why but now I can attrib a label with a macro variable.
Thanks a lot for your support, I'm now gonna try to split this label to add "and time" just after "date".
Why is "split" a step here? Why not just replace, as I did, the label with a new label "Date and Time of Procedure", no "split" step needed.
In addition, I think a DATA step is simply the wrong tool here, either PROC SQL or PROC DATASETS is a better tool because it allows you to access the data set metadata (where the labels are stored) and modify the metadata, without reading the entire data set.
So, I wound up using a macro to handle the case where you possibly have multiple variables with labels to modify.
data have;
date='01JAN2022'd;
another_date='02JAN2022';
another_variable=72.07;
label date='Date of Procedure' another_date='Meaningless Text Plus Date of Zebra'
another_variable='Dollars';
run;
proc sql noprint;
select distinct name into :varnames separated by ' ' from sashelp.vcolumn where libname='WORK' and memname='HAVE'
and find(label,'date','i')>0;
quit;
%macro dothis;
%do i=1 %to %sysfunc(countw(&varnames));
%let thisname=%scan(&varnames,&i,%str( ));
select label into :thislabel from sashelp.vcolumn where libname='WORK' and memname='HAVE'
and upcase(name)="%upcase(&thisname)";
%let where=%sysfunc(find(&thislabel,date,i));
alter table have modify &thisname
label="%substr(&thislabel,1,%eval(4+&where))%str(and Time )%substr(&thislabel,%eval(&where+5))";
%end;
%mend;
proc sql noprint;
%dothis
quit;
@Mathis91 wrote:
Thanks for your answers,
I finally find a solution : I've added a call symputx instead of defining a macrovariable with a %let and it works. I don't really understand why but now I can attrib a label with a macro variable.
Thanks a lot for your support, I'm now gonna try to split this label to add "and time" just after "date".
Not sure what you tried but you probably ran into the same timing issue as trying to get ATRRIB to modify the variable attributes after they were already set.
The macro processor finishes its work modifying the source code and passes the result onto the SAS processor to evaluate and run. So if you hide a %LET in the middle of data step it will still be run by the macro processor before the SAS processor even begins to compile the data step.
So writing code like:
data want;
set have;
%let mvar=something;
run;
Is better written in this way to reflect the order that the statements will actual execute (and so avoid confusing the humans trying to understand the code).
%let mvar=something;
data want;
set have;
run;
Using SAS Macro code often adds complexity which means you then will need to spend more time for documentation and if it ever falls over then the code will be harder to debug and maintain/change by someone else. Ask yourself if for the solution of your actual problem dynamic code is really necessary. Sometimes it's better to just type a few more lines of code.
Below a sample macro that should do what you're asking for (or at least what I understand that you're asking for).
data sample;
date='01JAN2022'd;
another_date='02JAN2022';
another_variable=72.07;
label
date='Date of Procedure is outdated'
another_date='Meaningless Text Plus Date of Zebra'
another_variable='outDATEd information';
run;
%macro change_label(ds);
%local libref table new_labels;
%let libref=%scan(work.&ds,-2,.);
%let table =%scan(&ds,-1,.);
%let new_labels=;
proc sql noprint;
select
strip(name)||' '||cats('label=',quote(prxchange('s/\b(date)\b/$1 and Time/oi',-1,trim(label))))
into :new_labels separated by ' '
from dictionary.columns
where
libname="%upcase(&libref)"
and memname="%upcase(&table)"
and findw(label,'date',' ','i')>0
;
run;
%if %nrbquote(&new_labels) ne %nrbquote() %then
%do;
proc datasets lib=&libref nolist;
modify &table;
attrib &new_labels;
%end;
%mend;
%change_label(sample);
proc contents data=work.sample;
run;quit;
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.