我有一个使用Spreadsheet :: ParseExcel的Perl程序。但是,出现了两个困难,我无法弄清楚如何解决。该程序的脚本如下:
#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseExcel;
use WordNet::Similarity::lesk;
use WordNet::QueryData;
my $wn = WordNet::QueryData->new();
my $lesk = WordNet::Similarity::lesk->new($wn);
my $parser = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse ( 'input.xls' );
if ( !defined $workbook ) {
die $parser->error(), ".\n";
}
WORKSHEET:
for my $worksheet ( $workbook->worksheets() ) {
my $sheetname = $worksheet->get_name();
my ( $row_min, $row_max ) = $worksheet->row_range();
my ( $col_min, $col_max ) = $worksheet->col_range();
my $target_col;
my $response_col;
# Skip worksheet if it doesn't contain data
if ( $row_min > $row_max ) {
warn "\tWorksheet $sheetname doesn't contain data. \n";
next WORKSHEET;
}
# Check for column headers
COLUMN:
for my $col ( $col_min .. $col_max ) {
my $cell = $worksheet->get_cell( $row_min, $col );
next COLUMN unless $cell;
$target_col = $col if $cell->value() eq 'Target';
$response_col = $col if $cell->value() eq 'Response';
}
if ( defined $target_col && defined $response_col ) {
ROW:
for my $row ( $row_min + 1 .. $row_max ) {
my $target_cell = $worksheet->get_cell( $row, $target_col);
my $response_cell = $worksheet->get_cell( $row, $response_col);
if ( defined $target_cell && defined $response_cell ) {
my $target = $target_cell->value();
my $response = $response_cell->value();
my $value = $lesk->getRelatedness( $target, $response );
print "Worksheet = $sheetname\n";
print "Row = $row\n";
print "Target = $target\n";
print "Response = $response\n";
print "Relatedness = $value\n";
}
else {
warn "\tWroksheet $sheetname, Row = $row doesn't contain target and response data.\n";
next ROW;
}
}
}
else {
warn "\tWorksheet $sheetname: Didn't find Target and Response headings.\n";
next WORKSHEET;
}
}
所以,我的两个问题:
首先,有时程序会返回错误“文件中找不到Excel数据”,即使数据存在。每个Excel文件的格式都相同。只有一张纸,A和B列分别标有“目标”和“响应”,下面有一个单词列表。但是,它始终不会返回此错误。它适用于一个Excel文件,但它不适用于另一个Excel文件,即使两者的格式完全相同(并且是的,它们也是相同的文件类型)。我找不到任何理由不读取第二个文件,因为它与第一个文件相同。唯一的区别是第二个文件是使用Excel宏创建的;但是,为什么会这么重要?文件类型和格式完全相同。
其次,变量'$ target'和'$ response'需要格式化为字符串,以便'my $ value'表达式起作用。如何将它们转换为字符串格式?分配给每个变量的值是来自Excel电子表格的相应单元格的单词。我不知道是什么格式(并且在Perl中没有明显的方法供我检查)。
有什么建议吗?
答案 0 :(得分:3)
关于您的第一个问题,“未找到数据”错误表示文件格式存在问题。我在伪Excel文件中看到了这个错误,例如具有xls扩展名的Html或CSV文件。我也看到了第三方应用生成的格式错误的文件出现此错误。
您可以通过对工作和非工作文件执行hexdump / xxd转储来查看文件的初始验证,并查看整体结构是否大致相同(例如,如果它在开始时具有相似的幻数并且不是'Html)。
Spreadsheet :: ParseExcel也可能存在问题。我是该模块的维护者。如果您愿意,可以通过文档中的电子邮件地址向我发送“好”和“坏”文件,我将会看一下它们。
答案 1 :(得分:0)
首先,如果您收到“未找到数据”,您可以感谢专有的Excel数据文件格式以及即使是一个优秀的Perl库也无法从中提取信息。
我强烈建议您将Excel数据导出为像CSV一样易于解析的内容,特别是考虑到您所描述的数据布局的简单特性。可能有办法让Excel处理批处理但我不知道。快速搜索产生了tool to use OpenOffice to do batch conversion。
一旦您接受Excel数据文件无法正常播放,您的其余问题就没有实际意义了。
答案 2 :(得分:0)
在客户无法确定他每周发送的XLS是否真的是XLS格式还是只有CSV格式之后,我写了这段代码.... HTH!
sub testForXLS ()
{
my ( $FileName ) = @_;
my $signature = '';
my $XLSsignature = 'D0CF11E0A1B11AE10000';
open(FILE, "<$FileName")||die;
read(FILE, $buffer, 10, 0);
close(FILE);
foreach (split(//, $buffer))
{ $signature .= sprintf("%02x", ord($_)); }
$signature =~ tr/a-z/A-Z/;
if ( $signature eq $XLSsignature )
{ return 1; } else { return 0; }
}