tags:

views:

85

answers:

2

I have tried using the following Perl code, but the worksheet does not copy (nor move) and no error message is returned. Thanks in advance for your ideas.

#!/usr/bin/perl -w
use strict;
use warnings;
use OLE;
use Win32::OLE::Const 'Microsoft Excel';

my $Excel = CreateObject OLE "Excel.Application";
my $Book2 = $Excel->Workbooks->Add();
my $Book3 = $Excel->Workbooks->Open("C:\\temp\\test.xlsm");
my $Sheet3 = $Book3->Worksheets(1);
$Sheet3->Select;
$Sheet3->Move("Before" => $Book2->Worksheets(1));
$Book3->Close(0);
$Book2->SaveAs({Filename =>"C:\\temp\\new.xlsm",FileFormat => xlOpenXMLWorkbookMacroEnabled}); 
$Book2->Close();
$Excel -> Quit();
+1  A: 

If you need to die on errors in Excel, you need to set the relevant flag to 3 (works with Office 2000):

$Win32::OLE::Warn = 3; # Die on errors in Excel

A more fundamental issue may have to do with your Office version though. The underlying OLE architecture has been overhauled since (I believe) Office 2007. I faced this issue a while back when a script I developed in tandem with Office 2007 refused to run with Office 2000.

The best modus operandi I can suggest is to work with Excel's (rather confusing) OLE browser by hitting the F2 key when in VBA mode.


The 'Hello, World' of Perl + OLE + Excel (works with Excel 2000):

use strict;
use warnings;
use Win32::OLE qw/in with/;
use Win32::OLE::Const 'Microsoft Excel';
$Win32::OLE::Warn = 3; # Die on errors in Excel

my $excel = Win32::OLE->GetActiveObject('Excel.Application')
   || Win32::OLE->new('Excel.Application', 'Quit');
my $workbook = $excel->Workbooks->Add || warn "Couldn't add a workbook";
my $sheet = $excel->Worksheets->Add || warn "Couldn't add a worksheet";
$sheet->{Name} = "Hello World";
Zaid
This was very helpful. After adding it to the code above, the script now throws an error with the Move command but unfortunately, the return code (0) doesn't provide much insight.
If, as you suggest, I instead use my $Excel = Win32::OLE->GetActiveObject('Excel.Application') or Win32::OLE->new('Excel.Application', 'Quit'); in the original script, I can now catch an error (Can't call method "Workbooks" on unblessed reference) on the my $Book2 = $Excel->Workbooks->Add() line.
Making progress here. If I change "or" to ||, the unblessed ref error goes away and I now get something more meaningful:Thu Sep 2 14:32:33 2010 - OLE exception from "Microsoft Office Excel":Unable to get the Copy property of the Worksheet classWin32::OLE(0.1709) error 0x800a03ec in METHOD/PROPERTYGET "Copy"Still not sure how to resolve this, but I'm thinking that worksheet copying may not be possible in Perl using OLE. I'm using Excel 2007, btw.
@user338714 : I'm quite confident that Perl can copy... am I missing something here because I don't see which line in your original post would cause that error.
Zaid
Sorry, I believe I had changed $Sheet3->Move("Before" => $Book2->Worksheets(1)); to $Sheet3->Copy("Before" => $Book2->Worksheets(1)); when I ran that test. If I use the original Move command, I receive the error message: OLE exception from "Microsoft Office Excel":Unable to get the Move property of the Worksheet classWin32::OLE(0.1709) error 0x800a03ec in METHOD/PROPERTYGET "Move" at C:\Temp\test.pl line 14.
A: 

I found a workaround here using Copy/Paste over a large cell range. This approach could likely be refined by programatically identifying the active cell range instead of hard coding, which could also lead to some problems when going between different versions of Excel.

#!/usr/bin/perl -w
use strict;
use warnings;
use Win32::OLE qw/in with/;
use Win32::OLE::Const 'Microsoft Excel';
$Win32::OLE::Warn = 3; # Die on errors in Excel

my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
   || Win32::OLE->new('Excel.Application', 'Quit');
$Excel -> {"Visible"} = 0;
$Excel -> {"DisplayAlerts"} = 0;  
my $Book2 = $Excel->Workbooks->Add();
my $Book3 = $Excel->Workbooks->Open("C:\\temp\\test.xlsm");
$Book3->Worksheets(1)->Range("A:AM")->Copy;
$Book2->Worksheets(1)->Range("A:AM")->PasteSpecial;
$Book3->Close(0);
$Book2->SaveAs({Filename =>"C:\\temp\\new.xlsm",FileFormat => xlOpenXMLWorkbookMacroEnabled}); 
$Book2->Close();
$Excel->Quit();