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

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?

 

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.
1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

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  ;

View solution in original post

5 REPLIES 5
Quentin
Super User

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))<< ;
The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.
Quentin
Super User

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))<< ;

 

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.
Patrick
Opal | Level 21

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<<;

Patrick_0-1696728607549.png

 

Quentin
Super User

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.

 

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.
Tom
Super User Tom
Super User

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: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 5 replies
  • 1076 views
  • 0 likes
  • 3 in conversation