Classical Reports — WRITE Statement Formatting
Format ABAP report output with WRITE: column alignment, headers, totals, colors, horizontal lines, and page breaks.
Classical Reports — WRITE Statement Formatting
What You'll Learn
- Formatting output with column positions and widths
- Creating headers and underlines
- Adding color to output
- Page breaks and page headers
- Building a complete formatted report
Column-Aligned Output
REPORT z_classical_report LINE-SIZE 100.
* Header
WRITE: / 'Emp ID' COLOR COL_HEADING,
20 'Name' COLOR COL_HEADING,
50 'Department' COLOR COL_HEADING,
75 'Salary' COLOR COL_HEADING.
ULINE. " Horizontal line
* Data rows
WRITE: / '001', 20 'Alice Johnson', 50 'Engineering', 75 '120,000.00'.
WRITE: / '002', 20 'Bob Smith', 50 'Marketing', 75 '95,000.00'.
WRITE: / '003', 20 'Charlie Brown', 50 'Engineering', 75 '130,000.00'.
ULINE.
WRITE: / 'Total:', 75 '345,000.00' COLOR COL_TOTAL.
Expected Output
Emp ID Name Department Salary
────────────────────────────────────────────────────────────────────────────────────
001 Alice Johnson Engineering 120,000.00
002 Bob Smith Marketing 95,000.00
003 Charlie Brown Engineering 130,000.00
────────────────────────────────────────────────────────────────────────────────────
Total: 345,000.00
The number after the variable (e.g., 20 'Name') is the column position. ULINE draws a horizontal line. COLOR adds background highlighting.
WRITE Formatting Options
DATA: lv_amount TYPE p DECIMALS 2 VALUE '123456.78',
lv_date TYPE d VALUE '20260412',
lv_pct TYPE p DECIMALS 1 VALUE '85.5'.
WRITE: / 'Amount:', lv_amount. " Default: 123,456.78
WRITE: / 'No sign:', lv_amount NO-SIGN. " Remove negative sign
WRITE: / 'Left aligned:', lv_amount LEFT-JUSTIFIED. " Left-align (default is right)
WRITE: / 'Date formatted:', lv_date DD/MM/YYYY. " 12/04/2026
WRITE: / 'Date ISO:', lv_date YYYYMMDD. " 20260412
WRITE: / 'Percentage:', lv_pct, '%'.
Colors
* Available colors
WRITE: / 'COL_HEADING' COLOR COL_HEADING. " Blue/grey header
WRITE: / 'COL_NORMAL' COLOR COL_NORMAL. " Normal background
WRITE: / 'COL_TOTAL' COLOR COL_TOTAL. " Yellow — for totals
WRITE: / 'COL_KEY' COLOR COL_KEY. " Blue-green — for key fields
WRITE: / 'COL_POSITIVE' COLOR COL_POSITIVE. " Green — good values
WRITE: / 'COL_NEGATIVE' COLOR COL_NEGATIVE. " Red — bad values
WRITE: / 'COL_GROUP' COLOR COL_GROUP. " Purple — group headers
A Complete Formatted Report
REPORT z_employee_report LINE-SIZE 120 NO STANDARD PAGE HEADING.
TYPES: BEGIN OF ty_employee,
id TYPE n LENGTH 10,
name TYPE string,
department TYPE string,
salary TYPE p DECIMALS 2,
END OF ty_employee.
DATA: lt_employees TYPE TABLE OF ty_employee,
lv_total TYPE p DECIMALS 2,
lv_count TYPE i.
PARAMETERS: p_dept TYPE c LENGTH 30 DEFAULT 'Engineering'.
TOP-OF-PAGE.
WRITE: / 'EMPLOYEE SALARY REPORT' COLOR COL_HEADING CENTERED.
WRITE: / |Department: { p_dept }| COLOR COL_HEADING,
80 |Date: { sy-datum DATE = USER }| COLOR COL_HEADING,
105 |Page: { sy-pagno }| COLOR COL_HEADING.
ULINE.
WRITE: / 'ID' COLOR COL_HEADING,
15 'Name' COLOR COL_HEADING,
50 'Department' COLOR COL_HEADING,
80 'Salary' COLOR COL_HEADING.
ULINE.
START-OF-SELECTION.
lt_employees = VALUE #(
( id = '0000000001' name = 'Alice Johnson' department = 'Engineering' salary = '120000.00' )
( id = '0000000003' name = 'Charlie Brown' department = 'Engineering' salary = '130000.00' )
( id = '0000000006' name = 'Frank Wilson' department = 'Engineering' salary = '145000.00' )
).
LOOP AT lt_employees INTO DATA(ls_emp).
WRITE: / ls_emp-id,
15 ls_emp-name,
50 ls_emp-department,
80 ls_emp-salary.
lv_total = lv_total + ls_emp-salary.
lv_count = lv_count + 1.
ENDLOOP.
END-OF-SELECTION.
ULINE.
WRITE: / 'Total:' COLOR COL_TOTAL,
80 lv_total COLOR COL_TOTAL.
WRITE: / |Employees: { lv_count }| COLOR COL_TOTAL.
SKIP 1.
WRITE: / |Report generated by { sy-uname } at { sy-uzeit TIME = USER }|.
When to Use Classical Reports
Classical WRITE-based reports are simple and fast to build. Use them for:
- Quick ad-hoc reports
- Simple list output
- Debugging (writing intermediate values)
- Legacy maintenance (many existing reports use this style)
For professional reports, use ALV (next lesson). ALV provides sorting, filtering, column reordering, export to Excel, and a modern look — all built in. Classical reports require you to code all of this manually.
Common Mistakes
- Not setting LINE-SIZE. Default line width is 83 characters — too narrow for most reports. Use
LINE-SIZE 120orLINE-SIZE 200in the REPORT statement. - Hardcoding column positions that overlap. If you put name at position 15 and department at position 30, a name longer than 15 characters bleeds into the department column. Test with long values.
- Forgetting NO STANDARD PAGE HEADING. By default, SAP adds its own page header (program name, page number). If you use TOP-OF-PAGE for custom headers, add
NO STANDARD PAGE HEADINGto the REPORT statement to suppress the default.
Key Takeaways
- Classical reports use WRITE with column positions for formatted output.
- ULINE draws horizontal lines. SKIP adds blank lines. COLOR adds background highlighting.
- TOP-OF-PAGE creates page headers. LINE-SIZE sets the output width.
- For professional output, use ALV reports (next lesson) instead of classical WRITE.
- Classical reports are still useful for debugging and quick ad-hoc output.
Next Lesson
Classical reports require manual formatting for everything. In Lesson 21: ALV Reports, we'll learn the modern way to display data — with built-in sorting, filtering, totals, and Excel export.