2
votes

I used the sashelp library data sets as an example

proc datasets library=sashelp;
    contents
        data=company
        out=work.var_names;
quit;
run;

Now i using proc sql into to store the variable names

proc sql noprint;
    select name into: varname separated by ' '
    from var_names;
quit;
%put &varname;

Now i would like to print the variables name on the log

data newdata (drop=i);
    array temp{*} &varname;
    do i=1 to dim(temp);
        put temp{i};
    end;
run;

While it print . instead of the variable names.

Thanks

log:

337  %put &varname;
DEPTHEAD JOB1 LEVEL1 LEVEL2 LEVEL3 LEVEL4 LEVEL5 N

While i want

DEPTHEAD 
JOB1 
LEVEL1 
LEVEL2 
LEVEL3 
LEVEL4 
LEVEL5 
N
4
Aren't you already printing the variable - "name" into the log, using %put &varname;? Do you want to do the same using datastep?NEOmen
@NEOmen please see the amendment. It would be great if i able to only print second element of varname. JOB1useR
You can do what you ask, but its not generalizable very much. Perhaps, post what you're trying to do overall instead. Also, look at sashelp.vcolumn as well.Reeza

4 Answers

3
votes

Suppose the variables in the company are name, salary, the varname macro variable is "name salary". When the last segments were run, it is acually like this:

array temp{*} name salary;

The name and salary are set to default numeric variables with missing value '.'.

Why not just put the variables in the var_names:

data _null_;
    set var_names;
    put name;
run;
2
votes

Not sure why your method is not working, but for now you can use scan function to extract the elements, code is pretty much self explanatory, let me know if you don't get it

data _null_;
array temp{*} &varname;
do i=1 to dim(temp);
temp_1 = scan("&varname.",i);
put temp_1;
end;
second_element=scan("&varname.",2);
put second_element=;
run;

EDIT: Your method

array temp{*} &varname

which eventually translates to

array temp{*} DEPTHEAD JOB1 LEVEL1 LEVEL2 LEVEL3 LEVEL4 LEVEL5 N;

is not working because by doing that array variable names are defined and not the values are initialized

http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000201956.htm

Look for this statement

array simple{3} red green yellow;

If you want to do it your way then you have to do something like this

data _null_;
   array tempar{8} $ tempar1-tempar8 ("DEPTHEAD" "JOB1" "LEVEL1" "LEVEL2" "LEVEL3" "LEVEL4" "LEVEL5" "N");
   do i=1 to dim(tempar);
   put tempar(i)=;
   end;
run;

Notice first I have defined the individual elements of the array - tempar1-tempar8 and have defined it char using $ and then I have intialized the values that too in quotes.


EDIT2:

Tested If you absolutely can't deviate from your approach, below is the code(which is less efficient than what I have suggested above)

   proc datasets library=sashelp;
    contents
        data=company
        out=work.var_names;
quit;
run;

proc sql noprint;
    select quote(compress(name)) into: varname separated by ' '
    from var_names;
    select count(name) into: Numofelements from var_names;
quit;

%put %quote(&varname.);
%put &Numofelements;

data _null_;
   array tempar{%sysfunc(compress(&Numofelements.))} $ tempar1-tempar%sysfunc(compress(&Numofelements.)) (%quote(&varname.));
   do i=1 to dim(tempar);
   put tempar(i)=;
   end;
run;
2
votes

This seems like a long way to do something that may be accomplished more easily, if you explained why you wanted to do it :). Here's a solution that uses a stores the values using quotes and then puts them into a temporary array.

proc sql noprint;
    select quote(trim(name)) into: varname separated by ' '
    from var_names;
quit;
%put &varname;

data new data;
array var_names{&sqlobs} $ _temporary_  (&varname);
put var_names(2);
do i=1 to dim(var_names);
   put var_names(i);
end;
run;

Here's a second solution that uses your dataset, since I find it a good practice to avoid macros wherever possible.

data newdata;
   set var_names;
   if _n_=2 then put name;
run;

And a note that you can use the

 _all_, _numeric_ or _character_ 

shortcut to reference variable lists. An array can only have one type, so I assume that all variables are numeric or character. As well as the fact that SASHELP.VCOLUMN contains various metadata about all SAS library and tables.

2
votes

I don't really understand the premise of this question, as you're doing something waaaaay more complicated than you need to.

First of all, you don't need proc contents.

proc sql noprint;
    select name into :varname separated by ' '
    from dictionary.columns
    where libname='SASHELP' and memname='COMPANY';
quit;

Second, this is a much easier way to get the variable names, even assuming you don't want them as %put.

data _null_;
  set sashelp.company;
  array _names &varname.;
  do _i = 1 to dim(_names);
    _v = vname(_names[_i]);
    put _v=;
  end;
run;

I don't see what value a _temporary_ array has here at all. vname will happily give you the names of the variables in the array, if that's what you're after. Honestly this seems like a contrived example though as Reese and others pointed out.