IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Extraction certaines données feuille XLSX pour générer nouvelle feuille


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 8
    Par défaut Extraction certaines données feuille XLSX pour générer nouvelle feuille
    Bonjour @ tous,

    toute mes excuses de vous solliciter pour résoudre à ma place un problème pour lequel je n'ai aucune connaissance. En effet je n'ai absolument aucune compétence en programmation. Mais en lisant parfois certaines choses, je pense que PYTHON devrait certainement être le langage à utiliser. Aujourd'hui, vu mon âge et aussi par manque de temps, je ne suis plus/pas en mesure de me mettre à la programmation.
    Aussi c'est un véritable appel au secours que je lance à la communauté !

    J'assure la gestion d'un cabinet infirmier. Les réformes techniques actuelles mis en place par la CPAM/CNAM nous obligent à changer notre logiciel de gestion de cabinet au 1 juillet 2025. Jusqu'à maintenant, notre logiciel de gestion de cabinet nous permettait de générer tous les mois, au format .CSV, la liste détaillée des soins réalisés par notre remplaçante durant tout le mois. A la fin du mois j'intégrais dans notre comptabilité (feuilles CALC) les informations contenues dans ce fichier .CSV, ce qui me permettait de connaitre la somme total pour le mois, que je devais alors rétrocéder à la remplaçante.

    Comme vous vous en douter, notre nouveau logiciel ne génère pas tout à fait ce dont nous avons besoin. Il génère un fichier .XLSX qui contient des informations qui ne sont pas du tout ordonnées de la même manière et absolument inexploitables l'état. Certaines cellules d'une même colonne peuvent contenir des données de natures différentes. Les informations qui sont présentées dans ce fichier ne sont pas du tout les mêmes que celles dont j'ai besoin. Mais bien que je ne sois pas très doué en informatique, j'arriverai grâce à quelques formules simples à retrouver ce dont j'ai besoin. Pour information je fais ma comptabilité sur LibreOffice avec CALC.

    J'ai besoin de votre aide pour extraire certaines informations d'une feuille du fichiers .XLSX et les réorganiser au sein d'une nouvelle feuille à créer dans le même fichier .XLSX. Je me chargerai ensuite de faire ma " cuisine " pour exploiter ces informations et... payer notre remplaçante !!

    Pour vous aider, je vous ai généré le fichier .XLSX . Vous y trouverez la feuille "désordonnés" ainsi que la nouvelle feuille à créer avec les informations correspondantes à utiliser et à afficher.
    Je ne sais pas si cela peut être important pour vous, mais je ne vous ai mis que quelques lignes. Il n'est pas rare que la nouvelle feuille à créer contienne plusieurs centaines de lignes (cela peut varier de 250 à 1000). Comme vous l'avez compris, je fait cette manipulation tous les mois avec un fichier différent, qu'il faudra aller chercher dans un répertoire de mon HDD.
    Sans vouloir abuser de votre gentillesse, je vous serais extrêmement reconnaissant si vous vouliez bien abondamment commenter votre programme. En effet, si il est très peu probable que je sois un jour capable d'y mettre le nez dedans, cela simplifiera énormément l’âme charitable qui acceptera de me venir en aide d'ici quelques mois ou semaines ou années, parce que l'éditeur du logiciel aura eu la bonne idée de modifier la structure de son fichier .XLSX ou/et les informations qui y sont contenues....

    Je reste à votre disposition pour répondre à vos questions.

    Le mot est bien peu de chose en comparaison de l'aide inestimable que vous m'apporterez et du temps que vous me consacrerez, mais il vient du coeur : MERCI
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 725
    Par défaut
    Salut,

    Si vous n'avez pas le temps d'apprendre (ce qui se comprend tout à fait) vous avez toujours la possibilité de trouver un freelance pour faire ce boulot (qui pourra peut être même utiliser un autre langage que python).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 210
    Par défaut
    Hello,
    si tu utilises Calc, on peut faire des macros en python , sinon on peut utiliser la bibliothèque python pandas pour lire des fichiers xlsx. Le souci c'est que ton fichier source n'a pas des données par ligne donc en fait il faut lire le classeur source ligne par ligne et se synchroniser par patient .
    J'ai fait un premier essai avec ce code en macro python LibreOffice :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    # coding: utf-8from __future__ import unicode_literals
    from datetime import datetime, timedelta
    import uno
    import re
    try:
        CTX = uno.getComponentContext()
        SM = CTX.getServiceManager()
        desktop = XSCRIPTCONTEXT.getDesktop()
        ODOC = desktop.getCurrentComponent()
        parentwin = ODOC.CurrentController.Frame.ContainerWindow
        dispatcher = SM.createInstanceWithContext("com.sun.star.frame.DispatchHelper", CTX)
        model = desktop.getCurrentComponent()
    except:
        print("ModulePython init Error")
     
    def fraction_to_time(fraction):
        # Ensure only the fractional part is used
        fraction = fraction % 1.0
        # Total seconds in 24 hours
        total_seconds = int(fraction * 24 * 60 * 60)
        # Use timedelta to format as H:M:S
        time_string = str(timedelta(seconds=total_seconds))    
        # Optional: zero-pad if needed
        if total_seconds < 36000:  # less than 10:00:00
            time_string = "0" + time_string
        return time_string
     
    def extractData(*args):
        oSheet = ODOC.getSheets().getByName("Feuille reçue")
        # Create a cursor to find the used range
        oCursor = oSheet.createCursor()
        oCursor.gotoEndOfUsedArea(True)
        # Get the used cell range
        oCellRange = oSheet.getCellRangeByPosition(0, 1,
                           oCursor.RangeAddress.EndColumn,
                           oCursor.RangeAddress.EndRow - 2)
        # Get the data from the used range
        aData = oCellRange.getDataArray()
        PeC = False # PatientEnCours booléen
        for ligne in aData:
            #print(ligne)
            row0 = ligne[0]
            if not PeC:
                PatientEnCours = row0
                #print("Patient en cours : ",PatientEnCours)
                PeC = True
            else:
                if isinstance(row0, str):
                    res1 = re.search(r"(\w+)\s([\d/]+)", row0)
                    if res1:
                        jour = res1.group(1)
                        date = res1.group(2)
                    if 'Total ' + PatientEnCours in row0:
                        PeC = False
                if isinstance(row0, float):
                    heure =  fraction_to_time(row0)
                    print(PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8])
                    continue
     
    g_exportedScripts = extractData,
    et voici que j'obtiens pour le print :
    BLABLA Caroline 15/06/2025 08:30:00 4.73 0.0 1.35 2.75 0.0 8.5 0.0
    BLABLA Caroline 16/06/2025 08:30:00 4.73 0.0 1.35 2.75 0.0 0.0 0.0
    BLABLA Caroline 17/06/2025 08:30:00 4.73 0.0 1.35 2.75 0.0 0.0 0.0
    BLABLA Caroline 18/06/2025 08:30:00 4.73 0.0 1.35 2.75 0.0 0.0 0.0
    DESMOTS Nathalie 16/06/2025 12:00:00 4.73 0.0 1.35 2.75 0.0 0.0 0.0
    DESMOTS Nathalie 16/06/2025 00:00:00 3.78 0.0 1.35 2.75 0.0 0.0 0.0
    DESMOTS Nathalie 17/06/2025 12:00:00 4.73 0.0 1.35 2.75 0.0 0.0 0.0
    DESMOTS Nathalie 17/06/2025 00:00:00 3.78 0.0 1.35 2.75 0.0 0.0 0.0
    DESMOTS Nathalie 18/06/2025 12:00:00 4.73 0.0 1.35 2.75 0.0 0.0 0.0
    DESMOTS Nathalie 18/06/2025 00:00:00 3.78 0.0 1.35 2.75 0.0 0.0 0.0
    Après on peut écrire ces données dans une nouvelle feuille.
    Si cela te semble intéressant, je peux continuer à investiguer. Pour les personnes qui veulent optimiser le programme mais qui ne connaissent pas pyuno l'interface de python avec LibreOffice, on récupère les données de feuille dans python (avec le getDataArray) sous forme de tuples de tuples voici les tuples récupérés :
    (('BLABLA Caroline', '', '', '', '', '', '', '', '', ''), ('Dimanche 15/06/2025', '', '', '', '', '', '', '', '', ''), (45823.35416666671, 4.73, '', 0.0, 1.35, 2.75, 0.0, 8.5, 0.0, 17.33), ('Total Dimanche 15/06/2025', 4.73, '', 0.0, 1.35, 2.75, 0.0, 8.5, 0.0, 17.33), ('Lundi 16/06/2025', '', '', '', '', '', '', '', '', ''), (45824.35416666671, 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), ('Total Lundi 16/06/2025', 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), ('Mardi 17/06/2025', '', '', '', '', '', '', '', '', ''), (45825.35416666671, 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), ('Total Mardi 17/06/2025', 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), ('Mercredi 18/06/2025', '', '', '', '', '', '', '', '', ''), (45826.35416666671, 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), ('Total Mercredi 18/06/2025', 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), ('Total BLABLA Caroline', 18.92, '', 0.0, 5.4, 11.0, 0.0, 8.5, 0.0, 43.82), ('DESMOTS Nathalie', '', '', '', '', '', '', '', '', ''), ('Lundi 16/06/2025', '', '', '', '', '', '', '', '', ''), (45824.5, 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), (0.0, 3.78, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 7.88), ('Total Lundi 16/06/2025', 8.51, '', 0.0, 2.7, 5.5, 0.0, 0.0, 0.0, 16.71), ('Mardi 17/06/2025', '', '', '', '', '', '', '', '', ''), (45825.5, 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), (0.0, 3.78, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 7.88), ('Total Mardi 17/06/2025', 8.51, '', 0.0, 2.7, 5.5, 0.0, 0.0, 0.0, 16.71), ('Mercredi 18/06/2025', '', '', '', '', '', '', '', '', ''), (45826.5, 4.73, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 8.83), (0.0, 3.78, '', 0.0, 1.35, 2.75, 0.0, 0.0, 0.0, 7.88), ('Total Mercredi 18/06/2025', 8.51, '', 0.0, 2.7, 5.5, 0.0, 0.0, 0.0, 16.71), ('Total DESMOTS Nathalie', 25.53, '', 0.0, 8.1, 16.5, 0.0, 0.0, 0.0, 50.13))
    Voici ce que cela donne en écrivant les données de sortie sur la même feuille que les données reçues en dessous des données d'entrée.

    Nom : LoPythonExtract.gif
Affichages : 88
Taille : 60,8 Ko

    Le code pour écrire les données dans la feuille ( à partir de A35) avec setDataArray en utilisant des tuples :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    def extractData(*args):
        oSheet = ODOC.getSheets().getByName("Feuille reçue")  # sélection de la feuille
        # Create a cursor to find the used range
        oCursor = oSheet.createCursor()
        oCursor.gotoEndOfUsedArea(True)
        # Get the used cell range
        oCellRange = oSheet.getCellRangeByPosition(0, 1,
                           oCursor.RangeAddress.EndColumn,
                           oCursor.RangeAddress.EndRow - 2)
        # Get the data from the used range
        aData = oCellRange.getDataArray()
        tupHeader = (('Patient','Date soin','Heure passage','AMI','Répartition',
                     'AIS/BSX','MAU/MCI','IF','IK','Maj.','Autres*'),)
        cursor = oSheet.createCursorByRange(oSheet.getCellRangeByName("A35")) # écriture de l'entête des données de sortie à partir de A35
        cursor.collapseToSize( len(tupHeader[0]) , 1 )
        cursor.setDataArray(tupHeader)
        PeC = False # PatientEnCours booléen
        listeData=[]
        for ligne in aData:
            #print(ligne)
            row0 = ligne[0]
            if not PeC:
                PatientEnCours = row0
                #print("Patient en cours : ",PatientEnCours)
                PeC = True
            else:
                if isinstance(row0, str):
                    res1 = re.search(r"(\w+)\s([\d/]+)", row0)
                    if res1:
                        jour = res1.group(1)
                        date = res1.group(2)
                    if 'Total ' + PatientEnCours in row0:
                        PeC = False
                if isinstance(row0, float):
                    heure =  fraction_to_time(row0)
                    print(PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8])
                    l = [PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8]]
                    listeData.append(tuple(l))  # création de la liste des données de sortie
                    continue
        tupData = tuple(listeData)
        cursor = oSheet.createCursorByRange(oSheet.getCellRangeByName("A36")) # écriture des données de sortie à partir de A36
        cursor.collapseToSize( len(tupData[0]) , len(tupData) )
        cursor.setDataArray(tupData)
    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko :zen:

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Si j'ai bien suivi, vous (votre cabinet) achète un produit à une bande d'incapables qui n'ont même pas pensé (ou fait l'effort) de séparer les colonnes en fonction des datas. Rien que là c'est clairement du je m'en foutisme absolu. Si vous alliez au restaurant et qu'on vous serve le repas complet en même temps dans la même assiette (en y incluant bien évidemment le vin et café), est-ce que vous accepteriez ? Alors pourquoi l'accepter ici ?? Parce que c'est de l'informatique ??? Non mais sans déconner je suis le chef de projet les types ils repartent dans leur poubelle mais direct !!!

    Et maintenant il faut rattraper le truc.
    Nom : metaphore_gestion_projet_balancoire_arbre.jpg
Affichages : 87
Taille : 11,6 Ko

    Toutefois, pour montrer que dans ce métier il y a aussi des gens qui ont un petit peu d'estime de soi, j'ai aussi écrit une solution. Mais je te le dis honnêtement pas pour toi car demander un code quelle qu'en soit la raison est clairement en dehors des règles du forum ni pour les connards qui vous ont vendus leur merde (eux en plus ils vont être payés pour ça) mais juste parce que ça me donnait l'occasion de m'exercer à traiter de l'excel. Ceci dit puisque j'ai écrit le truc, autant t'en faire profiter (j'ai déjà écrit des codes pour le forum donc un de plus un de moins...). Perso je ne passe pas par pandas car je ne le connais pas mais par openpyxl. Pandas est une méga machine capable d'extraire et traiter des données tandis qu'openpyxl est juste dédié à lire et écrire de l'excel (ce qui me semble suffisant ici).

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #!/usr/bin/env python
    # coding: utf-8
     
    import openpyxl
    import datetime
     
    def genereXLS(fic):
    	# Bon ben on ouvre le bouzin
    	# On se connecte sur la feuille à traiter
    	# On prépare la feuille à écrire
    	workbook = openpyxl.load_workbook(fic, read_only=False)
    	sheet_in = workbook["Feuille reçue"]
    	sheet_out = workbook.create_sheet("Feuille à générer")
     
    	# Les lignes
    	row=sheet_in.iter_rows()
     
    	# On récupère la première ligne qui va servir de support d'informations
    	title=next(row)
     
    	# On crée les clefs issues des intitulés de cette première ligne
    	keys=tuple(t.value for t in title)
     
    	# Et on écrit cette première ligne
    	sheet_out.append(("Patient", "Date soin", "Heure passage") + keys)
     
    	# Maintenant on traite les lignes
    	for (cpt, r) in enumerate(row, 2):
    		# Et là c'est la merde: comment détecter qu'on est sur un nom, un intitulé ou une date ?
    		# Il semble que les dates soient de type "datetime" et le reste soit "str"
    		# Bon ben partons sur cette idée...
    		if isinstance(r[0].value, str):
    			# Ici c'est soit un nom, soit une data à la con
    			# Si la data commence par un mot très précis
    			if r[0].value.strip().split(" ")[0].lower() in (
    				"dimanche", "lundi", "mardi",
    				"mercredi", "jeudi", "vendredi",
    				"samedi", "total", "totaux", "*",
    			):
    				# il semble qu'on soit sur une ligne totalement inutile
    				continue
     
    			# Ici on est clairement sur un nouveau patient... On prépare donc le patient
    			patient=dict()
    			patient["nom"]=r[0].value
    			patient["Date soin"]=None
    			patient["Heure passage"]=None
    			continue
    		# Si maintenant on n'est pas sur une date
    		elif not isinstance(r[0].value, datetime.datetime):
    			# Donc une ligne qui n'est pas un texte... pas une date... Poubelle
    			continue
    		# if
     
    		# Ici on est sur une date (donc une ligne à infos)... on va traiter toutes les infos
    		for (i, col) in enumerate(r):
    			patient[keys[i]]=col.value
     
    		# Et maintenant on écrit les infos dans l'onglet
    		sheet_out.append(
    			(
    				patient["nom"],
    				patient["Patient"].strftime("%d/%m/%y"),
    				patient["Patient"].strftime("%H:%M"),
    			) + tuple(patient[k] for k in keys)
    		)
    	# for
     
    	# Ne reste qu'à ré-enregistrer le fichier
    	workbook.save(fic)
     
    	# Un petit retour indiquant qu'on a tout traité
    	return {"fic" : fic, "total" : cpt, "status" : True}
    # genrereXLS()
     
    # Test
    if __name__ == "__main__":
    	if (r:=genereXLS("Retrocession.xlsx"))["status"]:
    		print("%s: ok (%d lignes)" % (r["fic"], r["total"]))
    # if

    Voilà. Au résultat ça donne un truc sympa. Petit bug car il crée une seconde colonne "Patient". La première vient du fait que je crée une colonne spécifique pour le nom que je nomme "Patient" et la seconde vient des colonnes d'origine que je reclaque telles quelles (ce qui permet ainsi au code de s'adapter automatiquement si la feuille d'origine vient à avoir d'autres colonnes mais amène donc à avoir aussi la colonne d'origine "Patient"). On peut l'enlever mais ça oblige à rajouter un test et j'avais pas envie (en plus faut le mettre deux fois, la première là où on écrit le titre et la seconde là où on écrit la ligne) donc ça va quoi. C'est déjà bien beau d'avoir réussi à rattraper les 9 dixièmes du travail des autres branluchons.
    Autre détail: chaque fois qu'on relance le programme il génère un nouvel onglet. Pareil c'est gérable mais ça rajoute encore un test donc moi je fais avec (ou plutôt sans).
    Nom : xxx.jpg
Affichages : 88
Taille : 240,6 Ko
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre Expert
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    920
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 920
    Billets dans le blog
    8
    Par défaut
    Bonjour.
    Citation Envoyé par wiztricks Voir le message
    vous avez toujours la possibilité de trouver un freelance pour faire ce boulot (qui pourra peut être même utiliser un autre langage que python).
    Je plussoie.

    [HS ou pas]
    Pour l'anecdote : Plus jeune j'ai travaillé une année bénévolement pour une activité qui me plaisait et que je voulais découvrir. Suite à quoi, j'eus trouvé une promesse d'embauche dans une autre structure concernant cette activité( afin de remplacer un congé de maternité).
    Le jour J où je devais commencer à travailler enfin rétribué pour cette activité voilà que l'on m'informe qu'ils (la structure) ont trouvé un bénévole pour faire ce remplacement.
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Envie de développer pour Android avec Python? Pensez à Kivy
    Kivy c'est aussi ça: https://www.youtube.com/@MPython_Alaplancha

  6. #6
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 210
    Par défaut
    Hello,
    j'ai amélioré mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    def importData(*args):
        #Utilisation d'une boîte de dialogue de type filepicker pour choisir le classeur d'import
        filepicker = SM.createInstanceWithContext( "com.sun.star.ui.dialogs.OfficeFilePicker",CTX )
        #Choix du répertoire initial de la boîte de dialogue
        filepicker.setDisplayDirectory(uno.systemPathToFileUrl("d:/temp/Import"))
        filepicker.appendFilter( "Fichiers xlsx (*.xlsx)", "*.xlsx" )
        filepicker.setCurrentFilter("Fichiers xlsx (*.xlsx)")
        filepicker.initialize( ( 0,) )
        if filepicker.execute():
            print(filepicker.getFiles()[0])
        else:
            #si on annule dans la boîte de dialogue, on ne fait rien
            return
        path = filepicker.getFiles()[0]
        #ouverture du classeur d'import
        doc = desktop.loadComponentFromURL(path, '_default', 0, ())
        oSheets = ODOC.getSheets()
        oSheetsImport = doc.getSheets()
        #Feuille à utiliser dans le fichier source
        oSheet = oSheetsImport.getByName("Feuille reçue")
        #Feuille à créer dans le classeur en cours
        if oSheets.hasByName("Import"):
            oSheets.removeByName("Import")
        oSheets.insertNewByName("Import",oSheets.getCount())
        oSheetD = oSheets.getByName("Import")
        # Créer un curseur pour trouver la plage utilisée
        oCursor = oSheet.createCursor()
        oCursor.gotoEndOfUsedArea(True)
        # obtenir les cellules à utiliser à partir de la deuxième ligne (1) jusqu'à la fin moins deux lignes (Totaux et *) 
        oCellRange = oSheet.getCellRangeByPosition(0, 1,
                           oCursor.RangeAddress.EndColumn,
                           oCursor.RangeAddress.EndRow - 2)
        # Obtenir les données d'import à partir de la plage 
        aData = oCellRange.getDataArray()
        #créer la ligne d'entête de la feuille d'import
        tupHeader = (('Patient','Date soin','Heure passage','AMI','Répartition',
                     'AIS/BSX','MAU/MCI','IF','IK','Maj.','Autres*'),)
        #Création du curseur pour insérer la ligne d'entête à partir de la cellule A1
        cursor = oSheetD.createCursorByRange(oSheetD.getCellRangeByName("A1"))
        cursor.collapseToSize( len(tupHeader[0]) , 1 )
        cursor.setDataArray(tupHeader)
        #boucle pour récupérer les données du classeur d'import
        PeC = False # PatientEnCours booléen
        #liste des données
        listeData=[]
        for ligne in aData:
            #print(ligne)
            row0 = ligne[0]
            if not PeC:
                PatientEnCours = row0
                #print("Patient en cours : ",PatientEnCours)
                PeC = True
            else:
                if isinstance(row0, str):
                    res1 = re.search(r"(\w+)\s([\d/]+)", row0)
                    if res1:
                        jour = res1.group(1)
                        date = res1.group(2)
                    if 'Total ' + PatientEnCours in row0:
                        PeC = False
                if isinstance(row0, float):
                    # A chaque fois qu'une heure est détectée , on complète la liste
                    heure =  fraction_to_time(row0)
                    #print(PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8])
                    #choix des données à importer
                    l = [PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8]]
                    listeData.append(tuple(l))
                    continue
        tupData = tuple(listeData)
        #Création du curseur pour insérer les lignes de données à partir de la cellule A2
        cursor = oSheetD.createCursorByRange(oSheetD.getCellRangeByName("A2"))
        cursor.collapseToSize( len(tupData[0]) , len(tupData) )
        cursor.setDataArray(tupData)
        #fermeture du classeur d'import
        doc.close(True)
    1 - Le fichier script python (en pièce jointe , Import.py dans le zip) est à mettre dans (sous windows) :
    C:\Users\<nom User>\AppData\Roaming\LibreOffice\4\user\Scripts\python
    2 - Dans Calc dans Outils/Macros/Exécuter la macro, normalement il apparaît dans Mes macros: le sélectionner et exécuter la macro importData.
    Nom : ExecuterMacro.png
Affichages : 77
Taille : 20,2 Ko
    3 - choix du fichier xlsx à importer par une boîte de dialogue :
    Nom : ChoisirClasseur.png
Affichages : 76
Taille : 19,2 Ko
    Pour modifier le répertoire de départ du choix du fichier modifier la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    filepicker.setDisplayDirectory(uno.systemPathToFileUrl("d:/temp/Import"))
    4 - L'import se fait directement dans le document calc en cours dans une nouvelle feuille appelée Import
    5 - Une fois la macro exécutée, allez dans la nouvelle feuille et copier les données pour les coller à l'endroit qu'il faut dans le classeur

    Avec les données réelles, il y a peut être des corrections ou des ajustements à faire.


    Normalement, ce n'est pas trop dangereux d'utiliser la macro dans le classeur Calc principal car on crée une nouvelle feuille mais par sécurité dans un premier temps sauvegarder le fichier calc original avant de faire des essais.


    Ami calmant, J.P
    Fichiers attachés Fichiers attachés
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko :zen:

  7. #7
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 210
    Par défaut
    Hello,
    dans le code de Sve@r et dans mon code , il y a un souci : les données en sortie pour la date et l'heure sont en texte alors que d'après le classeur de départ de Christophe , il faut qu'elles soient en format date.
    J'ai modifié mon code
    1 - Pour que les colonnes Date Soin et Heure de passage soit en format date ( A noter que les deux colonnes contiennent la même valeur car celle-ci contient à la fois la date et l'heure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
        listeData=[]
        for ligne in aData:
            #print(ligne)
            row0 = ligne[0]
            if not PeC:
                PatientEnCours = row0
                #print("Patient en cours : ",PatientEnCours)
                PeC = True
            else:
                if isinstance(row0, str):
                    if 'Total ' + PatientEnCours in row0:
                        PeC = False
                if isinstance(row0, float):
                    # A chaque fois qu'une heure est détectée , on complète la liste
                    date = row0
                    heure =  row0 # pour éliminer la date : heure = row0 % 1
                    #print(PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8])
                    #choix des données à importer
                    l = [PatientEnCours,date,heure,ligne[1],ligne[2],ligne[3],ligne[4],ligne[5],ligne[6],ligne[7],ligne[8]]
                    listeData.append(tuple(l))
                    continue
        tupData = tuple(listeData)
        #Création du curseur pour insérer les lignes de données à partir de la cellule A2
        cursor = oSheetD.createCursorByRange(oSheetD.getCellRangeByName("A2"))
        cursor.collapseToSize( len(tupData[0]) , len(tupData) )
        cursor.setDataArray(tupData)
        format_all_columns(oSheetD)
        #fermeture du classeur d'import
        doc.close(True)
    2 - J'ai rajouté une fonction (format_all_columns) pour formater les colonnes de la feuille de sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    def format_all_columns(sheet):
        from com.sun.star.table.CellHoriJustify import CENTER
        # Get number formats and locale
        number_formats = ODOC.NumberFormats
        locale = uno.createUnoStruct("com.sun.star.lang.Locale")
        locale.Language = "fr"
        locale.Country = "FR"
        # Query or create time format key
        format_heure = number_formats.queryKey("H:MM", locale, True)
        if format_heure == -1:
            format_heure = number_formats.addNew("H:MM", locale)
        format_date = number_formats.queryKey("JJ/MM/AA", locale, True)
        if format_date == -1:
            format_date = number_formats.addNew("JJ/MM/AA", locale)
        format_euros =number_formats.queryKey("# ##0,00[$ €-40C]* ", locale, True)
        if format_euros == -1:
            format_euros = number_formats.addNew("# ##0,00[$ €-40C]* ", locale)
        columns = sheet.Columns
     
     
        for i in range(11):  # Adjust range as needed
            column = columns.getByIndex(i)
            # Apply number format to  column (rows 1 to 1000)
            cell_range = sheet.getCellRangeByPosition(i, 1, i, 1000)
            if i == 1:
                cell_range.NumberFormat = format_date
                cell_range.HoriJustify = CENTER # centrage
            if i == 2:
                cell_range.NumberFormat = format_heure
                cell_range.HoriJustify = CENTER
            if i in [3,5,6,7,8,9,10]:
                cell_range.NumberFormat = format_euros
            column.OptimalWidth = True # ajustement de la largeur des colonnes
    Nom : Import.png
Affichages : 69
Taille : 33,4 Ko


    Ami calmant, J.P
    Fichiers attachés Fichiers attachés
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko :zen:

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 8
    Par défaut
    Bonjour @ tous,

    je vous remercie pour aide et pour vos solutions, tout particulièrement jurassic pork et Sve@r.

    Je vous suis vraiment très reconnaissant de voler à mon secours et je comprends les commentaires qui ont été fait.

    Je suis actuellement en formation toute cette semaine, du coup je n'ai pas accès à mes fichiers.

    Exécuter un script Python ne devrait pas trop me poser de problème (Même si je n'ai jamais fait cela). En revanche saisir une macro Python dans calc devrait se révéler un peu plus ardu pour moi, car là aussi c'est nouveau pour moi et je n'ai jamais travaillé avec des macros. Mais je vais chercher.

    Je serai de retour de ma formation pour le week-end prochain, du coup je vous tient au courant dès mon retour.

    Merci beaucoup à tous.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jurassic pork Voir le message
    dans le code de Sve@r et dans mon code , il y a un souci : les données en sortie pour la date et l'heure sont en texte alors que d'après le classeur de départ de Christophe , il faut qu'elles soient en format date.
    Bien vu

    Citation Envoyé par jurassic pork Voir le message
    J'ai modifié mon code
    Pour ma part, il suffit de remplacer...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    		# Et maintenant on écrit les infos dans l'onglet
    		sheet_out.append(
    			(
    				patient["nom"],
    				patient["Patient"].strftime("%d/%m/%y"),
    				patient["Patient"].strftime("%H:%M"),
    			) + tuple(patient[k] for k in keys)
    		)
    	# for
    ...par...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    		# Et maintenant on écrit les infos dans l'onglet
    		sheet_out.append(
    			(
    				patient["nom"],
    				patient["Patient"].date(),
    				patient["Patient"].time(),
    			) + tuple(patient[k] for k in keys)
    		)
    	# for
    .

    Citation Envoyé par Christophe FRT Voir le message
    Exécuter un script Python ne devrait pas trop me poser de problème (Même si je n'ai jamais fait cela).
    Hum... En admettant que tu sois sous Windows, il te faudra
    1. télécharger Python https://www.python.org/downloads puis l'installer
    2. pour mon script, installer le module openpyxl qui n'est pas installé par défaut (taper la commande pip install openpyxl depuis un terminal MsDos ou Powershell ; mais qui ne fonctionnera que si tu as pensé à indiquer le dossier contenant cette commande dans le PATH de ton environnement). Généralement ce dossier se nomme "C:\Program Files\Python313\Scripts" mais c'est "généralement" (ça dépend surtout de la façon dont tu installes Python, si c'est en tant qu'admin ou en tant qu'user). De même le chiffre "313" dépend de la version (ici 3.13)
    3. pour le script de Jurassic Pork, installer le module "uno" (je ne le connais pas mais une rapide recherche montre que lui non plus n'est pas installé par défaut). Donc là aussi commande pip install uno depuis un terminal MsDos ou Powershell
    4. enfin tu pourras taper la commande python ton_programme.py là aussi depuis un terminal mais là aussi si tu as pensé à placer le dossier "C:\Program Files\Python313" dans le PATH afin que ton OS sache où trouver la commande "python"

    Bref lancer un script Python ce n'est pas ultra-compliqué MAIS ça demande quand-même quelques petites bases (c'est quoi le PATH, comment accéder au terminal MsDos, comment se déplacer dans l'arborescence depuis la ligne de commande pour aller chercher le script à exécuter... quelle différence si on installe Python en tant qu'admin ou en tant qu'utilisateur...bref...)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 210
    Par défaut
    Hello,

    Citation Envoyé par Sve@r Voir le message
    pour le script de Jurassic Pork, installer le module "uno" (je ne le connais pas mais une rapide recherche montre que lui non plus n'est pas installé par défaut).

    Sous windows le module uno est inclus dans le python intégré à LibreOffice, donc pas la peine de l'installer. Dans les versions récentes de LibreOffice, le python intégré est en version 3.8 ou 3.9.


    Citation Envoyé par Christophe FRT Voir le message
    Exécuter un script Python ne devrait pas trop me poser de problème (Même si je n'ai jamais fait cela). En revanche saisir une macro Python dans calc devrait se révéler un peu plus ardu pour moi, car là aussi c'est nouveau pour moi et je n'ai jamais travaillé avec des macros
    Il existe une extension LibreOffice qui est presque indispensable si on veut manipuler des macros écrites en python, c'est APSO (voir doc ici). La dernière version de l'extension se trouve ici (télécharger le fichier apso.oxt) :

    Nom : APSO.gif
Affichages : 56
Taille : 45,8 Ko


    Avec cette extension on peut :
    éditer un module python (en utilisant son éditeur python préféré (par exemple Notepad++)
    Déboguer ses fonctions :

    Nom : APSO_DEBUG.png
Affichages : 54
Taille : 36,0 Ko


    Ouvrir dans une fenêtre, l'interpréteur python de LibreOffice ce qui permet par exemple de visualiser des print écrits dans sa macro :

    Nom : APSO_Console.png
Affichages : 53
Taille : 9,5 Ko


    Gérer les modules extérieurs par un gestionnaire pip ( en version bêta) :


    Nom : APSO_Pip.png
Affichages : 53
Taille : 20,6 Ko

    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko :zen:

Discussions similaires

  1. Aide Commandbutton pour insertion nouvelle feuille
    Par vicelow dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 21/10/2008, 21h44
  2. Message d'erreur pour un nouvel enregistrement
    Par Miss Ti dans le forum Access
    Réponses: 4
    Dernier message: 18/01/2007, 16h11
  3. MAJ d'un attibut pour chaque nouvelle entrée
    Par yoshï dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 24/03/2006, 13h06
  4. Extraction de donnés dans un fichier XML
    Par ANISSS dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 27/01/2006, 13h16
  5. Réponses: 6
    Dernier message: 30/06/2004, 08h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo