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 :

[Résolu][PyPDF2] PdfFileWriter ne crée pas les bookmarks [Python 3.X]


Sujet :

Python

  1. #1
    Membre confirmé Avatar de ptissendier
    Homme Profil pro
    Retraité
    Inscrit en
    Juillet 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juillet 2011
    Messages : 64
    Par défaut [Résolu][PyPDF2] PdfFileWriter ne crée pas les bookmarks
    Bonjour,
    J'utilise PyPDF2 pour gérer mes fichiers pdf.
    Je voudrais créer un fichier en lui ajoutant des bookmarks.
    Voici mon code en exemple, le vrai est un peu plus compliqué.
    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
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys
    from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger
    from PyQt5 import QtWidgets, QtGui, QtCore
     
     
    def maSub():
     
    # Sélection du fichier à lire
    	chemin="/home/monChemin/"
    	inputPdf=QtWidgets.QFileDialog.getOpenFileName(None,"Sélection du fichier",chemin,"PDF (*.pdf *.PDF)")
    	reader=PdfFileReader(inputPdf[0],"rb")
     
    	outputPdf=QtWidgets.QFileDialog.getSaveFileName(None,"Création/Sélection du fichier de sauvegarde",chemin,"PDF (*.pdf *.PDF)")
     
    	output=PdfFileWriter()
    	f_output=open(outputPdf[0],"wb")
     
     
    	for p in range(0,reader.getNumPages()-1):
    		output.addPage(reader.getPage(p))
    		output.addBookmark("Page " + str(p), p)
     
     
    	output.setPageMode("/UseOutlines")
    	output.write(f_output)
     
    	f_output.close()
    	maSub.close()
     
    if __name__ == '__main__':
     
    	app = QtWidgets.QApplication([])
    	maSub()
    	sys.exit(app.exec_())
    Les pages ajoutées sont bien présentes, mais pas les bookmarks.
    L'ajout de l'option "/UseOutlines" ne donne rien puisque les bookmarks ne sont crées.
    J'ai bien cherché des exemples sur le web. Mais tous ceux que j'ai essayé ne donnent rien.
    Quelqu'un peut-il m'aider.
    Merci

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Le code a l'air de créer un index: on voit bien en lecture les "Page xx" à gauche en index quand on visualise avec Adobe Reader.
    Cependant, cliquer sur l'index "Page 10" affiche bien une page, mais c'est la page 11 puisque le numéro 0 est affecté à la 1ère page.

    Par contre, il faut supprimer "maSub.close()" puisque maSub n'est pas une classe graphique.

  3. #3
    Membre confirmé Avatar de ptissendier
    Homme Profil pro
    Retraité
    Inscrit en
    Juillet 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juillet 2011
    Messages : 64
    Par défaut
    Merci tyrtamos.
    Pour moi le résultat n'est pas bon.
    J'ai ajouté dans mon code une fontion simple pour "afficher" les bookmarks
    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
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys
    from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger
    from PyQt5 import QtWidgets, QtGui, QtCore
     
    def afficheBmk(ficPdf):
    	'''
            PyPDF2 stocke les bookmarks du fichier dans la propriété "outlines" de PdfFileReader (en lecture seule).
            La propriété "outlines" est une liste de dictionnaires de bookmarks.
            Chaque dictionnaire contient {'/Title':"libelle",'/Page':numéro de page,'/Type':"/Fit"' (voir la classe Destinations de PyPDF2)
            '''
    	reader_out=PdfFileReader(ficPdf)
    	outlines=reader_out.outlines
    	for bmk in outlines:
    		 print(bmk['/Title'],bmk['/Page'],bmk['/Type'])
     
     
     
    def maSub():
     
     
    # Sélection du fichier à lire
    	chemin="/home/monChemin/"
    	inputPdf=QtWidgets.QFileDialog.getOpenFileName(None,"Sélection du fichier",chemin,"PDF (*.pdf *.PDF)")
    	reader=PdfFileReader(inputPdf[0],"rb")
     
    	afficheBmk(inputPdf[0])
     
    	outputPdf=QtWidgets.QFileDialog.getSaveFileName(None,"Création/Sélection du fichier de sauvegarde",chemin,"PDF (*.pdf *.PDF)")
     
    	output=PdfFileWriter()
    	f_output=open(outputPdf[0],"wb")
     
     
    	for p in range(0,reader.getNumPages()):
    		output.addPage(reader.getPage(p))
    		output.addBookmark("Page " + str(p),p)
     
     
    	output.setPageMode("/UseOutlines")
    	output.write(f_output)
     
    	f_output.close()
     
    	afficheBmk(outputPdf[0])	
     
     
     
    if __name__ == '__main__':
     
    	app = QtWidgets.QApplication([])
    	maSub()
    	sys.exit(app.exec_())
    Chez mois le résultat de afficheBmk donne ceci, le numéro de page est remplacé par un dictionnaire ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Page2 {'/Type': '/Page', '/Parent': IndirectObject(1, 0), '/Resources': IndirectObject(100, 0), '/MediaBox': [0, 0, 595.30394, 841.88976], '/Group': {'/S': '/Transparency', '/CS': '/DeviceRGB', '/I': <PyPDF2.generic.BooleanObject object at 0x7ff9830b6f28>}, '/Contents': IndirectObject(114, 0)} /Fit
    Je ne vois pas où je fais l'erreur.
    J'utilise la PyPDF2 1.26.0-2 avec python3 sur ubuntu 18.4 LTS
    Merci pourton aide.

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    En fait, le type de bmk dans "afficheBmk" n'est pas un dictionnaire courant mais : "<class 'PyPDF2.generic.Destination'>". Ainsi, quand on fait bmk['/Title'], le résultat dépend de la structure de cette classe.

    Mais on peut faire plus simple: en affichant simplement "bmk" à chaque boucle, on trouve:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {'/Title': 'Page 1', '/Page': IndirectObject(3, 0), '/Type': '/Fit'}
    {'/Title': 'Page 2', '/Page': IndirectObject(7, 0), '/Type': '/Fit'}
    {'/Title': 'Page 3', '/Page': IndirectObject(10, 0), '/Type': '/Fit'}
    {'/Title': 'Page 4', '/Page': IndirectObject(13, 0), '/Type': '/Fit'}
    {'/Title': 'Page 5', '/Page': IndirectObject(16, 0), '/Type': '/Fit'}
    ...
    Ce qui correspond bien à ce qui a été créé par mySub.

    (j'en ai profité pour rectifier le numéro de page avec: output.addBookmark("Page " + str(p+1), p))

    [edit]
    On peut aller plus loin dans la fonction afficheBmk en constatant que bmk['/Page'] est un dictionnaire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        for bmk in outlines:
            print("="*79)
            print('/Title:', '=>', bmk['/Title'])
            print()
            for cle, val in bmk['/Page'].items():
                print(cle, "=>", val)
            print()
            print('/Type:', '=>', bmk['/Type'])
            print()
    Ce qui affiche par exemple pour la page 2 de l'exemple que j'ai pris en pdf:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ===============================================================================
    /Title: => Page 2
     
    /Annots => [IndirectObject(782, 0), IndirectObject(783, 0), IndirectObject(784, 0), IndirectObject(785, 0), IndirectObject(786, 0), IndirectObject(787, 0), IndirectObject(788, 0), IndirectObject(789, 0), IndirectObject(790, 0), IndirectObject(791, 0), IndirectObject(792, 0), IndirectObject(793, 0), IndirectObject(794, 0), IndirectObject(795, 0), IndirectObject(796, 0), IndirectObject(797, 0), IndirectObject(798, 0), IndirectObject(799, 0), IndirectObject(800, 0), IndirectObject(801, 0), IndirectObject(802, 0), IndirectObject(803, 0)]
    /Contents => IndirectObject(804, 0)
    /Type => /Page
    /Parent => IndirectObject(1, 0)
    /Rotate => 0
    /MediaBox => [0, 0, 595, 842]
    /CropBox => [0, 0, 595, 842]
    /Resources => IndirectObject(805, 0)
     
    /Type: => /Fit
    J'imagine que la complexité du dictionnaire bmk['/Page'] est due au fait que les bookmarks peuvent être arborescents.

  5. #5
    Membre confirmé Avatar de ptissendier
    Homme Profil pro
    Retraité
    Inscrit en
    Juillet 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juillet 2011
    Messages : 64
    Par défaut
    J'ai bien compris.
    Merci beaucoup !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Monogame ne crée pas les fichiers
    Par Flashouilleur dans le forum XNA/Monogame
    Réponses: 7
    Dernier message: 25/12/2016, 19h18
  2. Les cookies ne se crée pas
    Par orokham dans le forum Langage
    Réponses: 7
    Dernier message: 02/07/2010, 13h04
  3. Xml Serialization ne crée pas les objets que je veux
    Par FadeOut dans le forum C++/CLI
    Réponses: 1
    Dernier message: 17/03/2009, 12h36
  4. Réponses: 4
    Dernier message: 03/03/2008, 16h31
  5. Réponses: 5
    Dernier message: 16/09/2006, 22h39

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