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

Hello!

 

I was wondering if someone could explain to me why my code isn't working correctly. I think it's something to do with how the SAS processor handles macro variables but I'm not entirely sure.

 

 

data test;
	input unformatted_var $;
	DATALINES;
	1
	;
run;

%let format = not_a_format;

data test;
	set test;

	have_format = 0;

	if have_format then do;
		formatted_var = put(unformatted_var, &format.);
	end; else do;
		formatted_var = unformatted_var;
	end;

run;


PROC PRINT DATA = test; run;

 

 

The code is a simplified version of my main code which runs within a macro. It's purpose is to take unformatted_var and output it as formatted_var. Sometimes the code will have a format stored in the "format" macro variable in which case a format is applied to the formatted _var, other times there is no format supplied and the formatted_var is the same as unformatted_var.

 

In the case above there is no format supplied so the have_format variable is set to 0. However despite this the code produces an error because it is trying to execute the line 

formatted_var = put(unformatted_var, &format.);

Which can't run correctly because the "format" macro variable does not contain a format, even though that line should not be executed within the data step.

 

I am able to solve my problem by coding it differently, but I'm not sure why it's not working in the first place!

 

Thanks in advance.

1 ACCEPTED SOLUTION

Accepted Solutions
Patrick
Opal | Level 21

@StephenM 

The correctness of SAS syntax gets checked during compilation time. Because the format doesn't exist this leads to an error. 

The IF conditions comes only into play during execution time - and that's after the syntax check during compilation time.

 

On top of this: A format needs to end with a dot. Resolving a macro variable consumes a dot. So even if there is a format supplied in your macro variable you need to use two dots for the resolved value of the macro variable (the format name) still to end with a dot.

 

formatted_var = put(unformatted_var, &format..);

 

You could avoid the error for a non existing format via option

options nofmterr;

Or - and better in my opinion - don't generate the SAS code at all if there is no value supplied for the format (assuming that macro variable &format exists but is empty if no format gets supplied).

data test;
  input unformatted_var $;
  DATALINES;
1
;

%let format =;
%macro doit();
  data test;
    set test;
    %if %bquote(&format) = %bquote() %then
      %do;
        formatted_var = unformatted_var;
      %end;
    %else
      %do;
        formatted_var = put(unformatted_var, &format..);
      %end;
  run;
%mend;
%doit()

PROC PRINT DATA = test;
run;

If you're on a very recent SAS version then you can use SAS macro %IF %then %else even without a macro definition.

data test;
  input unformatted_var $;
  DATALINES;
1
;

%let format =;

data test;
  set test;
  %if %bquote(&format) = %bquote() %then
    %do;
      formatted_var = unformatted_var;
    %end;
  %else
    %do;
      formatted_var = put(unformatted_var, &format..);
    %end;
run;

PROC PRINT DATA = test;
run;

 

View solution in original post

5 REPLIES 5
PeterClemmensen
Tourmaline | Level 20

Right now, SAS interprets the dot in &format. as the end of the macro variable. Not the end of a format specification. Therefore, put an extra dot efter your format macro variable

 

data test;
	set test;

	have_format = 0;

	if have_format then do;
		formatted_var = put(unformatted_var, &format..);
	end; else do;
		formatted_var = unformatted_var;
	end;

run;

This will issue a note, not an error, that the format was not found because the Put Function looks for the format at compile time.

Patrick
Opal | Level 21

@StephenM 

The correctness of SAS syntax gets checked during compilation time. Because the format doesn't exist this leads to an error. 

The IF conditions comes only into play during execution time - and that's after the syntax check during compilation time.

 

On top of this: A format needs to end with a dot. Resolving a macro variable consumes a dot. So even if there is a format supplied in your macro variable you need to use two dots for the resolved value of the macro variable (the format name) still to end with a dot.

 

formatted_var = put(unformatted_var, &format..);

 

You could avoid the error for a non existing format via option

options nofmterr;

Or - and better in my opinion - don't generate the SAS code at all if there is no value supplied for the format (assuming that macro variable &format exists but is empty if no format gets supplied).

data test;
  input unformatted_var $;
  DATALINES;
1
;

%let format =;
%macro doit();
  data test;
    set test;
    %if %bquote(&format) = %bquote() %then
      %do;
        formatted_var = unformatted_var;
      %end;
    %else
      %do;
        formatted_var = put(unformatted_var, &format..);
      %end;
  run;
%mend;
%doit()

PROC PRINT DATA = test;
run;

If you're on a very recent SAS version then you can use SAS macro %IF %then %else even without a macro definition.

data test;
  input unformatted_var $;
  DATALINES;
1
;

%let format =;

data test;
  set test;
  %if %bquote(&format) = %bquote() %then
    %do;
      formatted_var = unformatted_var;
    %end;
  %else
    %do;
      formatted_var = put(unformatted_var, &format..);
    %end;
run;

PROC PRINT DATA = test;
run;

 

StephenM
Fluorite | Level 6

Thanks for the replies everyone. I didn't realise SAS checked syntax before executing, I'll take this into account with my code.

Patrick
Opal | Level 21

@StephenM 

Using PUTC/PUTN as @Kurt_Bremser suggests is another option closer to the code you've posted as there the check of the format only happens during execution time. For this reason PUTC/PUTN also doesn't perform as good as PUT

Kurt_Bremser
Super User

If you want to conditionally use a format, use either putc or putn:

data test;
	set test;

	have_format = 0;

	if have_format then do;
		formatted_var = putc(unformatted_var, "&format..");
	end; else do;
		formatted_var = unformatted_var;
	end;

run;

Since the format can be dynamic with these functions, the check occurs during runtime only when the function is actually called.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 2079 views
  • 1 like
  • 4 in conversation