예제 #1
0
class CTRL(HTL.HyperTreeList):
    def __init__(self, parent): 
        HTL.HyperTreeList.__init__(self, parent, -1)
        self.parent = parent
        self.dictImpression = {}
        
        # Paramètres
        self.mode_affichage = "mois" # "mois", "annee"
        self.affichage_details = True
        self.type = "depots"
        self.date_debut = None
        self.date_fin = None
        self.listeActivites = []
        self.listeDepots = []
        
##        # Création de l'ImageList
##        il = wx.ImageList(16, 16)
##        self.img_ok = il.Add(wx.Bitmap(Chemins.GetStaticPath('Images/16x16/Ok.png'), wx.BITMAP_TYPE_PNG))
##        self.img_pasok = il.Add(wx.Bitmap(Chemins.GetStaticPath('Images/16x16/Interdit.png'), wx.BITMAP_TYPE_PNG))
##        self.AssignImageList(il)
        
        # wx.TR_COLUMN_LINES |  | wx.TR_HAS_BUTTONS
        self.SetBackgroundColour(wx.WHITE)
        if 'phoenix' in wx.PlatformInfo:
            TR_COLUMN_LINES = HTL.TR_COLUMN_LINES
        else :
            TR_COLUMN_LINES = wx.TR_COLUMN_LINES
        self.SetAGWWindowStyleFlag(wx.TR_HIDE_ROOT  | wx.TR_ROW_LINES | TR_COLUMN_LINES | wx.TR_HAS_BUTTONS | wx.TR_HAS_VARIABLE_ROW_HEIGHT | wx.TR_FULL_ROW_HIGHLIGHT ) # HTL.TR_NO_HEADER
    
    def SetModeAffichage(self, mode="depots"):
        self.mode_affichage = mode
    
    def SetAffichageDetails(self, etat=True):
        self.affichage_details = etat
        
    def SetTypeDepots(self, listeDepots=[]):
        self.type = "depots"
        self.listeDepots = listeDepots
        
    def SetTypePrestations(self, date_debut=None, date_fin=None, listeActivites=[]):
        self.type = "prestations"
        self.date_debut = date_debut
        self.date_fin = date_fin
        self.listeActivites = listeActivites

    def SetTypeVide(self):
        self.type = "vide"

    def Importation_depots(self):
        """ Importation des données """
        DB = GestionDB.DB()
        
        if len(self.listeDepots) == 0 : conditionDepots = "()"
        elif len(self.listeDepots) == 1 : conditionDepots = "(%d)" % self.listeDepots[0]
        else : conditionDepots = str(tuple(self.listeDepots))
        
        req = """SELECT depots.IDdepot, depots.date, nom, verrouillage, depots.IDcompte,
        SUM(reglements.montant)
        FROM depots
        LEFT JOIN reglements ON reglements.IDdepot = depots.IDdepot
        WHERE depots.IDdepot IN %s
        GROUP BY depots.IDdepot
        ORDER BY depots.date
        ;""" % conditionDepots
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        dictDepots = {}
        for IDdepot, date, nom, verrouillage, IDcompte, montantTotal in listeDonnees :
            date = UTILS_Dates.DateEngEnDateDD(date)
            if montantTotal == None : montantTotal = 0.0
            dictDepots[IDdepot] = {"date":date, "nom":nom, "verrouillage":verrouillage, "IDcompte":IDcompte, "montantTotal":montantTotal}
        
        DB.Close() 
        return dictDepots

    def Importation_ventilation(self):
        """ Importation des données """
        DB = GestionDB.DB()
        
        if self.type == "depots" :
            # Type Dépôts
            if len(self.listeDepots) == 0 : condition = "depots.IDdepot IN ()"
            elif len(self.listeDepots) == 1 : condition = "depots.IDdepot IN (%d)" % self.listeDepots[0]
            else : condition = "depots.IDdepot IN %s" % str(tuple(self.listeDepots))
        else:
            # Type Prestations
            if len(self.listeActivites) == 0 : conditionActivites = ""
            elif len(self.listeActivites) == 1 : conditionActivites = "AND prestations.IDactivite=%d" % self.listeActivites[0]
            else : conditionActivites = "AND prestations.IDactivite IN %s" % str(tuple(self.listeActivites))
            condition = "prestations.date>='%s' AND prestations.date<='%s' %s" % (self.date_debut, self.date_fin, conditionActivites)
                            
        # Récupèration de la ventilation des prestations des dépôts
        req = """SELECT 
        ventilation.IDventilation, ventilation.IDreglement, ventilation.IDprestation, ventilation.montant,
        reglements.date, reglements.date_saisie, depots.IDdepot, depots.date,
        prestations.date, prestations.label, prestations.IDactivite, activites.nom, activites.abrege
        FROM ventilation
        LEFT JOIN reglements ON reglements.IDreglement = ventilation.IDreglement
        LEFT JOIN prestations ON prestations.IDprestation = ventilation.IDprestation
        LEFT JOIN depots ON depots.IDdepot = reglements.IDdepot
        LEFT JOIN activites ON activites.IDactivite = prestations.IDactivite
        WHERE %s
        ORDER BY prestations.date; """ % condition
        DB.ExecuterReq(req)
        listeVentilation = DB.ResultatReq()
        dictVentilation = {}
        listePeriodes = []
        dictIDreglements = {}
        for IDventilation, IDreglement, IDprestation, montantVentilation, dateReglement, dateSaisieReglement, IDdepot, dateDepotReglement, datePrestation, labelPrestation, IDactivite, nomActivite, abregeActivite in listeVentilation :
            dateReglement = UTILS_Dates.DateEngEnDateDD(dateReglement)
            dateSaisieReglement = UTILS_Dates.DateEngEnDateDD(dateSaisieReglement)
            dateDepotReglement = UTILS_Dates.DateEngEnDateDD(dateDepotReglement)
            datePrestation = UTILS_Dates.DateEngEnDateDD(datePrestation)
            
            # Compte le nombre de règlements dans chaque dépôt
            if dictIDreglements.has_key(IDdepot) == False :
                dictIDreglements[IDdepot] = []
            if IDreglement not in dictIDreglements[IDdepot] :
                dictIDreglements[IDdepot].append(IDreglement)
            
            # Rajoute le nom de l'activité dans le label de la prestation
            if nomActivite != None :
                labelPrestation = u"%s - %s" % (nomActivite, labelPrestation)
            
            # Retient la période de ventilation
            if datePrestation != None :
                annee = datePrestation.year
                mois = datePrestation.month
                if self.mode_affichage == "mois" :
                    periode = (annee, mois)
                else:
                    periode = annee
                
                if periode not in listePeriodes :
                    listePeriodes.append(periode)
                    
                if dictVentilation.has_key(IDdepot) == False :
                    dictVentilation[IDdepot] = {}
                if dictVentilation[IDdepot].has_key(periode) == False :
                    dictVentilation[IDdepot][periode] = {}
                if dictVentilation[IDdepot][periode].has_key(labelPrestation) == False :
                    dictVentilation[IDdepot][periode][labelPrestation] = 0.0
                dictVentilation[IDdepot][periode][labelPrestation] += montantVentilation
        
        DB.Close() 
        listePeriodes.sort()
        
        return dictVentilation, listePeriodes, dictIDreglements
    
    def CreationColonnes(self, listePeriodes=[]):
        """ Création des colonnes """
        # Création de la première colonne
        self.AddColumn(_(u"Dépôts"))
        self.SetColumnWidth(0, 270)
        self.SetColumnAlignment(0, wx.ALIGN_LEFT)
        
        # Création des colonnes périodes
        numColonne = 1
        if self.mode_affichage == "mois" :
            # Mode affichage MOIS
            for annee, mois in listePeriodes :
                self.AddColumn(PeriodeComplete(mois, annee))
                self.SetColumnWidth(numColonne, 65)
                self.SetColumnAlignment(numColonne, wx.ALIGN_CENTRE)
                numColonne += 1
        else:
            # Mode affichage ANNEE
            for annee in listePeriodes :
                self.AddColumn(str(annee))
                self.SetColumnWidth(numColonne, 65)
                self.SetColumnAlignment(numColonne, wx.ALIGN_CENTRE)
                numColonne += 1

        # Création de la colonne Non Ventilé
        if self.type == "depots" :
            self.AddColumn(_(u"Non ventilé"))
            self.SetColumnWidth(numColonne, 65)
            self.SetColumnAlignment(numColonne, wx.ALIGN_CENTRE)
            numColonne += 1

        # Création de la colonne Total
        self.AddColumn(_(u"Total"))
        self.SetColumnWidth(numColonne, 75)
        self.SetColumnAlignment(numColonne, wx.ALIGN_CENTRE)
        
    def MAJ(self):        
        """ Remplissage du ctrl """
        if self.type == "vide" :
            self.RAZ()
            return

        # Importation des données
        dictVentilation, listePeriodes, dictIDreglements = self.Importation_ventilation() 
        if self.type == "prestations" :
            self.listeDepots = dictVentilation.keys()
            if None in self.listeDepots : self.listeDepots.remove(None)
        dictDepots = self.Importation_depots()
        
        # Si on est en type PRESTATIONS, on crée un dépôt virtuel pour les règlements non déposées
        if self.type == "prestations" and dictVentilation.has_key(None) :
            dictDepots[None] = {"date":datetime.date(1977, 1, 1), "nom":_(u"----- %d règlements non déposés -----") % len(dictIDreglements[None]), "verrouillage":False, "IDcompte":None, "montantTotal":0.0}
        
        self.dictImpression = { "entete" : [], "contenu" : [], "total" : [], "coloration" : [] }
        
        # Mémorisation des colonnes
        dictColonnes = {}
        index = 1
        self.dictImpression["entete"].append(_(u"Dépôts"))
        for periode in listePeriodes :
            dictColonnes[periode] = index
            if self.mode_affichage == "mois" :
                label = PeriodeComplete(periode[1], periode[0])
            else:
                label = str(periode)
            self.dictImpression["entete"].append(label)
            index += 1
        if self.type == "depots" :
            dictColonnes["sansVentilation"] = index
            self.dictImpression["entete"].append(_(u"Non ventilé"))
            index += 1
        dictColonnes["total"] = index
        self.dictImpression["entete"].append(_(u"Total"))
        
        # Initialisation du CTRL
        self.RAZ() 
        self.CreationColonnes(listePeriodes) 
        self.root = self.AddRoot(_(u"Racine"))
    
        # Création des branches
        
        # ------------------ Branches DEPOTS -----------------
        
        # Tri des dépôts par date de dépôt
        listeDepotsTemp = []
        for IDdepot, dictDepot in dictDepots.iteritems() :
            if dictDepot["date"] == None :
                dateDepot = datetime.date(1977, 1, 1)
            else:
                dateDepot = dictDepot["date"] 
            listeDepotsTemp.append( (dateDepot, IDdepot, dictDepot) )
        listeDepotsTemp.sort()
        
        dictLigneTotal = {}
        totalSansVentilation = 0.0
        
        for dateDepot, IDdepot, dictDepot in listeDepotsTemp :
            if dateDepot == datetime.date(1977, 1, 1) : 
                dateStr = _(u"Sans date de dépôt")
            else:
                dateStr = u"%02d/%02d/%04d" % (dateDepot.day, dateDepot.month, dateDepot.year)
            label = u"%s (%s - %.2f %s)" % (dictDepot["nom"], dateStr, dictDepot["montantTotal"], SYMBOLE)
            if IDdepot == None : label = dictDepot["nom"]
            niveauDepot = self.AppendItem(self.root, label)
                        
            impressionLigne = [label,] 
            if self.affichage_details == True :
                self.dictImpression["coloration"].append(len(self.dictImpression["contenu"]))
                        
            # Colonnes périodes
            totalLigne = 0.0
            for periode in listePeriodes :
                if dictVentilation.has_key(IDdepot) and dictVentilation[IDdepot].has_key(periode) :
                    valeur = 0.0
                    for labelPrestation, montantVentilation in dictVentilation[IDdepot][periode].iteritems() : 
                        valeur += montantVentilation
                    totalLigne += valeur
                    texte = u"%.2f %s" % (valeur, SYMBOLE)
                    self.SetItemText(niveauDepot, texte, dictColonnes[periode])
                    impressionLigne.append(texte)
                else:
                    impressionLigne.append("")
                           
            # Colonne NON VENTILE
            if self.type == "depots" :
                totalDepot = dictDepots[IDdepot]["montantTotal"]
                sansVentilation = totalDepot - totalLigne
                if sansVentilation != 0.0 :
                    totalLigne += sansVentilation
                    totalSansVentilation += sansVentilation
                    texte = u"%.2f %s" % (sansVentilation, SYMBOLE)
                    self.SetItemText(niveauDepot, texte, dictColonnes["sansVentilation"])
                    impressionLigne.append(texte)
                else:
                    impressionLigne.append(u"")

            # Colonne Total
            texte = u"%.2f %s" % (totalLigne, SYMBOLE)
            self.SetItemText(niveauDepot, texte, dictColonnes["total"])
            impressionLigne.append(texte)
            
            self.dictImpression["contenu"].append(impressionLigne)
            
            # ----------------- Branches LABELS DE PRESTATIONS -------------
                
            listeLabelsPrestations = []
            for periode in listePeriodes :
                if dictVentilation.has_key(IDdepot) :
                    if dictVentilation[IDdepot].has_key(periode) :
                        for labelPrestation, montantVentilation in dictVentilation[IDdepot][periode].iteritems() : 
                            if labelPrestation not in listeLabelsPrestations :
                                listeLabelsPrestations.append(labelPrestation)
            listeLabelsPrestations.sort()

            for labelPrestation in listeLabelsPrestations :
                if self.affichage_details == True :
                    niveauPrestation = self.AppendItem(niveauDepot, labelPrestation)
                    self.SetItemFont(niveauPrestation, wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL))
                    self.SetItemTextColour(niveauPrestation, wx.Colour(160, 160, 160) )
                    impressionLigne = [labelPrestation,] 
                
                # Colonnes périodes
                totalLigne = 0.0
                for periode in listePeriodes :
                    texte = None
                    if dictVentilation.has_key(IDdepot) :
                        if dictVentilation[IDdepot].has_key(periode) :
                            if dictVentilation[IDdepot][periode].has_key(labelPrestation) :
                                valeur = dictVentilation[IDdepot][periode][labelPrestation]
                                totalLigne += valeur
                                if dictLigneTotal.has_key(labelPrestation) == False :
                                    dictLigneTotal[labelPrestation] = {}
                                if dictLigneTotal[labelPrestation].has_key(periode) == False :
                                    dictLigneTotal[labelPrestation][periode] = 0.0
                                dictLigneTotal[labelPrestation][periode] += valeur
                                if self.affichage_details == True :
                                    texte = u"%.2f %s" % (valeur, SYMBOLE)
                                    self.SetItemText(niveauPrestation, texte, dictColonnes[periode])
                                    impressionLigne.append(texte)
                    if texte == None and self.affichage_details == True : impressionLigne.append("")
                
                # Colonne Non ventilé
                if self.type == "depots" and self.affichage_details == True :
                    impressionLigne.append(u"")
                
                # Colonne Total
                if self.affichage_details == True :
                    texte = u"%.2f %s" % (totalLigne, SYMBOLE)
                    self.SetItemText(niveauPrestation, texte, dictColonnes["total"])
                    impressionLigne.append(texte)
                
                    self.dictImpression["contenu"].append(impressionLigne)
        
        # ------------ Ligne Total --------------
        niveauTotal = self.AppendItem(self.root, _(u"Total"))
        self.SetItemBackgroundColour(niveauTotal, wx.Colour(150, 150, 150) )
        self.SetItemTextColour(niveauTotal, wx.Colour(255, 255, 255) )
        
        impressionLigne = [_(u"Total"),]
        
        listeLabels = dictLigneTotal.keys()
        listeLabels.sort()
        
        # Ligne de TOTAL pour chaque PERIODE
        totalLigne = 0.0
        for periode in listePeriodes :
            totalColonne = 0.0
            for dateDepot, IDdepot, dictDepot in listeDepotsTemp :
                for label in listeLabels :
                    if dictVentilation.has_key(IDdepot) :
                        if dictVentilation[IDdepot].has_key(periode):
                            if dictVentilation[IDdepot][periode].has_key(label):
                                valeur = dictVentilation[IDdepot][periode][label]
                                totalColonne += valeur
            texte = u"%.2f %s" % (totalColonne, SYMBOLE)
            totalLigne += totalColonne
            self.SetItemText(niveauTotal, texte, dictColonnes[periode])
            impressionLigne.append(texte)
        
        # Total SANS VENTILATION
        if self.type == "depots" :
            texte = u"%.2f %s" % (totalSansVentilation, SYMBOLE)
            totalLigne += totalSansVentilation
            self.SetItemText(niveauTotal, texte, dictColonnes["sansVentilation"])
            impressionLigne.append(texte)
        
        # Total de la ligne de Total
        texte = u"%.2f %s" % (totalLigne, SYMBOLE)
        self.SetItemText(niveauTotal, texte, dictColonnes["total"])
        impressionLigne.append(texte)
        
        self.dictImpression["total"].append(impressionLigne)
        
        # Total des colonnes par label de prestation
        if self.affichage_details == True :
        
            for label in listeLabels :
                niveauPrestation = self.AppendItem(niveauTotal, label)
                self.SetItemFont(niveauPrestation, wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL))
                self.SetItemTextColour(niveauPrestation, wx.Colour(120, 120, 120) )
                self.SetItemBackgroundColour(niveauPrestation, wx.Colour(210, 210, 210) )
                
                impressionLigne = [label,]
                
                totalLigne = 0.0
                for periode in listePeriodes :
                    texte = None
                    if dictLigneTotal.has_key(label):
                        if dictLigneTotal[label].has_key(periode) :
                            valeur = dictLigneTotal[label][periode]
                            totalLigne += valeur
                            texte = u"%.2f %s" % (valeur, SYMBOLE)
                            self.SetItemText(niveauPrestation, texte, dictColonnes[periode])
                            impressionLigne.append(texte)
                    if texte == None : impressionLigne.append(u"")
                
                # Colonne None ventilé
                if self.type == "depots" :
                    impressionLigne.append(u"")
                
                # Colonne Total
                texte = u"%.2f %s" % (totalLigne, SYMBOLE)
                self.SetItemText(niveauPrestation, texte, dictColonnes["total"])
                impressionLigne.append(texte)
                
                self.dictImpression["total"].append(impressionLigne)
        
        self.ExpandAllChildren(self.root)   
        
    def RAZ(self):
        self.DeleteAllItems()
        for indexColonne in range(self.GetColumnCount()-1, -1, -1) :
            self.RemoveColumn(indexColonne)
        self.DeleteRoot() 
    
    def DevelopperTout(self):
        item = self.GetFirstChild(self.root)[0]
        for index in range(0, self.GetChildrenCount(self.root)-1) :
            self.Expand(item)
            item = self.GetNext(item)
        
    def ReduireTout(self):
        item = self.GetFirstChild(self.root)[0]
        for index in range(0, self.GetChildrenCount(self.root)-1) :
            self.Collapse(item)
            item = self.GetNext(item)
        
    def Imprimer(self):
        dlg = DLG_Options_impression_pdf.Dialog(self, categorie="synthese_ventilation", ctrl=CTRL_Parametres)
        if dlg.ShowModal() == wx.ID_OK:
            dictOptions = dlg.GetOptions()
            dlg.Destroy()
        else :
            dlg.Destroy()
            return

        # Création du PDF
        from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
        from reportlab.lib.pagesizes import A4
        from reportlab.lib import colors
        from reportlab.lib.styles import ParagraphStyle
        
        hauteur_page = A4[0]
        largeur_page = A4[1]
            
        # Initialisation du PDF
        nomDoc = FonctionsPerso.GenerationNomDoc("STATS_VENTILATION", "pdf")
        if sys.platform.startswith("win") : nomDoc = nomDoc.replace("/", "\\")
        doc = SimpleDocTemplate(nomDoc, pagesize=(largeur_page, hauteur_page), topMargin=30, bottomMargin=30)
        story = []
        
        # Création du titre du document
        def Header():
            dataTableau = []
            largeursColonnes = ( (largeur_page-175, 100) )
            dateDuJour = UTILS_Dates.DateEngFr(str(datetime.date.today()))
            dataTableau.append( (_(u"Analyse croisée ventilation/dépôts"), _(u"%s\nEdité le %s") % (UTILS_Organisateur.GetNom(), dateDuJour)) )
            style = TableStyle([
                    ('BOX', (0,0), (-1,-1), 0.25, colors.black), 
                    ('VALIGN', (0,0), (-1,-1), 'TOP'), 
                    ('ALIGN', (0,0), (0,0), 'LEFT'), 
                    ('FONT',(0,0),(0,0), "Helvetica-Bold", 16), 
                    ('ALIGN', (1,0), (1,0), 'RIGHT'), 
                    ('FONT',(1,0),(1,0), "Helvetica", 6), 
                    ])
            tableau = Table(dataTableau, largeursColonnes)
            tableau.setStyle(style)
            story.append(tableau)
            story.append(Spacer(0,20))       
        
        # Insère un header
        Header() 
        
        # Tableau
        dataTableau = []
        largeursColonnes = [dictOptions["largeur_colonne_labels"],]
        for x in range(0, len(self.dictImpression["entete"])-1):
            largeursColonnes.append(dictOptions["largeur_colonne_valeurs"])
        
        # Entetes labels
        dataTableau.append(self.dictImpression["entete"])

        paraNormal = ParagraphStyle(name="normal", fontName="Helvetica", fontSize=dictOptions["taille_texte"], spaceAfter=0, leading=dictOptions["taille_texte"]+1, spaceBefore=0)
        paraTitre = ParagraphStyle(name="titre", fontName="Helvetica-Bold", fontSize=dictOptions["taille_texte"], spaceAfter=0, leading=dictOptions["taille_texte"]+1, spaceBefore=0)

        # Contenu du tableau
        listeRubriques = ("contenu", "total")
        for rubrique in listeRubriques :
            listeLignes = self.dictImpression[rubrique]

            indexLigne = 0
            for ligne in listeLignes :
                ligneTemp = []
                indexColonne = 0
                for texte in ligne :

                    # Aligne à droite les montants
                    if indexColonne > 0 :
                        texte = _(u"<para align='right'>%s</para>") % texte

                    case = Paragraph(texte, paraNormal)

                    # Ligne de titre
                    if rubrique == "contenu" and indexLigne in self.dictImpression["coloration"] :
                        case = Paragraph(texte, paraTitre)

                    ligneTemp.append(case)
                    indexColonne += 1

                dataTableau.append(ligneTemp)
                indexLigne += 1
        
        positionLigneTotal = len(self.dictImpression["contenu"]) + 1
        listeStyles = [
            ('VALIGN', (0,0), (-1,-1), 'MIDDLE'), # Centre verticalement toutes les cases
            ('FONT',(0,0),(-1,-1), "Helvetica", dictOptions["taille_texte"]), # Donne la police de caract. + taille de police
            ('GRID', (0,0), (-1,-1), 0.25, colors.black), # Crée la bordure noire pour tout le tableau
            ('ALIGN', (0,0), (-1,-1), 'CENTRE'), # Centre les cases
            ('BACKGROUND', (0,0), (-1,0), UTILS_Divers.ConvertCouleurWXpourPDF(dictOptions["couleur_fond_entetes"]) ), # Donne la couleur de fond du label
            ('BACKGROUND', (0, positionLigneTotal), (-1, positionLigneTotal), UTILS_Divers.ConvertCouleurWXpourPDF(dictOptions["couleur_fond_total"]) ), # Donne la couleur de fond du label
            ]

        # Formatage des lignes "Activités"
        for indexColoration in self.dictImpression["coloration"] :
            listeStyles.append( ('BACKGROUND', (0, indexColoration+1), (-1, indexColoration+1), UTILS_Divers.ConvertCouleurWXpourPDF(dictOptions["couleur_fond_depot"])))
                
        # Création du tableau
        tableau = Table(dataTableau, largeursColonnes)
        tableau.setStyle(TableStyle(listeStyles))
        story.append(tableau)
        story.append(Spacer(0,20))
            
        # Enregistrement du PDF
        doc.build(story)
        
        # Affichage du PDF
        FonctionsPerso.LanceFichierExterne(nomDoc)
예제 #2
0
                                if (numColonne
                                        in dict_totaux_colonnes) == False:
                                    dict_totaux_colonnes[numColonne] = 0
                                dict_totaux_colonnes[numColonne] += valeur

                        else:
                            style = style_texte
                            valeur = valeur.replace("\n", "<br/>")
                    ligne.append(Paragraph(six.text_type(valeur), style))
                    numColonne += 1

                # Ajout de la ligne au tableau
                dataTableau.append(ligne)

        # Style du tableau
        couleur_fond_entetes = UTILS_Divers.ConvertCouleurWXpourPDF(
            dictOptions["couleur_fond_entetes"])
        couleur_fond_total = UTILS_Divers.ConvertCouleurWXpourPDF(
            dictOptions["couleur_fond_total"])

        listeStyles = [
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
            ('FONT', (0, 0), (-1, -1), "Helvetica",
             dictOptions["taille_texte"]),
            ('GRID', (0, 0), (-1, -1), 0.25, colors.black),
            ('ALIGN', (0, 1), (-2, -1), 'RIGHT'),  # Centre les cases
            ('FONT', (0, 0), (0, -1), "Helvetica-Bold",
             dictOptions["taille_texte"]),
            ('FONT', (0, 0), (-1, 0), "Helvetica-Bold",
             dictOptions["taille_texte"]),
            ('BACKGROUND', (0, 0), (-1, 0), couleur_fond_entetes),
            ('BACKGROUND', (0, 0), (0, -1), couleur_fond_entetes),
    def OnBoutonOk(self, event):
        dictParametres = self.ctrl_notebook.GetParametres()

        # Récupération et vérification des données
        listeActivites = dictParametres["liste_activites"]
        if len(listeActivites) == 0 :
            self.ctrl_notebook.AffichePage("generalites")
            dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement cocher au moins une activité !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return False

        # Récupération et vérification des données
        listeGroupes = dictParametres["liste_groupes"]
        if len(dictParametres["liste_groupes"]) == 0 :
            self.ctrl_notebook.AffichePage("generalites")
            dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement cocher au moins un groupe !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return False

        # Vérification qu'il y a des colonnes
        if not dictParametres["colonnes"]:
            dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement créer au moins une colonne !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return False

        # Recherche les catégories utilisées
        liste_categories_utilisees = []
        for nom_categorie, categories in dictParametres["colonnes"]:
            for IDcategorie in UTILS_Texte.ConvertStrToListe(categories):
                if IDcategorie not in liste_categories_utilisees :
                    liste_categories_utilisees.append(IDcategorie)

        # Création du PDF
        from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
        from reportlab.platypus.flowables import ParagraphAndImage, Image
        from reportlab.lib.pagesizes import A4
        from reportlab.lib import colors
        from reportlab.lib.styles import ParagraphStyle
        
        self.taille_page = A4
        if dictParametres["orientation"] == "portrait" :
            self.hauteur_page = self.taille_page[1]
            self.largeur_page = self.taille_page[0]
        else:
            self.hauteur_page = self.taille_page[0]
            self.largeur_page = self.taille_page[1]
        
        # Création des conditions pour les requêtes SQL
        conditionsPeriodes = GetSQLdates(dictParametres["liste_periodes"])
        
        if len(listeActivites) == 0 : conditionActivites = "()"
        elif len(listeActivites) == 1 : conditionActivites = "(%d)" % listeActivites[0]
        else : conditionActivites = str(tuple(listeActivites))
        
        if len(listeGroupes) == 0 : conditionGroupes = "()"
        elif len(listeGroupes) == 1 : conditionGroupes = "(%d)" % listeGroupes[0]
        else : conditionGroupes = str(tuple(listeGroupes))
                
        # Récupération des noms des groupes
        dictGroupes = dictParametres["dict_groupes"]
        dictActivites = dictParametres["dict_activites"]

        DB = GestionDB.DB()

        # ------------ MODE PRESENTS ---------------------------------

        if dictParametres["mode"] == "presents" :

            # Récupération de la liste des groupes ouverts sur cette période
            req = """SELECT IDouverture, IDactivite, IDunite, IDgroupe
            FROM ouvertures 
            WHERE ouvertures.IDactivite IN %s AND %s
            AND IDgroupe IN %s
            ; """ % (conditionActivites, conditionsPeriodes, conditionGroupes)
            DB.ExecuterReq(req)
            listeOuvertures = DB.ResultatReq()
            dictOuvertures = {}
            for IDouverture, IDactivite, IDunite, IDgroupe in listeOuvertures :
                if (IDactivite in dictOuvertures) == False :
                    dictOuvertures[IDactivite] = []
                if IDgroupe not in dictOuvertures[IDactivite] :
                    dictOuvertures[IDactivite].append(IDgroupe)

            # Récupération des individus grâce à leurs consommations
            req = """SELECT individus.IDindividu, IDactivite, IDgroupe,
            IDcivilite, nom, prenom, date_naiss
            FROM consommations 
            LEFT JOIN individus ON individus.IDindividu = consommations.IDindividu
            WHERE consommations.etat IN ("reservation", "present")
            AND IDactivite IN %s AND %s
            GROUP BY individus.IDindividu, IDactivite, IDgroupe
            ORDER BY nom, prenom
            ;""" % (conditionActivites, conditionsPeriodes)
            DB.ExecuterReq(req)
            listeIndividus = DB.ResultatReq()


        # ------------ MODE INSCRITS ---------------------------------

        if dictParametres["mode"] == "inscrits" :

            dictOuvertures = {}
            for IDgroupe, dictGroupe in dictGroupes.items() :
                IDactivite = dictGroupe["IDactivite"]
                if (IDactivite in dictOuvertures) == False :
                    dictOuvertures[IDactivite] = []
                if IDgroupe not in dictOuvertures[IDactivite] :
                    dictOuvertures[IDactivite].append(IDgroupe)

            # Récupération des individus grâce à leurs consommations
            req = """SELECT individus.IDindividu, IDactivite, IDgroupe,
            IDcivilite, nom, prenom, date_naiss
            FROM individus 
            LEFT JOIN inscriptions ON inscriptions.IDindividu = individus.IDindividu
            WHERE inscriptions.statut='ok' AND IDactivite IN %s
            GROUP BY individus.IDindividu, IDactivite, IDgroupe
            ORDER BY nom, prenom
            ;""" % conditionActivites
            DB.ExecuterReq(req)
            listeIndividus = DB.ResultatReq()


        # Analyse des individus
        dictIndividus = {}
        listeIDindividus = []
        for IDindividu, IDactivite, IDgroupe, IDcivilite, nom, prenom, date_naiss in listeIndividus:
            if date_naiss != None: date_naiss = UTILS_Dates.DateEngEnDateDD(date_naiss)
            age = self.GetAge(date_naiss)

            # Mémorisation de l'individu
            dictIndividus[IDindividu] = {
                "IDcivilite": IDcivilite, "nom": nom, "prenom": prenom,
                "age": age, "date_naiss": date_naiss, "IDgroupe": IDgroupe, "IDactivite": IDactivite,
            }

            # Mémorisation du IDindividu
            if IDindividu not in listeIDindividus:
                listeIDindividus.append(IDindividu)


        # Dict Informations médicales
        req = """SELECT IDprobleme, IDindividu, IDtype, intitule, date_debut, date_fin, description, traitement_medical,
        description_traitement, date_debut_traitement, date_fin_traitement, eviction, date_debut_eviction, date_fin_eviction
        FROM problemes_sante 
        WHERE diffusion_listing_enfants=1
        ;"""
        DB.ExecuterReq(req)
        listeInformations = DB.ResultatReq()
        DB.Close()
        dictInfosMedicales = {}
        for IDprobleme, IDindividu, IDtype, intitule, date_debut, date_fin, description, traitement_medical, description_traitement, date_debut_traitement, date_fin_traitement, eviction, date_debut_eviction, date_fin_eviction in listeInformations :
            if (IDindividu in dictInfosMedicales) == False :
                dictInfosMedicales[IDindividu] = []
            dictTemp = {
                "IDprobleme" : IDprobleme, "IDcategorie" : IDtype, "intitule" : intitule, "date_debut" : date_debut,
                "date_fin" : date_fin, "description" : description, "traitement_medical" : traitement_medical, "description_traitement" : description_traitement, 
                "date_debut_traitement" : date_debut_traitement, "date_fin_traitement" : date_fin_traitement, "eviction" : eviction, 
                "date_debut_eviction" : date_debut_eviction, "date_fin_eviction" : date_fin_eviction, 
                }
            dictInfosMedicales[IDindividu].append(dictTemp)
        
        # Récupération des photos individuelles
        dictPhotos = {}
        taillePhoto = 128
        if dictParametres["afficher_photos"] == "petite" : tailleImageFinal = 16
        if dictParametres["afficher_photos"] == "moyenne" : tailleImageFinal = 32
        if dictParametres["afficher_photos"] == "grande" : tailleImageFinal = 64
        if dictParametres["afficher_photos"] != "non" :
            for IDindividu in listeIDindividus :
                IDcivilite = dictIndividus[IDindividu]["IDcivilite"]
                nomFichier = Chemins.GetStaticPath("Images/128x128/%s" % DICT_CIVILITES[IDcivilite]["nomImage"])
                IDphoto, bmp = CTRL_Photo.GetPhoto(IDindividu=IDindividu, nomFichier=nomFichier, taillePhoto=(taillePhoto, taillePhoto), qualite=100)
                
                # Création de la photo dans le répertoire Temp
                nomFichier = UTILS_Fichiers.GetRepTemp(fichier="photoTmp%d.jpg" % IDindividu)
                bmp.SaveFile(nomFichier, type=wx.BITMAP_TYPE_JPEG)
                img = Image(nomFichier, width=tailleImageFinal, height=tailleImageFinal)
                dictPhotos[IDindividu] = img
            
        # ---------------- Création du PDF -------------------
        
        # Initialisation du PDF
        nomDoc = FonctionsPerso.GenerationNomDoc("LISTE_INFORMATIONS_MEDICALES", "pdf")
        if sys.platform.startswith("win") : nomDoc = nomDoc.replace("/", "\\")
        doc = SimpleDocTemplate(nomDoc, pagesize=(self.largeur_page, self.hauteur_page), topMargin=30, bottomMargin=30)
        story = []
        
        largeurContenu = self.largeur_page - 75
        
        # Création du titre du document
        def Header():
            dataTableau = []
            largeursColonnes = ( (largeurContenu-100, 100) )
            dateDuJour = UTILS_Dates.DateEngFr(str(datetime.date.today()))
            dataTableau.append( (_(u"Informations médicales"), _(u"%s\nEdité le %s") % (UTILS_Organisateur.GetNom(), dateDuJour)) )
            style = TableStyle([
                    ('BOX', (0,0), (-1,-1), 0.25, colors.black), 
                    ('VALIGN', (0,0), (-1,-1), 'TOP'), 
                    ('ALIGN', (0,0), (0,0), 'LEFT'), 
                    ('FONT',(0,0),(0,0), "Helvetica-Bold", 16), 
                    ('ALIGN', (1,0), (1,0), 'RIGHT'), 
                    ('FONT',(1,0),(1,0), "Helvetica", 6), 
                    ])
            tableau = Table(dataTableau, largeursColonnes)
            tableau.setStyle(style)
            story.append(tableau)
            story.append(Spacer(0,20))       
        
        # Insère un header
        Header() 
        
        # Activités
        for IDactivite in listeActivites :

            # Groupes
            if IDactivite in dictOuvertures :
                nbreGroupes = len(dictOuvertures[IDactivite])
                indexGroupe = 1
                for IDgroupe in dictOuvertures[IDactivite] :
                    nomGroupe = dictGroupes[IDgroupe]["nom"]
                    if isinstance(dictActivites[IDactivite], dict):
                        nomActivite = dictActivites[IDactivite]["nom"]
                    else:
                        nomActivite = dictActivites[IDactivite]

                    # Initialisation du tableau
                    dataTableau = []
                    largeursColonnes = []
                    labelsColonnes = []
                                        
                    # Recherche des entêtes de colonnes :
                    if dictParametres["afficher_photos"] != "non" :
                        labelsColonnes.append(_(u"Photo"))
                        largeursColonnes.append(tailleImageFinal+6)
                        
                    labelsColonnes.append(_(u"Nom - prénom"))
                    if dictParametres["largeur_colonne_nom"] == "automatique" :
                        largeursColonnes.append(120)
                    else :
                        largeursColonnes.append(int(dictParametres["largeur_colonne_nom"]))

                    if dictParametres["afficher_age"] == True :
                        labelsColonnes.append(_(u"Âge"))
                        if dictParametres["largeur_colonne_age"] == "automatique":
                            largeursColonnes.append(20)
                        else:
                            largeursColonnes.append(int(dictParametres["largeur_colonne_age"]))

                    # Calcule la largeur restante
                    largeurRestante = largeurContenu - sum(largeursColonnes)

                    # Calcul des largeurs de colonnes
                    largeurColonnes = largeurRestante * 1.0 / len(dictParametres["colonnes"])
                    for nom_categorie, categories in dictParametres["colonnes"]:
                        labelsColonnes.append(nom_categorie)
                        largeursColonnes.append(largeurColonnes)

                    # Création de l'entete de groupe
                    ligne = [u"%s - %s" % (nomActivite, nomGroupe),]
                    for x in range(0, len(labelsColonnes)-1):
                        ligne.append("")
                    dataTableau.append(ligne)
        
                    # Création des entêtes
                    ligne = []
                    for label in labelsColonnes :
                        ligne.append(label)
                    dataTableau.append(ligne)
                    
                    # --------- Création des lignes -----------
                            
                    # Création d'une liste temporaire pour le tri
                    listeIndividus = []
                    if IDactivite in dictOuvertures :
                        if IDgroupe in dictOuvertures[IDactivite] :
                            for IDindividu in listeIDindividus :
                                dictIndividu = dictIndividus[IDindividu]
                                if dictIndividu["IDgroupe"] == IDgroupe :
                                    valeursTri = (IDindividu, dictIndividu["nom"], dictIndividu["prenom"], dictIndividu["age"])
                                    
                                    # + Sélection uniquement des individus avec infos
                                    if dictParametres["individus_avec_infos"] == False or (dictParametres["individus_avec_infos"] == True and IDindividu in dictInfosMedicales ) :
                                        listeIndividus.append(valeursTri)
                    
                    if dictParametres["tri"] == "nom" : paramTri = 1 # Nom
                    if dictParametres["tri"] == "prenom" : paramTri = 2 # Prénom
                    if dictParametres["tri"] == "age" : paramTri = 3 # Age
                    if dictParametres["ordre"] == "croissant" :
                        ordreDecroissant = False
                    else:
                        ordreDecroissant = True
                    listeIndividus = sorted(listeIndividus, key=operator.itemgetter(paramTri), reverse=ordreDecroissant)
                    
                    # Récupération des lignes individus
                    for IDindividu, nom, prenom, age in listeIndividus :
                        dictIndividu = dictIndividus[IDindividu]
                        
                        ligne = []
                        
                        # Photo
                        if dictParametres["afficher_photos"] != "non" and IDindividu in dictPhotos :
                            img = dictPhotos[IDindividu]
                            ligne.append(img)
                        
                        # Nom
                        ligne.append(u"%s %s" % (nom, prenom))
                        
                        # Age
                        if dictParametres["afficher_age"] == True :
                            if age != None :
                                ligne.append(age)
                            else:
                                ligne.append("")
                        
                        # Informations médicales
                        paraStyle = ParagraphStyle(name="infos",
                                    fontName="Helvetica",
                                    fontSize=7,
                                    leading=8,
                                    spaceAfter=2,
                                    )

                        # Création des colonnes
                        has_infos = False
                        for nom_categorie, categories in dictParametres["colonnes"]:
                            liste_categories = UTILS_Texte.ConvertStrToListe(categories)

                            case = []
                            # Recherche s'il y a une info médicale dans cette case
                            if IDindividu in dictInfosMedicales:
                                for infoMedicale in dictInfosMedicales[IDindividu] :
                                    IDcategorie = infoMedicale["IDcategorie"]

                                    if IDcategorie in liste_categories or (0 in liste_categories and IDcategorie not in liste_categories_utilisees) :

                                        intitule = infoMedicale["intitule"]
                                        description = infoMedicale["description"]
                                        traitement = infoMedicale["traitement_medical"]
                                        description_traitement = infoMedicale["description_traitement"]
                                        date_debut_traitement = infoMedicale["date_debut_traitement"]
                                        date_fin_traitement = infoMedicale["date_fin_traitement"]

                                        # Intitulé et description
                                        if description != None and description != "":
                                            texteInfos = u"<b>%s</b> : %s" % (intitule, description)
                                        else:
                                            texteInfos = u"%s" % intitule
                                        if len(texteInfos) > 0 and texteInfos[-1] != ".": texteInfos += u"."
                                        # Traitement médical
                                        if traitement == 1 and description_traitement != None and description_traitement != "":
                                            texteDatesTraitement = u""
                                            if date_debut_traitement != None and date_fin_traitement != None:
                                                texteDatesTraitement = _(u" du %s au %s") % (UTILS_Dates.DateEngFr(date_debut_traitement), UTILS_Dates.DateEngFr(date_fin_traitement))
                                            if date_debut_traitement != None and date_fin_traitement == None:
                                                texteDatesTraitement = _(u" à partir du %s") % UTILS_Dates.DateEngFr(date_debut_traitement)
                                            if date_debut_traitement == None and date_fin_traitement != None:
                                                texteDatesTraitement = _(u" jusqu'au %s") % UTILS_Dates.DateEngFr(date_fin_traitement)
                                            texteInfos += _(u"Traitement%s : %s.") % (texteDatesTraitement, description_traitement)

                                        # Création du paragraphe
                                        case.append(Paragraph(texteInfos, paraStyle))
                                        has_infos = True

                            # Ajoute la case à la ligne
                            ligne.append(case)

                        # Ajout de la ligne individuelle dans le tableau
                        if dictParametres["individus_avec_infos"] == False or (dictParametres["individus_avec_infos"] == True and has_infos == True):
                            dataTableau.append(ligne)
                    
                    # Création des lignes vierges
                    for x in range(0, dictParametres["nbre_lignes_vierges"]):
                        ligne = []
                        for col in labelsColonnes :
                            ligne.append("")
                        dataTableau.append(ligne)
                                                
                    # Style du tableau
                    couleur_fond_entetes = UTILS_Divers.ConvertCouleurWXpourPDF(dictParametres["couleur_fond_entetes"])
                    
                    style = TableStyle([
                            ('VALIGN', (0,0), (-1,-1), 'MIDDLE'), # Centre verticalement toutes les cases
                            
                            ('FONT',(0,0),(-1,-1), "Helvetica", 7), # Donne la police de caract. + taille de police 
                            ('GRID', (0,0), (-1,-1), 0.25, colors.black), # Crée la bordure noire pour tout le tableau
                            ('ALIGN', (0,1), (-2,-1), 'CENTRE'), # Centre les cases
                            
                            ('ALIGN', (0,1), (-1,1), 'CENTRE'), # Ligne de labels colonne alignée au centre
                            ('FONT',(0,1),(-1,1), "Helvetica", 6), # Donne la police de caract. + taille de police des labels
                            
                            ('SPAN',(0,0),(-1,0)), # Fusionne les lignes du haut pour faire le titre du groupe
                            ('FONT',(0,0),(0,0), "Helvetica-Bold", 10), # Donne la police de caract. + taille de police du titre de groupe
                            ('BACKGROUND', (0,0), (-1,0), couleur_fond_entetes), # Donne la couleur de fond du titre de groupe
                            
                            ])
                        
                       
                    # Création du tableau
                    tableau = Table(dataTableau, largeursColonnes)
                    tableau.setStyle(style)
                    story.append(tableau)
                    story.append(Spacer(0,20))
                    
                    # Saut de page après un groupe
                    if dictParametres["saut_page_groupe"] == True :
                        story.append(PageBreak())
                        # Insère un header
                        if indexGroupe < nbreGroupes :
                            Header() 
                    
                    indexGroupe += 1
            
        # Enregistrement du PDF
        doc.build(story)
        
        # Affichage du PDF
        FonctionsPerso.LanceFichierExterne(nomDoc)