Антон Орлов (Москва)
Эта проблема нередко возникает при разработке сайтов для небольших организаций. В таких фирмах основной документ для покупателей — прайс-лист — просто готовится в программе типа Excel и распечатывается на принтере. Однако наличия прайс-листа в торговом зале недостаточно, его еще необходимо поместить на сайт, чтобы удаленные пользователи также могли ознакомиться с ценами. Поместить прайс-лист в zip-архиве несложно, но, к сожалению, не все посетители смогут им воспользоваться: на компьютерах Интернет-салонов, офисов иногда отсутствуют программы для распаковки архивов. Поэтому часто требуется разместить на веб-страницах сайта еще и онлайновую версию прайс-листа, доступную посредством браузера.
Оформить его в виде веб-страницы уже куда как сложнее, особенно если требуется вписать его в общий дизайн сайта: в этом случае ничего не даст и средство «сохранения в формате HTML», встроенное в офисный продукт Microsoft. Можно, конечно, нанять специального человека, чтобы он ежедневно за пару часов заверстывал тысячестрочечный прайс в веб-страницу, но, как вы понимаете, это не выход…
А можно прибегнуть к помощи языка программирования PHP, сделав интерфейс для загрузки прайса на сайт и его автоматического «заверстывания» в дизайн сайта.
Постановка задачи
Примерные требования к интерфейсу загрузки могут выглядеть примерно так (возьмем для примера фирму, торгующую компьютерными комплектующими):
1. На страницах сайта должен располагаться прайс-лист фирмы: список товаров и цен на них.
2. Прайс-лист должен быть разбит на категории: списки процессоров, жестких дисков, мониторов должны располагаться на разных веб-страницах.
3. Исходная форма прайс-листа — файл Excel. Администратор сайта должен иметь возможность отправлять этот файл на сайт с тем, чтобы внести изменения в находящиеся на сайте прайс-листы.
4. Число действий администратора должно быть сведено к минимуму, а знание HTML, PHP и языков программирования от администратора не требуется.
Если поразмышлять над поставленной задачей, то особенности ее решения могжно сформулировать следующим образом.
* Прайс-лист должен быть разбит на разделы. Чтобы обеспечить выведение данных по каждому из разделов прайса на свою веб-страницу, имеет смысл:
— хранить в отдельной папке данные всех разделов прайс-листа;
— данные каждого из разделов помещать в отдельный файл;
— сделать специальный сценарий «вывод раздела», который выбирал бы из этой папки файл с данными нужного раздела и включал эти данные в выводимую им веб-страницу;
— чтобы сценарий знал, какой файл выбрать, передавать ему указание о файле через переменную в ссылке — по типу http://www.*****.ru/price.php?razdel=12.
* У каждого раздела прайс-листа должно быть название. Оно должно выводиться в списке разделов на главной странице прайс-листа и наверху каждой из веб-страницы с содержимым раздела. Проще всего помещать это название в самом файле с данными раздела, при выведении данных раздела на веб-страницу его особым образом оформлять, а для списка разделов собирать названия из всех файлов (лучше это сделать один раз заранее при загрузке, но можно и каждый раз при обращении посетителя).
* Научить программу на PHP понимать формат файла Excel — сложная задача (официальных описаний этого формата нет). Поэтому перед помещением на сайт прайс-лист в формате Excel необходимо конвертировать в обычный текстовый файл. Такая функция в Excel имеется: «Файл — Сохранить как… — «Текстовые файлы с разделителями табуляции», и именно табуляциями будут разделены в полученном файле значения различных ячеек одной строки. Перед конвертацией из прайс-листа также следует удалить все лишнее, например, заголовок с логотипом фирмы.
* Так как после загрузки прайс-листа на сайт программа на PHP должна будет разделить полученный текстовый файл на части (разделы), поместив данные каждого из разделов в отдельный текстовый файл, то для этого в текстовом файле и в исходном файле Excel должны быть границы между будущими разделами прайс-листа. Если же таких разделителей не имеется, их необходимо туда вставить, например, написав макрос для Excel, вставляющий разделители.
Алгоритм решения
Решение задачи может быть следующим. Допустим, у нас есть прайс-лист (рис. 1), и нам надо выкладывать на сайт именно его. Необходимо написать следующие программы:
1. Программу предварительной подготовки прайс-листа.
Эта программа из исходного прайс-листа удалит заголовок (в нашем примере — первые 6 строк), после чего сохранит Excel-файл с листом в формате «Текстовые файлы с разделителями табуляции». Это может сделать макрокоманда на встроенном в Microsoft Office языке программирования VBA. Хотя, по большому, счету, выполнить данные действия нетрудно и вручную.
2. Программу загрузки прайс-листа на сайт.
Полученный текстовый файл должен быть закачан на сайт — это сделает стандартный PHP-сценарий загрузки файла, уже ранее рассматривавшийся в нашем журнале.
3. Программу разделения прайс-листа на отдельные файлы с данными каждого из разделов. Закачанный текстовый файл должен быть разбит на отдельные текстовые файлы, в каждом из которых содержится информация одного из разделов прайс-листа — «Процессоры», «Жесткие диски» и т. д. Проще всего при разделении прайс-листа на разделы помещать каждый раздел в файл со специально составляемым именем, включающим в себя увеличивающееся число — например, первый выделенный из прайс-листа раздел поместить в файл с именем «price1.txt», второй — «price2.txt», третий — «price3.txt» и так далее.
4. Программу создания списка разделов.
При подобном сохранении вверху каждого из текстовых файлов с данными раздела окажется название этого самого раздела. Чтобы сценариям вывода было удобнее выводить список разделов, имеет смысл приказать программе «вытащить» эти самые первые строчки из всех файлов и поместить их в отдельный файл «список» в порядке увеличения числа в именах файлов.
Это все были программы, срабатывающие однажды — при загрузке прайс-листа на сайт. А вот еще две программы, которые потребуются для вывода содержимого прайс-листа посетителю.
5. Программа вывода списка разделов.
Эта программа должна просмотреть файл со списком разделов, вывести на веб-страницу строчки этого файла в столбик друг за другом, сделав каждую строчку ссылкой на страницу со сценарием «вывод раздела», указав в ней номер раздела, соответствующий порядковому номеру этой строчки.
6. Программу вывода содержимого раздела.
Эта программа должна на основании переданной переменной составить имя нужного файла раздела, добавив спереди к ее значению символы «price» (в нашем случае), а сзади — «.txt», после чего, взяв файл с этим именем, вывести на веб-страницу его строчки. Удобнее всего вставить их в таблицу и задать каждой четной строчке таблицы белый цвет фона, а каждой нечетной — серый, чтобы лучше читалось
Реализация алгоритма
Макрос для сохранения файла Excel в текстовом формате можно сделать, если включить режим записи макроса и, удалив лишние строки, сохранить полученный лист как «Текстовый файл с разделителями табуляции». Если в исходном прайс-листе уже были комбинации символов, которые можно использовать как разделители разделов (например, на рис. 1 это семь «звездочек» подряд), то макрос придется дополнить командами вставки таких разделителей в прайс-лист.
Следует сделать стандартную форму загрузки файла с прайсом (допустим, что сценарии разделения и оформления файла находятся на странице div.php), при необходимости дополнив его системой авторизации:
<FORM ENCTYPE=»multipart/form-data» ACTION=&qoutdiv.php» METHOD=POST>
INPUT NAME=»zak» TYPE=»file»>
<INPUT TYPE=»submit» VALUE=»Закачать»></FORM>
Об устройстве сценария загрузки файла на сайт вы можете узнать из Справочной системы по PHP (ссылка — в конце статьи), а о принципах устройства системы авторизации рассказывалось в нашем журнале год назад.
В файле div.php можно поместить примерно такой код:
<?php
copy($zak, «price.txt»);
Это команда копирования загруженного файла из временной папки в ту папку, где находится файл с выполняемым сценарием, и переименования его в price.txt. $x=file_get_contents(«price.txt»);
В результате выполнения этой команды все содержимое закачанного файла помещено в переменную $x (данная команда будет работать только в PHP версии 4.3 и выше).
$y=explode(«*******», $x);
Данная команда и выполняет одно из основных действий по обработке прайс-листа — разделение его на отдельные фрагменты с информацией по каждому из разделов. Она разбивает текстовую строку, находящуюся в переменной $x (то есть содержимое закачанного файла) на фрагменты, используя в качестве границы между фрагментами комбинацию символов, указанную в ее первом параметре. В данном примере эта комбинация — «*******», в вашем случае она может быть другой.
Функция возвращает массив с результатом разбиения — то есть в данном случае фрагменты файла будут записаны в массив $y. Сами разделители в фрагменты не войдут.
$l=sizeof($y);
Команда определения числа элементов в массиве и записи этой величины в переменную $l.
for ($i=1; $i<$l; $i++)
{
А теперь запишем каждый из фрагментов в отдельный файл, для чего их все по очереди переберем с помощью оператора цикла for. В первом элементе массива $y (то есть в первом фрагменте) текста не будет — команда explode поместит в этот элемент то, что стоит между началом файла и первым разделителем, а так как разделители стоят перед названиями разделов, то первый разделитель как раз и окажется в начале файла.
$fp = fopen(«prices/pric».$i.».txt», «w+»);
Эта команда создает в папке prices файл с именем «pricNN.txt», где NN — порядковый номер раздела (при каждом проходе цикла он увеличивается на 1), и открывает его для записи (описание команды fopen смотрите в справочной системе по PHP). Если файл с таким именем уже там был (то есть прайс-лист обновляется, а не создается), то старый файл автоматически удаляется.
fwrite ($fp, $y[$i]);
fclose ($fp);
}
Эти команды осуществляют собственно запись данных в файл.
В результате в каждом из файлов окажутся данные одного из разделов, при этом первой строчкой каждого файла будет название раздела, а за ней будут следовать данные раздела — список товаров и цен на них.
Теперь необходимо эти самые первые строчки из файлов повытаскивать и вставить в список разделов. Опять переберем все файлы — тем же самым оператором цикла:
for ($i=1; $i<$l; $i++)
{
$o=file(«prices/pric».$i.».txt»);
Эта команда считывает указанный в ее параметрах файл в массив, в каждый элемент массива помещается одна строчка файла. Следовательно, название раздела окажется в самом первом элементе этого массива.
$a=»$an».substr($o[0], 0, -6);
Эта команда присоединяет к списку новую строку — очередное название раздела, отделяя его от предыдущих символом конца строки «n». Сам список помещается в переменной $a и растет с каждым проходом цикла до тех пор, пока названия разделов не будут вытащены из всех файлов с фрагментами прайс-листа.
Каждое название раздела перед помещением в список обрабатывается командой substr — из него удаляются лишние символы табуляции с конца, которые туда попали при сохранении листа Excel с прайс-листом в формате «Текстовый файл с разделителями табуляции» (вследствие того, что в нашем случае справа от ячеек с названиями разделов находились пустые ячейки). В данном случае таких символов было по 5 (шестой — символ разрыва строки), в вашем случае строка с названием раздела может выглядеть иначе, если, скажем, в исходном файле это название помещалось не в самой левой ячейке строчки. Впрочем, данное действие необязательно, и команду substr можно было и не использовать.
}
Конец цикла. Осталось записать получившийся список в файл — теми же командами fopen, fwrite, fclose…
$fp = fopen(«spisok.txt», «w+»);
fwrite ($fp, $a);
fclose ($fp);
…и можно выводить сообщение о завершении процесса:
echo («Прайс-лист загружен»);
?>
Вот и весь сценарий загрузки прайс-листа на сервер — результатом его работы станет ряд файлов с именами pric01.txt, pric02.txt и т. д. в папке prices и файл spisok.txt со списком разделов прайс-листа.
Сценарий вывода списка разделов, пожалуй, самый простой из всех рассматриваемых.
>?php
$s=file(«spisok.txt»);
Считаем командой file файл списка в массив $s — в итоге в каждом элементе массива окажется одна строчка этого файла.
Затем переберем все эти элементы…
$i1=$i;
echo («<a href=razd.php?rz=».$i1++.»>$s[$i]</a><br>»);
…и выведем ссылки на страницу.
Несколько запутанный вид команды, выводящей ссылку, объясняется тем, что при составлении списка его самым первым элементом оказался символ разрыва строки (подумайте, что поместит в переменную $a команда $a=»$an».substr($o[0], 0, -6); из сценария размещения прайс-листа при своем самом первом срабатывании). В результате первый элемент массива $s будет содержать не имя первого раздела, а именно этот самый символ, и нумерация элементов $s и заголовков раздела будет сдвинута на единицу относительно друг друга (команда $i1++ увеличивает на единицу значение переменной $i1). Поэтому же перебор элементов массива начинается с элемента с номером 1, а не 0 (помните, что в PHP нумерация элементов массива ведется с нуля).
Ситуацию можно было бы исправить и другим путем — добавив в конец сценария составления списка разделов команду удаления первого символа в полученном файле. Тогда команда вывода ссылки на прайс-лист раздела в этом сценарии выглядела бы проще:
echo («<a
href=razd.php?rz=».$i.»>$s[$i]</a><br>»);.
echo («<a
href=razd.php?rz=».$i.»>$s[$i]</a><br>»);.
}
?>
Вот и все. Остальное содержание страницы с каталогом может быть любым.
Сценарий, выводящий прайс-лист, получает в ссылке со страницы каталога переменную с именем rz и значением, равным номеру того раздела, информацию которого требуется поместить на веб-страницу.
<?php
$p=file(«prices/pric».$rz.».txt»);
Первая команда — считывание содержимого соответствующего файла в массив по одной строчке в каждом элементе. А как же — ведь именно это содержимое необходимо выводить на веб-страницу, а для этого его удобнее всего брать именно из переменной.
В изначальном файле прайс-листа (рис. 1) каждая строка состояла из четырех клеточек — номера позиции, названия товара, цены в рублях и цены в условных единицах. При конвертации в текстовый формат места границ ячеек заняли символы табуляции. В принципе можно было бы просто вывести прайс-лист на веб-страницу непосредственно в том виде, в котором он хранится в файле — окаймив его, скажем, тегами <pre>… </pre>, чтобы символы конца строк не игнорировались. Но куда как красивее будет вставить данные о товарах и ценах в таблицу, к тому же раскрасив соседние строки в контрастные цвета, чтобы лучше читалось. Смотрите, как это делается.
foreach ($p as $d)
{
Переберем все элементы массива строк файла по очереди…
$b1[]=strtok($d,» «);
$b2[]=strtok(» «);
$b3[]=strtok(» «);
$b4[]=strtok(» «);
…и разделим каждую строку на четыре части по символам табуляции, записав каждую часть в отдельный массив. В итоге получим четыре массива, в каждом из которых будут храниться сведения из одной из колонок прайс-листа, а в их элементах с одним и тем же индексом — данные одной из строк прайс-листа.
Обратите внимание, в этом сценарии в параметре функции strtok необходимо указывать именно символ табуляции (с клавиатуры).
}
echo («<h1>$b1[0]</h1>»);
Разумеется, в вашем случае число колонок может быть иным — в этом случае соответственно откорректируйте сценарий. Выведем на веб-страницу название раздела прайс-листа, взяв его из первой строчки файла с разделом — как нетрудно догадаться, оно будет находиться в самом первом (с индексом «0») элементе первого из массивов.
echo («<table>»);
Сам же прайс-лист упакуем в таблицу.
<?php
$e=sizeof($b1);
for ($u = 1; $u < $e; $u++)
{
Переберем по очереди все элементы массивов.
if ($u%2>0) {$l=»#eeeeee»} else {$l=»#ffffff»}
При этом каждой второй строке таблицы сделаем красивый сероватый фон — чтобы она отличалась по цвету от соседних.
echo («<tr
bgcolor=$l><td>$b1[$u]</td><td>$b2[$u]</td><td>$b3[$u]</td><td>$b4[$u]</
td></tr>»);
И выведем на веб-страницу прайс-лист по строкам, формируя из каждой строки прайс-листа строку таблицы. Просто поместим в каждую из ячеек строки по очередному элементу каждого из массивов с данными прайс-листа.
}
?></table></center>
О командах, использованных в описанном сценарии, читайте в справочной системе к языку.
После реализации указанного алгоритма обновление сайта составит всего два действия: запуск макроса на VBA для получения текстового файла и закачку полученного файла на сайт. Все остальное выполнят программы
Где взять?
Русскую версию справочной системы по PHP для версий 4.0 и выше вы можете загрузить с сайта разработчиков PHP http://www.php.net или с ресурса Александра Пирамидина http://pyramidin.narod.ru. Для тестирования сценариев на вашем компьютере вам также потребуется установить на нем веб-сервер с интерпретатором PHP — комплект «Денвер» http://dklab.ru/chicken/web или набор питерского программиста Дмитрия Бородина http://php.spb.ru.