Perl: Spreadsheet::parseexcel (проблема c кодировками)

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

Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

Spreadsheet::ParseExcel - Перл модуль для работы с xls файлами.
Проблема с кодировкой CP1251

когда я юзаю такую конструкцию:

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

use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::FmtUnicode;
my $file='test.xls';
my $spar = new Spreadsheet::ParseExcel;
my $frmt =  Spreadsheet::ParseExcel::FmtUnicode->new(Unicode_Map=>"cp1251");
my $excel = $spar -> Parse($file,$frmt);
    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});
                }
            }
        }
    }

названия листов пишутся на русском, а значения ячеек - нет. причем при изменении кодировок меняются опять же только названия листов, а значения ячеек - нет.
прога взята собственно с www.cpan.org, изменил только первые строки согласно рекомендациям форума http://www.linux.opennet.ru/prog/info/950.shtml
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

SK_666 писал(а):
12.04.2007 20:39
Spreadsheet::ParseExcel - Перл модуль для работы с xls файлами.
Проблема с кодировкой CP1251
...


У меня такой работает

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

#!/usr/bin/perl
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::FmtUnicode;
use Unicode::Map;
use Encode qw/from_to/;

my $file='test.xls';
my $spar = new Spreadsheet::ParseExcel;
my $cp1251 = Unicode::Map->new("CP1251");
my $excel = $spar -> Parse($file);
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) {
                my $value = $cp1251->from_unicode( $cell->{Val} );
                from_to($value, "cp1251", "utf-8");
                print $value, "\n";
                printf("( %s , %s ) => %s\n", $row, $col, $value);
            }
        }
    }
}


P.S. Надеюсь, кто-то подскажет решение покрасивее :)
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

Интересно конечно, но у меня локаль CP1251. а как я вижу тут перекодировка идет из CP1251 в UTF8. и ведь почему-то имена листов у меня пишутся правильно, а вот значения в ячейках - нет. Причем у меня есть еще прога на перле для преобразования XLS в HTML, в ней все нормально работает, хотя вроде все сделано так же как и у меня. Меня интересует именно причина, если кто сккккажет, где ошибка - буду очень благодарен. Приведенная программа - только пример, я ее использую только для того, чтобы в библиотечке разобраться, дальше буду писать прогу, чтоб в XML преобразовывать.
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

SK_666 писал(а):
13.04.2007 20:49
Интересно конечно, но у меня локаль CP1251. а как я вижу тут перекодировка идет из CP1251 в UTF8. и ведь почему-то имена листов у меня пишутся правильно, а вот значения в ячейках - нет. Причем у меня есть еще прога на перле для преобразования XLS в HTML, в ней все нормально работает, хотя вроде все сделано так же как и у меня. Меня интересует именно причина, если кто сккккажет, где ошибка - буду очень благодарен. Приведенная программа - только пример, я ее использую только для того, чтобы в библиотечке разобраться, дальше буду писать прогу, чтоб в XML преобразовывать.


Привести к корретному выводу в локали cp1251 просто
Предположу, что причина в том, что данные в excel пишутся в cp1251, а хранятся в юникоде. А названия листов пишутся и хранятся в юникоде.

UPDATE: предположение фигня скорее всего. Как-то была задачка получения данных и екселя. Как получить данные из перла я понял, но форматом xls особо не интересовался. :)
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

нет, уж это вряд ли. т.к. ексель формат все-таки виндовый. Тем более у меня есть пример, где все нормально работает, если надо - могу зааттачить, но сомневаюсь, что это целесообразно, т.к. пример довольно большой. Я его просмотрел, вроде бы все так как у меня, но почему-то там все нормально. Ладно, сейчас - спать, а уж в понедельник попробую тот вариант упростить, хотя хотелось бы узнать, где у меня ошибка, а не урезать чужой код. Не хочется опять попасть в тупик, когда большая чать проги будет уже написана
Спасибо сказали:
Аватара пользователя
Bruce
Сообщения: 647
Статус: beat maniac
ОС: Debian GNU/Linux 4.0

Re: Perl: Spreadsheet::parseexcel

Сообщение Bruce »

в сисадмине была статья как раз про перл и excel. и у них всё работало ;) предлагаю ознакомиться :)
Samsung r40 (t5500, 1.5G ram, 80 gb hdd)

koolkhel's lj
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

Bruce писал(а):
13.04.2007 23:31
в сисадмине была статья как раз про перл и excel. и у них всё работало ;) предлагаю ознакомиться :)


Дык у меня работает. Вопрос: почему :)
А статью, спасибо, поищем-с
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

SK_666 писал(а):
13.04.2007 23:06
нет, уж это вряд ли. т.к. ексель формат все-таки виндовый. Тем более у меня есть пример, где все нормально работает, если надо - могу зааттачить, но сомневаюсь, что это целесообразно, т.к. пример довольно большой. Я его просмотрел, вроде бы все так как у меня, но почему-то там все нормально. Ладно, сейчас - спать, а уж в понедельник попробую тот вариант упростить, хотя хотелось бы узнать, где у меня ошибка, а не урезать чужой код. Не хочется опять попасть в тупик, когда большая чать проги будет уже написана


В общем, если в твоем первоначальном коде заменить $cell->{Val} на $cell->Value() - все будет ок в локали CP1251. А ексель действительно все данные в юникоде хранит :).
Удачи.
Спасибо сказали:
Аватара пользователя
halturin
Сообщения: 167
ОС: Linux

Re: Perl: Spreadsheet::parseexcel

Сообщение halturin »

а гуглить никто не умеет конечно же...
вот два варианта, как лечить сие:

1)
my $map = Unicode::Map->new("WINDOWS-1251");
my $utf16 = $map->to_unicode("Пример");

$worksheet->write_unicode('A7', $utf16);

2)
use encoding "ru_RU.CP1251";
use Spreadsheet::WriteExcel;

my $workbook=Spreadsheet::WriteExcel->new("-");
my $worksheet=$workbook->add_worksheet("лист 1");
$worksheet->write_string(0, 0, "текст по Русски");
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

halturin писал(а):
14.04.2007 15:38
а гуглить никто не умеет конечно же...
вот два варианта, как лечить сие:

1)
my $map = Unicode::Map->new("WINDOWS-1251");
my $utf16 = $map->to_unicode("Пример");

$worksheet->write_unicode('A7', $utf16);

2)
use encoding "ru_RU.CP1251";
use Spreadsheet::WriteExcel;

my $workbook=Spreadsheet::WriteExcel->new("-");
my $worksheet=$workbook->add_worksheet("лист 1");
$worksheet->write_string(0, 0, "текст по Русски");


Круто! Только тема про Spreadsheet::ParseExcel. И вроде как разобрались :)
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

Всем спасибо за помощь, сейчас доберусь до работы и попробую с Cell->Value()
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

попробовал с Cell->Value().
Проблема с русским решилась, но появилась другая - с числами.
при выводе ячейки с числом (именно когда используется числовой формат) вместо числа выводится GENERAL.
что, делать условие и если значение 'GENERAL', то читать через cell->{Val} ?
Некрасиво как-то. есть лидругое решение?
Возможно есть проблемы с другими форматами ячеек. сталкивался ли кто-нибудь?

еще нашел проблему с денежным форматом: вместо 11руб. выводит 1..[$руб.419].
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

SK_666 писал(а):
15.04.2007 15:42
попробовал с Cell->Value().
Проблема с русским решилась, но появилась другая - с числами.
при выводе ячейки с числом (именно когда используется числовой формат) вместо числа выводится GENERAL.
что, делать условие и если значение 'GENERAL', то читать через cell->{Val} ?
Некрасиво как-то. есть лидругое решение?
Возможно есть проблемы с другими форматами ячеек. сталкивался ли кто-нибудь?

еще нашел проблему с денежным форматом: вместо 11руб. выводит 1..[$руб.419].


Пример xls файла можно с проблемными ячейками?
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

Файл не приаттачивается. вообще создавал в OO, сохранял в формате ms excel.
вообще-то непонятно, почему не приаттачивается. вобщем вот:

Неудачная загрузка. Вам запрещено загружать такой тип файлов
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Perl: Spreadsheet::parseexcel

Сообщение sash-kan »

SK_666 писал(а):
16.04.2007 11:00
такой тип файлов
тип (здесь - суффикс) - издержки cp/m философии, перекочевавшие в dos и движок этого форума.
добавил разрешение на прикрепление файлов с суффиксом .xls
p.s. но можно ведь было обойти и элементарным переименованием. например, добавкой разрешенного суффикса. хотя бы .txt
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

Спасибо. Загружаю файло. Вот что выводит программа при работе с этим файлом.

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

[sk@server excel]$ ./test.pl
Sheet: Лист1
( 0 , 0 ) => A1
( 0 , 1 ) => B1
( 1 , 0 ) => А2 рус
( 1 , 1 ) => В2 рус
( 2 , 0 ) => GENERAL
( 2 , 1 ) => 31
( 3 , 0 ) => 1..0[$руб.419]
( 3 , 1 ) => 12.00%
( 4 , 0 ) => 121212
( 4 , 1 ) => 4.55E+002
Sheet: Лист2
Sheet: Лист3

проблемы с ячейками (2,0) (числовой формат) и (3,0) (денежный формат)
если читать через {Val}, то с этими ячейками все в порядке. Неудели придется писать условие и читать через {Val}?
нет ли более красивого способа?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
tba
Сообщения: 48
ОС: Debian, Centos

Re: Perl: Spreadsheet::parseexcel

Сообщение tba »

SK_666 писал(а):
16.04.2007 15:17
Спасибо. Загружаю файло. Вот что выводит программа при работе с этим файлом.

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

[sk@server excel]$ ./test.pl
Sheet: Лист1
( 0 , 0 ) => A1
( 0 , 1 ) => B1
( 1 , 0 ) => А2 рус
( 1 , 1 ) => В2 рус
( 2 , 0 ) => GENERAL
( 2 , 1 ) => 31
( 3 , 0 ) => 1..0[$руб.419]
( 3 , 1 ) => 12.00%
( 4 , 0 ) => 121212
( 4 , 1 ) => 4.55E+002
Sheet: Лист2
Sheet: Лист3

проблемы с ячейками (2,0) (числовой формат) и (3,0) (денежный формат)
если читать через {Val}, то с этими ячейками все в порядке. Неудели придется писать условие и читать через {Val}?
нет ли более красивого способа?


Да, все так и есть. Сорри сейчас на работе запарка, как разгребусь - посмотрю. Но кроме условия, вижу лишь вариант с написанием своего Fmt класса(куда это условие и вставить). Если найдешь решение - дай знать плз
Спасибо сказали:
Аватара пользователя
SK_666
Сообщения: 58
ОС: open SUSE 10.3, RHEL5

Re: Perl: Spreadsheet::parseexcel

Сообщение SK_666 »

пока с глючными полями не связываюсь, а потом наверное просто условие вставлю. а вообще хорошо-бы саму эту бмблиотечку покопать. кстати и работает она не очень-то быстро
Спасибо сказали: