使用perl将图表添加到现有的Excel中

时间:2015-12-02 13:31:29

标签: excel perl unix graph perl-module

我是perl的新手。 我有一个包含大量数据的Excel表格。我需要更新它并根据数据创建图表。使用perl。 我成功更新了现有的excel .. 现在添加图表没有发生

use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::SaveParser;
use Spreadsheet::WriteExcel;

# Open an existing file with SaveParser
my $parser      = Spreadsheet::ParseExcel::SaveParser->new();
my $template    = $parser->Parse('MyExcel.xls');
my $worksheet   = $template->worksheet('Firstsheet');
my $chart       = $template->add_chart( type => 'line' );
$chart->add_series(
   categories => '=URV!$A$17:$A$442',
   values     => '=URV!$D$17:$D$442',
   name       => 'pended graph',
);

这不起作用。 无法调用方法" add_chart"在chart4.ps第20行的未定义值 请帮我一个示例工作代码.. 想知道这里的问题是什么。

2 个答案:

答案 0 :(得分:1)

add_chart()是WORKBOOK方法之一。尝试这样的代码:

use Spreadsheet::WriteExcel;                             

my $workbook = Spreadsheet::WriteExcel->new('perl.xls'); 
$worksheet   = $workbook->add_worksheet();               
$worksheet->write('A1', 'Hi Chart!');                    
my $chart = $workbook->add_chart( type => 'line', embedded => 1, name => 'pended graph' );

# Insert the chart into the a worksheet.
$worksheet->insert_chart( 'E2', $chart );

<强>更新

问题是使用perl很难更新excel。

  

Excel文件是二进制文件中的二进制文件。它包含   几个相互关联的校验和甚至改变一个字节都可能导致它   变得腐败。

     

因此,您不能简单地附加或更新Excel文件。唯一的办法   实现这一点就是将整个文件读入内存,制作出来   需要更改或添加,然后再次写出文件。

Spreadsheet :: ParseExcel将读入现有的excel文件:

my $parser   = Spreadsheet::ParseExcel->new();
# $workbook is a Spreadsheet::ParseExcel::Workbook object
my $workbook = $parser->Parse('blablabla.xls');

你真正想要的是 Spreadsheet :: ParseExcel :: SaveParser ,它是 Spreadsheet :: ParseExcel Spreadsheet :: WriteExcel 。

Here is an example

总结一下,我建议你阅读excel数据,然后尝试以下任何一种方法:

  • 创建另一个xls文件并使用 Spreadsheet :: WriteExcel :: Chart 库。
  • 创建xlsx文件并使用 Excel :: Writer :: XLSX :: Chart 库。
  • 另一个接近的选择是用中读取excel 电子表格:: ParseExcel :: SaveParser ,然后添加图表并保存
    它,但是使用这个模块,所有原始图表都会丢失。

如果您使用的是Windows计算机,则可以尝试使用 Win32 :: OLE 。 以下是 Win32 :: OLE 自己的文档中的示例:

use Win32::OLE;

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

# get a new workbook
$book = $ex->Workbooks->Add;

# write to a particular cell
$sheet = $book->Worksheets(1);
$sheet->Cells(1,1)->{Value} = "foo";

# write a 2 rows by 3 columns range
$sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ],
                                   [ 42,    'Perl',  3.1415  ]];

# print "XyzzyPerl"
$array = $sheet->Range("A8:C9")->{Value};
for (@$array) {
    for (@$_) {
        print defined($_) ? "$_|" : "<undef>|";
    }
    print "\n";
}

# save and exit
$book->SaveAs( 'test.xls' );
undef $book;
undef $ex;

<强> UPDATE @ 2

以下是一个示例代码:

use strict;
use Spreadsheet::WriteExcel;

my $workbook  = Spreadsheet::WriteExcel->new( 'chart_column.xls' );
my $worksheet = $workbook->add_worksheet();
my $bold      = $workbook->add_format( bold => 1 );

# Add the worksheet data that the charts will refer to.
my $headings = [ 'Category', 'Values 1', 'Values 2' ];
my $data = [
    [ 2, 3, 4, 5, 6, 7 ],
    [ 1, 4, 5, 2, 1, 5 ],
    [ 3, 6, 7, 5, 4, 3 ],
];

$worksheet->write( 'A1', $headings, $bold );
$worksheet->write( 'A2', $data );


###############################################################################
#
# Example 1. A minimal chart.
#
my $chart1 = $workbook->add_chart( type => 'column',  embedded => 1 );

# Add values only. Use the default categories.
$chart1->add_series( values => '=Sheet1!$B$2:$B$7' );

# Insert the chart into the main worksheet.
$worksheet->insert_chart( 'E2', $chart1 );

###############################################################################
#
# Example 2. One more chart
#
my $chart2 = $workbook->add_chart( type => 'column', embedded => 1 );

# Configure the chart.  # change the categories if required change the values as required
$chart2->add_series(
    categories => '=Sheet1!$A$4:$A$7',
    values     => '=Sheet1!$B$4:$B$7',
);

$worksheet->insert_chart( 'N1', $chart2, 3, 3 );

另外,
如果你不介意xlsx xlsx,你可以使用 Excel :: Writer :: XLSX 。它更积极地维护。

答案 1 :(得分:0)

能够同时解析和使用WriteExcel模块内部功能的技巧是使用use Spreadsheet :: ParseExcel :: SaveParser ;模块。

下面我有一个例子。该示例将不使用图表函数,但您遇到的问题不在于如何使用WriteExcel模块的图表函数,而在于如何解析现有的excel文件,然后将解析后的信息与WriteExcel模块一起使用(最初只考虑新的Excel文件)。

if ( ( -f $excel_file_name ) && ( ( stat $excel_file_name )[7] > 0 ) ) {

#PARSE EXCEL
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::SaveParser;

# Open the template with SaveParser
my $parser   = new Spreadsheet::ParseExcel::SaveParser;
my $template = $parser->Parse("$excel_file_name");
my $sheet    = 0;
my $row      = 0;
my $col      = 0;

if ( !defined $template ) {
    die $parser->error(), " Perlline:", __LINE__, " \n ";    #probably the file is already open by your GUI
}

# Get the format from specific cell
my $format = $template->{Worksheet}[$sheet]->{Cells}[$row][$col]->{FormatNo};

# Add a new worksheet
#for my $worksheet ( $template->worksheets() ) {
my $worksheet_parser = $template->worksheet("$metrict_data_worksheet_name");
my ( $row_min, $row_max ) = $worksheet_parser->row_range();
my ( $col_min, $col_max ) = $worksheet_parser->col_range();
my @row_array_value;
for my $row ( 1 .. $row_max ) {    #avoid header start from 1
    for my $col ( $col_min .. $col_max ) {

        my $cell = $worksheet_parser->get_cell( $row, $col );
        next unless $cell;

        #print "Row, Col    = ($row, $col)\n";
        #print "Value       = ", $cell->value(),       "\n";
        #print "Unformatted = ", $cell->unformatted(), "\n";
        #print "\n";
        push( @row_array_value, $cell->value() );

    }    #end header column loops for one regression
}    #end row loop all lines
     #}

# The SaveParser SaveAs() method returns a reference to a
# Spreadsheet::WriteExcel object. If you wish you can then
# use this to access any of the methods that aren't
# available from the SaveParser object. If you don't need
# to do this just use SaveAs().
#
my $workbook;

{
    # SaveAs generates a lot of harmless warnings about unset
    # Worksheet properties. You can ignore them if you wish.
    local $^W = 0;

    # Rewrite the file or save as a new file
    my $check_if_possible2write = Spreadsheet::WriteExcel->new($excel_file_name);
    if ( defined $check_if_possible2write ) {    #if not possible it will be undef
        $workbook = $template->SaveAs("$excel_file_name");#IMPORTANT this is of type WriteExcel and not ParseExcel
    }
    else {
        print "Not possible to write the Excel file :$excel_file_name, another user may have the file open. Aborting... ", __LINE__, " \n ";
        exit;
    }
}
#####################FROM HERE YOU CAN USE AGAIN use Spreadsheet::WriteExcel; ####################
use Spreadsheet::WriteExcel;
my $worksheet = $workbook->sheets("$metrict_data_worksheet_name");

my $column_header_count = 0;
foreach my $name ( sort { lc $a cmp lc $b } keys %merged_all_metrics ) {

    $worksheet->write( $row_max + 1, $column_header_count, "$merged_all_metrics{$name}" );    #row,col start
    $column_header_count++;
}
$worksheet->set_column( 'A:L', 50, undef, 0, 1, 0 );                                          #grouping                                                     #comp_src group
$worksheet->set_column( 'N:R', 50, undef, 0, 1, 0 );                                          #grouping
$workbook->close() or die "Error closing file: $!";                                           #CLOSE
}

代码的重要部分是在注释行之后发生的事情:

#####################FROM HERE YOU CAN USE AGAIN use Spreadsheet::WriteExcel; ####################

在那之后,您将看到您有一个$ workbook处理程序。此变量具有所有已解析的信息,更重要的是它来自WriteExcel Object类型,因此您将使用此模块的所有方法

重要通知。解析器无法解析图表和公式(仅用于解析值),因此您将不得不在每个parse-> write循环中再次编写。