Pergunta

I'd like to add a range of values I have in an array of arrays into a range of cells in an Excel spreadsheet; I wrote the following but it fails:

use Win32::OLE;
use Cwd;

eval {$excel = Win32::OLE->GetActiveObject('Excel.Application')};
die "Excel not installed" if $@;
unless (defined $excel) 
{
    $excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;})
    or die "Oops, cannot start Excel";
}

$workbook = $excel->Workbooks->Open(getcwd() . "/test.xlsx");
$worksheet = $workbook->Worksheets(1);
@matrix = ( [0, 1], [2, 3] );

$worksheet->Range("B5:C6")->{Value} = @matrix;

$worksheet->Save;

The code above updates the cells B5:C6 with (2, 2, 2, 2) instead of (0, 1, 2, 3) and I couldn't figure out the reason for this ... what I'm doing wrong?

Foi útil?

Solução

The documentation example passes an array reference:

$sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ],
                                   [ 42,    'Perl',  3.1415  ]];

Change your code to do the same:

$worksheet->Range("B5:C6")->{Value} = \@matrix;

The number 2 is likely coming from the size of @matrix.

Outras dicas

Check out the speed improvement I got from setting a range of cells to an array of values verses setting each cell to a value, 1 cell at a time:

Process times:

start 29:29 to stop 31:41    = 2 min, 12 sec    (The SLOW WAY)  
start 19:55 to stop 20:33    = 0 min, 38 sec    (The SPEEDY WAY) 

That's 132 seconds vs. 38 seconds

CODE:

use Win32::OLE; 
$EXCEL = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit; print "MS-Excel is shutting 
down.\n"; sleep 2;}); 
$EXCEL->{SheetsInNewWorkbook} = 1; 
$BOOK       = $EXCEL->Workbooks->Add(); 
$SHEET      = $BOOK->Worksheets(1);

$SHEET->Range( "A1" )->{Value} = "Book"; 
$SHEET->Range( "B1" )->{Value} = "Chapter";
$SHEET->Range( "C1" )->{Value} = "Verse";
$SHEET->Range( "D1" )->{Value} = "Text"; 

$start=1; $stop=66; 
$row=1;   $cnt=0;

@worksheet_array=();

#-- Process the MS-Access database (ODBC connection), SQL Query Result Set, 
#-- which selected all Bible verses from Books 1-66 (i.e. Genesis thru Revelation).

while ($db->FetchRow()) {  
   $row++;   $cnt++;  
    if (($cnt % 1000) == 0) { 
       print "Processed ($cnt Verses from the Bible Database: Books ($start-$stop) of 66\n";
    } 

   $worksheet_array[$row-2][0] = $book        = $db->Data("book");   
   $worksheet_array[$row-2][1] = $chapter     = $db->Data("chapter");
   $worksheet_array[$row-2][2] = $verse       = $db->Data("verse"); 
   $worksheet_array[$row-2][3] = $verse_text  = $db->Data("verse_text"); 

   print OUT "$book|$chapter|$verse|$verse_text\n";  #-- This output goes to a text (*.txt) file

   #-- The Too Slow Way!  Write data 1 cell at a time.
   #  $SHEET->Range( "A$row" )->{Value} = $book; 
   #  $SHEET->Range( "B$row" )->{Value} = $chapter; 
   #  $SHEET->Range( "C$row" )->{Value} = $verse;
   #  $SHEET->Range( "D$row" )->{Value} = $verse_text; 
}

Write all the data at once instead... The Speedy Way!

$SHEET->Range( "A2:D$row" )->{Value} = \@worksheet_array;   #-- $row = 31102 (total nbr verses)
$SHEET->Columns("A")->AutoFilter; 
$SHEET->Columns( "A:D" )->AutoFit(); 
$EXCEL->Windows(1)->{SplitRow}    = 1;
$EXCEL->Windows(1)->{FreezePanes} = 1;
$BOOK->SaveAs($excel97outputfile_dot_xls);
$BOOK->Close();       sleep 1;   
$EXCEL->Quit;         sleep 1;
undef $BOOK;  undef $EXCEL;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top