0
votes

I'm having this macro. The aim is to take the name of variables from the table dicofr and put the rows inside into variable name using a symput.

However , something is not working correctly because that variable, &nvarname, is not seen as a variable.

This is the content of dico&&pays&l

varname descr
var12   aza
var55   ghj
var74   mcy

This is the content of dico&&pays&l..1

varname 
var12
var55
var74

Below is my code

%macro testmac;

%let pays1=FR ;

%do l=1 %to 1 ;

data dico&&pays&l..1 ; set dico&&pays&l (keep=varname); 
call symput("nvarname",trim(left(_n_))) ;
run ;


data a&&pays&l;
set a&&pays&l;
nouv_date=mdy(substr(date,6,2),01,substr(date,1,4));
format nouv_date monyy5.;
run;



proc sql;
create table toto 
(nouv_date date , nomvar varchar (12));
quit;

proc sql;

insert into toto SELECT max(nouv_date),"&nvarname" as nouv_date as varname FROM a&&pays&l WHERE (&nvarname ne .);


%end;

%mend;

%testmac;

A subsidiary question. Is it possible to have the varname and the date related to that varname into a macro variable? My man-a told me about this but I have never done that before.

Thanks in advance.

Edited: I have this table

date    col1 col2 col3 ... colx
1999M12 .    .    .        .
1999M11 .    2    .        .
1999M10 1    3    .        3
1999M9  0.2  3    2        1

I'm trying to do know the name of the column with the maximum date , knowing the value inside of the column is different than a missing value.

For col1, it would be 1999M10. For col2, it would be 1999M11 etc ...

2
Your as are wrong. You probably also want to create &nvarname differently, but it is probably okay. I think this entire procedure is wrongheaded, though; but I don't understand entirely what you're doing. Odds are you can do this all in datastep or similar without bothering the macro facility.Joe
It would help if you could post an example of the sort output dataset that you're trying to create.user667489
Hi, please find my explanation on the edited part. Thanks. Let me know if anything is unclear.Andy K

2 Answers

0
votes

It looks to me that you're trying to use macros to generate INSERT INTO statements to populate your table. It's possible to do this without using macros at all which is the approach I'd recommend.

You could use a datastep statement to write out the INSERT INTO statements to a file. Then following the datastep, use a %include statement to run the file.

This will be easier to write/maintain/debug and will also perform better.

0
votes

Based on your update, I think the following code does what you want. If you don't mind sorting your input dataset first, you can get all the values you're looking for with a single data step - no macros required!

data have;
length date $7;
input date col1 col2 col3;
format date2 monyy5.;
date2 = mdy(substr(date,6,2),1,substr(date,1,4));
datalines;
1999M12 .    .    .   
1999M11 .    2    .   
1999M10 1    3    .   
1999M09 0.2  3    2   
;
run;

/*Required for the following data step to work*/
/*Doing it this way allows us to potentially skip reading most of the input data set*/
proc sort data = have;
  by descending date2;
run;

data want(keep = max_date:);
  array max_dates{*} max_date1-max_date3;
  array cols{*} col1-col3;
  format max_date: monyy5.;

  do until(eof); /*Begin DOW loop*/
    set have end = eof;

    /*Check to see if we've found the max date for each col yet.*/
    /*Save the date for that col if applicable*/
    j = 0;
    do i = 1 to dim(cols);
      if missing(max_dates[i]) and not(missing(cols[i])) then max_dates[i] = date2;
      j + missing(max_dates[i]);
    end;
    /*Use j to count how many cols we still need dates for.*/
    /* If we've got a full set, we can skip reading the rest of the data set*/
    if j = 0 then do;
      output;
      stop;
    end;
  end; /*End DOW loop*/
run;

EDIT: if you want to output the names alongside the max date for each, that can be done with a slight modification:

data want(keep = col_name max_date);
  array max_dates{*} max_date1-max_date3;
  array cols{*} col1-col3;
  format max_date monyy5.;

  do until(eof); /*Begin DOW loop*/
    set have end = eof;

    /*Check to see if we've found the max date for each col yet.*/
    /*If not then save date from current row for that col*/
    j = 0;
    do i = 1 to dim(cols);
      if missing(max_dates[i]) and not(missing(cols[i])) then max_dates[i] = date2;
      j + missing(max_dates[i]);
    end;
    /*Use j to count how many cols we still need dates for.*/
    /* If we've got a full set, we can skip reading the rest of the data set*/
    if j = 0 or eof then do;
      do i = 1 to dim(cols);
        col_name = vname(cols[i]);
        max_date = max_dates[i];
        output;  
      end;
      stop;
    end;
  end; /*End DOW loop*/
run;