=head1 NOM perlwin32faq12 - Utiliser OLE avec Perl =head1 DESCRIPTION Comment utiliser l'automatisation OLE avec Perl et le module Win32::OLE =head2 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. C n'exporte aucune variable ou fonction dans l'espace de nommage principal, donc si vous voulez un accEs facile aux fonctions C et C vous devez charger le module avec : use Win32::OLE qw(in with); =head2 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. =head2 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; =head2 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é C<{'Text'}> à la place de la propriété C<{'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'}; =head2 Comment faire un graphique dans Microsoft Excel ? Une bonne méthode est d'enregistrer une macro dans Excel et de la L. 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"; =head2 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; =head2 Comment exécuter une macro sous Microsoft Excel ? Les macros sous Microsoft Excel peuvent être appelées avec la méthode $Excel-ERun, par exemple : $Excel->Run("PrintPDFFile"); Pour faire ceci vous devez bien sûr avoir une macro sous Excel appelée 'PrintPDFFile'... =head2 Comment nommer une cellule sous Microsoft Excel ? Utilisez la méthode Names-EAdd sur une feuille, en lui donnant un nom et un objet à nommer, par exemple : $Sheet->Names->Add({Name => 'NetCost', RefersTo => $Sheet->Range('$B$10')}); =head2 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"); =head2 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/ ). =head2 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/ ) =head2 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. =head2 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; =head2 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 =head2 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. =head2 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 CLastError()> =head2 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); =head2 Pourquoi cela ne fonctionne-t-il pas - même après tout ça ? Exécutez vos scripts avec C et C - 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. =head1 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. =head1 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/ . =head1 TRADUCTION EN FRANÇAIS Fabien Martinet Jean-Louis Morel (mise à jour perl 5.8.0) =cut