Click here to Skip to main content
15,119,322 members
Articles / Desktop Programming / MFC
Posted 23 Nov 2001


105 bookmarked

Easy! Reports

Rate me:
Please Sign up or sign in to vote.
4.92/5 (10 votes)
23 Nov 2001CPOL4 min read
A class for generating Business style reports



One of the problems while writing programs in C++ is that the tools and API that one can use to generate reports is very limited. For instance, there are a plethora of classes to view (CView, CHtmlView etc.) but no reporting API.

The present tool here is a simple API that can be used to print fairly complex business style reports.

Almost all reports have the following standard elements:

  1. A Report header. Typically, this is the establishment name, business address etc. The report header is printed only on the first page of the report.
  2. The page header. This generally consists of the report title, e.g. "Payroll Summary" and a date. This page header is printed on every page of the report.
  3. The Data Section. The page header is followed by one or more tabular data sections. For instance, a payroll summary may include employee names and their salaries grouped by their department. There may be several sections, one for each department. Each group may be followed by a summary section, summarizing the data for that group.
  4. PageFooter. The data section is followed by a page footer. This page footer generally consists of a page number. The page footer is generally printed on every page.
  5. Report Footer. The page footer is optionally followed by the Report footer. This report footer is printed only on the last page.

Given the above, we present a simple yet powerful layout class. This class is called CEasyReport. There are basically three functions that are really the key:

  1. SetDataCols, which starts a new tabular section. The arguments are a array of CColInfo items describing each column in the section. The description includes the column name, the column width and alignment. The column name can contain '\n', which sets up a multiple row column heading.
  2. AtTab(int, CString). This is the workhorse function which can be used to print text in columns. The first parameter is the column number and the second character is the text to be printed. For instance, if your tabular section consists of a "Name" column and a "Date of Birth" column, you would print the name using:
    AtTab(0,"Lal, Vipul");    // write the name in col 0
    AtTab(1,"12/04/1980");    // write DOB in col 1
    We could have overloaded this function to print a long, double, a CTime etc, but we left that to the user to suit his/her own requirements.
  3. Call NextRow to advance the printing to the next row. Typically, you would do this when you have printed all the columns in one row. This function checks to see if there is enough space on the current page to print another row, and ejects the page if not.
Whenever you need to start a new section, simply call SetDataCols. Thus, if your report consists of a main section followed by a summary section for each group, your typical code loop would be:
while(! m_Recordset.IsEof())
    m_CurGroup = m_Recordset.GroupColumnData;
        ... other columns...
        NextRow(); // advance the printer row;
        // compute summary items
    while( !m_Recordset.IsEof() && 
        m_Recordset.GroupColumnData == m_CurGroup);
    // Start a summary section...
    AtTab(...);    // print summary data

While generating a report content, no actual image is generated. Rather, the generation process simply generates "report objects". For instance, a CTextObject contains the text to be written and the rectangular co-ordinates for the text. Thus, every page consists of a set of "report objects". Later, when we are called to print or preview the report, we simply call upon the report object to draw itself. Since every such object has the co-ordinates with respect to the top of the page, we can draw any page. Thus, the user can select to print or preview page 3,5 and 7 of the report and we simply draw all objects for those pages. The current version supports a Text object, a Line object and a Date and PageNumber object.

Note: The current version simply generates these report objects in memory. You might want to serialize these to disk if the report is really long.

The API has a RepeatHdr flag, which forces the column headings to be printed on every page. When this flag is off, the column header is printed every time the tabular section is set up. Therefore, if you have only one section, i.e your report consists of one long list, and you like the column headings to be printed on every page, set this flag on.

The report also has "SuppressBlankHdr" flag. When this flag is set, the column headings are not printed unless you print something in one of the columns.

The report also has a "word-wrap" mode in which one can print a "paragraph" of text. The text is aligned within the page margins.

The demo report project generates a report of all employees, grouped by department. The demo project also has a small Access database which has two tables - an Employee table and a Departments table. The SQL Query used for the report is:

SELECT * FROM employees 
   INNER JOIN departments ON employees.DeptID = departments.DeptID 
   GROUP BY employees.DeptID
However, the current API is not limited to SQL databases in any way and the source of the data could be anything, even an in-memory array. However, the algorithm presented above does rely on the fact that the data is already grouped and sorted. This would generally be the case, since the database can use indexes etc to sort and group the data.

Please do feel free to email me your suggestions, comments and bug fixes.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Vipul Lal
India India
No Biography provided

Comments and Discussions

QuestionRe: Not work in Windows 7, 8, 10 Pin
allviewsystem from Bayamon18-Feb-18 3:32
Memberallviewsystem from Bayamon18-Feb-18 3:32 
Questionhow to add a icon in the report Pin
neo6186-Apr-15 23:21
Memberneo6186-Apr-15 23:21 
GeneralNo page scrolling or navagation Pin
Steve Johnson (Sven)17-Apr-06 15:13
MemberSteve Johnson (Sven)17-Apr-06 15:13 
QuestionHi. Nice article. But need some advice about an issue Pin
g_gili16-Feb-06 11:01
Memberg_gili16-Feb-06 11:01 
GeneralCrystal Report cannot run without install VS.NET Pin
taithien16-Sep-04 23:05
Membertaithien16-Sep-04 23:05 
Bill Gates Antimatter Particle5-Feb-04 6:00
MemberBill Gates Antimatter Particle5-Feb-04 6:00 
Stober31-Mar-04 10:10
MemberStober31-Mar-04 10:10 
Scheduling22-Jul-04 2:11
MemberScheduling22-Jul-04 2:11 
GeneralError when compling Sample Pin
blongtq25-Nov-02 15:43
Memberblongtq25-Nov-02 15:43 
GeneralRe: Error when compling Sample Pin
pizio10-Dec-02 13:38
Memberpizio10-Dec-02 13:38 
GeneralRe: Error when compling Sample Pin
jonslover7-Dec-03 20:43
Memberjonslover7-Dec-03 20:43 
GeneralCEasyReport problem Pin
25-Mar-02 6:22
suss25-Mar-02 6:22 
GeneralSample Bug Pin
Darryl Palmer20-Mar-02 17:19
MemberDarryl Palmer20-Mar-02 17:19 
GeneralView Independent of the Printer Pin
Oscar Raig25-Feb-02 2:27
MemberOscar Raig25-Feb-02 2:27 
GeneralNeed METRICS clarification Pin
Earl Allen20-Feb-02 7:29
MemberEarl Allen20-Feb-02 7:29 
GeneralImage in the report Pin
Hernan Breinbauer17-Feb-02 18:40
MemberHernan Breinbauer17-Feb-02 18:40 
GeneralEasy Reports with MDI Pin
Earl Allen21-Jan-02 18:27
MemberEarl Allen21-Jan-02 18:27 
GeneralRe: Easy Reports with MDI Pin
Hernan Breinbauer17-Feb-02 18:36
MemberHernan Breinbauer17-Feb-02 18:36 
GeneralRe: Easy Reports with MDI Pin
Earl Allen20-Feb-02 7:31
MemberEarl Allen20-Feb-02 7:31 
GeneralRe: Easy Reports with MDI Pin
Hernan Breinbauer20-Feb-02 10:33
MemberHernan Breinbauer20-Feb-02 10:33 
QuestionHow can Unkown MultineLine String done? Pin
11-Jan-02 4:10
suss11-Jan-02 4:10 
GeneralReport Graphs Pin
19-Dec-01 6:31
suss19-Dec-01 6:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.