BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Batman
Quartz | Level 8

This quick macro displays the format type for a variable.   Is there a macro function that will do the same without having to create a null dataset, limit the input file to the first observation and use symput?

 

29 /*Determine the type of format of a variable in a dataset*/
30 %macro det_format(memname,var_name);
31 data _null_;
32 set &memname(obs=1);
33 call symput('formval',fmtinfo(vformatn(&var_name),'cat'));
34 run;
35
36 %put &formval;
37 %mend;
38 %det_format(dat.AP_455021_9_5,enroll_dt)
MPRINT(DET_FORMAT): data _null_;
MPRINT(DET_FORMAT): set dat.AP_455021_9_5(obs=1);
MPRINT(DET_FORMAT): call symput('formval',fmtinfo(vformatn(enroll_dt),'cat'));
MPRINT(DET_FORMAT): run;

NOTE: There were 1 observations read from the data set DAT.AP_455021_9_5.
NOTE: DATA statement used (Total process time):
real time 0.09 seconds
cpu time 0.00 seconds

date

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

So you don't want the variable TYPE or the FORMAT attached to the variable.

Instead you want what FMTINFO() calls the CAT or category of the format that is attached.

 

You can use the VARFMT() function to get the FORMAT specification that is attached.

You can use a little trickery to convert that into the NAME of the format.

You also will probably want to know the TYPE of the variable in case the variable does not have any format specification attached to it.

 

Everything you need to do this can be retrieved by the VAREXIST() macro.

 

Let's use SASHELP.STOCKS as our test dataset since it has some different types of variables and different types (categories) or formats attached.

Tom_0-1698959284766.png

So here is a macro that uses %VAREXIST().

%macro fmtcat(ds,var);
%local format ;
%let format=%varexist(&ds,&var,fmt);
%if %length(&format) %then 
  %let format=%sysfunc(substrn(&format,1,%sysfunc(findc(&format,.,-49,sdk))))
;
%if %length(&format) %then %sysfunc(fmtinfo(&format,cat));
%else %if %varexist(&ds,&var,type)=C %then char;
%else num;
%mend fmtcat;

So let's test it:

1    %put %fmtcat(sashelp.stocks,stock);
char
2    %put %fmtcat(sashelp.stocks,date);
date
3    %put %fmtcat(sashelp.stocks,open);
curr
4    %put %fmtcat(sashelp.stocks,volume);
num

 

 

View solution in original post

14 REPLIES 14
maguiremq
SAS Super FREQ

Is there a reason you can't use dictionary.columns?

proc sql;
select
	name
	, type
from
	dictionary.columns
where
	libname = "SASHELP"
	and memname = "CARS";
quit;

Or even PROC CONTENTS?

 

What is the purpose of the macro variable?

 

If you need to, you can still place it in a macro variable.

 

proc sql;
select
	type
from
	dictionary.columns
where
	libname = "SASHELP"
	and memname = "CARS"
	and name = "MSRP";
quit;
Batman
Quartz | Level 8
Dictionary.columns will give me the format itself, i.e. yymmdd10. but it won't give me the type (num, char, date, etc).
Batman
Quartz | Level 8

Sorry, it will give the type as "num" or "char" but not "date"

maguiremq
SAS Super FREQ

My apologies - sometimes I read too quickly.

 

data want;
x = TODAY();
format x yymmddn8.;
run;

proc sql;
select
	format
from
	dictionary.columns
where
	libname = "WORK"
	and memname = "WANT";
quit;
PaigeMiller
Diamond | Level 26

The is no variable type "date" in SAS. The only variable types in SAS are number or text (character).

 

A variable can be treated as a date if the human programmer uses DATE functions, formats and informats on the variable. SAS thinks it is simply a number.

--
Paige Miller
Batman
Quartz | Level 8

Actually, the fmtinfo does give the format type (see my example in the first post on this topic).    I'm just looking for a way to generate the result without having to run a data step.

Tom
Super User Tom
Super User

@Kurt_Bremser wrote:

You can retrieve the format name from DICTIONARY.COLUMNS, and then use the FMTINFO function with %SYSFUNC.


But DICTIONARY.COLUMNS does not have the format name.  It has the full format specification.  And FMTINFO() only works with the bare name.  See above for algorithm to extract the format name from a format specification.

Tom
Super User Tom
Super User

So you don't want the variable TYPE or the FORMAT attached to the variable.

Instead you want what FMTINFO() calls the CAT or category of the format that is attached.

 

You can use the VARFMT() function to get the FORMAT specification that is attached.

You can use a little trickery to convert that into the NAME of the format.

You also will probably want to know the TYPE of the variable in case the variable does not have any format specification attached to it.

 

Everything you need to do this can be retrieved by the VAREXIST() macro.

 

Let's use SASHELP.STOCKS as our test dataset since it has some different types of variables and different types (categories) or formats attached.

Tom_0-1698959284766.png

So here is a macro that uses %VAREXIST().

%macro fmtcat(ds,var);
%local format ;
%let format=%varexist(&ds,&var,fmt);
%if %length(&format) %then 
  %let format=%sysfunc(substrn(&format,1,%sysfunc(findc(&format,.,-49,sdk))))
;
%if %length(&format) %then %sysfunc(fmtinfo(&format,cat));
%else %if %varexist(&ds,&var,type)=C %then char;
%else num;
%mend fmtcat;

So let's test it:

1    %put %fmtcat(sashelp.stocks,stock);
char
2    %put %fmtcat(sashelp.stocks,date);
date
3    %put %fmtcat(sashelp.stocks,open);
curr
4    %put %fmtcat(sashelp.stocks,volume);
num

 

 

Tom
Super User Tom
Super User

You might also like the TYPEF variable created by this %CONTENTS() macro.

 

Example:

%contents(sashelp.stocks,out=contents);
proc print;
run;

Results

Obs libname memname varnum name     length typen type typef format    informat formatn formatl formatd informn informl informd

 1  SASHELP STOCKS     1   Stock       9     2   char char                                 0      0                0      0
 2  SASHELP STOCKS     2   Date        8     1   num  date  DATE.     DATE.    DATE        0      0     DATE       0      0
 3  SASHELP STOCKS     3   Open        8     1   num  curr  DOLLAR8.2 BEST32.  DOLLAR      8      2     BEST      32      0
 4  SASHELP STOCKS     4   High        8     1   num  curr  DOLLAR8.2 BEST32.  DOLLAR      8      2     BEST      32      0
 5  SASHELP STOCKS     5   Low         8     1   num  curr  DOLLAR8.2 BEST32.  DOLLAR      8      2     BEST      32      0
 6  SASHELP STOCKS     6   Close       8     1   num  curr  DOLLAR8.2 BEST32.  DOLLAR      8      2     BEST      32      0
 7  SASHELP STOCKS     7   Volume      8     1   num  num   COMMA12.  BEST32.  COMMA      12      0     BEST      32      0
 8  SASHELP STOCKS     8   AdjClose    8     1   num  curr  DOLLAR8.2 BEST32.  DOLLAR      8      2     BEST      32      0

Obs     label      nvar nobs              crdate              modate typemem memtype                   memlabel

 1                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 2                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 3                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 4                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 5                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 6                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 7                   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005
 8  Adjusted Close   8   699  06SEP2017:23:02:27  06SEP2017:23:02:27          DATA   Performance of Three Stocks from 1996 to 2005

 

Ksharp
Super User
data stocks;
 set sashelp.stocks ;
 format stock $40.;
run;

%let dsn= stocks ;
%let vname= stock ;




%let dsid=%sysfunc(open(&dsn.));
%let var_n=%sysfunc(varnum(&dsid.,&vname.));
%let var_fmt=%sysfunc(prxchange(s/[\.\d]+$//,1,%sysfunc(varfmt(&dsid.,&var_n.))));
%let fmt_type=%sysfunc(fmtinfo(&var_fmt.,cat));
%let dsid=%sysfunc(close(&dsid.));

%put &=var_n. &=var_fmt. &=fmt_type.;
Tom
Super User Tom
Super User

Why did you attach the $ format to STOCK?  It is just a normal character variable it does not need to have a format attached.

Why did you remove all of the digits from the format value?  That would convert something like S370FRB8. (which is a valid SAS supplied numeric format specification) to SFRB which is not a SAS supplied format name.

 

Ksharp
Super User

By default, there is no FORMAT attached with STOCK as showed in your picture. Otherwise,my code would get a NULL value .

 

P.S. since OP only need the FORMAT , So no need to consider the variable on which there is no format.

Ksharp
Super User
"Why did you remove all of the digits from the format value? That would convert something like S370FRB8."
OK. You are right. I didn't consider it. The code has been updated .

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

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
  • 14 replies
  • 1971 views
  • 2 likes
  • 6 in conversation