How to format a macro variable

11

format a macro variableWould you like to format your macro variables?

Easy!  Just use the %FORMAT function, like this:

format a macro variable

What?! You never heard of the %FORMAT function?
Of course not, cuz it doesn't exist! No problem.
Just create it, like this:

%macro format(value,format);
	%if %datatyp(&value)=CHAR
		%then %sysfunc(putc(&value,&format));
		%else %left(%qsysfunc(putn(&value,&format)));
%mend format;

The %FORMAT function also accepts user-defined formats, like this:

format a macro variable

The PROC SQL step below creates the macro variable HIGHSALARY, which is referenced in the TITLE statement and formatted with the user-defined %FORMAT function.

proc sql noprint;
 
	select 5*avg(salary) into :highsalary
		from orion.staff;
 
	reset print;
 
	title "Salaries over %format(&highsalary,dollar11.2)";
 
	select employee_ID, salary 
		from orion.staff
			where salary > &highsalary
				order by salary desc;
quit;

 

Be sure to save your user-defined %FORMAT function in your stored compiled macro or autocall library for convenient re-use!

If you enjoyed this tip on how to format a macro variable in SAS, and want more like it, consider taking our SAS Macro Language 1: Essentials course and/or our SAS Macro Language 2: Advanced Techniques, offered in the classroom, as Live Web classes, or as self-paced e-Learning. These courses are part of our SAS Programming curriculum.

You can also find more programming tips here. And, check back often. New tips, from a variety of SAS blogs, are added regularly!

Share

About Author

Jim Simon

Principal Technical Training Consultant

Jim Simon is a principal instructor and course developer for SAS Education. Jim has a bachelor's degree from UCLA and a master's degree from California State University at Northridge. Prior to joining the SAS Irvine office in 1988, Jim was an instructor at Ventura College and a SAS programmer at The Medstat Group in Santa Barbara. Jim's areas of specialization include the DATA step, application development, web enablement, and the SAS macro language. A native of Southern California, Jim enjoys anything in the warm California sun. On weekends, Jim loves jumping in his Corvette, turning up the stereo, and cruising Pacific Coast Highway, top down, South to Laguna Beach or North to his old home town, Santa Barbara.

11 Comments

  1. Great!
    I suggest add a "strip" to remove the tailing blank character.

    %macro format(value,format);
    %if %datatyp(&value)=CHAR
    %then %sysfunc(strip(%sysfunc(putc(&value,&format))));
    %else %left(%qsysfunc(putn(&value,&format)));
    %mend format;

    • Michele, the bad news is you cannot, but the good news is you never need to. Consider these examples ...

      %let x=3;
      %put y=%eval(&x+&x);

      data a;
      z=&x;
      run;

      In the first example, y is 6.
      In the second example, z is a numeric variable.
      Macro variable x remains character.

      Cheers,
      Jim

      proc contents;
      run;

  2. Q.1 How to get date9. format for cutoff_stdat variable , kindly help.

    %let cutoff_stdt = 19MAY2019:00:00:00.000 ;
    %let cutoff_stdat= %sysfunc(inputn(&cutoff_stdt.,DATETIME22.3)) ;
    %put &cutoff_stdat. ; /* Tried %put %format (&cutoff_stdat , date9. ) ; */

    • %let cutoff_stdt=19MAY2019:00:00:00.000;
      %let cutoff_stdat=%sysfunc(inputn(&cutoff_stdt.,DATETIME22.3)) ;
      %put &cutoff_stdat.;
      %put %sysfunc(putn(&cutoff_stdat,DATETIME22.3));

      %let dateonly=%sysfunc(datepart(&cutoff_stdat));
      %put %sysfunc(putn(&dateonly,DATE9.));

  3. I am sorry, but I have to add more water to the wine.
    On top of what Quentin pointed out already (potential quoting problems), the data type is derived from the value. Well, the caller has to provide the data type-specific format name, anyways.
    And now try
    %put %format(123,$3.);
    The helper macro will generate a putn() call which will FAIL with the char format.
    Instead of using %datatyp() it should inspect 1st char of the format name.

  4. Clever idea, Jim. I want to point out a subtle aspect of Jim's example that might not be apparent. Namely, the example shows a single procedure that assigns a macro variable and then immediately uses the (formatted) macro variable in a global statement (TITLE). This works for PROC SQL because SQL is an INTERACTIVE procedure, which means that each statement is executed as it is encountered. Similarly, the same idea would work in PROC IML. However, in the DATA step, the macro variable is not created until after the DATA step exits. That means that you would need to put the TITLE statement after the RUN statement that ends the step. Here is an example:

    %symdel pi / nowarn;
    title;
    data _null_;
    call symputx("pi", 3.14159);
    shortPi = "%format(&pi, 5.2)"; /* ERROR: macro var not defined yet */
    run;

    %put &=pi;
    title "pi = %format(&pi, 5.2)"; /* macro var is now defined */

    • Jim Simon

      Rick is spot on. I chose PROC SQL for its ability to:

      1) Calculate a statistic
      2) Store the statistic into a macro variable
      3) Produce a report

      ... all in a single step!

      Are there other ways? Of course!

      proc means data=orion.staff noprint;
      var salary;
      output out=mystats mean=avgsal;
      run;

      data _null_;
      set mystats;
      call symputx('meansalary',avgsal);
      run;

      proc print data=orion.staff;
      where salary > &meansalary;
      title "Salaries over %format(&meansalary,dollar11.2)";
      run;

      But that's three steps! I'll almost always choose one step over three!

  5. Nifty. To protect against macro triggers inside a format value (e.g. value 1='Tom&Jerry'), maybe it would be a good idea to macro quote the returned value, by using %qsysfunc and %qleft, like:
    %if %datatyp(&value)=CHAR %then %qsysfunc(putc(&value,&format)); %else %qleft(%qsysfunc(putn(&value,&format)));

Back to Top