Writing a Report with a DATA Step

Example 1: Creating a Report without Creating a Data Set

You can use a DATA step to generate a report without creating a data set by using _NULL_ in the DATA statement. This approach saves system resources because SAS does not create a data set. The report can contain both TITLE statements and FOOTNOTE statements. If you use a FOOTNOTE statement, be sure to include FOOTNOTE as an option in the FILE statement in the DATA step.
title1 'Budget Report';  1
title2 'Mid-Year Totals by Department';
footnote 'compiled by Manager, 
Documentation Development Department';  2

data _null_;  3
   set budget;  4
   file print footnote;  5
   MidYearTotal=Jan+Feb+Mar+Apr+May+Jun;  6
   if _n_=1 then  7
      do; 
         put @5 'Department' @30 'Mid-Year Total';  
      end;
   put @7 Department @35 MidYearTotal;  8 
run;  9
1 Define titles.
2 Define the footnote.
3 Begin the DATA step. _NULL_ specifies that no data set is created.
4 Read one observation per iteration from data set BUDGET.
5 Name the output file for the PUT statements and use the PRINT fileref. By default, the PRINT fileref specifies that the file contains carriage-control characters and titles. The FOOTNOTE option specifies that each page of output will contain a footnote.
6 Calculate a value for the variable MidYearTotal on each iteration.
7 Write variable name headings for the report on the first iteration only.
8 Write the current values of variables Department and MidYearTotal for each iteration.
9 Execute the DATA step.
The example above uses the FILE statement with the PRINT fileref to produce LISTING output. If you want to print to a file, specify a fileref or a complete filename. Use the PRINT option if you want the file to contain carriage-control characters and titles. The following example shows how to use the FILE statement in this way.
file 'external-file' footnote print;
You can also use the data _null_; statement to write to an external file. For more information about writing to external files, see the FILE statement in SAS Statements: Reference, and the SAS documentation for your operating environment.

Example 2: Creating a Customized Report

You can create very detailed, fully customized reports by using a DATA step with PUT statements. The following example shows a customized report that contains three distinct sections: a header, a table, and a footer. It contains existing SAS variable values, constant text, and values that are calculated as the report is written.
Sample of a Customized Report
                      Around The World Retailers

EMPLOYEE BUSINESS, TRAVEL, AND TRAINING EXPENSE REPORT


Employee Name: ALEJANDRO MARTINEZ          Destination: CARY, NC                                         Departure Date: 11JUL2010
   Department: SALES & MARKETING           Purpose of Trip/Activity: MARKETING TRAINING                     Return Date: 16JUL2010
     Trip ID#: 93-0002519                                                                                 Activity from: 12JUL1993
                                                                                                                     to: 16JUL2010

+-----------------------------------+--------+--------+--------+--------+--------+--------+--------+--------+
|                                   |   SUN  |   MON  |   TUE  |   WED  |   THU  |   FRI  |   SAT  |        |   PAID BY  PAID BY
| EXPENSE DETAIL                    |  07/11 |  07/12 |  07/13 |  07/14 |  07/15 |  07/16 |  07/17 | TOTALS |   COMPANY EMPLOYEE
|-----------------------------------|--------|--------|--------|--------|--------|--------|--------|--------|
|Lodging, Hotel                     |   92.96|   92.96|   92.96|   92.96|   92.96|        |        |  464.80|    464.80
|Telephone                          |    4.57|    4.73|        |        |        |        |        |    9.30|               9.30
|Personal Auto   36 miles @.28/mile |    5.04|        |        |        |        |    5.04|        |   10.08|              10.08
|Car Rental, Taxi, Parking, Tolls   |        |   35.32|   35.32|   35.32|   35.32|   35.32|        |  176.60|    176.60
|Airlines, Bus, Train (Attach Stub) |  485.00|        |        |        |        |  485.00|        |  970.00|    970.00
|Dues                               |        |        |        |        |        |        |        |        |
|Registration Fees                  |   75.00|        |        |        |        |        |        |   75.00|              75.00
|Other (explain below)              |        |        |        |        |        |    5.00|        |    5.00|               5.00
|Tips (excluding meal tips)         |    3.00|        |        |        |        |    3.00|        |    6.00|               6.00
|-----------------------------------|--------|--------|--------|--------|--------|--------|--------|--------|
|Meals                              |        |        |        |        |        |        |        |        |
|Breakfast                          |        |        |        |        |        |    7.79|        |    7.79|               7.79
|Lunch                              |        |        |        |        |        |        |        |        |
|Dinner                             |   36.00|   28.63|   36.00|   36.00|   30.00|        |        |  166.63|             166.63
|Business Entertainment             |        |        |        |        |        |        |        |        |
|-----------------------------------|--------|--------|--------|--------|--------|--------|--------|--------|
|TOTAL EXPENSES                     |  641.57|  176.64|  179.28|  179.28|  173.28|  541.15|        | 1891.20|   1611.40   279.80
+-----------------------------------+--------+--------+--------+--------+--------+--------+--------+--------+

Travel Advance to Employee ..................................................................................              $0.00

Reimbursement due Employee (or ATWR) ........................................................................            $279.80

Other: (i.e. miscellaneous expenses and/or names of employees sharing receipt.)

CAR RENTAL INCLUDE $5.00 FOR GAS








APPROVED FOR PAYMENT BY: Authorizing Manager:  _________________________________________________   Emp. #  _______


                          Employee Signature:  _________________________________________________   Emp. #  1118


     Charge to Division: ATW          Region:  TX         Dept:  MKT          Acct:      6003      Date:  27JUL2010
 
The code shown below generates the report example. You must create your own input data. It is beyond the scope of this discussion to fully explain the code that generated the report example. For a complete explanation of this example, see the SAS Guide to Report Writing: Examples.
options ls=132 ps=66 pageno=1 nodate;

data travel;   
                                                   
  /* infile 'SAS-data-set' missover; */
  infile 'c15expense.dat' missover;
 input acct div $ region $ deptchg $ rptdate : date9.             
     other1-other10 /                                             
     empid empname & $char35. / dept & $char35. /                 
     purpose & $char35. / dest & $char35. / tripid & $char35. /   
     actdate2 : date9. /                                          
     misc1 & $char75. / misc2 & $char75. / misc3 & $char75. /     
     misc4 & $char75. /                                           
     misc5 & $char75. / misc6 & $char75. / misc7 & $char75. /     
     misc8 & $char75. /                                           
     dptdate : date9. rtrndate : date9. automile permile /        
     hotel1-hotel10 /                                             
     phone1-phone10 / peraut1-peraut10 / carrnt1-carrnt10 /       
     airlin1-airlin10 / dues1-dues10 / regfee1-regfee10 /         
     tips1-tips10 / meals1-meals10 / bkfst1-bkfst10 /             
     lunch1-lunch10 / dinner1-dinner10 / busent1-busent10 /       
     total1-total10 / empadv reimburs actdate1 : date9.;          
run;                                                              

proc format;
   value category 1='Lodging, Hotel'
                  2='Telephone'
                  3='Personal Auto'
                  4='Car Rental, Taxi, Parking, Tolls'
                  5='Airlines, Bus, Train (Attach Stub)'
                  6='Dues'
                  7='Registration Fees'
                  8='Other (explain below)'
                  9='Tips (excluding meal tips)'
                 10='Meals'
                 11='Breakfast'
                 12='Lunch'
                 13='Dinner'
                 14='Business Entertainment'
                 15='TOTAL EXPENSES';
value blanks  0=' '
             other=(|8.2|);
   value $cuscore ' '='________';
   value nuscore   . ='________';
run;

data _null_;
   file print;
   title 'Expense Report';
   format rptdate actdate1 actdate2 dptdate rtrndate date9.;
   set travel;

   array expenses{15,10} hotel1-hotel10  phone1-phone10 
                         peraut1-peraut10 carrnt1-carrnt10 
                         airlin1-airlin10 dues1-dues10
                         regfee1-regfee10 other1-other10 
                         tips1-tips10 meals1-meals10 
                         bkfst1-bkfst10 lunch1-lunch10
                         dinner1-dinner10 busent1-busent10 
                         total1-total10;
   array misc{8} $ misc1-misc8;
   array mday{7} mday1-mday7;
   dptday=weekday(dptdate);
   mday{dptday}=dptdate;
   if dptday>1 then
      do dayofwk=1 to (dptday-1);
        mday{dayofwk}=dptdate-(dptday-dayofwk);
      end;
   if dptday<7 then
      do dayofwk=(dptday+1) to 7;
         mday{dayofwk}=dptdate+(dayofwk-dptday);
      end;
   if rptdate=. then rptdate="&sysdate9"d;

tripnum=substr(tripid,4,2)||'-'||substr(scan(tripid,1),6);

   put // @1 'Around The World Retailers' //

          @1 'EMPLOYEE BUSINESS, TRAVEL, AND TRAINING EXPENSE REPORT' ///

          @1 'Employee Name: ' @16 empname 
          @44 'Destination: ' @57 dest
          @106 'Departure Date:' @122 dptdate /

          @4 'Department: ' @16 dept
          @44 'Purpose of Trip/Activity: ' @70 purpose
          @109 'Return Date:' @122 rtrndate /

          @6  'Trip ID#: ' @16 tripnum
          @107 'Activity from:' @122 actdate1 /

          @118 'to:' @122 actdate2 //
          @1 '+-----------------------------------+--------+--------+'
             '--------+--------+--------+--------+--------+--------+' /

          @1 '|                                   |   SUN  |   MON  |'
             '   TUE  |   WED  |   THU  |   FRI  |   SAT  |        |'
             '   PAID BY  PAID BY' /

          @1 '| EXPENSE DETAIL                   '
             ' |  ' mday1 mmddyy5. ' |  ' mday2  mmddyy5.
             ' |  ' mday3 mmddyy5. ' |  ' mday4  mmddyy5.
             ' |  ' mday5 mmddyy5. ' |  ' mday6  mmddyy5.
             ' |  ' mday7 mmddyy5.
          @100 '| TOTALS |   COMPANY EMPLOYEE' ;
   do i=1 to 15;

      if i=1 or i=10 or i=15 then
        put @1 '|-----------------------------------|--------|--------|'
               '--------|--------|--------|--------|--------|--------|';
      if i=3 then
         put @1 '|' i category. @16 automile 4.0 @21 'miles @'
           @28 permile 3.2 @31 '/mile'  @37 '|' @;
         else put @1 '|' i category.  @37 '|' @;
     col=38;
     do j=1 to 10;
       if j<9 then put @col expenses{i,j} blanks8. '|' @;
          else if j=9 then put @col expenses{i,j} blanks8. @;
          else put @col expenses{i,j} blanks8.;
       col+9;
       if j=8 then col+2;
     end;
   end;
   Put @1 '+-----------------------------------+--------+--------+'
          '--------+--------+--------+--------+--------+--------+' //

@1 'Travel Advance to Employee ...............................'
          '...................................................'
       @121 empadv dollar8.2 //

       @1 'Reimbursement due Employee (or ATWR) .....................'
          '...................................................'
       @121 reimburs dollar8.2 //

       @1 'Other: (i.e. miscellaneous expenses and/or names of '
          'employees sharing receipt.)' /;
   do j=1 to 8;
     put @1 misc{j} ;
   end;
   put / @1  'APPROVED FOR PAYMENT BY: Authorizing Manager:'
       @48 '_________________________________________________'
       @100 'Emp. #  _______' ///

       @27 'Employee Signature:'
       @48 '_________________________________________________'
       @100 'Emp. #  ' empid ///

       @6 'Charge to Division:' @26 div $cuscore.
       @39 'Region:'            @48 region $cuscore.
       @59 'Dept:'              @66 deptchg $cuscore.
       @79 'Acct:'              @86 acct nuscore.
       @100 'Date:'             @107 rptdate /
       _page_;
run;

Example 3: Creating an HTML Report Using ODS and the DATA Step


ods html body='your_file.html';

title 'Leading Grain Producers';
title2 'for 2012'; 

proc format;    
   value $cntry 'BRZ'='Brazil'                 
                'CHN'='China'
                'IND'='India' 
                'INS'='Indonesia'          
                'USA'=''United States';
run;

data _null_;    
   length Country $ 3 Type $ 5;    
   input Year country $ type $ Kilotons;    
   format country $cntry.;    
   label type='Grain';

file print
ods=(variables=(country type kilotons));

put _ods_;

   datalines;
2012 BRZ  Wheat    3302 
2012 BRZ  Rice     10035 
2012 BRZ  Corn     31975
2012 CHN  Wheat    109000 
2012 CHN  Rice     190100 
2012 CHN  Corn     119350
2012 IND  Wheat    62620 
2012 IND  Rice     120012 
2012 IND  Corn     8660
2012 INS  Wheat    . 
2012 INS  Rice     51165 
2012 INS  Corn     8925 
2012 USA  Wheat    62099
2012 USA  Rice     7771 
2012 USA  Corn     236064
; 
run;

HTML File Produced by ODS
HTML File Produced by ODS