Comment simuler des sous-rapports avec libreoffice-report-builder ?
TDF LibreOffice Document Liberation Project Blogs communautaires Weblate Nextcloud Redmine Ask LibreOffice Donner
Description
Cet article traite du problème des sous-rapports dans LibreOffice.
Quand on fait ses rapports avec l'extension libreoffice-report-builder, la difficulté rencontrée avec cet outil puissant est qu'il ne gère pas les sous-rapports et les différentes solutions à ce problème proposées sur Internet ne sont pas satisfaisantes.
Le problème rencontré par beaucoup de personnes dans des logiciels de facturation par exemple est : comment afficher le montant total de chaque TVA, comme illustré ci-dessous.
Pour obtenir cela, on commence par construire notre rapport comme d'habitude avec l'extension libreoffice-report-builder.
Les champs dans l'en-tête idFacture et dans la section Détail proviennent d'une requête qui contient les données des clients, les lignes des données des factures et les montants totaux sont calculés en utilisant une fonction d'accumulation dans l'extension libreoffice-report-builder. Il y a un critère de regroupement par idFacture.
C'est tout pour notre rapport.
Ce rapport est ouvert en cliquant sur le bouton d'impression du formulaire suivant:
L'astuce consiste simplement à recopier le contenu du sous-formulaire qui contient le coût total par taxe (ce qui est facile à calculer avec une requête et encore plus facile à afficher dans un sous-formulaire) dans le pied de page de groupe idFacture en utilisant des champs d'étiquette.
Code
Voici les macros qui font ceci :
REM ***** BASIC *****
Option Explicit
REM Copyright (C) 2015 P. « James00cat » M. <darthcat at free point fr>
REM This program is free software: you can redistribute it and/or modify
REM it under the terms of the GNU General Public License as published by
REM the Free Software Foundation, either version 3 of the License, or
REM (at your option) any later version.
REM This program is distributed in the hope that it will be useful,
REM but WITHOUT ANY WARRANTY; without even the implied warranty of
REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
REM GNU General Public License for more details.
REM You should have received a copy of the GNU General Public License
REM along with this program. If not, see <http://www.gnu.org/licenses/>.
Sub btnPrint(oEv as object)
REM tableau de propriétés du rapport
dim aProp(2) as new com.sun.star.beans.PropertyValue
dim oReportsDocuments as object
dim oReportDesign as object
dim oResultSet as object
dim i as integer
dim j as integer
REM les positions sont indiquées dans le concepteur de rapports en cm, ici : *1000
REM les origines sont à partir des bords de section et de page
dim posY as integer
const ORIG_POS_Y_TAX_AMOUNT = 500 REM origine des positions des montants des taxes
const ORIG_FOOTER_HEIGHT = 2000
const TXT_CTL_HEIGHT = 500 REM hauteur des etiquettes et champs
const LEFT_MARGIN = 1000
const VAT_LBL_WIDTH = 4100
const VAT_LBL_PmacOS = 10600
const VAT_TOTAL_AMOUNT_LBL = 1800
const VAT_TOTAL_AMOUNT_PmacOS = 14900
if not oEv.source.model.parent.IsNew then
aProp(0).Name = "ActiveConnection"
aProp(0).Value = ThisComponent.DrawPage.Forms.GetByIndex(0).ActiveConnection
aProp(1).Name = "Hidden"
aProp(1).Value = true
aProp(2).Name = "OpenMode"
aProp(2).Value = "openDesign"
oReportsDocuments = ThisDatabaseDocument.ReportDocuments
oReportDesign = oReportsDocuments.loadComponentFromURL("Facture", "", 0, aProp())
with oReportDesign.groups.getbyindex(0).footer
REM effacement des données d'un ancien "sous-rapport" (étiquettes libelleTVAi et montantTotalTVAi)
REM en supprimant les objets par indices décroissants pour éviter le problème d'index hors limite.
for i = .count - 1 to 0 step -1
if instr(.getbyindex(i).name, "libelleTVA") or instr(.getbyindex(i).name, "montantTotalTVA") then
.remove(.getbyindex(i))
end if
next i
REM remise des _totaux_ à leur position d'origine
.getbyindex(0).positionY = ORIG_POS_Y_TAX_AMOUNT + 500
for i=1 to 3
.getbyindex(i).positionY = ORIG_POS_Y_TAX_AMOUNT + 1000
next i
REM remise à sa taille d'origine de la hauteur du pied de groupe
.height = ORIG_FOOTER_HEIGHT
REM sélection de la facture affichée dans le formulaire
oReportDesign.filter = "idFacture = " + oEv.source.model.parent.GetByName("txtIdFacture").value
REM récupération du jeu de résultats du sous-formulaire de taxes
oResultSet = oEv.source.model.parent.GetByName("SFTaxes").createResultSet()
if not isnull(oResultSet) then
oResultSet.beforefirst()
j = 0
posY = ORIG_POS_Y_TAX_AMOUNT
while oResultSet.next
REM augmentation de la hauteur du pied de page de groupe
.height = .height + TXT_CTL_HEIGHT
REM décalage des totaux vers le bas
for i=0 to 3
.getbyindex(i).positionY = .getbyindex(i).positionY + TXT_CTL_HEIGHT
next i
REM position = marge + positionX
addFixedText(oReportDesign, "libelleTVA" + j, VAT_LBL_WIDTH, 500, LEFT_MARGIN + VAT_LBL_PmacOS, posY, 0, 150, "Total " + oResultSet.getstring(4))
addFixedText(oReportDesign, "montantTotalTVA" + j, VAT_TOTAL_AMOUNT_LBL, 500, LEFT_MARGIN + VAT_TOTAL_AMOUNT_PmacOS, posY, 1, 150, _
format(oResultSet.getfloat(3), "0.#0 €"))
j = j + 1
posY = posY + TXT_CTL_HEIGHT
wend
endif
end with
aProp(1).Value = false REM propriete hidden
aProp(2).Value = "open" REM propriete OpenMode
oReportsDocuments.loadComponentFromURL("Facture", "", 23, aProp())
end if
End Sub
REM le type float est single en Basic!!!
sub addFixedText(oReport as object, sName as string, iWidth as integer, iHeight as integer, iPmacOS as integer, iPosY as integer, iParaAdjust as integer, fCharWeight as single, sLabel as string)
dim oFixedText as object
oFixedText = oReport.createinstance("com.sun.star.report.FixedText")
with oFixedText
.name = sName
.width = iWidth
.height = iHeight
.positionX = iPmacOS
.positionY = iPosy
.ParaAdjust = iParaAdjust
.CharWeight = fCharWeight
.Label = sLabel
end with
oReport.groups.getbyindex(0).footer.add(oFixedText)
end sub
Les techniques utilisées ici permettent de faire des rapports dynamiques avec libreoffice-report-builder car elles donnent accès aux composants du rapport et permettent d'en créer de nouveaux, de les supprimer et de les déplacer le cas échéant.