BookmarkSubscribeRSS Feed
Mathis91
Calcite | Level 5

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.

10 REPLIES 10
PaigeMiller
Diamond | Level 26

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;
--
Paige Miller
Mathis91
Calcite | Level 5

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.

Tom
Super User Tom
Super User

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;
PaigeMiller
Diamond | Level 26

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;

 

--
Paige Miller
Mathis91
Calcite | Level 5

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".

PaigeMiller
Diamond | Level 26

@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.

--
Paige Miller
Mathis91
Calcite | Level 5
My finally goal is to be used in macro, I can't just wrote in "hard" (I dont speak english very well so i don't know if it's the right word), the code has to detect "date" in a string, add "and time", and the rest of the string, it can be "of procedure" or everything else.

I didn't use SAS for a while, so i'm mainly using DATA procedures instead of SQL ones, I'm gonna try to do it in PROC SQL if you say it's a better tool.

Thanks again
PaigeMiller
Diamond | Level 26

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; 
--
Paige Miller
Tom
Super User Tom
Super User

@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;
Patrick
Opal | Level 21

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;

Patrick_0-1653191801500.png

 

 

Ready to join fellow brilliant minds for the SAS Hackathon?

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!
How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 10 replies
  • 945 views
  • 1 like
  • 4 in conversation