Модераторы: ginnie, korob2001
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Spreadsheet::ParseExcel::SaveParser, форматирование эксель файла 
:(
    Опции темы
kosyakLA
Дата 24.6.2011, 04:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



столкнулся с такой проблемой. вот код:

 
Код

   my $parser   = Spreadsheet::ParseExcel::SaveParser->new();
    my $template = $parser->Parse($fileIn);

    for my $worksheet ( $template->worksheet(0) ) {
        my ( $row_min, $row_max ) = $worksheet->row_range();
        my ( $col_min, $col_max ) = $worksheet->col_range();
        for my $row ( $row_min .. $row_max ) {
            for my $col ( $col_min .. $col_max ) {
                my $cell = $worksheet->get_cell( $row, $col );
                next unless $cell;
                $value = $cell->value();

                if($value eq "%driver_fio%") {

                    print $worksheet->cell->font->{Name};
                    print "Row, Col    = ($row, $col)<br>";
                    print "Value       = ", $value,       "<br>";
                    print "<hr>";
                    $fio = Encode::decode('cp1251',"Фамилия"); 
                    $cell->value() = $fio;
                    $worksheet->AddCell( $row, $col, $fio);

                }
            }
        }
    }
         $template->SaveAs($fileOut);


переписывается целиком ячейка эксельная, соответственно и форматирование удаляется. Если возможность:
1) изъять формат ячейки до внесения изменений
2) или же не переписывать ячейку по новой, а просто внести изменения

заранее спасибо
PM MAIL   Вверх
afiskon
Дата 24.6.2011, 06:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 294
Регистрация: 31.3.2011
Где: Россия, Москва

Репутация: нет
Всего: 4



В Spreadsheet::WriteExcel вроде есть форматирование. Как минимум, можно пропарсить табличку вашим модулем и отформатировать этим.
PM MAIL WWW   Вверх
kosyakLA
Дата 24.6.2011, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



В модуле ParseExcel тоже про форматирование сказано...но не нашел инфы как применять
PM MAIL   Вверх
NuINu
Дата 24.6.2011, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 19.7.2008

Репутация: нет
Всего: 6



покажу код, которым я когда то заполнял отчеты по обслуживаемому оборудованию в эксел таблицы, смысл простой имею шаблоннный файл, в котором проставлено форматирование ячеек, далле код читает это форматирование - заголовок, обычная строка, и подвал таблицы отчета. ну то как там работется с форматированием видно.
далее по имеющимся данным формируются файлы с отчетами, и формируются отчет с произвольным количеством строк.

Обращу внимание на функцию МайСейф, дело в том что стандартная процедура сейф сохраняет не всю информацию о  полученной таблице ))) но возвращает указатель ввода.  что дает возможность, досохранить данные, я этим воспользовался и досохранил нужное мне обьединение ячеек.

досохранять там можно много чего...

да замечеу что делалось это довольно двано, так что код вполне возможно или не работает или код современного Spreadsheet уже изменен. не знаю
Код

#!/usr/bin/perl -w

use strict;
use Data::Dumper;

use Encode;
use Spreadsheet::ParseExcel::SaveParser::Workbook;
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::SaveParser;
use Spreadsheet::ParseExcel::FmtUnicode;
use Spreadsheet::WriteExcel;


#читаем файлы из директории raw разбираем данные из них, составляем структуру данных
#полученные данные использую имеющийся файл шаблона xls сохраним в файлы xls в директории xls/

my $raw_dir = "./dlink_raw/";

#получим первичные данные по свичам
my $switch_db  = 'list_dlink_xls';
my $sw_port_db = 'dl2port_name';
my $sw_addr_db = 'dl2router_addr';

my %sw_db;
    #создадим сначала хеш соответвия свитч->[ip, mark]
my ($l, $d, $k);
my @row;
open(F, '<', $switch_db);
while ($l = <F>) {
    chomp $l;
    @row = split(/:/, $l);
    $sw_db{$row[0]} = [$row[1], $row[2]];
}
close(F);
#print "Rezult hash:\n", Dumper(\%sw_db);

    #Теперь загрузим данные по портам для каждого свича
my %sw2port;

open(F, '<', $sw_port_db);
while ($l = <F>) {
    chomp $l;
    @row = split(/:/, $l);
    if(exists $sw2port{$row[0]}) { #свитч уже есть в хеше
        push @{$sw2port{$row[0]}}, [$row[1], $row[2], $row[3], $row[4], $row[5], $row[6]];
    } else {
        $sw2port{$row[0]} = [ [$row[1], $row[2], $row[3], $row[4], $row[5], $row[6]] ]; #иницилизируем ссылку на массив содержащий ссылки на массивы
    }
}
close(F);
#print "Rezult hash:\n", Dumper(\%sw2port);

    #теперь загрузим данные соответвия switch->[улица, дом]
my %sw2addr;
open(F, '<', $sw_addr_db);
while ($l = <F>) {
    chomp $l;
    @row = split(/:/, $l);
    $sw2addr{$row[0]} = [$row[2], $row[3]];
}
close(F);
#print "Rezult hash:\n", Dumper(\%sw2addr);

#теперь для каждого свича заполняем отчет в XLS файл по шаблону
#данные о том что заполнять берем из
foreach my $sw (keys %sw_db) {
    makeXLS($sw, $sw2addr{$sw}, $sw_db{$sw}, $sw2port{$sw});
}

exit(0);


sub get_filelist {
    my $dir = shift;
    opendir(Z, $dir);
    my @listf = grep {-f $dir.$_ } readdir(Z);
    return @listf;
}

sub trim {
    my $str = shift;
    $str =~ s/^\s+//;
    $str =~ s/\s+$//;
    return $str;
}


sub SaveMy {
    my ($oExcel, $oBook, $o_file) = @_;
    my $wBook = $oExcel->SaveAs($oBook, $o_file);
    my @w_sheets=$wBook->sheets();
        #теперь сохраним данные об объединенных ячейках
    for(my $iSheet=0; $iSheet < $oBook->{SheetCount} ; $iSheet++) {
        my $oWkS = $oBook->{Worksheet}[$iSheet];
        my $wWkS = $w_sheets[$iSheet];
            #для каждой WoorkSheet выясняем есть ли у нее объединенные области и сохраняем информацию о них
        #print "Save Merged area sheet[$iSheet]:\n";
        foreach my $merg (@{$oWkS->{MergedArea}}) {
                #print "Save: StartRow: $merg->[0], StartColumn: $merg->[1], EndRow: $merg->[2], EndColumn: $merg->[3]\n";
                $wWkS->merge_cells(@$merg);
        }
    }
    $wBook->set_codepage(1251);
    #open(T, '>', 'debug2.txt');
    #print T "wBook: \n", Dumper($wBook),"\n";
    #close(T);
    return $wBook;
}

sub ru {
    return Encode::decode('koi8r', shift);
}

sub makeXLS {
    my $rez_dir = "./xls_rezDlink/";
    my $ext_xls = ".xls";
    my $shabl_file = './xls_test/shabl1.xls';

    my ($name, $addr, $ip_type, $ports) = @_;
    #начинаем заполнять

    my $oExcel = Spreadsheet::ParseExcel::SaveParser->new();
    my $oBook = $oExcel->Parse($shabl_file);
    my $i_sheet = 0;

    my $sheet = $oBook->{Worksheet}->[$i_sheet];
    binmode(STDOUT=>':encoding(koi8r)');
    
    #Название улицы
    my ($r_i, $c_i) = (1, 3);
    my $l = ru($addr->[0]);
    $oBook->AddCell($i_sheet, $r_i, $c_i, $l, $oBook->{Worksheet}[$i_sheet]->{Cells}[$r_i][$c_i]);
    #Номер дома
    ($r_i, $c_i) = (2, 3);
    $l = ru($addr->[1]);
    $oBook->AddCell($i_sheet, $r_i, $c_i, $l, $oBook->{Worksheet}[$i_sheet]->{Cells}[$r_i][$c_i]);
    #модель оборудования
    ($r_i, $c_i) = (6, 3);
    $l = ru($ip_type->[1]);
    $oBook->AddCell($i_sheet, $r_i, $c_i, $l, $oBook->{Worksheet}[$i_sheet]->{Cells}[$r_i][$c_i]);
    #IP адрес
    ($r_i, $c_i) = (7, 3);
    $l = ru($ip_type->[0]);
    $oBook->AddCell($i_sheet, $r_i, $c_i, $l, $oBook->{Worksheet}[$i_sheet]->{Cells}[$r_i][$c_i]);
    #Пытаемся заполнить табличную часть
    #сохраним форматирование ячеек табличной части
    my (@up_row, @center_row, @down_row); #3 набора форматирований для верхней строки, центральных строк, и нижней строки
    my ($irow_up, $irow_center, $irow_down) = (11, 12, 13); #индексы строк
    my @icol = (0..5);
    #формат массива- номер порта:тип:вилан:тип порта:имя: лицевой счет
    #[$row[1], $row[2], $row[3], $row[4], $row[5], $row[6]]
    my @transl = (0, 1, 4, 5, 2, 3);
    #my ($icol_num, $icol_type, $icol_abon, $icol_lc, $icol_vlan, $col_stype) = @icol;

    foreach my $i (@icol) {
        #форматы верхней строки
    push @up_row,  $oBook->{Worksheet}[$i_sheet]->{Cells}[$irow_up][$i]->{FormatNo};
         #форматы средней строки
    push @center_row, $oBook->{Worksheet}[$i_sheet]->{Cells}[$irow_center][$i]->{FormatNo};
         #форматы нижней строки
    push @down_row, $oBook->{Worksheet}[$i_sheet]->{Cells}[$irow_down][$i]->{FormatNo};
    }
    my $cnt = 0;
    my $fmt;

    foreach my $row_save (@$ports) {
    foreach my $i (@icol) {
             #выберем формат для ячейки в зависимости от того первая она средняя или последняя
         if($cnt == 0) {
         $fmt = $up_row[$i];
         } elsif ($cnt < $#$ports) {
         $fmt = $center_row[$i];
         } else { #последняя строка
         $fmt = $down_row[$i];
         }
         #добавим ячейку
         $oBook->AddCell($i_sheet, $irow_up+$cnt, $i, ru($row_save->[ $transl[$i] ]), $fmt);
    }
    $cnt++;
    }

    SaveMy($oExcel, $oBook, $rez_dir.$name.$ext_xls)->close();

}


PM MAIL   Вверх
kosyakLA
Дата 27.6.2011, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



Я так понял, что {FormatNo} - это тип поля будет числовой?...а как задать тип поля текстовый?
PM MAIL   Вверх
kosyakLA
Дата 27.6.2011, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



В обшем проблема в мерджет целлс(...как из сохранить не пойму...пролучают вот что


    my $parser   = Spreadsheet::ParseExcel::SaveParser->new();
    my $template = $parser->Parse($fileIn);

    for my $worksheet ( $template->worksheet(0) ) {

        foreach my $merg (@{$worksheet->{MergedArea}}) {
            print $merg->[0];
        }

        my ( $row_min, $row_max ) = $worksheet->row_range();
        my ( $col_min, $col_max ) = $worksheet->col_range();
        for my $row ( $row_min .. $row_max ) {
            for my $col ( $col_min .. $col_max ) {
                my $cell = $worksheet->get_cell( $row, $col );
                next unless $cell;
                my $value = $cell->value();
                my $format = $cell->get_format();
                foreach $newVals(keys %arrayData) {
                    if($value =~/$newVals/igs) {
                        my $mrg = $cell->is_merged();
                        my $out_val = Encode::decode('cp1251',$arrayData{$newVals});
                        my $format_number = $cell->{FormatNo};
                        $value=~s/$newVals/$out_val/igs;
                        $worksheet->AddCell( $row, $col, "$value$arrayData{add_symbol}", $format_number);
                    }
                }
            }
        }
    }
у 
    $template->SaveAs($fileOut);

к какому объектру в моем случае нужно применить merge_cells? чтобы они не потерялись

в примере вообще не понял, что есть $wWkS
PM MAIL   Вверх
NuINu
Дата 27.6.2011, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 19.7.2008

Репутация: нет
Всего: 6



Цитата(kosyakLA @  27.6.2011,  07:56 Найти цитируемый пост)
Я так понял, что {FormatNo} - это тип поля будет числовой?...а как задать тип поля текстовый?


 по команде $oBook->{Worksheet}[$i_sheet]->{Cells}[$irow_center][$i]->{FormatNo}; вы получаете номер формата определенного для конкретной ячейки, как он может быть текстовым? если может посмотрите полностью поле дампом.
не понимаю зачем вам именно текстовое название формата?




Цитата(kosyakLA @  27.6.2011,  12:59 Найти цитируемый пост)
 обшем проблема в мерджет целлс(...как из сохранить не пойму...пролучают вот что

вы совершенно не прочитали то что я написал, и код программы, там ведеться работа специально  по сохранению данного форматирования.

Цитата(kosyakLA @  27.6.2011,  12:59 Найти цитируемый пост)
 в примере вообще не понял, что есть $wWkS
к какому объектру в моем случае нужно применить merge_cells? чтобы они не потерялись
 

ну как что? мы сохраняем книгу, в книге есть страницы шити, там стоит цикл пройтись по всем страницам
и что бы не городить длинные ссылки я присваиваю адрес конкретной странцы этой переменной, w это рабочая WkS воркшит страница.

ну к какому обьекту применять? у меня там даже расшифровка стоит отладочная что получается  при @{$oWkS->{MergedArea}}
тут из обьекта извлекаются диапазоны которые выделены как обьединенные ячейки.
в моем случае я применяю мердже целс в УЖЕ СОХРАНЕННОМ документе, к диапазону ячеек.
в вашем случае надо применять тоже к диапазону для кторого вы хотите чтобы он был обьединен. 

Это сообщение отредактировал(а) NuINu - 27.6.2011, 17:08
PM MAIL   Вверх
NuINu
Дата 27.6.2011, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 19.7.2008

Репутация: нет
Всего: 6



ну и если у вас в исходной книге есть форматирование с обьединением ячеек а при изменении значений оно удаляется, ну перед изменением возьмите как у меня и методом @{$oWkS->{MergedArea}}  сохраните все обьединенные диапазоны в массиве, а потом при сохранении продитесь по этому диапазону, и все будет сохранено.
PM MAIL   Вверх
kosyakLA
Дата 28.6.2011, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



перечитал ещё раз....

добавил к своему коду:

    $wBook = $template->SaveAs($fileOut);

    my @w_sheets=$wBook->sheets();

    for(my $iSheet=0; $iSheet < $template->{SheetCount} ; $iSheet++) {
        my $oWkS = $template->{Worksheet}[$iSheet];
            my $wWkS = $w_sheets[$iSheet];
            foreach my $merg (@{$oWkS->{MergedArea}}) {
                    $wWkS->merge_cells(@$merg);
        }      
    }

    $wBook->close();


Правда не срабатывает после сохранения данный код. Ошибок не выдает по строкам пробегается.
PM MAIL   Вверх
kosyakLA
Дата 28.6.2011, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



Сегодня попробовал Ваш код. Результат такой же. По виду файла сделал вывод, что просто мерж кривой какой-то делается или просто не применяется. По крайней мере, если например объединяешь в исходном файле несколько вертикальных ячеек и ставишь в свойствах переносить по строкам , то после обработки "переностить по строкам" остается, а галочка "объединить ячейки" исчезает
PM MAIL   Вверх
NuINu
Дата 28.6.2011, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 19.7.2008

Репутация: нет
Всего: 6



ну что я могу сказать ищите пробуйте, все работает! смотрите демо

в конце у файла убирите .pl

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  demo.tar.gz.pl 3,49 Kb
PM MAIL   Вверх
kosyakLA
Дата 30.6.2011, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 16.2.2007

Репутация: нет
Всего: нет



В примере так же не ставится галочка ;-)...У меня в файле около 100 smile  ячеек таких...работает очччч. криво метод этот...поэтому нашел более хорошую альтернативу - сохраняю в xml...там намного проще все редактировать
PM MAIL   Вверх
shamber
Дата 30.6.2011, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1422
Регистрация: 5.9.2006
Где: Россия

Репутация: 1
Всего: 18



Цитата(kosyakLA @  30.6.2011,  14:03 Найти цитируемый пост)
нашел более хорошую альтернативу - сохраняю в xml...там намного проще все редактировать 

я в свое время проблему решил подобным образом. Работал с XML
PM MAIL Jabber   Вверх
NuINu
Дата 30.6.2011, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 19.7.2008

Репутация: нет
Всего: 6



Цитата(kosyakLA @  30.6.2011,  12:03 Найти цитируемый пост)
В примере так же не ставится галочка 


вы хотите сказать что в файле DemoXls1.xls ячейки не обьединены?
не знаю чем вы смотрите я смотрю опенофисом, все форматирование есть.

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

Это сообщение отредактировал(а) NuINu - 1.7.2011, 11:33
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: Системное программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к системному программированию на Perl
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1207 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.