【问题标题】:Using Spreadsheet::ParseExcel in Perl, but need help在 Perl 中使用 Spreadsheet::ParseExcel,但需要帮助
【发布时间】:2011-10-14 08:46:16
【问题描述】:

我有一个使用 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 中没有明显的方法可供我检查)。

有什么建议吗?

【问题讨论】:

  • 很高兴看到一些格式良好的代码进行更改!

标签: string perl variables import-from-excel


【解决方案1】:

关于您的第一个问题,“找不到数据”错误表明文件格式存在问题。我在伪 Excel 文件(例如具有 xls 扩展名的 Html 或 CSV 文件)中看到了此错误。我还看到第三方应用生成的格式错误的文件出现此错误。

您可以通过对工作文件和非工作文件进行 hexdump/xxd 转储并查看整体结构是否大致相同(例如,如果它在开始时具有相似的幻数并且不是't HTML)。

Spreadsheet::ParseExcel 也可能存在问题。我是那个模块的维护者。如果您愿意,可以将“好”和“坏”文件发送给我,发送至文档中的电子邮件地址,我会查看它们。

【讨论】:

  • 我对 hexdumps 了解得不够多,无法从中得到任何东西。除非我能弄清楚为什么它不喜欢该文件,否则我可能最终会切换到使用 .txt 文件或其他东西。无论如何,非常感谢,我刚刚给你发了一封电子邮件。
  • 只是为了对此进行更新。有问题的文件实际上是 Excel 2007 xlsx 文件。它们需要使用 Spreadsheet::XLSX 或 Spreadsheet::Read 读取。 Spreadsheet::ParseExcel 只能处理 2007 年以前的文件格式。
【解决方案2】:

首先,如果您得到“找不到数据”,您应该感谢专有的 Excel 数据文件格式,以及即使是好的 Perl 库也无法从中提取信息。

我强烈建议您以易于解析的格式(例如 CSV)导出 Excel 数据,特别是考虑到您描述的数据布局的简单性质。可能有一种方法可以让 Excel 处理一批,但我不知道。快速搜索得到tool to use OpenOffice to do batch conversion

一旦你接受 Excel 数据文件不能很好地播放,你剩下的问题就没有实际意义了。

【讨论】:

    【解决方案3】:

    在客户无法确定他每周发送的 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; }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 2011-03-14
      • 2023-03-06
      • 1970-01-01
      • 2014-11-19
      • 2011-08-06
      • 2020-11-09
      相关资源
      最近更新 更多