User Tools

Site Tools




22.11.4 Report projects

This chapter presents 5 very different report projects:

  • The first three projects are (SQLite) database reports.
  • In the first project, the gb.report2 component is not used. The layout of the report and the database data (text) are drawn with the classes of the gb.cairo component.
  • The report designer in the IDE is used consistently for projects 2 to 4.
  • Projects 2 to 5 each consist of only one report section.
  • Report 4 only presents text from a text file, which is displayed in different chapters and paragraphs. Each chapter always starts on a new page. The Report Project 4 was developed and tested through intensive collaboration with Gianluigi G. (
  • All reports offer a preview, can be printed to a PDF file or immediately output to a printer.

Necessary considerations and preparatory work on how a printable report can be generated from a layout design have already been described in chapters 22.11.0 to 22.11.4.

For all report projects:

  • first the structure of the report is described (report designer in the IDE and source code),
  • then follows the provision of the data to be displayed from various sources (database data, text, images (also in the form of diagrams) and
  • Finally, a preview of the report is presented with the option to print the report immediately.

The complete source code for all 5 report projects is made available to you in a project archive - including the SQLite databases used.

For your own report projects, we recommend that you adapt the reports presented to your own requirements in terms of layout and design. For this reason, a detailed description has been omitted and reference is made to the corresponding source code of the 5 report projects. This note also applies to the report project in the following chapter 22.11.5. Report 1

The Report Designer is not used in the first report. Instead, the layout of the database report and the database data are drawn as text with the classes of the gb.cairo component on the CairoPdfSurface(argList) control element.


Figure Database report (gb.cairo)

The report is drawn in the following procedure:

Private Sub Export2PDF()
    Dim PDFSurface As CairoPdfSurface
    Dim sPfadPDFDatei, sMessage As String
    Dim iDataSet As Integer
'-- Initialization
    iCWidth = PDF_WIDTH - MARGIN_LEFT - MARGIN_RIGHT    '-- Content-Width (Millimeter)
    iCHeight = PDF_HEIGHT - MARGIN_TOP - MARGIN_BOTTOM  '-- Content-Height (Millimeter)
    iCurrentPage = 1        '-- Page number of the page (start)
    iCurrentTableRow = 1    '-- Number of table rows (start)
    fCurrentY = 0           '-- y-coordinate on the current page (start)
    sPfadPDFDatei = Application.Path &/ "kontakte.pdf"
'-- DIN A4 - portrait format
    PDFSurface = New CairoPdfSurface(sPfadPDFDatei, PDF_WIDTH, PDF_HEIGHT)
'-- Shift of the coordinate origin - >> Left = MARGIN_LEFT, Top = MARGIN_TOP
      Cairo.Matrix = Cairo.Matrix.Translate(MMToPoints(MARGIN_LEFT), MMToPoints(MARGIN_TOP))
      Cairo.Matrix = Cairo.Matrix.Scale(1, 1) '-- Zoom factor = 1
      Cairo.Font.Name = FONT_NAME
'-- Provision of the DB data to be displayed in a DB result
      If resDBData.Count = 0 Then
         sMessage = "<font color='red'><center>The DB selection set is empty.</font>"
         sMessage &= "<hr>"
         sMessage &= "A DB report cannot be generated!</center>"
'-- Set record pointer to the first record
      DrawTableRow() '-- Show first record
'-- DrawBorder() '-- Only for control purposes in testing
'-- Draw all records (text) of the selected set
      For iDataSet = 1 To resDBData.Max
        If iCurrentPage = 1 Then
           If iCurrentTableRow = iPage1RowMax Then
              iCurrentPage = 2
              iCurrentTableRow = 0
              fCurrentY = 0
           '--DrawBorder() '-- Only for control purposes in testing
           Inc iCurrentTableRow
           If iCurrentTableRow = iPage2RowMax Then
              Inc iCurrentPage
              iCurrentTableRow = 0
              fCurrentY = 0
          '-- DrawBorder() '-- Only for control purposes in testing
           Inc iCurrentTableRow
'-- Preview DB Report
End Report 2

On each page, database report 2 consists of a header line, a separator line, the static table header, the individual database rows, another separator line and a footer line with the current page and details of all pages:


Figure Report2 content 1st page Report 3

Database report 3 with a different layout to report 2, but with the same database, consists on each page of a header, a separator, the individual database rows after the initial, a further separator and a footer with the current page and details of all pages:


Figure Report3 content of the last page

The following source code excerpt shows the creation of the capital letters (initials) in the procedure Set-Initial(sFirstChar) and the individual field contents within a data record. Please also note the generation of the different background colours (alternating) and the special format of the date of birth:

    sLastChar = "@"
    If hDBResult.Available Then
       For i = 0 To hDBResult.Max
         sFirstChar = Left(hDBResult["nachname"])
         If Upper(sFirstChar) <> Upper(sLastChar) Then
            iMod = i Mod 2
            sLastChar = sFirstChar
         rhboxDBRow = New ReportHBox(rvboxContent)
         rhboxDBRow.Spacing = "3mm"
         rhboxDBRow.Height = "6mm"
         rhboxDBRow.Padding = ReportPadding["1mm"]
         If iMod = 0 Then
            If i Mod 2 = 0 Then rhboxDBRow.BackGround = ReportBrush["#E0E0E0"]
            If i Mod 2 <> 0 Then rhboxDBRow.BackGround = ReportBrush["#E0E0E0"]
     '-- SurName
         rlblDBField = New ReportLabel(rhboxDBRow)
         rlblDBField.Font = hDBFieldFont
         rlblDBField.Width = cMaxFieldLength[sTablename & "." & "vorname"]
         rlblDBField.Text = hDBResult["vorname"]
     '-- Name
         rlblDBField = New ReportLabel(rhboxDBRow)
         rlblDBField.Font = hDBFieldFont
         rlblDBField.Width = cMaxFieldLength[sTablename & "." & "nachname"]
         rlblDBField.Text = hDBResult["nachname"]
     '-- Birthday
         rlblDBField = New ReportLabel(rhboxDBRow)
         rlblDBField.Font = hDBFieldFont
         rlblDBField.Width = cMaxFieldLength[sTablename & "." & "gebdatum"]
         sDate = hDBResult["gebdatum"]
         rlblDBField.Text=Format(Date(Split(sDate,"-")[0],Split(sDate,"-")[1], Split(sDate,"-")[2]),"")
Private Sub SetInitial(sArg As String)
    Dim rlblInitial As ReportLabel
    Dim rlblPlaceholder As ReportLabel
    Dim rhboxInitial As ReportHBox
'-- Container: ReportHBox in container vbxReport
    rhboxInitial = New ReportHBox(rvboxContent)
    rhboxInitial.Spacing = "30mm"
    rhboxInitial.Margin.Top = "2mm"
    rhboxInitial.Height = "8mm"
'-- Control ReportLabel in container ReportHBox
    rlblInitial = New ReportLabel(rhboxInitial)
    rlblInitial.Font.Name = "Sans Serif"
    rlblInitial.Font.Size = 12
    rlblInitial.Font.Bold = True
    rlblInitial.BackGround = ReportBrush["#C3DDFF"]  '-- Background: light blue
'-- rlblInitial.BackGround = ReportBrush["LinearGradient(0,0,1,1,[#000000,#FFFFFF,#C3DDFF],[0,1,0.5])"]
    rlblInitial.Brush = ReportBrush.Color(&FF6347)     '-- Forground: 'tomato' Favorite
'-- rlblInitial.Brush = ReportBrush["Color(#FF6347)"]  '-- Forground: 'tomato'
'-- rlblInitial.Brush = ReportBrush["#FF6347"]         '-- Forground: 'tomato'
    rlblInitial.Height = "8mm" ' fix
    rlblInitial.Width = "8mm"  ' fix
    rlblInitial.Padding = ReportPadding["Top: 1px; Left:3px; Right:3px"]
    rlblInitial.Border = ReportBorder["Top:1px #7F7F7F;Bottom:1px #7F7F7F;Left:1px #7F7F7F;
    Right:1px #7F7F7F;TopLeftCorner:4mm;TopRightCorner:4mm;BottomRightCorner:4mm;BottomLeftCorner:4mm"]
    rlblInitial.Alignment = Align.Center
    rlblInitial.Text = Upper(sArg)
'-- ReportLabel in container ReportHBox as a required placeholder (right)
    rlblPlaceholder = New ReportLabel(rhboxInitial)
    rlblPlaceholder.Expand = True
End Report 4

In this special report 4, only text is displayed next to an image (with separator line). The (specially formatted) text is read from a text file. The special features of displaying text in a report have already been discussed in chapters and In this project, the theory described there is put into practice.


Figure Text report


  • If you set the properties of report containers and the other control elements they contain directly in the report designer, you will immediately see the effects in the IDE. If, on the other hand, you set some properties of the report and other project control elements in the source code, you will only see the effects at runtime. In project 4, the properties were only set in the source code.
  • Note the type of some report properties. For example, the height of a report label is of the (data) type String such as rtlblText.Height = ‘18px’.

The following source code snippet shows tried and tested procedures for the correct display of text in a report:

'' The following procedures are only required to display the plain text
Fast Private Function GetUsableWidth() As Integer
'   If we use only the report padding, it is correct to subtract only the
'   left and right padding of the book as here.
'   But if we also use margins and/or padding of other containers and/or
'   borders, these too must will be subtracted.
    Dim fReport, fLeft, fRight, fUsableWidth As Float
'-- Conversion of report width from `cm` (default) to `mm`
    Report1.Width = Report1.UnitTo(GetValue(Report1.Width), "cm", "mm") & "mm"
    fReport = GetValue(Report1.Width)
    fRight = GetValue(Report1.Padding.Right)
    fLeft = GetValue(Report1.Padding.Left)
    fUsableWidth = Round(GetValue(Report1.UnitTo(fReport - (fLeft + fRight), "mm", "px")), 0)
    Return fUsableWidth
    Error.Raise(("The value of measure can't be extracted"))
'' It is determined how many lines a text paragraph consists of.
'' The value depends on the text paragraph, the space for a line
'' in the text container 'ReportTextLabel' and the intended font.
Fast Private Function GetNumberOfRows(argParagraph As String, argLineWidth As Integer, argFont As Font) As Integer
    Dim i, k As Integer
    Dim aWords As String[]
    Dim sRow, sWord As String
'-- The text paragraph fits on one line
    If argFont.TextWidth(argParagraph) < argLineWidth Then Return 1
    aWords = Split(argParagraph, " ")
    For Each sWord In aWords
      If k = 0 Then
         sRow &= sWord
         Inc k
         sRow &= " " & sWord
      If argFont.TextWidth(sRow) > argLineWidth Then
         sRow = sWord
         Inc i
         k = 0
    Return i + 1
Fast Private Function GetValue(argValue As String) As Float
    Return CFloat(Left(argValue, Len(argValue) - 2))
    Error.Raise(("The numerical value of the value cannot be determined"))

Source code snippet for displaying the individual chapters and text sections in a chapter:

'-- Loading RawText
'-- Static text - cannot be changed afterwards
'-- sRawText = File.Load("./data/lorem.txt")
'-- Dynamic text that can be changed afterwards
    sRawText = File.Load(Application.Path & "/data/lorem.txt")
    aParagraphs = Split(sRawText, "\n")
    iUsableWidth = GetUsableWidth()
'-- Selected properties of rtlblText (Typ: ReportTextLabel)
'-- Inserting text with many paragraphs
    For Each sParagraph In aParagraphs
    '-- Each new *chapter* starts on a new page
    '-- Individual NewPage-Markup <NewPage> in sRawText
        If Left(sParagraph, 9) = "<NewPage>" Then
           rPageBreak = New ReportPageBreak(rvboxText)
           sParagraph = Replace(sParagraph, "<NewPage>", "")
        rtlblText = New ReportTextLabel(rvboxText)
        rtlblText.Font = Font["Noto Sans, 11"]
        rtlblText.Alignment = Align.Justify
        rtlblText.Text = sParagraph
        iHeight = rtlblText.Font.TextHeight(sParagraph)
        rtlblText.Height = CStr(GetNumberOfRows(sParagraph, iUsableWidth, rtlblText.Font) * iHeight) & "px"
    Next Report 5

Report 5 only uses the report component to display a line of text and an image. The image is a screenshot of the current window. The complete report source text is displayed:

' Gambas class file
Private $hReport As Report
Public Sub Form_Open()
    FMain.Resizable = False
Public Sub btnReportPreview_Click()
'-- Preview of the report and print dialogue
Private Sub GenerateReport()
    Dim hReportLabel As ReportLabel
    Dim hReportImage As ReportImage
    Dim hScreenshotImage As Image
    $hReport = New Report
    $hReport.Padding = ReportPadding["2cm"]
    $hReport.Spacing = "7mm"
'-- Printout: DIN A4 landscape format (default)
    $hReport.Paper = Printer.A4
    $hReport.Orientation = Printer.Landscape
    hReportLabel = New ReportLabel($hReport)
    hReportLabel.Font.Size = 24
    hReportLabel.Text = "Druck einer Bildschirm-Kopie (Screenshot)"
    hReportLabel.Autoresize = True
    hReportLabel.Alignment = Align.Center
    hReportLabel.Border = ReportBorder["Bottom:1px #606060;"]
'-- The programme window is hidden
      Wait 0.2
  '-- A screenshot of the complete, current desktop is created.
      hScreenshotImage = Desktop.Screenshot().Image
'-- The programme window is displayed again
'-- A new ReportImage is created for the (current) report.
    hReportImage = New ReportImage($hReport)
'-- The screenshot image is inserted into the report and configured
    hReportImage.Image = hScreenshotImage
    hReportImage.Autoresize = True
    hReportImage.Stretch = Report.Proportional
    hReportImage.Expand = True


Figure Report GUI


Figure Report5 with a text line and an image


The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k22/k22.11/k22.11.4/start.txt · Last modified: 17.05.2024 by emma

Page Tools