Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Системное программирование > Парсим xls


Автор: WERT 26.6.2007, 08:17
Подскажите, какой модуль лучше всего использовать для того, чтобы распарсить Exsel-файл.
есть тема на данном форуме http://forum.vingrad.ru/topic-144702.html, но она не совсем профильная.
Интересует именно чем проще. Предполагается наличие только цифоровой и текстовой информации. Без диаграмм и т.п.

Автор: dimes 26.6.2007, 09:10
Насчет проще не уверен
но я использовал Spreadsheet::ParseExcel
Поищи на search.cpan.org там много разных парсеров, по примерам кодов сам решишь какой самый простой  smile

Автор: nitr 26.6.2007, 09:33
dimes, минус этого модуля - медленно.
WERT, но это самый оптимальный из многих. Можно (если Win OS) потестировать с OLE...

Автор: dimes 26.6.2007, 09:45
Цитата(nitr @  26.6.2007,  10:33 Найти цитируемый пост)
dimes, минус этого модуля - медленно.

Ну, спорить не буду, на скорость я его не тестил.

Автор: WERT 26.6.2007, 09:57

ОК, спасиб, попробую с этим поковыряться smile 

Автор: nitr 26.6.2007, 10:13
WERT, ковыртся не надо. В комплекте с модулем есть примеры - ОЧЕНЬ много smile Думаю ковырятся много не придётся. Если что - то не спешите создавать новую тему - НА ФОРУМЕ есть поиск ;)

Автор: TTT 26.6.2007, 12:38
Поделюсь сабом.
С использованием OLE:
Код

use Win32::OLE;
use Win32::OLE::Variant;
use Win32::OLE::Const 'Microsoft Excel';

sub ParseExcel{
    my $ex_file = shift;
    my $self_excel = {}; my @sheets = ();
    my ($book, $LastRow, $LastCol, $last_cell);
    $book = Win32::OLE->GetObject($ex_file);
    for (my $i=1; $i <= $book->Sheets->{Count}; $i++ ) {
        my $self = {};
        my $sheet = $book->Worksheets($i);
        
        $LastRow = $sheet->UsedRange->Find({What=>"*",
            SearchDirection=>xlPrevious,
            SearchOrder=>xlByRows})->{Row};
        $LastCol = $sheet->UsedRange->Find({What=>"*",
            SearchDirection=>xlPrevious,
            SearchOrder=>xlByColumns})->{Column};
        $last_cell = $sheet->Range("A1")->EntireColumn->SpecialCells(11)->{Address};
        my ($MaxCol, $MaxRow) = $last_cell =~ /\$(\w+)\$(\d+)/;
        $sheet->Columns("A:$MaxCol")->{NumberFormat} = "VT_EMPTY";
        my $array = $sheet->Range("A1:$last_cell")->{Value};
        
        $self->{Name} = $sheet->{Name};
        $self->{MaxRow} = $LastRow;
        $self->{MaxCol} = $LastCol;
        $self->{Cells} = $array;
        
        push @sheets, $self;
    }
    $self_excel->{Worksheet} = \@sheets;
    return $self_excel;
}

Пример вызова
my $excel = ParseExcel("$open_dir.$file_name");

строка 22
($sheet->Columns("A:$MaxCol")->{NumberFormat} = "VT_EMPTY";)
нужна для правильного чтения ячейки в формате даты (подбирал параметр методом тыка).

Поначалу использовал модуль Spreadsheet::ParseExcel, но некоторые файлы он отказывался обрабатывать.
Если на виндозной машине все работать будет, лучше через OLE однозначно.

Надеюсь поможет  smile 

Автор: WERT 27.6.2007, 08:19
Ок, спасибо. Можно считать вопрос исчерпанным. smile 

Автор: Nandy 18.10.2007, 10:31
А вот у меня возник такой вопрос: почему значения массива ячеек заносятся в скалярную переменную?

$array = $sheet->Range("A1:$last_cell")->{Value};

Как же теперь обращаться к отдельным значениям ячеек?
Разве нельзя значения массива ячеек занести в массив, типа 

@array = $sheet->Range("A1:$last_cell")->{Value};

чтобы потом по отдельности обращаться?
Подскажите, пожалуйста.

Автор: nitr 18.10.2007, 14:37
Nandy, вы в курсе - "что есть и будет ссылки" smile ?

$array->[0] - первое знач. в массиве smile и т.п.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)