perlwin32faq12 - Utiliser OLE avec Perl


NOM

perlwin32faq12 - Utiliser OLE avec Perl

Retour en haut de la page


DESCRIPTION

Comment utiliser l'automatisation OLE avec Perl et le module Win32::OLE

Puis-je utiliser OLE avec Perl ?

Oui - sinon cette FAQ ne serait pas une FAQ séparée, mais juste une partie de perlwin32faq4 ;-)

Pour utiliser OLE avec Perl, il est nécessaire d'installer le module Win32::OLE. Et vous avez besoin de lire la documentation l'accompagnant.

use Win32::OLE n'exporte aucune variable ou fonction dans l'espace de nommage principal, donc si vous voulez un accès facile aux fonctions in et with vous devez charger le module avec :

    use Win32::OLE qw(in with);

Qu'est-ce qui a changé dans OLE depuis les versions 3xx ?

Beaucoup de choses - Gurusamy Sarathy puis Jan Dubois ont refait le code et ajouté un paquet d'extensions. Les anciens scripts devraient fonctionner avec peu ou pas de modification. Dans l'écriture de nouveaux scripts il n'y a aucune excuse pour ne pas utiliser les nouvelles options du module Win32::OLE.

Regardez la documentation de Win::OLE (sous Incompatibilities) et en particulier 'Qu'est-ce qui a changé depuis les séries 300' dans les notes de versions.

Comment imprimer un document Microsoft Word ?

Utilisez la méthode PrintOut sur un objet document, par exemple:

    use strict;
    use Win32::OLE;
    use Win32::OLE::Const 'Microsoft Word';
    my $Word = Win32::OLE->new('Word.Application', 'Quit');
    # $Word->{'Visible'} = 1;         # si vous voulez voir ce qui se passe
    $Word->Documents->Open("C:\\DOCUMENTS\\test.doc")
        || die("Unable to open document ", Win32::OLE->LastError());
    $Word->ActiveDocument->PrintOut({
        Background => 0,
        Append     => 0,
        Range      => wdPrintAllDocument,
        Item       => wdPrintDocumentContent,
        Copies     => 1,
        PageType   => wdPrintAllPages,
    });

ou simplement

    $Word->ActiveDocument->PrintOut;

Comment extraire une série de cellules depuis Microsoft Excel ?

Si vous avez un objet feuille vous pouvez extraire la valeur d'une série de cellules avec $Sheet->Range->{'Value'}, par exemple:

    my $array = $Sheet->Range("A8:B9")->{'Value'};

Maintenant $array[0][0] contient la valeur de la cellule A8, $array[0][1] la valeur de la cellule B8, $array[1][0] celle de A9 et $array[1][1] celle de B9.

Ce qui est retourné est un tableau à 2 dimensions (OK, un tableau avec des références de tableaux) qui contient les valeurs des cellules demandées.

Voici un exemple complet :

    use strict;
    use Win32::OLE qw(in with);
    use Win32::OLE::Const 'Microsoft Excel';
    $Win32::OLE::Warn = 3;                                # S'arrête sur erreur...
    my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
        || Win32::OLE->new('Excel.Application', 'Quit');  # utilise le process Excel en cours
                                                          # d'application ou ouverture d'une nouvelle
    my $Book = $Excel->Workbooks->Open("C:\\DOCUMENTS\\test.xls"); # ouvre un fichier Excel
    my $Sheet = $Book->Worksheets(1);                     # selectionne la feuille numéro 1
    my $array = $Sheet->Range("A8:B9")->{'Value'};        # Recupere le contenu
    $Book->Close;
    foreach my $ref_array (@$array) {                     # boucle sur les tableaux
                                                          # référencés par $array
        foreach my $scalar (@$ref_array) {
            print "$scalar\t";
        }
        print "\n";
    }

Pour retrouver la valeur formatée d'une cellule vous devez utiliser la propriété {'Text'} à la place de la propriété {'Value'}. Cela retourne exactement ce qui serait affiché à l'écran ! Si la colonne n'est pas assez grande vous obtiendrez '######':

    my $array = $Sheet->Range("A8:B9")->{'Text'};

Comment faire un graphique dans Microsoft Excel ?

Une bonne méthode est d'enregistrer une macro dans Excel et de la convertir en Perl. Mais voici un exemple :

    use strict;
    use Win32::OLE;
    use Win32::OLE::Const 'Microsoft Excel';
    my $Excel = Win32::OLE->new("Excel.Application");
    $Excel->{Visible} = 1;
    my $Book = $Excel->Workbooks->Add;
    my $Sheet = $Book->Worksheets(1);
    my $Range = $Sheet->Range("A2:C7");
    $Range->{Value} =
        [['Delivered', 'En route', 'To be shipped'],
         [504, 102, 86],
         [670, 150, 174],
         [891, 261, 201],
         [1274, 471, 321],
         [1563, 536, 241]];
    my $Chart = $Excel->Charts->Add;
    $Chart->{ChartType} = xlAreaStacked;
    $Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
    $Chart->{HasTitle} = 1;
    $Chart->ChartTitle->{Text} = "Items delivered, en route and to be shipped";

Comment sauver un graphique depuis Microsoft Excel en GIF/JPEG/PNG ?

Vous pouvez utiliser la méthode Export d'un graphique. Si vous avez un objet graphique le code est :

    $ChartObj->Chart->Export({
        FileName    => "$graphics_filename",
        FilterName  => 'GIF',
        Interactive => 0});

Un exemple complet qui ouvre un classeur Excel, boucle sur tous les graphiques, les sauve en GIF et ferme le classeur est :

    use strict;
    use Win32::OLE qw(in with);
    use Win32::OLE::Const;
    use Win32::OLE::Const 'Microsoft Excel';
    $Win32::OLE::Warn = 3;        # S'arrête sur erreur...
    my $filename = 'c:\\documents\\test.xls';
    my $filter = 'GIF';           # peut-être GIF, JPG, JPEG or PNG
    my $count = 0;
    my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
        || Win32::OLE->new('Excel.Application', 'Quit');  # Utilise Excel si ouvert, sinon le lance
    my $Book = $Excel->Workbooks->Open( $filename );      # ouvre le fichier
    foreach my $Sheet (in $Book->Sheets) {                # boucle sur toutes les feuilles
        foreach my $ChartObj (in $Sheet->ChartObjects) {  # boucle sur tous les graphiques de la feuille
            my $savename = "$filename." . $count++ . ".$filter";
            $ChartObj->Chart->Export({
                FileName    => $savename,
                FilterName  => $filter,
                Interactive => 0});
        }
    }
    $Book->Close;

Comment exécuter une macro sous Microsoft Excel ?

Les macros sous Microsoft Excel peuvent être appelées avec la méthode $Excel->Run, par exemple :

    $Excel->Run("PrintPDFFile");

Pour faire ceci vous devez bien sûr avoir une macro sous Excel appelée 'PrintPDFFile'...

Comment nommer une cellule sous Microsoft Excel ?

Utilisez la méthode Names->Add sur une feuille, en lui donnant un nom et un objet à nommer, par exemple :

    $Sheet->Names->Add({Name => 'NetCost', RefersTo => $Sheet->Range('$B$10')});

Comment créer un folder dans Outlook ?

Encore un exemple :-)

    use strict;
    use Win32::OLE;
    use Win32::OLE::Const 'Microsoft Outlook';
    my $Outlook = Win32::OLE->new('Outlook.Application', 'Quit');
    my $ol = Win32::OLE::Const->Load($Outlook);
    my $namespace = $Outlook->GetNamespace("MAPI");
    my $Folder = $namespace->GetDefaultFolder(olFolderInbox);
    my $NewFolder = $Folder->Folders->Add("Test1");

Comment utiliser ADO ?

Pour utiliser ActiveX Data Objects (ADO) il suffit de faire :

    use strict;
    use Win32::OLE;
    use Win32::OLE::Const 'Microsoft ActiveX Data Objects';
    my $Conn = Win32::OLE->new('ADODB.Connection'); # crée un objet de connexion
    my $RS = Win32::OLE->new('ADODB.Recordset');    # crée un objet recordset
    $Conn->Open('DBname');                          # ouvre une connexion sur la base de données
    my $Fields = ['Id', 'Name', 'Phone'];
    my $Values = [1, 'Joe Doe', '555-1234'];
    $RS->AddNew($Fields, $Values);                  # ajoute un enregistrement
    print "This didn't go well: ", Win32::OLE->LastError(), "\n";
        if (Win32::OLE->LastError());
    $RS->Close;
    $Conn->Close;

Pour aller plus loin, vous devriez regarder la FAQ ADO sur http://www.fastnetltd.ndirect.co.uk/Perl/perl-win32-database.html ou l'article de Jan Dubois dans TPJ#10 (visitez The Perl Journal à http://tpj.com/ ).

Comment utiliser Lotus Notes ?

On peut accéder à Lotus avec OLE; par exemple :

    use strict;
    use Win32::OLE;
    my $Notes = Win32::OLE->new('Notes.NotesSession')
        or die "Cannot start Lotus Notes Session object.\n";
    my ($Version) = ($Notes->{NotesVersion} =~ /\s*(.*\S)\s*$/);
    print "The current user is $Notes->{UserName}.\n";
    print "Running Notes \"$Version\" on \"$Notes->{Platform}\".\n";
    my $Database = $Notes->GetDatabase('', 'help4.nsf');
    my $AllDocuments = $Database->AllDocuments;
    my $Count = $AllDocuments->Count;
    print "There are $Count documents in the database.\n";
    for (my $Index = 1 ; $Index <= $Count ; ++$Index) {
        my $Document = $AllDocuments->GetNthDocument($Index);
        printf "$Index. %s\n", $Document->GetFirstItem('Subject')->{Text};
        my $Values = $Document->GetItemValue('Index_Entries');
        foreach my $Value (@$Values) {
            print " Index: $Value\n";
        }
        last unless $Index < 5;
    }

Vous pouvez accéder à tous les objets accessibles en LotusScript, et les classes LotusScript sont visibles à http://www.lotus.com/products/lotusscript.nsf. Une bonne idée serait de lire l'article de Jan Dubois dans TPJ#10 (visitez The Perl Journal à http://tpj.com/ )

Comment choisir l'imprimante ?

L'imprimante active peut être fixée et retrouvée au travers de l'objet d'application Word avec le code

  $Word->{ActivePrinter} = $printername.

Comment convertir une macro VBA en Perl ?

Si vous enregistrez une macro sous Microsoft Office, elle peut souvent être directement traduite en Perl. En Visual Basic for Applications (VBA) la syntaxe est :

    object.method(argument).property = value

En Perl elle devient

    object->method(argument)->{property} = value;

Par exemple le code VBA suivant :

    ActiveChart.Axes(xlCategory, xlPrimary).CategoryType = xlCategoryScale

devient en Perl:

    $Chart->Axes(xlCategory, xlPrimary)->{CategoryType} = xlCategoryScale;

Où trouver de la documentation sur le modèle objet ?

Si la documentation n'est pas accessible, le meilleur moyen de se renseigner sur les propriétés/méthodes disponibles, est d'utiliser un navigateur OLE.

Si vous avez Microsoft Excel ou Microsoft Word disponibles, allez dans l'éditeur Visual Basic (Alt+F11). Maintenant vous pouvez ouvrir la fenêtre de navigateur objet (F2) et regarder ce qu'il affiche.

Il y a aussi un programme OleView (différents noms et versions) inclus avec Microsoft Visual C++ / Microsoft Visual Studio si vous n'avez pas Office. Ou vous pouvez le télécharger sur le site Microsoft COM ( http://www.microsoft.com/com/ ).

Mais il est encore possible que Notes ne révéle rien ; les objets ne sont pas requis de fournir un support. Par exemple Lotus Notes ne révèle rien à propos de ses constantes interne, méthodes et propriétés ; vous devez les chercher dans la documentation.

Pour Lotus Notes regardez sur http://www.lotus.com/products/lotusscript.nsf

D'accord, mais puis-je au moins trouver les constantes exportées par Win32::OLE::Const ?

Oui, vous pouvez utiliser le code suivant pour voir toutes les constantes - vous ne devriez pas en avoir réellement besoin, mais, si vous voulez savoir ce qui se passe, vous pouvez le faire :

    use strict;
    use Win32::OLE;
    use Win32::OLE::Const;
    my $xl = Win32::OLE::Const->Load("Microsoft Excel");
    printf "Excel type library contains %d constants:\n", scalar keys %$xl;
    foreach my $Key (sort keys %$xl) {
        print "$Key = $xl->{$Key}\n";
    }

Généralement vous devriez regarder la documentation de Win32::OLE::Const.

Pourquoi $! n'est pas initialisé avec le message d'erreur que j'ai indiqué ?

Les messages d'erreurs de Win32::OLE ne vont pas dans la variable $!, mais peuvent être obtenus avec Win32::OLE->LastError()

Pourquoi ai-je une erreur quand j'utilise ODBC et OLE ?

Pour une raison inconnue, vous obtenez une erreur 'OleInitialize' si vous ouvrez une application OLE en premier puis ensuite une connexion ODBC avec les pilotes ODBC Access. Si vous procédez dans l'autre sens, il n'y a pas de problème.

Apparemment les pilotes ODBC Access appellent OleInitialize(). Cela échoue quand Win32::OLE a déjà initialisé le sous-système COM comme «apartment threaded».

Pour supprimer l'erreur, initialisez le pilote ODBC avant l'application OLE ou, encore mieux, initialisez le système OLE avec

  Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);

Pourquoi cela ne fonctionne-t-il pas - même après tout ça ?

Exécutez vos scripts avec perl -w et use strict - cela signale la plupart des erreurs. A part ça, lisez la documentation pour Win32::OLE (c'est un bon début) et peut-être la documentation pour l'objet que vous utilisez.

Dans le cas de Microsoft Office 97, soyez sûr de l'avoir mis à jour avec au moins le service pack 1 - la plupart des OLE dans Microsoft Office 97 ne fonctionnent pas sans cette mise à jour.

Retour en haut de la page


AUTEUR ET COPYRIGHT

Cette FAQ a été à l'origine assemblée et maintenue par Evangelo Prodromou. Elle a été révisée et mise à jour par Brian Jepson de O'Reilly and Associates, David Grove, David Dmytryshynet et Murray Nesbitt d'ActiveState, Henning Michael Møller-Nielsen de RTO, Kevin Meltzer, et David Sparks d'ActiveState.

Cette FAQ est dans le domaine public. Si vous l'utilisez, cependant, vérifiez, s'il vous plaît, que vous donniez le crédit aux auteurs originaux.

Retour en haut de la page


VERSION FRANÇAISE

Cette traduction française correspond à la version anglaise distribuée avec perl 5.8.0. Pour en savoir plus concernant ces traductions, consultez http://www.enstimac.fr/Perl/ .

Retour en haut de la page


TRADUCTION EN FRANÇAIS

Fabien Martinet <ho.fmartinet@cma-cgm.com>

Jean-Louis Morel <jl_morel@bribes.org> (mise à jour perl 5.8.0)

Retour en haut de la page

 perlwin32faq12 - Utiliser OLE avec Perl