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

Qt Discussion :

Manipulation de chaines de caractères dans un document Word


Sujet :

Qt

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Points : 24
    Points
    24
    Par défaut Manipulation de chaines de caractères dans un document Word
    Bonjour,
    Je dois modifier des propriétés d'un document Word. Ces propriétés sont bien visibles lorsque j'ouvre le fichier avec un éditeur de texte.
    J'ai tout d'abord essayé de modifier directement dans le document la partie qui m’intéresse.
    Par exemple, pour remplacer "xxxxx" par 20631:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    QFile fichier(document);
    QTextStream flux(&fichier);
    QString recherche = flux.readAll();
    fichier.open(QIODevice::ReadWrite);
    fichier.seek( recherche.indexOf("xxxxx") );
    fichier.write("20631");
    Problème: cette façon de faire ne marche que lorsque les chaines ont la même taille. Si je veux remplacer "nom_de_l'auteur" par "toto" par exemple ça ne marche plus.
    Y-a-t-il une façon d'insérer du texte directement dans un fichier?? ( C'est à dire supprimer une chaîne et en écrire une autre à la place )

    N'ayant pas trouvé comment faire j'ai essayé via la classe QTextStream. Là aussi problème: un document word n'étant pas un bête fichier texte, il n'est pas possible de stocker le contenu dans une string puis de la réécrire. Le document word obtenu est corrompu.

    Je me suis ensuite tourné vers la classe QDataStream. Elle me permet bien de charger le contenu du document dans un char*, par compte après impossible de chercher une chaîne de caractère à l'intérieur, le format n'est plus le bon.

    Une idée pour résoudre ce problème?

    Merci d'avance

  2. #2
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Points : 1 738
    Points
    1 738
    Par défaut
    J'ai trouvé ton sujet intéressant alors j'ai essayé. Un .doc avec "123test", et c'est parti. Code très crade désolé j'ai pas de temps à perdre.
    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
        QFile fichier("D:\\test.doc");
     
        if (fichier.open(QIODevice::ReadOnly)) {
            QDataStream flux(&fichier);
            char* raw = new char[fichier.size()+1];
            memset(raw, '\0', fichier.size()+1);
            flux.readRawData(raw,fichier.size());
     
            QString textToSearch ( "123test" );
            QString textToReplace ( "123456test" );
            quint64 newSize = fichier.size()-textToSearch.length()+textToReplace.length();
     
            for (int i = 0; i < fichier.size() - textToSearch.length(); i++) {
                bool l_bFound ( true );
     
                for (int j = 0; j < textToSearch.length(); j++) {
                    if (raw[i+j] != textToSearch.at(j))
                        l_bFound &= false;
                }
     
                if ( l_bFound ) {
                    char* raw2 = new char[newSize+1];
                    memset(raw2, '\0', newSize+1);
     
                    for (int j = 0; j < i; j++) {
                        raw2[j] = raw[j];
                    }
     
                    for (int j = i; j < i + textToReplace.length(); j++) {
                        raw2[j] = textToReplace.at(j-i).toAscii();
                    }
     
                    for (int j = i + textToReplace.length(); j < newSize; j++) {
                        raw2[j] = raw[j+textToSearch.length()-textToReplace.length()];
                    }
     
                    delete raw;
                    raw = raw2;
     
                    break;
                }
            }
     
            fichier.close();
     
            if (fichier.open(QIODevice::WriteOnly)) {
                QDataStream flux2(&fichier);
                flux2.writeRawData(raw,newSize);
            }
     
            delete raw;
        }
    Ceci remplace bien la chaine voulu en travaillant directement sur les octets, c'est barbare mais ça fonctionne. Cependant, Word refuse d'ouvrir le document après ça, même en "Ouvrir et réparer" comme il préconise, donc ça sous-entend qu'il y a un contrôle tout de même, de type CRC par exemple... Ça risque de rendre impossible ton affaire.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Points : 24
    Points
    24
    Par défaut
    Damned! Ca ne m'arrange pas cette histoire. Pourtant quand je modifie directement une chaine de caractère dans un document word sans passer par un QDataStream ça fonctionne, le contrôle devrait m'empêcher de faire ça aussi non?

    Merci pour la réponse en tout cas, je ne savais pas comment travailler directement sur les octets. Je vais continuer à chercher un peu.

  4. #4
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Août 2008
    Messages
    26 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 26 617
    Points : 188 587
    Points
    188 587
    Par défaut
    Tu peux regarder du côté de Calligra (ex-Koffice) http://www.calligra-suite.org/, Words supportant le DOCX et le tout étant écrit avec Qt (ça risque cependant de faire un certain temps de lecture de code).
    Vous souhaitez participer aux rubriques Qt (tutoriels, FAQ, traductions) ou HPC ? Contactez-moi par MP.

    Créer des applications graphiques en Python avec PyQt5
    Créer des applications avec Qt 5.

    Pas de question d'ordre technique par MP !

  5. #5
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Points : 1 738
    Points
    1 738
    Par défaut
    Déjà j'ai fait une supposition, c'est qu'il s'agit du format 97-2003 (.doc), vu que le .docx est une archive et devrait poser moins de souci. C'est bien ça ?
    J'ai testé la bête édition avec notepad++ et j'ai exactement le même résultat qu'avec mon code.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Points : 24
    Points
    24
    Par défaut
    Tu peux regarder du côté de Calligra
    Merci je vais regarder.

    Déjà j'ai fait une supposition, c'est qu'il s'agit du format 97-2003 (.doc), vu que le .docx est une archive et devrait poser moins de souci. C'est bien ça ?
    J'ai testé la bête édition avec notepad++ et j'ai exactement le même résultat qu'avec mon code.
    Oui il s'agit bien du format 97-2003. Effectivement même résultat pour une édition à la main. Il s'agit donc d'un contrôle sur le nombre de caractères.

  7. #7
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Points : 1 672
    Points
    1 672
    Par défaut
    Pour info Microsoft avait publié la spec des binaire word, Excel...

    C'est assez complexe comme format mais au moins tu auras toutes les infos:

    http://www.microsoft.com/interop/doc...ryFormats.mspx
    Vous voulez participer aux Tutoriels, FAQ ou Traductions et faire partie de l'équipe Qt de Developpez.
    N'hésitez pas à me contacter par MP.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 25
    Points : 24
    Points
    24
    Par défaut
    J'ai finalement réussi à modifier les propriétés de Word.
    J'ai utilisé activeQt pour manipuler les documents.
    Mon code ressemble à ça, ça peut intéresser quelqu'un:

    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
     
        // Initialisation des pointeurs vers le document
        // et vers les propriétés du document
        QAxObject *p_word = new QAxObject( "Word.Application");
        QAxObject *documents = p_word->querySubObject("Documents");
        QAxObject *doc = documents->querySubObject( "Open(const QString&, bool, bool)", document, false, false);
        QAxObject *customProperties = doc->querySubObject( "CustomDocumentProperties");
        QAxObject *customProperty;
     
        // Modification des propriétés du document
        customProperty = customProperties->querySubObject( "Item(String&)",
                                                               "nom_auteur");
        customProperty->dynamicCall( "value", "toto");
     
     
        // Sauvegarde du document modifié dans un document temporaire.
        doc->dynamicCall("saveAs2( QString&, int )"," temporaire.doc", 0);
     
        // Mise à jour des champs du document dans le corps du doc
        QAxObject *fields = doc->querySubObject("fields");
        fields->dynamicCall("update()");
     
        // Mise à jour des champs du document dans les entêtes
        QAxObject *sections = doc->querySubObject("sections");
        QVariant nombreSection = sections->dynamicCall("count()");
        int nbSection = nombreSection.toInt();
        QAxObject *section;
        QAxObject *headers;
        QAxObject *header;
        QVariant nombreHeader;
        int nbHeader;
        QAxObject *range;
        // Parcours de toutes les entêtes
        for(int i=1; i<nbSection+1;i++){
            section = sections->querySubObject("Item(int&)",i);
            headers = section->querySubObject("headers");
            nombreHeader = headers->dynamicCall("count()");
            nbHeader = nombreHeader.toInt();
            for(int j=1; j<nbHeader+1;j++)
            {
                header = headers->querySubObject("Item(int&)",i);
                range = header->querySubObject("Range");
                fields = range->querySubObject("Fields");
                fields->dynamicCall("Update()");
            }
        }
     
        // Fermeture du document
        documents->dynamicCall("close(int, int)", -1, 1);
        // Fermeture de Word
        p_word->dynamicCall( "quit( )");
        delete p_word;
     
        // Suppression du document squelette original
        if( !QFile::remove (document) ) return false;
     
        // Copie du document modifié dans le bon répertoire
        if( !QFile::copy(" temporaire.doc", document) ) return false;
     
        // Suppression du document temporaire
        if( !QFile::remove (" temporaire.doc") ) return false;
     
        return true;
    J'ai été obligé d'utiliser un fichier temporaire car je n'ai pas réussi à sauvegarder en fermant le document ni même sauvegarder avant de fermer.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/08/2004, 10h59
  2. [String]Recherche d'une chaine de caractères dans une autre
    Par Crazyblinkgirl dans le forum Langage
    Réponses: 3
    Dernier message: 29/07/2004, 11h51
  3. recherche d'une chaine de caractère dans une données text
    Par jdeheul dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 17/06/2004, 16h35
  4. chaines de caractères dans fichier .rc ou .res
    Par raggadoll dans le forum C++Builder
    Réponses: 5
    Dernier message: 22/03/2004, 15h19

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