Хостинг, который может больше
26.01.2012

Отправка данных из PHP в Office

У публикации есть спонсор (как стать спонсором):

Питомник йоркширских терьеров Люкс Миа продает щенков мини и стандарт.

Приветствую уважаемого читателя! В данной публикации мы снова коснемся темы программирования на PHP средствами фреймворка Kohana — научимся сохранять результат работы скрипта PHP в документ Open Office.

Я часто сталкиваюсь с задачей вывода результатов работы сайта в Word. Ведь отображения страницы в браузере не всегда достаточно: встречаются требования заполнить ту или иную форму, подготовленную в Office, данными, сформированными посредством PHP. Думаю, сегодня прекрасный день, чтобы решить эту задачу.

Для начала давайте скажем решительное НЕТ сложностям работы с форматом *.doc от MS Office. Результаты работы PHP-скрипта мы будем выводить в *.odt-файл (формат офисного текстового документа в пакете Open Office).

Заодно, очистим свои компьютеры от ворованного софта. Этот пост я набираю именно в Open Office и замечательно себя при этом чувствую. Что может быть приятнее, чем на совершенно законных основаниях скачать свежую версию Open Office с официального сайта. А нервно поскуливающих бабулек из бухгалтерии можно успокоить демонстрацией процесса сохранения подготовленного нами документа *.odt в так полюбившийся им *.doc.

Сохранение в Open Office

Оказывается, существует специальный модуль odtPHP, предназначенный для решения поставленной задачи. Разберем принцип работы с данным модулем.

1. Подготавливаем PHP скрипт

<?php
require_once('../library/odf.php');
$odf = new odf("tutoriel1.odt");
$odf->setVars('titre', 'PHP');
$message = "PHP  est un langage de scripts libre ...";
$odf->setVars('message', $message);
$odf->exportAsAttachedFile();
?>

2-я строка — подключение модуля (в скобках указывается местоположение скачанного модуля odtPHP).

3-я строка — указываем путь к шаблону документа Open Office.

4-я строка — устанавливается значение для переменной titre (titre указывается в шаблонном документе OpenOffice). Теперь вместо кодового {titre} в шаблоне tutoriel1.odt будет выводится буквосочетание «PHP».

2. Подготавливается шаблон

Создаем в Open Office новый документ и в нужных местах ставим метки {titre}и {message}, которые будут заменены на «PHP» и «PHP  est un langage de scripts libre … ».

А вот как выглядит шаблонный документ:

{titre}
{message}

Думаю, дальше пояснять нет смысла все и так понятно из раздела Tutorials.

Мы будем копать глубже и прикрутим к фреймворку Kohana 3.2 модуль для работы с odt на основе odtPHP. Заодно я проиллюстрирую процесс вывода результатов работы скрипта PHP в Office-документ.

Если вы не знакомы с фреймворком Kohana, то у меня есть видеокурс, посвященный его изучению.

Реальная задача по выводу результатов работы PHP скрипта в Office

Постановка задачи. Есть сайт, на котором выводится таблица с номерами сертификатов и фамилиями лиц, прошедших обучение. Необходимо выбрать чекбоксом нужные фамилии и, нажав кнопку Экспорт, отправить данные по выбранным слушателям курсов в офисный документ утвержденной формы.

Видеоурок

Скачать видеоурок (21.2 МБ, *.wmv).

Публикую ссылку на загрузку заточки модуля odtPHP под Kohana 3.2.

Форма Office-документа:

Форма Word

Теперь пройдем все шаги от загрузки нужного модуля для Kohana 3.2 до открытия готового документа Open Office.

Итак, я считаю, что вы знакомы с видеокурсом по Kohana 3. Поэтому, без лишних скромностей, создайте в папке application каталог templates. Будем хранить там наши odt-шаблоны.

В свежесозданный каталог templates сохраним odt-докумет следующего вида:

Шаблон odt для вставки данных из PHP

Как видно из скриншота, в местах вывода информации по обучаемому (ФИО, номер сертификата и т. д.) установлены специальные символы ({number}, {surname}, {name}…), которые будут заменены на значения, полученные PHP-скриптом.

Поскольку строк в таблице может быть несколько — необходимо выводить информацию по обучаемым в цикле (каждая итерация выводит данные одного курсанта). Именно это и означает связка

[!-- BEGIN row.certificates --]
...
[!-- END row.certificates --]

Все, что находится между данными операторами будет повторятся в цикле для блока данных row.certificates, который мы подготовим в контроллере.

Следующий шаг — скачать и подключить специальный модуль для Kohana 3.2, созданный на основе odtPHP.

Для подключения модуля нужно скопировать папку odtphp в каталог modules и указать инструкцию подключения в файле application/bootstrap.php

Подключение модуля odtPHP в bootstrap.php

Далее, в методе, запускающем формирование odt-файла нужно указать следующий код:

protected function export_certificates()
	{
		$odf = new Odtphp(APPPATH.'templates/register.odt');

		$odf->setVars('privet', 'Иван', $encode = TRUE, $charset='UTF-8');

		$seg = $odf->setSegment('certificates');
		if(isset($_POST['cb']))
		{
			foreach($_POST['cb'] as $key => $null)
			{
				$cert = ORM::factory('certificate', $key);

				$seg->setVars('number', $cert->number, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('surname', $cert->surname, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('name', $cert->name, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('lastname_ru', $cert->lastname_ru, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('name_ru', $cert->name_ru, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('patronymic_ru', $cert->patronymic_ru, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('birthdate', $cert->birthdate, $encode = TRUE, $charset='UTF-8');
				$seg->setVars('certdate', $cert->certdate, $encode = TRUE, $charset='UTF-8');

				$seg->merge();
			}
		}

		$odf->mergeSegment($seg);
		$odf->exportAsAttachedFile();

		exit;
	}

Если что-то не понятно — смотрите видеоурок.

Еще раз публикую ссылку на загрузку заточки модуля odtPHP под Kohana 3.2.

С уважением, Андрей Морковин.


Если статья вам понравилась и вы не хотите пропустить свежие публикации, то подписывайтесь на RSS-ленту или получайте обновления сайта на эл. почту.


Похожие материалы:


Отзывов: 24 на «Отправка данных из PHP в Office»

  1. Alexey, 27.01.2012 в 10:56

    Андрей, большое спасибо за видео. Очень полезная штука!
    кстати, по поводу word/excel против OpenOffice по набору стандартных функций они, конечно, почти не отличаются. но если копнуть глубже, то бесплатный продукт все-таки проигрывает (рисование (word), условное форматирование (excel), выделение цветом(excel), работа с данными(excel). самое обидное, что многие люди все-равно не пользуются всеми благами платных продуктов и используют их так же, как могли бы OpenOffice.
    а вообще, полностью Вас поддерживаю в попытках перевести сознание людей на легальное использование программного обеспечение! с Вашей подачи, так сказать, я удалил Dreamweaver )))

    • Андрей Морковин, 27.01.2012 в 11:18

      Я рад, что видео оказалось полезным.

      Конечно, есть моменты, где бесплатный софт значительно слабее своих аналогов. Но на то он и бесплатный, видимо.

      Отлично, что отказались от Dreamweaver.

  2. Алексей, 01.02.2012 в 09:56

    Андрей, а не могли бы вы выложить исходника view? Я просто не могу понять как odtphp, узнает, что надо именно с галочками экспортировать. И как сделать соответствующий вид.

    • Алексей, 02.02.2012 в 08:38

      Ошибка! что делать? Все проверил, все как в уроке. Вот сама ошибка: ErrorException [ Warning ]: tempnam() [function.tempnam]: open_basedir restriction in effect. File() is not within the allowed path(s): (/home/users2/k/kondyrev/:/usr/local/zend/share/pear/:/tmp/)

      • Алексей, 02.02.2012 в 12:01

        Андрей ответьте, пожалуйста, я уже всю голову сломал.

  3. Елена, 02.02.2012 в 16:55

    У меня тоже выскакивает такая же ошибка, хотя проверила все 100 раз, и шаблон лежит в папке templates/ Вот сама ошибка: ErrorException [ Warning ]: tempnam() [function.tempnam]: open_basedir restriction in effect. File() is not within the allowed path(s):

  4. Игорь, 02.02.2012 в 17:35

    И у меня такая же проблема, так как её решить? Андрей подскажите… Важный проект — я в тупике, завтра сдавать…. Все делал по вашим урокам, остался только экспорт, а тут затык…..

  5. PS, 02.02.2012 в 18:41

    Скорее всего проблема в том, что не указан параметр PATH_TO_TMP модуля odtphp.
    Скопируйте конфиг модуля (MODPATH/odtphp/config/odtphp.php) в каталог application/config, затем откройте его в редакторе и установите параметр PATH_TO_TMP. Это путь к временному каталогу. Пример:

    ‘PATH_TO_TMP’ => ‘/tmp’,

    А если хотите быстрый и точный ответ, всегда сообщайте также файл и номер строки, где возникла ошибка.

    • Алексей, 02.02.2012 в 19:04

      Я все сделал как вы сказали, но все равно результат тот же…
      ErrorException [ Warning ]: tempnam() [function.tempnam]: open_basedir restriction in effect. File() is not within the allowed path(s): (/home/users2/k/kondyrev/:/usr/local/zend/share/pear/:/tmp/)

      MODPATH/odtphp/vendor/odtphp/odf.php [ 66 ]
      61 throw new OdfException(«Nothing to parse — check that the content.xml file is correctly formed»);
      62 }
      63
      64 $this->file->close();
      65
      66 $tmp = tempnam($this->config['PATH_TO_TMP'], md5(uniqid()));
      67 copy($filename, $tmp);
      68 $this->tmpfile = $tmp;
      69 $this->_moveRowSegments();
      70 }
      71 /**

  6. Алексей, 02.02.2012 в 19:05

    Я все сделал как вы сказали, но все равно результат тот же…

    MODPATH/odtphp/vendor/odtphp/odf.php [ 66 ]
    61 throw new OdfException(«Nothing to parse — check that the content.xml file is correctly formed»);
    62 }
    63
    64 $this->file->close();
    65
    66 $tmp = tempnam($this->config['PATH_TO_TMP'], md5(uniqid()));
    67 copy($filename, $tmp);
    68 $this->tmpfile = $tmp;
    69 $this->_moveRowSegments();
    70 }
    71 /**

  7. PS, 02.02.2012 в 19:21

    Покажите файл application/config/odtphp.php

    • Алексей, 02.02.2012 в 19:24

      ‘PclZipProxy’,
      // ‘DELIMITER_LEFT’ => ‘{‘,
      // ‘DELIMITER_RIGHT’ => ‘}’,
      // ‘PATH_TO_TMP’ => ‘/tmp’,
      );

      • PS, 02.02.2012 в 19:29

        У меня два вопроса:
        1) Хостер позволяет писать в /tmp ?
        2) Внимательно посмотрите на тот параметр, который Вы изменили в конфиге.

        • Алексей, 02.02.2012 в 19:35

          Права на templates выставлены 777
          А по поводу второго вопроса не понял?..

          • PS, 02.02.2012 в 19:42

            Что же тут непонятного ?
            Откройте файл application/config/odtphp.php в текстовом редакторе и посмотрите на его содержимое.
            Подумайте, какой будет результат выполнения этого файла. Это же php файл, так ?

            • Алексей, 02.02.2012 в 19:45

              АААААААА, там все закомментировано!!!!! Надо разкомментировать?

              • Алексей, 02.02.2012 в 19:50

                Разкомментировал, теперь другая ошибка…
                OdfException [ 0 ]: ‘certificates’ segment not found in the document

                MODPATH/odtphp/vendor/odtphp/odf.php [ 215 ]
                210 return $this->segments[$segment];
                211 }
                212 // $reg = «#\[!--\sBEGIN\s$segment\s--\](.*)\[!--\sEND\s$segment\s--\]#sm»;
                213 $reg = «#\[!--\sBEGIN\s$segment\s--\](.*)\[!--\sEND\s$segment\s--\]#sm»;
                214 if (preg_match($reg, html_entity_decode($this->contentXml), $m) == 0) {
                215 throw new OdfException(«‘$segment’ segment not found in the document»);
                216 }
                217 $this->segments[$segment] = new Segment($segment, $m[1], $this);
                218 return $this->segments[$segment];
                219 }
                220 /**

              • PS, 02.02.2012 в 20:04

                Алексей, научитесь читать сообщения об ошибках.
                Как переводится фраза: ‘certificates’ segment not found in the document ?

            • Алексей, 02.02.2012 в 19:59

              Разкомментировал, теперь другая ошибка…
              OdfException [ 0 ]: ‘certificates’ segment not found in the document

              MODPATH/odtphp/vendor/odtphp/odf.php [ 215 ]
              210 return $this->segments[$segment];
              211 }
              212 // $reg = «#\[!--\sBEGIN\s$segment\s--\](.*)\[!--\sEND\s$segment\s--\]#sm»;
              213 $reg = «#\[!--\sBEGIN\s$segment\s--\](.*)\[!--\sEND\s$segment\s--\]#sm»;
              214 if (preg_match($reg, html_entity_decode($this->contentXml), $m) == 0) {
              215 throw new OdfException(«‘$segment’ segment not found in the document»);
              216 }
              217 $this->segments[$segment] = new Segment($segment, $m[1], $this);
              218 return $this->segments[$segment];
              219 }
              220 /**

    • Андрей Морковин, 02.02.2012 в 20:03

      1. Знак // перед строкой ‘PATH_TO_TMP’ означает, что данная строка закомментирована и не участвует в конфигурировании модуля. Для начала раскомментируйте строку (просто удалите //).

      2. ‘/tmp’ это путь к временной папке сервера с ОС Linux, которая очищается автоматически и не имеет никакого отношения к папке template. Запросто может быть так, что хостер запрещает туда писать. Тогда вам нужно будет указать путь к временной папке внутри своей домашней директории.

      • Алексей, 02.02.2012 в 20:06

        Спасибо, я все сделал так, разкомментировал, проверил папку tmp на сервере, все ок. Но теперь другая ошибка…
        OdfException [ 0 ]: ‘certificates’ segment not found in the document

      • Алексей, 02.02.2012 в 20:27

        Андрей, подскажите, пожалуйста все проверил, и в odf уыть certificates и в контроллере я его указываю, просто не пойму в чем может быть проблема….

  8. Алексей, 02.02.2012 в 19:27

    Вот на всякий случай еще код:

    protected function export_sertificates(){

    $odf = new Odtphp(APPPATH.’templates/register.odt’);
    $seg = $odf->setSegment(‘certificates’);
    $export=array();
    $ch = $_POST['ch'];
    $seg->setVars(‘name’, ‘Василий’, $encode =TRUE, $charset = ‘UTF-8′);

    foreach($ch as $c){
    $edina = ORM::factory(‘zakaz’, array(‘id’=>$c));
    $edins = ORM::factory(‘ediniza’, array(‘id’=>$edina->idtov));

    $art = ORM::factory(‘article’, array(‘id’=>$edina->article))->name;
    $naim = $edins->name;
    $zvet = RM::factory(‘cvet’, array(‘id’=>$edina->cvet))->name;
    $k = $edina->colvo;
    $izm = RM::factory(‘edizm’, array(‘id’=>$edina->edizm))->name;

    $seg->setVars(‘article’, $art, $encode =TRUE, $charset = ‘UTF-8′);
    $seg->setVars(‘name’, $naim, $encode =TRUE, $charset = ‘UTF-8′);
    $seg->setVars(‘zvet’, $zvet, $encode =TRUE, $charset = ‘UTF-8′);
    $seg->setVars(‘kol’, $k, $encode =TRUE, $charset = ‘UTF-8′);
    $seg->setVars(‘izm’, $izm, $encode =TRUE, $charset = ‘UTF-8′);

    $seg->merge();
    }

    $odf->mergeSegment($seg);
    $odf->exportAsAttachedFile();
    exit;

    }

  9. Алексей, 02.02.2012 в 20:44

    СПАСИБО ВСЕМ!!! Во всем разобрался — все заработало! Андрей спасибо за ваши уроки, они просто супер!!! Жду, по возможности урок импорта из xml либо html либо из любого другого популярного файла! СПАСИБО!!!

Ваш отзыв

MAXCACHE: 0.87MB/0.00044 sec