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

Hello,

 

i am wondering if there is a simple way to keep the formated value instead of original value from a dataset.

 

for example if have a dataset "A" with many formatted vars inside,  i want to keep their formatted value instead of the formatted value in a dataset, its a pain to do "new_var=put(var, $format.);"  for every var.

1 ACCEPTED SOLUTION

Accepted Solutions
data_null__
Jade | Level 19

You could write the data set to file and then use PROC IMPORT to read it back in as all character.  Write two name rows forces all columns to character.

 

proc contents varnum data=sashelp.demographics;
   run;
filename FT72F001 temp;
data _null_;
   file FT72F001 dsd;
   *file log;
   set sashelp.demographics(obs=40);
   if _n_ eq 1 then link namerow;
   put (_all_)(:);
   return;
   /*Write name row twice */
namerow:
   length __NAME $32; 
   do _n_ = 1 to 2;
      call missing(__NAME);
      do until(missing(__name));
         call vnext(__name);
         if __name eq: '__' then leave;
         if not missing(__name) then put __name @;
         end;
      put;
      end; 
   return;
   run;

proc import file=FT72F001 dbms=csv out=allchar;
   run;
proc contents varnum data=allchar;
   run;

proc print data=allchar(obs=10);
   run;

Screenshot 2026-03-18 101537.png

 

 

I updated the code to use @Tom suggestion to quote the values using ~ format modifier.  Also, use _TEMPORARY_ array to hold variable name returned from CALL VNEXT.

proc contents varnum data=sashelp.demographics;
   run;
proc print data=sashelp.demographics(obs=40);
   run;
filename FT72F001 temp;
data _null_;
   file FT72F001 dsd;
   *file log dsd;
   set sashelp.demographics(obs=40);
   if _n_ eq 1 then link namerow;
   put (_all_)(~);
   return;
namerow:
   array __Name [1] $32 _temporary_;
   do until(missing(__name[1]));
      call vnext(__name[1]);
      if __name[1] eq: '_ERROR' then leave; /*When vnext is _ERROR_*/
      if not missing(__name[1]) then put __name[1] @;
      end;
   put;
   return;
   run;
proc import file=FT72F001 dbms=csv out=allchar replace;
   run;

proc contents varnum data=allchar;
   run;
proc print data=allchar(obs=10);
   run;

View solution in original post

5 REPLIES 5
PaigeMiller
Diamond | Level 26

I suppose you could create a macro that loops through all variables and does this PUT command. But even then there are problems, if the variable is numeric, you can't replace the original numeric value with a character value, you would have to create a new character variable (with a different name). If you have a character variable, then PUT would work but if the length of the formatted value is longer than the length of the unformatted value, the formatted value will get truncated. So, a somewhat complicated macro is needed that will handle these (and possibly other) situations.

 

You could do a similar thing with ARRAY.

 

May I ask why this is necessary? I have a feeling that if we knew why you want to do something like this, we might be able to figure out a better approach.

--
Paige Miller
Kathryn_SAS
SAS Employee

As @PaigeMiller suggested, you could use macro logic to do this. If the formats are permanently assigned in a DATA step, then you can use an output data set from PROC CONTENTS to build your statements. I have included an example below.

proc format;
 value $gen 'M'='Male' 'F'='Female';
run;

data class;
set sashelp.class;
format sex $gen. height weight dollar12.2;
run;

ods output variables=out(where=(format ne ' '));

proc contents data=class ;
run;

proc print data=out;
run;

data _null_;
set out;
by variable;
if first.variable then do;
 call symputx('varname'||left(_n_),variable);
 call symputx('fmt'||left(_n_),format);
end;
call symputx('total',_n_);
run;

%put _user_;

%macro loop;

data class1;
set class;
%do i=1 %to &total;
new_&&varname&i=put(&&varname&i,&&fmt&i);
%end;
run;

proc print data=class1;
run;

proc contents data=class1;
run;

%mend;
%loop
data_null__
Jade | Level 19

You could write the data set to file and then use PROC IMPORT to read it back in as all character.  Write two name rows forces all columns to character.

 

proc contents varnum data=sashelp.demographics;
   run;
filename FT72F001 temp;
data _null_;
   file FT72F001 dsd;
   *file log;
   set sashelp.demographics(obs=40);
   if _n_ eq 1 then link namerow;
   put (_all_)(:);
   return;
   /*Write name row twice */
namerow:
   length __NAME $32; 
   do _n_ = 1 to 2;
      call missing(__NAME);
      do until(missing(__name));
         call vnext(__name);
         if __name eq: '__' then leave;
         if not missing(__name) then put __name @;
         end;
      put;
      end; 
   return;
   run;

proc import file=FT72F001 dbms=csv out=allchar;
   run;
proc contents varnum data=allchar;
   run;

proc print data=allchar(obs=10);
   run;

Screenshot 2026-03-18 101537.png

 

 

I updated the code to use @Tom suggestion to quote the values using ~ format modifier.  Also, use _TEMPORARY_ array to hold variable name returned from CALL VNEXT.

proc contents varnum data=sashelp.demographics;
   run;
proc print data=sashelp.demographics(obs=40);
   run;
filename FT72F001 temp;
data _null_;
   file FT72F001 dsd;
   *file log dsd;
   set sashelp.demographics(obs=40);
   if _n_ eq 1 then link namerow;
   put (_all_)(~);
   return;
namerow:
   array __Name [1] $32 _temporary_;
   do until(missing(__name[1]));
      call vnext(__name[1]);
      if __name[1] eq: '_ERROR' then leave; /*When vnext is _ERROR_*/
      if not missing(__name[1]) then put __name[1] @;
      end;
   put;
   return;
   run;
proc import file=FT72F001 dbms=csv out=allchar replace;
   run;

proc contents varnum data=allchar;
   run;
proc print data=allchar(obs=10);
   run;
Tom
Super User Tom
Super User

Actually you can take advantage of a quirk of PROC IMPORT.  If it sees that all observations of a variable are quoted it decides the variable must be character.  So use the ~ modifier to write a CSV file where everything is quoted (whether the value needs quotes or not).

%let dsn=sashelp.cars;
filename csv temp;

* Write header row ;
proc transpose data=&dsn(obs=0) out=names ;
 var _all_;
run;
data _null_;
  file csv dsd ;
  set names;
  put _name_ ~ @ ;
run;
* Appedn data rows ;
data _null_;
  file csv dsd mod ;
  set &dsn ;
  put (_all_) (~);
run;

proc import dbms=csv file=csv out=want replace;
run;

proc contents data=want varnum;
run;
 
 
 

Screenshot 2026-03-18 at 12.36.03 PM.png

 

 

 

 

 
 

 

 

 

Ksharp
Super User

You need to resort to the function VVALUE().

Here is an example:

 

proc format;
value a
1='a'
2='b'
;
value b
1='xxx'
2='yyy'
;
run;


data have;
input a b;
format a a. b b.;
cards;
1 2
2 2
1 1
;

data want;
 set have;
 array x{*} a b;
 array y{*} $ 40 v1 v2;
 do i=1 to dim(x);
   y{i}=vvalue(x{i});
 end;
 run;

Catch up on SAS Innovate 2026

Dive into keynotes, announcements and breakthroughs on demand.

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

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 493 views
  • 5 likes
  • 6 in conversation