perlwin32faq12 - Utiliser OLE avec Perl |
perlwin32faq12 - Utiliser OLE avec Perl
Comment utiliser l'automatisation OLE avec Perl et le module Win32::OLE
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);
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.
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;
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'};
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";
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;
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'...
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')});
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");
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/ ).
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/ )
L'imprimante active peut être fixée et retrouvée au travers de l'objet d'application Word avec le code
$Word->{ActivePrinter} = $printername.
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;
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
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.
Les messages d'erreurs de Win32::OLE ne vont pas dans la variable $!, mais
peuvent être obtenus avec Win32::OLE->LastError()
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);
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.
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.
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/ .
Fabien Martinet <ho.fmartinet@cma-cgm.com>
Jean-Louis Morel <jl_morel@bribes.org> (mise à jour perl 5.8.0)
perlwin32faq12 - Utiliser OLE avec Perl |