The FORMAT Procedure docs for "Using a Function to Format Values" show an example of a function that computes the formatted values for a custom format.
My question is that when the function contains a PUT statement, nothing appears in the Log window. Where do the puts end up ?
ods html file='quirky.html';
proc fcmp outlib=work.functions.smd;
function qfmt(date) $;
put date; /************* DOES NOT GET LOGGED **************/
return ("foobar");
/* length qnum $4;*/
/* qnum=put(date,yyq4.);*/
/* if substr(qnum,3,1)='Q'*/
/* then return(substr(qnum,3,2));*/
/* else return(qnum);*/
endsub;
run;
/* Make the function available to SAS. */
options cmplib=(work.functions);
/* Create a format using the function created by the FCMP procedure. */
proc format; value qfmt other=[qfmt()]; run;
/* Use the format in a SAS program. */
data djia2009;
input closeDate date7. close;
datalines;
01jan09 800.86
02feb09 7062.93
02mar09 7608.92
01apr09 8168.12
01may09 8500.33
01jun09 8447.00
01jul09 9171.61
03aug09 9496.28
01sep09 9712.28
01oct09 9712.73
02nov09 10344.84
02dec09 10428.05
;
proc print data=djia2009;
format closedate qfmt. close dollar9.;
run;
ods html close;
Log
6132 ;
6133
6134 proc print data=djia2009;
6135 format closedate qfmt. close dollar9.;
6136 run;
NOTE: There were 12 observations read from the data set WORK.DJIA2009.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.06 seconds
cpu time 0.03 seconds
6137
Output
Didn't you try it?
data test;
y=qfmt(1111);
z=put(2222,qfmt.);
run;
It wrote it to the listing output when I tried it.
2366 filename list2 temp; 2367 filename log2 temp; 2368 options nosource nonotes; 2376 data _null_; 2377 put 'listing'; 2378 do until(eof1); 2379 infile list2 end=eof1; 2380 input; 2381 put _infile_; 2382 end; 2383 put 'log'; 2384 do until(eof2); 2385 infile log2 end=eof2; 2386 input; 2387 put _infile_; 2388 end; 2389 stop; 2390 run; NOTE: The infile LIST2 is: Filename=C:\Users\ABERNA~1\AppData\Local\Temp\1\SAS Temporary Files\_TD13900_AMRL20L6F1E4992_\#LN00747, RECFM=V,LRECL=32767,File Size (bytes)=136, Last Modified=17Apr2020:18:29:06, Create Time=17Apr2020:18:29:06 NOTE: The infile LOG2 is: Filename=C:\Users\ABERNA~1\AppData\Local\Temp\1\SAS Temporary Files\_TD13900_AMRL20L6F1E4992_\#LN00748, RECFM=V,LRECL=32767,File Size (bytes)=6, Last Modified=17Apr2020:18:29:06, Create Time=17Apr2020:18:29:06 listing 16:21 Thursday, April 16, 2020 99 2222 log 1111 NOTE: 3 records were read from the infile LIST2. The minimum record length was 0. The maximum record length was 126. NOTE: 1 record was read from the infile LOG2. The minimum record length was 4. The maximum record length was 4. NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.01 seconds
Apparently PROC PRINT calls it many times per observation.
proc print data=sashelp.class(obs=1);
format age qfmt.;
run;
16:21 Thursday, April 16, 2020 104
Obs Name Sex Age Height Weight
1 Alfred M foobar 69 112.5
16:21 Thursday, April 16, 2020 105
14
14
14
14
If you are attempting to test this in the Proc print then create a second variable with the raw date value and use a more typcial format for display.
For debugging in the data step
data djia2009; input closeDate date7. close; put "Date7 format" +1 closedate= date7. +1 "Custom format" +1 closedate= qfmt.; datalines; 01jan09 800.86 02feb09 7062.93 02mar09 7608.92 01apr09 8168.12 01may09 8500.33 ;
Tis the nature of functions that they return values, not create print style output.
My guess is since Proc FCMP uses the SAS language compiler to create user-defined functions. The compiler subsystem generates machine language code for the computer on which SAS is running. This guess leads me to put my bet of something akin to stored compiled macro. Plus the fact FCMP offers interaction with macro language by using the macro function %SYSFUNC and the macro statement %SYSCALL could have made the design overriding execution of PUT as null?
PS I am all ears to sit corrected and learn the proper mechanism besides the fun guess
Didn't you try it?
data test;
y=qfmt(1111);
z=put(2222,qfmt.);
run;
It wrote it to the listing output when I tried it.
2366 filename list2 temp; 2367 filename log2 temp; 2368 options nosource nonotes; 2376 data _null_; 2377 put 'listing'; 2378 do until(eof1); 2379 infile list2 end=eof1; 2380 input; 2381 put _infile_; 2382 end; 2383 put 'log'; 2384 do until(eof2); 2385 infile log2 end=eof2; 2386 input; 2387 put _infile_; 2388 end; 2389 stop; 2390 run; NOTE: The infile LIST2 is: Filename=C:\Users\ABERNA~1\AppData\Local\Temp\1\SAS Temporary Files\_TD13900_AMRL20L6F1E4992_\#LN00747, RECFM=V,LRECL=32767,File Size (bytes)=136, Last Modified=17Apr2020:18:29:06, Create Time=17Apr2020:18:29:06 NOTE: The infile LOG2 is: Filename=C:\Users\ABERNA~1\AppData\Local\Temp\1\SAS Temporary Files\_TD13900_AMRL20L6F1E4992_\#LN00748, RECFM=V,LRECL=32767,File Size (bytes)=6, Last Modified=17Apr2020:18:29:06, Create Time=17Apr2020:18:29:06 listing 16:21 Thursday, April 16, 2020 99 2222 log 1111 NOTE: 3 records were read from the infile LIST2. The minimum record length was 0. The maximum record length was 126. NOTE: 1 record was read from the infile LOG2. The minimum record length was 4. The maximum record length was 4. NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.01 seconds
Apparently PROC PRINT calls it many times per observation.
proc print data=sashelp.class(obs=1);
format age qfmt.;
run;
16:21 Thursday, April 16, 2020 104
Obs Name Sex Age Height Weight
1 Alfred M foobar 69 112.5
16:21 Thursday, April 16, 2020 105
14
14
14
14
@Tom. Good catch. I hadn't thought to look in the OUTPUT window, and there it was. Peculiar, because ODS LISTING was closed. I am using the PUT in the function as a way to observe what a PROC is doing in concert with ODS when a styling setting to apply is obtained via .... style-attr=format.
You guys are cleverer than me it seems.
I can't get that result. Using SAS UE, the RESULTS tab remains stubbornly empty (except for the proc print output if I add that).
What's the missing link? See my attempt below.
proc fcmp outlib=work.functions.smd;
function qfmt(date) $;
put '=>' date; /************* DOES NOT GET LOGGED **************/
return ("foobar");
/* length qnum $4;*/
/* qnum=put(date,yyq4.);*/
/* if substr(qnum,3,1)='Q'*/
/* then return(substr(qnum,3,2));*/
/* else return(qnum);*/
endsub;
run;
/* Make the function available to SAS. */
options cmplib=(work.functions);
/* Create a format using the function created by the FCMP procedure. */
proc format; value qfmt other=[qfmt()]; run;
/****** WHAT AM I DOING WRONG HERE? START ********/
filename list2 temp;
filename log2 temp;
ods listing;
data test;
y=qfmt(1111);
z=put(2222,qfmt.);
run;
proc print data=sashelp.class(obs=1);
format age qfmt.;
run;
ods listing close;
/****** WHAT AM I DOING WRONG HERE? END ********/
data _null_;
put 'listing';
do until(eof1);
infile list2 end=eof1;
input;
put _infile_;
end;
put 'log';
do until(eof2);
infile log2 end=eof2;
input;
put _infile_;
end;
stop;
run;
You left out the PROC PRINTTO step to redirect the PRINT destination to your temporary file.
Not sure where UE points the default print output.
@Tom This indeed works. Any idea why the redirected (printto) output is:
=> 2222 Obs Name Sex Age Height Weight 1 Joyce F foobar 51.3 50.5 => 11 => 11 => 11 => 11
but the non-redirected output (in the listing window) is:
=> 2222 Obs Name Sex Age Height Weight => 11 1 Joyce F foobar 51.3 50.5 => 11 => 11
Why should they be any different?
Interesting how proc print calls the format several times per obs.
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!
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.