Is it possible to use PROC FORMAT to create a null formatted value so that the formatted value is nothing (not a blank)?
Both of these store a blank as the formatted value:
proc format ;
value $foo
"blank"=" "
"null"="00"x
;
run ;
Log:
9 %put >>%sysfunc(putc(blank,$foo))<< ; >> << 10 %put >>%sysfunc(putc(null,$foo))<< ; >> <<
I want a null string, which would be nice if could do:
proc format ;
value $foo
"null"="" /*does not work, the value becomes a double quote*/
;
run ;
If I can't get a null string, I can deal with it by using trimn(), e.g.:
11 %put >>%sysfunc(trimn(%sysfunc(putc(blank,$foo))%str( )))<< ; >><<
But I wonder if I'm missing an obvious way to have a format definition store a null formatted value?
I doubt it.
What is the use case for this format? Why not just use logic instead?
The only format that can generate zero length string is $VARYING, but I don't think you can use that with PUT() function, only PUT statement.
Example:
data test;
input string $20. ;
len = lengthn(string) * (string ne 'null');
put string $varying10. len @;
cards;
String1
String2
String4
null
String5
;
Result:
694 data test; 695 input string $20. ; 696 len = lengthn(string) * (string ne 'null'); 697 put string $varying10. len @; 698 cards; String1String2String4String5 NOTE: The data set WORK.TEST has 6 observations and 2 variables. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 705 ;
Just hit submit, then realized this works (but also seems silly). Assign a macro variable reference as the formatted value, and assign a null value to the macro variable.
proc format ;
value $foo
"null"='&null'
;
run ;
%let null= ;
%put >>%sysfunc(putc(null,$foo))<< ;
Then that led me to this, which I'm starting to like:
proc format ;
value $foo
"null"='%str()' /*must be single quotes*/
;
run ;
%put >>%sysfunc(putc(null,$foo))<< ;
But perhaps I'm stuck with using TRIMN or some alternative for trimming blanks. Since the format itself has a fixed with, if I have another formatted value that is longer than six characters, I'll still get trailing blanks:
proc format ;
value $foo
'A'='Some long text'
'null'='%str()'
;
run ;
%put >>%sysfunc(putc(null,$foo))<< ;
You could do it as below.
proc format;
value $foo (default=10)
'blank'=' '
;
run;
%let val=%sysfunc(putc(blank,$foo));
%put >>&val<<;
%let val=%sysfunc(putc(some text,$foo));
%put >>&val<<;
Thanks @Patrick , yes, using the fact the %LET ignores leading and trailing blanks is another way to strip blanks. My curiosity was whether was a way to have the format actually return a null string.
Use case was basically making a report where the title includes information about an ID, some IDs have optional parenthetical information. Something like:
proc format ;
value idinfo
1=' (text info - ID1)'
2=' '
3='%str()%str()%str()'
;
run ;
title1 "ID 1%sysfunc(putn(1,idinfo)) enrolled..." ;
title2 "ID 2%sysfunc(putn(2,idinfo)) enrolled..." ;
title3 "ID 3%sysfunc(putn(3,idinfo)) enrolled..." ;
proc sql ;
select * from sashelp.vtitle ;
quit ;
Because of the PUT statement returning a fixed length string, you get the unwanted blanks for ID 2:
ID 1 (text info - ID1) enrolled... ID 2 enrolled... ID 3 enrolled...
But while my idea of using %STR() is perhaps amusing, it's not very practical, as it only 'works' if every formatted value is exactly the same length. So for my use case I'll probably stick with TRIM(), since it makes the purpose explicit. Obviously there are plenty of ways to do this.
Of course in a DATA step there is no such thing as a null string, since character variables are padded with blanks. So it's not surprising that a format wouldn't be designed to return a null value.
I doubt it.
What is the use case for this format? Why not just use logic instead?
The only format that can generate zero length string is $VARYING, but I don't think you can use that with PUT() function, only PUT statement.
Example:
data test;
input string $20. ;
len = lengthn(string) * (string ne 'null');
put string $varying10. len @;
cards;
String1
String2
String4
null
String5
;
Result:
694 data test; 695 input string $20. ; 696 len = lengthn(string) * (string ne 'null'); 697 put string $varying10. len @; 698 cards; String1String2String4String5 NOTE: The data set WORK.TEST has 6 observations and 2 variables. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 705 ;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.