просмотров:9230 | комметариев: 7
Замена текста в файле RTF средствами php

Эта статья о способах шаблонизации RTF документов, попросту говоря, замене текста в документе. Например, в бланк накладной или договора нужно подставить название организации и другие реквизиты. Так же будет небольшой обзор RTF формата и самых нужных(в рамках поставленной задачи) способах форматирования текста + работа с различными кодировками. В конце статьи будет полный пример следующего: будет браться RTF бланк, налету будут меняться некоторые данные, и сразу измененный файл будет отдаваться в браузер клиенту.

Немного теории не помешает.

Rich Text Format (англ. rich — богатый) — формат для кодирования текста и графики. Формат создан в далеком 1982 году компаний Microsoft. Rtf оказвается тоже Билл Гейтс придумал:). Это открытый формат, в отличии от doc и docx. Открыв rtf документ в блокноте, вы не увидите ни одного бинарного (непечатного) символа. Такой формат читается на различных, платформах и осях. И все вроде в нем хорошо, и полная обратная совместимость со старыми версиями Word(и пр.), и кроссплатформенность, но есть один недостаток. Т.к. вся информация хранится в обычном текстовом виде, в том числе служебная, файл получается слишком раздутым по объему. Большие по объему данные хранить в этом формате грешновато(для сравнения docx, это по сути zip-архив). Но для небольших по объему документов: бланков, накладных, договоров, это совсем не критично.

Откройте тот же ворд, напечатайте любое слово сохраните в rtf и потом посмотрите в блокноте сколько всякого-разного там понатыкано(не даром формат назван богатым:)). Надеюсь понятно, что это не обычный текстовой формат, в этом формате можно хранить форматированный текст, картинки, таблицы, формулы и прочее

Создание и редактирование.

Итак, приступим. Для создания rtf документов, есть отлично документированный класс PHPRtfLite, всем кому нужно создавать с нуля rtf документы, вам туда. Все же приведу небольшой кусок кода, который создает rtf документ. Так сказать, необходимый минимум.

$sData = '{\rtf1\ansi\deff  HELLO WORLD}';
file_put_contents('test-file.rtf', $sData);

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

Вот простой пример кода, который, это делает:

$sData = file_get_contents('source.rtf');
$sData = str_replace('COMPANYNAME', 'My Company', $sData);
file_put_contents('result.rtf', $sData);

Слово, которое нужно заменить писать именно в таком виде, одним словом, без всяких там {{COMPANYNAME}} или [[COMPANYNAME]] или COMPANY_NAME. Так работать не будет, дело в том , что такие конструкции не хранятся в виде одного слова, а в виде нескольких конструкций вперемешку с управляющими символами.

Если же нужно производить замену на слова любого другого языка, например русского, то нельзя просто вот так вписать символы в файл. Есть 2 момента. Первый, дело в том что rtf формат понимает только ANSI кодировку(для кириллицы это window-1251), соответственно нужно привести символы в эту кодировку(если это не так) и второй каждый символ нужно вписывать в виде его кода в шестнадцатеричной системе. Например, слово ‘Мир’ должно будет записано в виде \'cc\'e8\'f0

СС – это число 204 в шестнадцатеричной системе, а 204 – это код символа M в таблице символов window-1251. Символы должны разделяться слешем и кавычкой. Благо написана функция, которая будет все преобразования делать самостоятельно:

function strToHexByRtf($sString, $sEncoding = 'utf-8') {
    $sString = iconv($sEncoding, 'windows-1251', $sString);
    $sString = preg_replace("/([a-zA-Z0-9]{2})/", "\'$1", bin2hex($sString));
    return $sString;
}

Если заведомо известно, что текст в 'windows-1251', то первую строку в функции можно удалить. Итак, пример кода замены для кириллицы:

function strToHexByRtf($sString, $sEncoding = 'utf-8') {
    $sString = iconv($sEncoding, 'windows-1251', $sString);
    $sString = preg_replace("/([a-zA-Z0-9]{2})/", "\'$1", bin2hex($sString));
    return $sString;
}
$sData = file_get_contents('source.rtf');
$sReplace = strToHexByRtf('Моя компания');
$sData = str_replace('COMPANYNAME', $sReplace, $sData);
file_put_contents('result.rtf', $sData);

Вот собственно и все. Остается только выдать пользователю видоизмененные данные виде файла, прямо в браузер.

В итоге получилось

Итак, полный код:

function strToHexByRtf($sString, $sEncoding = 'utf-8') {
    $sString = iconv($sEncoding, 'windows-1251', $sString);
    $sString = preg_replace("/([a-zA-Z0-9]{2})/", "\'$1", bin2hex($sString));
    return $sString;
}
// считываем файл
$sFileName = 'source.rtf';
$sData = file_get_contents($sFileName);
// меняем текст
$sReplase = strToHexByRtf('Моя компания');
$sData = str_replace('COMPANYNAME', $sReplase, $sData);
// отдаем измененный файл пользователю прямо в браузер
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($sFileName));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . strlen($sData));
print $sData;

На этом основная часть статьи окончена. Осталось сказать пару слов о форматировании текста в формате rtf. Скорей всего будет нужен перенос строк и выделение текста жирным шрифтом.

Перенос строки, пример: $sReplace = '{ some text \par}';
'\par' и есть перенос строки(от параграф)

Выделение жирным шрифтом, пример: $sReplase = '{\b email:} {\b0 some@email.com}'
Слово email будет выделено жирным шрифтом.

Еще одно занятное наблюдение. LibreOffice криво сохраняет rtf формат, баг был отловлен на ОС Ubuntu. Я просто открыл doc документ и сохранил в формате rtf. При попытке открытия сохраненного(им же) документа LibreOffice выдал ошибку: "Ошибка формата файла в позиции..." или "File format error found at ..." Версия LibreOffice 4.0.2.2, Ubuntu 13.04 Если открыть в том-же netbeans, то видно, что в rtf документе не парное кол-во фигурных скобок. Дивно. Так-что, не юзайте LibreOffice для преобразования формата. В OpenOffice 3.3 под Windows 7 баг не повторился, нормально сохранило в rtf формате.

Спасибо за внимание. Вопросы, жалобы, предложения оставляйте в коментах или пишите на gubarevm@mail.ru. Удачи.

просмотров:9230 | комметариев: 7
Сергей Милн
21 декабря 2013, 17:12
Спасибо за статью, описано подробно и понятно!
juja
26 января 2015, 09:24
"Ошибка формата файла в позиции..."
а как починить документ с такой ошибкой?
Михаил
26 января 2015, 10:24
Тяжело сказать что-либо.. Может это поможет http://network-life.ru/windows/openoficce-oshibka-formata-fayla-v-poddokumente
Анатолий
15 мая 2015, 17:42
Здравствуйте, при открытии готового файла вот такая проблема:http://hostingkartinok.com/show-image.php?id=e1ee48bef0340722c33358e65f5fdf01
Губарев Михаил
15 мая 2015, 20:20
Пришлите ваши исходники мне на почту gubarevm@mail.ru
На выходных посмотрю, что там как..
Юрий
08 марта 2016, 17:33
При замене контекста в файле он вставляется другим шрифтом. Исходный шрифт докумена - Times New Roman, а у вставленного контекста - Liberation Serif
Yura
25 августа 2016, 09:45
Спасибо :-) Помогло! Работает :-)
просмотров:9230 | комметариев: 7

Оставить комментарий:    

Ваше имя:
 
Текст комментария:
 
+ 1 =