6

Spreadsheet::ParseExcelを使用したPerlプログラムがあります。しかし、私が解決する方法を理解することができなかったという2つの困難が生じました。プログラムのスクリプトは次のとおりです。

#!/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;
    }  
}

だから、私の2つの問題:

まず、データが存在していても、プログラムが「ファイルにExcelデータが見つかりません」というエラーを返すことがあります。各Excelファイルは同じ方法でフォーマットされます。シートは1つだけで、A列とB列にはそれぞれ「ターゲット」と「応答」のラベルが付いており、その下に単語のリストがあります。ただし、常にこのエラーが返されるわけではありません。1つのExcelファイルに対しては機能しますが、両方がまったく同じ方法でフォーマットされていても、別のファイルに対しては機能しません(もちろん、どちらも同じファイルタイプです)。最初のファイルと同じであるため、2番目のファイルを読み取らない理由を見つけることができません。唯一の違いは、2番目のファイルがExcelマクロを使用して作成されたことです。しかし、なぜそれが重要なのでしょうか?ファイルの種類と形式はまったく同じです。

次に、変数「$target」と「$response」は、「my$value」式が機能するために文字列としてフォーマットする必要があります。それらを文字列形式に変換するにはどうすればよいですか?各変数に割り当てられた値は、Excelスプレッドシートの適切なセルからの単語です。私はそれがどんなフォーマットであるかわかりません(そして私がチェックするためのPerlの明白な方法はありません)。

助言がありますか?

4

3 に答える 3

7

最初の質問に関連して、「データが見つかりません」というエラーは、ファイル形式に何らかの問題があることを示しています。このエラーは、拡張子が xls の Html ファイルや CSV ファイルなどの疑似 Excel ファイルで発生しました。サードパーティのアプリによって生成された不正な形式のファイルでも、このエラーが発生しました。

動作中のファイルと動作していないファイルの hexdump/xxd ダンプを実行し、全体の構造がほぼ同じかどうかを確認することで、ファイルの初期検証を行うことができます (たとえば、最初に同様のマジック ナンバーがあり、Html ではない場合)。 )。

また、Spreadsheet::ParseExcel の問題である可能性もあります。私はそのモジュールのメンテナーです。よろしければ、「良い」ファイルと「悪い」ファイルをドキュメントのメール アドレスに送っていただければ、それらを確認します。

于 2011-07-27T17:05:06.063 に答える
1

まず第一に、「データが見つかりません」というメッセージが表示される場合は、独自の Excel データ ファイル形式と、優れた Perl ライブラリでさえそれらから情報を抽出できないことに感謝できます。

特に、説明したデータ レイアウトの単純な性質を考えると、CSV のような簡単に解析できる形式で Excel データをエクスポートすることを強くお勧めします。Excelでバッチを処理する方法があるかもしれませんが、私にはわかりません。簡単に検索すると、OpenOffice を使用してバッチ変換を行うツールが見つかりました。

Excelデータファイルがうまく再生されないことを受け入れると、質問の残りの部分はかなり意味がなくなります。

于 2011-07-27T15:14:17.840 に答える
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; }

}
于 2011-07-29T15:10:25.350 に答える