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

    From The Document Foundation Wiki
    < Macros‎ | Base


    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.