2#МОК#Федяков#Андрей#9#М#ГОР#ВОРОНЕЖ#УЛ ШЕНДРИКОВА 7#394086#0732 317825#0#0#0#0#0#0#0#0#0#0#0#0
2#МОК#Амшеникова#Наталия#8#М##ВОРОНЕЖ#УЛ ШЕНДРИКОВА 7#394086#0732 317821#0#0#0#2#0#3#5#0#3#5#0#18
2#УЧЕБНО ВОСПИТАТЕЛЬНЫЙ КОМПЛЕКС#Протасов#Виталий#8#М#ГОР#ВОРОНЕЖ#УЛ ГЕРОЕВ СИБИРЯКОВ 5#394051#80732 335836#7#0#7#0#7#0#2#0#7#7#0#37
1#МУНИЦИПАЛЬНЫЙ ЛИЦЕЙ#Головин#Алексей#8#М#ГОР#ВОРОНЕЖ#УЛ ЛИЗЮКОВА 81#394088#0732 137587#7#7#7#7#7#6#7#7#7#7#0#69
0#ЯЗ ГИМНАЗИЯ ИМ А В КОЛЬЦОВА#Корж#Дмитрий#11#Б##ВОРОНЕЖ# ВОЛОДАРСКОГО 41#394000#0732 552759#3#8#6#8#7#4#6#0#0#0#0#42
0#ЯЗ ГИМНАЗИЯ ИМ А В КОЛЬЦОВА#Ладная#Екатерина#11#Б##ВОРОНЕЖ# ВОЛОДАРСКОГО 41#394000#0732 552759#4#5#4#7#6#3#3#0#0#0#0#32
0#ЯЗ ГИМНАЗИЯ ИМ А В КОЛЬЦОВА#Кузнецова#Наталья#11#Б##ВОРОНЕЖ# ВОЛОДАРСКОГО 41#394000#0732 552759#4#5#4#6#6#4#3#0#0#0#0#32
0#ЯЗ ГИМНАЗИЯ ИМ А В КОЛЬЦОВА#Де-Жорж#Инна#11#Б##ВОРОНЕЖ# ВОЛОДАРСКОГО 41#394000#0732 552759#4#5#4#6#6#4#3#0#0#0#0#32
0#ЯЗ ГИМНАЗИЯ ИМ А В КОЛЬЦОВА#Загонова#Виктория#11#Б##ВОРОНЕЖ# ВОЛОДАРСКОГО 41#394000#0732 552759#4#5#4#8#5#1#3#0#0#0#0#30
0#ГИМНАЗИЯ ИМ А В КОЛЬЦОВА#Гудков#Илья#11#Б#ГОР#ВОРОНЕЖ#УЛ ВОЛОДАРСКОГО 41#394000#0732 552759#4#4#4#6#3#2#3#0#0#0#0#26
2#МОК#Вдовина#Вера#11#Б##ВОРОНЕЖ#УЛ ШЕНДРИКОВА 7#394086#80732 317825#2#6#5#5#2#2#2#0#0#0#0#24
72#ШКОЛА#Холявка#Марина#11#Б##ВОРОНЕЖ# ЮЖНОМОРАВСКАЯ 18#394062#0732 331084#5#6#8#7#9#6#9#0#0#0#0#50
4#СРЕДНЯЯ ШКОЛА#Лукина#Дарья#11#Б#ГОР#ВОРОНЕЖ#БУЛЬВАР ПИОНЕРОВ 14#394038#0732 336762#3#6#6#2#3#3#2#0#0#0#0#25
4#СРЕДНЯЯ ШКОЛА#Кварацхелия#Кристина#11#Б#ГОР#ВОРОНЕЖ#БУЛЬВАР ПИОНЕРОВ 14#394038#0732 336730#3#5#6#3#3#3#0#0#0#0#0#23
...
и т.д.
Сначала это, правда, был файл *.dbf, но его при помощи программы
#!/usr/bin/perl
qx[dbfdump --fs="\x18" --rs="\x19" olimp.dbf >one.txt];
сделали текстовым, потом perl -i -n -p -e 's!\x18!#!;
s!\x19!\n!;' one.txt получили исходный.
Нужно сделать рассылку по школам, т.е. отсортировать по городам, по
названиям школ
и в каждую поместить по пользователю. Выходные данные должны быть в формате
excel,
т.к. для каждого конверта нужны полный адрес школы и список результатов
каждого учащегося.
Причем, excel позволяет отдавать на печать файлы
постранично, т.е. для каждой школы отдельная
страничка и потом удобно все это раскладывать по конвертам, т.е. нужно в
файле excel поставить
разрывы страниц. Данную задачу реализует следующий скрипт:
#!/usr/bin/perl
use Spreadsheet::WriteExcel;
open F, "<one.txt"; @mass=<F>; close F;
@res1=grep{s!^(.*?#.*?#)(.*?#.*?#.*?#.*?#)(.*?#.*?#)!$3$1$2!} @mass;
@res = grep{!$_{$_}++}
map{/^(.*?#.*?#).*?#.*?#/} @res1;
for $gr(@res){
for $line(@res1){push @{$hash{$gr}{$1}}, $2
if $line=~m!$gr(.*?#.*?#)(.*)$!}
}
my $workbook = Spreadsheet::WriteExcel->new("olimp2.xls");
my $sheet = $workbook->addworksheet("all children");
my $format = $workbook->addformat();
$format ->set_text_wrap();
$format->set_bold();
$format->set_size(11);
$format->set_color('blue');
$format->set_align('center');
$sheet->set_column(1, 3, 70);
$sheet->set_row(0,30);
$sheet->activate();
print "end build hash\n";
print "write file...\n";
for $a(sort keys %hash){
$m=$a; $m=~s!#! !ig;
for $key(sort keys %{$hash{$a}}){
$pb++;
$u=$key; $u=~s!#! !ig; $i++;
my $from = join " " => @{[split /#/ => ${$hash{$a}{$key}}[0]]}[4..6];
$sheet->write($i, 0, "$m $u $from", $format) if $pb >= 2000;
for my $test(sort @{$hash{$a}{$key}}){ $i++; $h++;
my $name = join " " => @{[split /#/ => $test]}[0 .. 3];
my $nums = join " " => @{[split /#/ => $test]}[7 .. 18];
$sheet->write($i, 0, "$name $nums") if $pb >= 2000;
}
print "$pb\n" if $pb % 1000 == 0;
$sheet->set_h_pagebreaks($i+1) if $pb >= 2000;
}
}
print "$m $u $from\n";
print "$h - done\n";
Разберем его работу. Скрипт использует хеши хешей массивов. Строчка
@res1=grep{s!^(.*?#.*?#)(.*?#.*?#.*?#.*?#)(.*?#.*?#)!$3$1$2!}
@mass;
заполняет массив будущими ключи хеша по названию города и улицы, т.к. в
городе Саратов
вполне может встретится воронежская или ленинградская улица, что смешает
результаты.
Строчка @res = grep{!$_{$_}++} map{/^(.*?#.*?#).*?#.*?#/}
@res1; убирает
повторяющиеся элементы для вложенного хеша, т.е. выделяет названия адресов
школ.
Цикл
for $gr(@res){
for $line(@res1){push @{$hash{$gr}{$1}}, $2
if $line=~m!$gr(.*?#.*?#)(.*)$!}
}
заполняет хеш хешей массивов. Далее требуется чтение man
Spreadsheet::WriteExcel
и начинаем вывод их хеша и запись файла excel.
Строчка
my $from = join " " => @{[split /#/ =>
${$hash{$a}{$key}}[0]]}[4..6];
расшифровывается как взять нулевой элемент массива ${$hash{$a}{$key}}, потом
разрезать его по строчкам в массив по разделителю #: [split /#/ => ${$hash{$a}{$key}}[0]].
Далее взять от массива срез, превратить его в строку, которая будет являться
адресом. Одно "но", excel
не позволяет ставить более 1000 pagebreaks для
каждого открытого файла, и поэтому приходится
придумывать различные условия, вроде постраничного вывода. Т.к. надо было
сделать быстро, то дабы не писать постраничный вывод обошелся условием
if $pb >= 1000 ... etc....Т.е. следите за обновлениями www.cpan.org! :)