Creare report con il componente gb.report2

Da Gambas-it.org - Wikipedia.

Introduzione

gb.report2 di Fabien Bodard è un utilissimo componente che ci permette con pochi passaggi di avere un'anteprima di stampa e di stampare su file o carta ogni sorta di documento da noi creato con Gambas. Come si intuisce dal nome il componente è stato studiato per creare dei report dalle interrogazioni delle tabelle dei database, ma come vedremo può essere usato per quasi tutti i programmi che necessitano della stampa. Per poter comprendere a fondo come creare un buon report occorre aver ben presente come si creano le finestre dei programmi con Gambas con l'aiuto imprescindibile dei contenitori (Container) che qui hanno il prefisso Report.

Di seguito creeremo due tipi di report uno che mostra il risultato di un interrogazione, l'altro invece la stampa di un documento di testo in stile libro. Questi esempi, pur essendo abbastanza completi, non possono mostrare tutte le potenzialità del componente, vi invito pertanto a dare un'occhiata al codice sorgente del componente e ai test scritti dallo stesso Bodard dove possiamo ottenere nuovi spunti.

Nota: Nella Software farm sono presenti i progetti completi dei report qui descritti.

Progetto ReportTest

Avviamo Gambas e creiamo un progetto grafico nominandolo ReportTest (questo è il nome nella farm) o in qualunque altro modo vi aggrada. In Progetto > Proprietà > Componenti mettiamo la spunta a gb.db e a gb.report2 che si porterà dietro anche il componente gb.eval. Ora nel browser di sinistra dell'editor della IDE, se clicchiamo con il tasto desto del mouse sopra Sorgenti appare in aggiunta ai soliti, il nuovo menu Report... clicchiamoci sopra e diamo l'ok così da aggiungere il Report1 al progetto. Ripetiamo l'operazione del clic sul tasto destro per aggiungere anche un Modulo che rinomineremo MBase. Prima di creare il report andiamo ad aggiungere un pulsante alla finestra FMain e riportiamo questo codice in FMain.class:

Property Read sPathDB As String
Private $sPathDB As String

Public Sub Form_Open()

 $sPathDB = User.Home &/ Application.Name
 If Not Exist($sPathDB) Then Mkdir $sPathDB
 If MBase.CheckDB() Then
   Print ("#Unable to create database")
   Me.Close
 Endif

End

Private Function sPathDB_Read() As String

 Return $sPathDB

End

Public Sub Button1_Click()

 Report1.Preview

End

Diamo uno sguardo a quanto abbiamo appena fatto:
Per prima cosa abbiamo creato una proprietà di sola lettura per fare in modo che il suo contenuto (la path) possa essere letto dagli altri moduli e/o classi, nel caso specifico rendere visibile la path al modulo del database. All'apertura della finestra e quindi del progetto stesso, viene creata una directory nella home dell'utente e attraverso un metodo del modulo del database (lo vedremo fra poco) il database stesso. Se il metodo ritorna true vuol dire che è sopraggiunto un errore e il database non si è formato, l'utente in questo caso verrà informato attraverso un messaggio in console. Come vedete la scritta è in inglese e avvolta da parentesi, queste ultime servono per poter tradurre le scritte e creare un progetto internazionale. Per renderlo tale, al momento della creazione del progetto basta spuntare la casella Il progetto è traducibile, se non lo abbiamo fatto basta andare al menu Progetto > Proprietà > Opzioni e swithcciare su Il progetto è traducibile, nella IDE appare il nuovo pulsante Traduci e se ci clicchiamo sopra possiamo tradurre la scritta che in caso di errore apparirà in italiano.
Nell'evento Button1_Click() c'è il codice che avvia il report.
Ora a seguire il codice del modulo del database MBase:

Private $nRecords As Integer
Private $hConn As New Connection
Private $sNameDB As String = "TestReport.db"
Private $sPathDB As String

Public Sub CheckDB() As Boolean

  $sPathDB = FMain.sPathDB
  If Not Exist($sPathDB) Then Return
  With $hConn
    .Close()
    .Type = "sqlite3"
    .Host = $sPathDB
    .Open()
    If Not $hConn.Databases.Exist($sNameDB) Then
      $nRecords = 100 'FRecords.ReturnRecords()
      'If $nRecords = 0 Then Return True
      .Databases.Add($sNameDB)
      .Close()
      .Name = $sNameDB
      .Open()
      MakeTable()
      FillRecords
      Print ("#Database successfully created!")
    Else
      Print ("#Existing database")
    Endif
    .Close()
  End With
Catch
  Message.Error(("Fatal error in ") & Error.Where & ("\nError number: ") & Error.Code & ("\nCause: ") & Error.Text, "OK")
  Return True

End

Private Sub OpenDB()

  With $hConn
    .Close()
    .Type = "sqlite3"
    .Host = $sPathDB
    .Name = $sNameDB
    .Open()
  End With

Catch
  Print Error.Text, Error.Code

End

Public Sub CloseDB()

  $hConn.Close

End

Public Function ExistConnection() As Boolean

  Return $hConn.Opened

End


Private Sub MakeTable()

  Dim sMySql As String

  $hConn.Begin()

  sMySql = "CREATE TABLE 'tuser' ("
  sMySql &= " 'uskey' INTEGER PRIMARY KEY,"
  sMySql &= " 'usnam' TEXT,"
  sMySql &= " 'ussur' TEXT,"
  sMySql &= " 'usdat' TEXT NOT NULL"
  sMySql &= " );"

  $hConn.EXEC(sMySql)

  $hConn.Commit()
Catch
  Print Error.Text, Error.Code

End

Private Sub FillUser(iKey As Integer, sName As String, sSurname As String, sDate As String)

  Dim sMySql As String

  sName = Replace(sName, "'", "")
  sSurname = Replace(sSurname, "'", "")

  sMySql = "INSERT INTO tuser ("
  sMySql &= " uskey,"
  sMySql &= " usnam,"
  sMySql &= " ussur,"
  sMySql &= " usdat"
  sMySql &= " )"
  sMySql &= " VALUES ("
  sMySql &= " " & iKey & ","
  sMySql &= " '" & sName & "',"
  sMySql &= " '" & sSurname & "',"
  sMySql &= " '" & sDate & "'"
  sMySql &= " );"
  $hConn.EXEC(sMySql)

Catch
  Print Error.Text, Error.Code

End

Private Sub FillRecords()

  Dim nCasual, i, nPar, nCon As Integer
  Dim sName, sSurname, sDate As String

  Randomize
  nPar = $nRecords Div 100
  nCon = nPar
  Wait
  OpenDB()
  $hConn.Begin()
  For i = 0 To $nRecords
    nCasual = Rand(1, 31)
    sName = firstName(nCasual)
    nCasual = Rand(1, 31)
    sSurname = lastName(nCasual)
    nCasual = Rand(2009, 2018)
    sDate = CStr(nCasual) & "-"
    nCasual = Rand(1, 12)
    sDate &= Format(nCasual, "0#") & "-"
    nCasual = Rand(1, 28)
    sDate &= Format(nCasual, "0#")
    FillUser(i + 1, sName, sSurname, sDate)
  Next
  $hConn.Commit()
  CloseDB()
Catch
  Print Error.Text, Error.Code

End

Private Function firstName(value As Integer) As String

  Select Case value
    Case 1
      Return "Binah"
    Case 2
      Return "Hanna"
    Case 3
      Return "Selassie"
    Case 4
      Return "Okpara"
    Case 5
      Return "Agustina"
    Case 6
      Return "Clema"
    Case 7
      Return "Coyan"
    Case 8
      Return "Eusebio"
    Case 9
      Return "Diego"
    Case 10
      Return "Alisha"
    Case 11
      Return "Daphne"
    Case 12
      Return "Wiley"
    Case 13
      Return "Valentine"
    Case 14
      Return "Lidwina"
    Case 15
      Return "Roxana"
    Case 16
      Return "Edmund"
    Case 17
      Return "Hildeger"
    Case 18
      Return "Adrianne"
    Case 19
      Return "Janette"
    Case 20
      Return "Quentin"
    Case 21
      Return "Sylvain"
    Case 22
      Return "Francesco"
    Case 23
      Return "Marco"
    Case 24
      Return "Aldina"
    Case 25
      Return "Ornella"
    Case 26
      Return "Carmencita"
    Case 27
      Return "Galena"
    Case 28
      Return "Florentino"
    Case 29
      Return "Rodrigo"
    Case 30
      Return "Benoit"
    Case Else
      Return "Mario"
  End Select

End

Private Function lastName(value As Integer) As String

  Select Case value
    Case 1
      Return "Smith"
    Case 2
      Return "Johnson"
    Case 3
      Return "Williams"
    Case 4
      Return "Brown"
    Case 5
      Return "Martin"
    Case 6
      Return "Bernard"
    Case 7
      Return "Dubois"
    Case 8
      Return "Thomas"
    Case 9
      Return "Robert"
    Case 10
      Return "Richard"
    Case 11
      Return "Müller"
    Case 12
      Return "Schmidt"
    Case 13
      Return "Schneider"
    Case 14
      Return "Fischer"
    Case 15
      Return "Weber"
    Case 16
      Return "Meyer"
    Case 17
      Return "Gunnarsson"
    Case 18
      Return "García"
    Case 19
      Return "González"
    Case 20
      Return "Rodríguez"
    Case 21
      Return "Fernández"
    Case 22
      Return "López"
    Case 23
      Return "Martínez"
    Case 24
      Return "Jensen"
    Case 25
      Return "Nielsen"
    Case 26
      Return "Cohen"
    Case 27
      Return "Friedman"
    Case 28
      Return "Rossi"
    Case 29
      Return "Bianchi"
    Case 30
      Return "Minisini"
    Case Else
      Return "Verdone"
  End Select

End

Public Function ReturnData() As Result

  Dim sMySql As String
  Dim hResult As Result

  If KeyCount() > 1 Then
    sMySql = "SELECT *"
    sMySql &= " FROM tuser"
    sMySql &= ";"
    OpenDB()
    hResult = $hConn.Exec(sMySql)
    If hResult.Available Then
      Return hResult
    Endif
  Endif
 Catch
  CloseDB()
  Print Error.Text, Error.Code

End

Public Function KeyCount() As Integer

  Dim sMySql As String
  Dim hResult As Result
  Dim i As Integer

  sMySql = "SELECT MAX( uskey )"
  sMySql &= " FROM tuser"
  sMySql &= ";"

  OpenDB()
  hResult = $hConn.Exec(sMySql)
  If hResult.Available Then
    If Not IsNull(hResult["0"]) Then
      i = CInt(hResult["0"]) + 1
    Else
      i = 1
    Endif
  Else
    i = -1
  Endif
  CloseDB()
  Return i
Catch
  CloseDB()
  Print Error.Text, Error.Code
  Return -1

End