perl (обработка xlsx)

Модератор: Модераторы разделов

Аватара пользователя
landgraf
Сообщения: 2142
Статус: *бунту ненавистник
ОС: linux

perl

Сообщение landgraf »

Появилась задачка для упрощения своей работы преобразовать большие XLSX файлы во что-то более автоматизированное и удобочитаемое.

Нашел перловый скрипт:

Код: Выделить всё

 use Text::Iconv;
 my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
 use Spreadsheet::XLSX;
 my $excel = Spreadsheet::XLSX -> new ('test.xlsx', $converter);

 foreach my $sheet (@{$excel -> {Worksheet}}) {

        printf("Sheet: %s\n", $sheet->{Name});

        $sheet -> {MaxRow} ||= $sheet -> {MinRow};

         foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) {

                $sheet -> {MaxCol} ||= $sheet -> {MinCol};

                foreach my $col ($sheet -> {MinCol} ..  $sheet -> {MaxCol}) {

                        my $cell = $sheet -> {Cells} [$row] [$col];

                        if ($cell) {
                            printf("  %s %%  %s %%  %s\n", $row, $col,  $cell -> {Val});
                        }

                }

        }

 }


Который выводит весь файл в виде:
Номер строки % Номер столбца % содержание ячейки



Так как перловку я знаю плохо ( а всякие двойные операторы еще хуже), помогите, пожалуйста, модернизировать срипт чтобы он выводил файл, например, так:

номер строки % номер столбца -> содержимое ячейки % номер столбца -> содержимое ячейки

то есть по одной строке на каждую строку xlsx файла
заранее благодарен
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: perl

Сообщение diesel »

как-то так можно(имя файла в качестве аргумента передается)

Код: Выделить всё

vasiliy@eifel:~$ cat 0.pl
#!/usr/bin/perl

use Text::Iconv;
my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
use Spreadsheet::XLSX;
my $excel = Spreadsheet::XLSX -> new ($ARGV[0], $converter);

foreach my $sheet (@{$excel -> {Worksheet}}) {

        printf("Sheet: %s\n", $sheet->{Name});

        $sheet -> {MaxRow} ||= $sheet -> {MinRow};

         foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) {

                $sheet -> {MaxCol} ||= $sheet -> {MinCol};

                print "$row";
                foreach my $col ($sheet -> {MinCol} ..  $sheet -> {MaxCol}) {

                        my $cell = $sheet -> {Cells} [$row] [$col];

                        if ($cell) {
                            printf(" %%  %s  -> %s", $col,  $cell -> {Val});

                        }

                }
                print "\n";

        }

}
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: perl

Сообщение diesel »

Правда, чтобы это было удобно парсить традиционными утилитами, я бы сделал как-то так(предполагая что ":::" - можно использовать в качестве разделителя, потому как внутри данных оно врядли есть):

Код: Выделить всё

#!/usr/bin/perl

use Text::Iconv;
my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
use Spreadsheet::XLSX;
my $excel = Spreadsheet::XLSX -> new ($ARGV[0], $converter);

foreach my $sheet (@{$excel -> {Worksheet}}) {

        printf("Sheet: %s\n", $sheet->{Name});

        $sheet -> {MaxRow} ||= $sheet -> {MinRow};

         foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) {

                $sheet -> {MaxCol} ||= $sheet -> {MinCol};

                print "$row";
                foreach my $col ($sheet -> {MinCol} ..  $sheet -> {MaxCol}) {

                        my $cell = $sheet -> {Cells} [$row] [$col];

                        # if ($cell) {
                        #                    printf(" %%  %s  -> %s", $col,  $cell -> {Val});

                        #}

                        print ":::" . $cell->{Val};

                }
                print "\n";

        }

}


А для себя я бы его сделал вот таким(разбрасывает данные в текстовые файлы вида "Название оригинального файла"-"название sheet'а", c разделителем ":::" и без номеров строк):

Код: Выделить всё

#!/usr/bin/perl

use Text::Iconv;
my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
use Spreadsheet::XLSX;
my $excel = Spreadsheet::XLSX -> new ($ARGV[0], $converter);

foreach my $sheet (@{$excel -> {Worksheet}}) {

        printf("Sheet: %s\n", $sheet->{Name});

        $sheet -> {MaxRow} ||= $sheet -> {MinRow};

                open (FILE, ">", $ARGV[0]."-".$sheet->{Name});
         foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) {

                $sheet -> {MaxCol} ||= $sheet -> {MinCol};

                                #       print "$row";
                foreach my $col ($sheet -> {MinCol} ..  $sheet -> {MaxCol}) {

                        my $cell = $sheet -> {Cells} [$row] [$col];

                                                # if ($cell) {
                                                #                    printf(" %%  %s  -> %s", $col,  $cell -> {Val});

                                                #}

                                                print FILE ":::" . $cell->{Val};

                }
                print FILE "\n";

        }
                close(FILE);

}
Спасибо сказали:
Аватара пользователя
landgraf
Сообщения: 2142
Статус: *бунту ненавистник
ОС: linux

Re: perl

Сообщение landgraf »

diesel
Спасибо. Я дальше результат буду питоном разбирать по кирпичикам.
Спасибо сказали: