Comment simuler des sous-rapports avec libreoffice-report-builder ?

From The Document Foundation Wiki
< Macros‎ | Base
Jump to navigation Jump to search

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.

Capture rapport resultat.png

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.

Capture rapport edition.png

Ce rapport est ouvert en cliquant sur le bouton d'impression du formulaire suivant:

Capture formulaire facture.png

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.