1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    décembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Industrie

    Informations forums :
    Inscription : décembre 2017
    Messages : 3
    Points : 1
    Points
    1

    Par défaut Openpyxl et insertion d'images

    Bonjour,

    Je suis habituellement assez autonome pour résoudre les problèmes rencontrés au cours du développement de mes outils. Mais là je sèche un peu.

    J'ai fait une mise à jour (je réalise que c'est une erreur) de openpyxl et depuis je n'arrive plus à insérer une image dans un fichier excel. Je rencontre l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IOError: cannot identify image file 'path image'
    Mon programme lit un premier fichier Excel (TableauSynthese.xlsx), chaque ligne correspond à un objet avec diverses informations le concernant. Pour chaque objet je souhaite créer une fiche résultat dans laquelle j'intègre ces diverses informations ainsi qu'une photo de cet objet et le logo de mon entreprise. Cette fiche résultat est créé à partir d'un fichier excel de référence (Excel_ref.xlsx), dans un onglet j'y ai créé l'aspect visuel de la fiche et un deuxième onglet sert à l'écriture des données récupérées par le script python.

    Passer par un Excel de référence me fait gagner du temps, car cela m'évite de coder entièrement l'aspect de la fiche résultat par contre, l'écriture dans ce fichier explose la mise en page. A priori, openpyxl a du mal à conserver la mise en page lors de l'écriture. Si vous avez des solutions concernant ce problème je suis preneur. Si non, je vais coder la mise en page de la fiche résultat.

    Et le problème pour lequel je sollicite votre aide concerne l'insertion d'image dans la fiche résultat. Ca fonctionnait très bien avant mais depuis la MàJ d'openpyxl ça ne fonctionne plus.

    Ci-dessous, voici mon script pour générer les fiches résultats :

    Il faut juste remplacer les XXXX dans les chemins d'accès par les chemins d'accès que vous utiliserez.

    TableauSynthese.xlsx
    Excel_Ref.xlsx

    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import os.path
    import shutil
    import os
    from openpyxl import Workbook
    from openpyxl.styles import PatternFill, Border, Side, Alignment, Protection, Font
    from openpyxl.drawing.image import Image
    from openpyxl.worksheet.pagebreak import Break
    from openpyxl.worksheet.properties import WorksheetProperties, PageSetupProperties
    from openpyxl.utils import get_column_letter, column_index_from_string
    from openpyxl import load_workbook
    from PIL import Image as PILImage
     
    path_xls_ref = "XXXX\Excel_Ref.xlsx"
    xls_synthese = "XXXX\TableauSynthese.xlsx"
    rep_resultat = r"XXXX\Fiche"
    logo = "XXXX\Logo.png"
     
    def lecture_tableau_synthese (a) :
        dico_synthese ={}
        wb = load_workbook(a,data_only=True)
     
        feuille_xls = wb['Synthese']
     
        # +1 car python commence une liste à 0
        nbr_colonne =  range(len(list(feuille_xls.columns))+1)
        nbr_ligne =  range(len(list(feuille_xls.rows))+1)
     
        #pour virer le 0 de la liste tout en gardant la dimension du tableau avec le +1 précédent
        nbr_colonne = nbr_colonne[1:]
     
        #on commence à 3 car il y a la ligne 0 qui n'existe pas, puis une ligne vide puis 2 ligne de titre
        nbr_ligne = nbr_ligne[4:]
     
     
        for ligne in nbr_ligne :
            temp = {}
     
            num_caisse = str(feuille_xls['A'+str(ligne)].value).strip()
            num_echant = str(feuille_xls['B'+str(ligne)].value)
            nom_echant = feuille_xls['C'+str(ligne)].value
            provenance = feuille_xls['D'+str(ligne)].value
            ded_contact = feuille_xls['E'+str(ligne)].value
            ded_10_cm = feuille_xls['F'+str(ligne)].value
            date_spectro = feuille_xls['G'+str(ligne)].value
            masse =feuille_xls['I'+str(ligne)].value
            conta_alpha_bq = feuille_xls['L'+str(ligne)].value
            conta_beta_bq = feuille_xls['M'+str(ligne)].value
            surf_frottee = feuille_xls['N'+str(ligne)].value
            commentaire = feuille_xls['O'+str(ligne)].value
     
            temp['num_caisse'] = num_caisse
            temp['nom_echant'] = nom_echant
            temp['provenance'] = provenance
            temp['ded_contact'] = ded_contact
            temp['ded_10_cm'] = ded_10_cm
            temp['date_spectro'] = date_spectro
            temp['masse'] = masse
            temp['conta_alpha_bq'] = conta_alpha_bq
            temp['conta_beta_bq'] = conta_beta_bq
            temp['surf_frottee'] = surf_frottee
            temp['commentaire'] = commentaire
     
            dico_synthese[ num_echant] = temp
     
        return dico_synthese
     
    def remplissage_fiche (a,b,c) :
        #ouverture du fichier et on se place dans le bon onglet
        wb = load_workbook(a, keep_links=True)
        ws = wb["Extraction"]
     
        ws["B1"]=c
        ws["B2"]=b['num_caisse']
        ws["B3"]=b['nom_echant']
        ws["B4"]=b['provenance'] 
        ws["B5"]=b['ded_contact'] 
        ws["B6"]=b['ded_10_cm'] 
        ws["B7"]=b['date_spectro']
        ws["B8"]=b['masse']
        ws["B9"]=b['conta_alpha_bq']
        ws["B10"]=b['conta_beta_bq']
        ws["B11"]=b['surf_frottee']
        ws["B12"]=b['commentaire'] 
     
        #on retoure sur la fiche mesure pour mettre le logo
        feuille_xls = wb['Feuil1']
        img = Image(logo,size=(50, None),nochangeaspect=True, nochangearrowheads=True)
        img.drawing.left = 85
        img.drawing.top = 21
        feuille_xls.add_image(img) 
     
        wb.save(a)
     
    donnees_synthese = lecture_tableau_synthese(xls_synthese)
     
    excel_ref = path_xls_ref.split("\\")
    for value in excel_ref:
        if not value :
            excel_ref.remove(value)
     
    nom_excel_ref = excel_ref[-1]
     
     
     
    for key in donnees_synthese.keys() :
        # on créée le chemin vers le répertoire de la caisse
        path_rep =  rep_resultat + "\\Caisse n " + str(donnees_synthese[key]['num_caisse'])
     
        # on test s'il existe ou non
        if os.path.isdir(path_rep) == FALSE :
            os.mkdir(path_rep)
     
        # on créée le chemin vers la fiche
        path_fiche = rep_resultat + "\\Caisse n " + str(donnees_synthese[key]['num_caisse']) + "\\" + str(key) +".xlsx"
     
        #on test si la fiche existe déjà ou non
        if os.path.isfile(path_fiche) == FALSE :
            # on copie l'excel de référence dans le nouveau répertoire
            shutil.copy(path_xls_ref,path_rep)
     
            # on renomme l'excel de référence
            nom_xls = str(path_rep) + "\\" +str(key)+".xlsx"
            path_temp_excel = str(path_rep) + "\\" + str(nom_excel_ref)
     
            #on renomme les fichiers excel
            os.rename(path_temp_excel,nom_xls)
     
     
            #on remplie les fichiers excel
            remplissage_fiche(nom_xls,donnees_synthese[key],key)
    D'avance merci, je poursuit tout de même mes recherches.

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    octobre 2008
    Messages
    3 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : octobre 2008
    Messages : 3 395
    Points : 5 214
    Points
    5 214

    Par défaut

    Salut,

    D'où est émit ce message "IOError: cannot identify image file 'path image'" ?

    Si c'est Python alors tu dois avoir un nom de module et un numéro de ligne.

    On devine, bien sûr, que "path image" doit être remplacé par un vrai chemin de fichier valide, mais bon où ?

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    décembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Industrie

    Informations forums :
    Inscription : décembre 2017
    Messages : 3
    Points : 1
    Points
    1

    Par défaut

    Bonjour,

    Le message d'erreur généré par python est présenté ci-dessous :

    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
        remplissage_fiche(nom_xls,donnees_synthese[key],key, path_photo)
      File "XXXX/Generation_fiche.py", line 91, in remplissage_fiche
        img = Image(logo,size=(50, None),nochangeaspect=True, nochangearrowheads=True)
      File "C:\Python27\lib\site-packages\openpyxl\drawing\image.py", line 53, in __init__
        image = _import_image(img)
      File "C:\Python27\lib\site-packages\openpyxl\drawing\image.py", line 36, in _import_image
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
        execfile(filename, namespace)
      File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 71, in execfile
        exec(compile(scripttext, filename, 'exec'), glob, loc)
      File "XXXX/Generation_fiche.py", line 145, in <module>
        img = PILImage.open(img)
      File "PIL\Image.py", line 2572, in open
    IOError: cannot identify image file 'XXXX\\Logo.png'
    Le problème viens de PILImage, j'ai tenté de l'update (module PILOW) mais ça n'a pas fonctionné.

    Désolé, je code un peu comme un cochon, mon chemin d'accès vers l'image porte le nom de variable "logo" à la ligne 19.

  4. #4
    Modérateur

    Homme Profil pro
    Architecte technique
    Inscrit en
    juin 2008
    Messages
    11 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : juin 2008
    Messages : 11 463
    Points : 18 776
    Points
    18 776

    Par défaut

    Citation Envoyé par Zox78 Voir le message
    Le problème viens de PILImage, j'ai tenté de l'update (module PILOW) mais ça n'a pas fonctionné.

    Désolé, je code un peu comme un cochon, mon chemin d'accès vers l'image porte le nom de variable "logo" à la ligne 19.
    Si c'est le cas, openpyxl n'est plus réellement concerné et vous pourriez/devriez reproduire cela avec PIL.Image.open(...).
    Et normalement un peu de recherche sur Internet devrait vous indiquer que, dans ce contexte, le message "IOError: cannot identify image file" signifie que PIL a essayé de décoder les en-têtes de l'image contenues dans le fichier et... il n'y retrouve pas ses petits.
    Dit autrement, c'est pas parce que le fichier a une extension .PNG que c'est une image au format png.... Et la première chose à faire est de remplacer ce fichier (possiblement "corrupt").

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

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    décembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Industrie

    Informations forums :
    Inscription : décembre 2017
    Messages : 3
    Points : 1
    Points
    1

    Par défaut

    Bonjour,

    Du coup j'avais un peu laissé tomber ce projet mais je m'y suis remis dessus hier.

    J'ai réussi à trouver une solution à mon double problème :
    • Destruction de la mise en page dans un fichier Excel après écriture
    • Perte des images présentent dans ce fichier Excel toujours après écriture
    • Problème pour insérer une image avec Pillow


    J'utilise désormais la bibliothèque win32. Je mets un bout de code si ça peut aider des gens comme moi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import win32com.client as win32
     
     #ouverture du fichier et on se place dans le bon onglet
    excel = win32.gencache.EnsureDispatch('Excel.Application')
    wb = excel.Workbooks.Open("lien vers votre fichier Excel")
    ws = wb.Worksheets("Feuil1")
    ws.Pictures().Insert(r"C:\Users\test.JPG")
     
    wb.SaveAs(d)
    excel.Application.Quit()
    L'inconvénient c'est que ça à l'air plutôt pauvre en document mais j'ai réussi à insérer mon image. Me reste plus qu'à trouver comment la redimensionner !

    Merci pour le temps consacrer

    Edit :

    Un bout de code pour compléter qui permet de faire le café, dans mon cas positionner l'image et la redimensionner !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ws.Shapes.AddPicture(logo, LinkToFile=False, SaveWithDocument=True, Left=100, Top=100, Width=200, Height=200)

Discussions similaires

  1. Formulaire et insertion d'image
    Par cadomalo dans le forum Access
    Réponses: 5
    Dernier message: 10/01/2006, 10h40
  2. Insertion d'image
    Par Bouboubou dans le forum Tableaux - Graphiques - Images - Flottants
    Réponses: 8
    Dernier message: 11/12/2005, 22h44
  3. [JTable] Insertion d'images dans la première colonne
    Par cocolepelo dans le forum Composants
    Réponses: 2
    Dernier message: 29/11/2005, 15h17
  4. [CR9] insertion d'image et poids des états
    Par cdu dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 06/07/2005, 17h33
  5. [CR8.5][Visual Adelia] Insertion d'images sur état
    Par adu dans le forum SAP Crystal Reports
    Réponses: 5
    Dernier message: 01/12/2004, 16h34

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