VarLength

Hallo zusammen,
gibt es eine Macro-Lösung um die Länge einer Variable in einem Data Set zu ermitteln?

Eine Base-Lösung habe ich die aus der sashelp.vcolumn die Länge ausliest:

%macro varleng(dataset, varname, varlenp);      /* ermittle 'VariablenLänge' */
  
/*-----------------------------------------------------------------------
   *      Variablen-Länge auslesen
   *                    Dieser Makro dient dem lesen der Länge der Variable,
   * Aufruf-Beispiele:
   *   %varleng( positone, zzkon, KonzLae );
   *   %put KonzLae=&KonzLae.;
   *----------------------------------------------------------------------- */
  
%put INFO: macro varleng(&dataset., &varname., &varlenp.);
  
%global &varlenp.;

  
%let _lib =%scan(&dataset.,1,.);
  
%let _dset=%scan(&dataset.,2,.);
  
%if &_dset. eq %then %do;
    
%let _dset=&_lib.;
    
%let _lib =work;
  
%end;
  %
*put INFO: _lib=&_lib. _dset=&_dset. varname=&varname.;

  
%let &varlenp.=;
  data _null_;
    set sashelp.vcolumn;
   
*put "INFO: " libname= memname= name= length=;
    
if     upcase(libname) = "%upcase(&_lib.)"
       
and upcase(memname) = "%upcase(&_dset.)"
       
and upcase(name)    = "%upcase(&varname.)"
    
then do;
      put
"INFO: length = " LENGTH;
      call symput(
"&varlenp.", compress(put( LENGTH, 8.)));
      stop;
    end;
  run;
  
%put INFO: macro varleng, Ende: varlenp=&varlenp.=&&&varlenp..;
%mend varleng;
Verwenden kann man den varleng-Macro zum Beispiel so:
data test(label='Label-Text zum test-Data-Set';
  abc=
"abc123";
run;
%varleng( work.test, abc, abcLAE );
%put abcLAE=&abcLAE.;

Ich hätte jetzt gerne eine reine Macro-Lösung, die ohne den Base-Zugriff auf die sashelp.vcolumn auskommt.
Die Lösung sollte so ähnlich sein wie das auslesen von label, sortedby, ... aus den Tiefen des Data Dictionary.
Diese Dinge findet man in der SAS-Online-Doc » SAS Language Reference: Dictionary » Functions and Call-Routines: ATTRC » LABEL, ...
Das Label auslesen geht z.B. so:

%macro dslabel( dataset, dslabp );              /* ermittle 'DataSetLabel' */
  
/*----------------------------------------------------------------------
   *      Data Set Label auslesen
   *                    Dieser Makro dient dem lesen von Labels,
   *                    ist bei Kopieren von data Sets hilfreich
   *                    wenn Kopie das gleiche Label haben soll wie Vorlage
   *                    neue Version, statt Zugriff auf 'sashelp.vtable'
   *                    jetzt 'sysfunc(attrc(&dsid.,LABEL))'
   *                    Laufzeit, alt: 0:00:06
   *                    Laufzeit, neu: 0:00:00
   * Aufruf-Beispiele:
   *   %dslabel(work.positone  , dslab  );
   *   %put dslab=&dslab.;
   *---------------------------------------------------------------------- */
  
%put INFO: macro dslabel(&dataset., &dslabp.);
  
%global &dslabp.;

  
%let _lib =%scan(&dataset.,1,.);
  
%let _dset=%scan(&dataset.,2,.);
  
%if &_dset. eq %then %do;
    
%let _dset=&_lib.;
    
%let _lib =work;
  
%end;
  %
*put INFO: _lib=&_lib. _dset=&_dset.;

  
%let &dslabp.=;
  
%global rc;
  
%let dsid = %sysfunc( open( &dataset. ) );
  
%if &dsid. %then %do;
    
%let &dslabp. =%sysfunc(attrc(&dsid.,LABEL));
    
%let rc       =%sysfunc(close(&dsid.));

    
%put INFO: macro dslabel: &_dset. has label: &&&dslabp.;
  
%end;
  
%else %do;
    
%let text=sysmsg()=...%substr(%bquote(%sysfunc(sysmsg())), %length(%substr(###ERROR,4))+1);  /* sysmsg-Text aber ohne das Wort Fehler am Anfang */
    
%put %substr(###NOTE,4): macro dslabel: Open for data set &dataset. failed - &text.;
    
%let rc     =1;
  
%end;
%mend dslabel;
Verwenden kann man den dslabel-Macro zum Beispiel so:
%dslabel( work.test, dslab );        /* mit work.test von oben */
%put dslab=&dslab.;

Gibt es mittlerweile (oder schon lange) eine Funktion (ähnlich wie die obige ATTRC- bzw. ATTRN-Funktion) um Attribute zu Variablen auszulesen ???

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

SAS Component Language

Hallo Herr Kneilmann,

diese Funktionen kommen von der SAS Component Language SCL und sind durch %sysfunc auch in Macro zugängig. Die Funktionen, um Variablenattribute auszulesen, beginnen mit VAR und gehen von VARFMT bis VARTYPE. Für die Sorted By Geschichte müssen Sie aber glaube ich über ATTRC gehen, zumindest habe ich nichts anderes gefunden. Anbei ein Link zum
SAS Component Language Dictionary

Dort müsste alles stehen, vielleicht findet sich auch eine Funktion für Sorted By, ich bin nicht alles durchgegangen.

Gruß
Wolfgang Hornung

Unwichtiges Beispiel: Sorted By

Hallo,
danke für den Link.
Das Sorted By war nur ein (unwichtiges) Beispiel. Unwichtig weil schon gelöst: Zugriff über die ATTRC-Funktion und den Attribut-Name SORTEDBY.

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Das geht mir der Funktion VARLEN

Hallo Herr Kneilmann,

das funktioniert genau wie das Auslesen des Datasetlabels. Man muss die Datei zuerst öffnen, dann über die Funktion VARNUM die Nummer der Variablen besorgen und schliesslich mittels der Funktion VARLEN und der Variablenummer die Länge auslesen.

Hier der Auszug aus der SAS-Hilfe:

/* This example obtains the length of the variable ADDRESS in the SAS data set MYDATA. */

%let dsid=%sysfunc(open(mydata,i));
%if &dsid %then
   
%do;
      
%let len=%sysfunc(varlen(&dsid,
                       
%sysfunc(varnum
                       (&dsid,ADDRESS))));
      
%let rc=%sysfunc(close(&dsid));
   
%end;
Das Gleiche gilt auch für die Funktion VARLABEL.

Gruß
Klaus Landwich

Danke für die super-prompte Antwort

Hallo Herr Landwich,
danke für den Tipp.
Ich habe mein Macro schon umgebaut und ist schon im Einsatz. Super!

%macro varleng(dataset, varname, varlenp);
  
/*----------------------------------------------------------------
   *      Variablen-Länge auslesen
   *                    Dieser Makro dient dem lesen der Länge der Variable,
   *                    ohne Zugriff auf 'sashelp.vcolumn'
   *                    mit '%sysfunc(varlen(...));'
   * Aufruf-Beispiele:
   *   %varleng( positone, zzkon, KonzLae );
   *   %put KonzLae=&KonzLae.;
   *--------------------------------------------------------------- */
  
%put INFO: macro varleng(&dataset., &varname., &varlenp.);
  
%global &varlenp.;
  
%let &varlenp.=;
  
%global rc;
  
%let dsid = %sysfunc( open( &dataset. ) );
  
%if &dsid. %then %do;
    
%let &varlenp.=%sysfunc(varlen( &dsid.
                                  ,
%sysfunc(varnum(&dsid.,&varname.))
                                  ));
    
%let rc       =%sysfunc(close(&dsid.));
    
%put INFO: macro varleng: &varname. has length: &&&varlenp.;
  
%end;
  
%else %do;
    
%let text=sysmsg()=...%substr(%bquote(%sysfunc(sysmsg())), %length(%substr(###ERROR,4))+1);
    
%put %substr(###NOTE,4): macro varleng: Open for data set &dataset. failed - &text.;
    
%let rc     =1;
  
%end;
  
%put INFO: macro varleng, Ende: varlenp=&varlenp.=&&&varlenp..;
%mend varleng;
Noch mal Danke!!
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)