Использование Spreadsheet :: ParseExcel в Perl, но нужна помощь - PullRequest
4 голосов
/ 27 июля 2011

У меня есть Perl-программа, использующая Spreadsheet :: ParseExcel.Однако возникли две трудности, которые я не смог понять, как решить.Сценарий для программы выглядит следующим образом:

#!/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;однако, почему это имеет значение?Типы файлов и формат точно такие же.

Во-вторых, переменные «$ target» и «$ response» должны быть отформатированы как строки, чтобы выражение «my $ value» работало.Как мне преобразовать их в строковый формат?Значение, присвоенное каждой переменной, является словом из соответствующей ячейки электронной таблицы Excel.Я не знаю, что это за формат (и в Perl нет очевидного способа проверить это).

Есть предложения?

Ответы [ 3 ]

3 голосов
/ 27 июля 2011

Что касается вашего первого вопроса, ошибка «данные не найдены» указывает на некоторую проблему с форматом файла.Я видел эту ошибку с псевдо-Excel файлами, такими как Html или CSV, которые имеют расширение xls.Я также видел эту ошибку с неправильно сформированными файлами, созданными сторонними приложениями.

Вы можете выполнить первоначальную проверку файлов, выполнив дамп hexdump / xxd рабочего и нерабочего файла и посмотрев,общая структура примерно одинакова (например, если в начале она имеет похожие магические числа и не является Html).

Это также может быть проблемой с Spreadsheet :: ParseExcel.Я поддерживаю этот модуль.Если хотите, вы можете прислать мне «хороший» и «плохой» файл на адрес электронной почты в документах, и я посмотрю на них.

0 голосов
/ 29 июля 2011

Я написал этот код после того, как клиент не смог решить, был ли 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; }

}
0 голосов
/ 27 июля 2011

Прежде всего, если вы получаете «данные не найдены», вы можете поблагодарить проприетарные форматы файлов данных Excel и неспособность даже хорошей библиотеки Perl извлекать информацию из них.

Я настоятельно рекомендую вамэкспортируйте данные Excel в нечто, легко разбираемое как CSV, особенно учитывая простую природу макета данных, который вы описали.Может быть способ заставить Excel обработать партию, но я понятия не имею.Быстрый поиск дал инструмент для использования OpenOffice для пакетного преобразования .

Остальной вопрос довольно спорный, если вы признаете, что файлы данных Excel будут воспроизводиться некорректно.

...