Формирование печатных форм в pdf




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

99 Comments

  1. detec

    Отдельная благодарность за код: хорошо оформленный визуально и снабжённый подробными комментариями.

    Reply
  2. detec

    И ещё вопросик. На сервере приложения обработка работает?

    Reply
  3. Spartan

    (1) Спасибо, буду рад, если кому-то мой опыт поможет…

    (2) Вообще писал для клиента, как видите, в коде присутствуют методы, не используемые на сервере — самый главный из которых Напечатать(). Возможно на сервере можно будет решить другими методами класса, но не уверен.

    Reply
  4. Свой

    для 1С 7.7 сделайте кто-нибудь аналогичный примерчик

    Reply
  5. ILM

    Очень Хорошо! А для PDFForm заполнения примерчика нету?

    Reply
  6. Spartan

    (5) К сожалению, нет. 🙂 Остановил свой выбор на PDFCreator, задачу решил — теперь можно отдыхать…

    Reply
  7. rahimov1965

    Решал аналогичную задачу, с помощью BullZip не справился с проблемой прозрачности печатей и факсимиле. Решается ли эта задача при помощи PDF-creator? Мне пришлось использовать платную программу Universal Document Convertor, но там есть смешная затыка: ТабличныйДокумент.Напечатать(Ложь) — только с открытием диалога.

    Reply
  8. Spartan

    (7) Честно говоря, не знаю… Мне нужно было формировать просто формы без печатей, поэтому с прозрачностью не разбирался.

    Reply
  9. itoz

    Автору респект за указание направления хода мысли и плюсик. Кому действительно надо, под себя переделает если-что.

    Reply
  10. cool.clo

    Плюс безусловно, но к сожалению pdf creator не понимает прозрачности, пытался как-то через метод pdfforge.StampPDFFileWithImage печать добавить, но все это не то. Наверно придется думать насчет Universal Document Convertor

    Reply
  11. Noy

    (0) Молодец — очень хорошо разжевано! Не просто кусок кода, а прямо таки лекция.

    Как один из аналогов для решения подобной задачи:

    начиная с 2007 версии МС офиса — есть бесплатное дополнение «Save as PDF & XPS» — в теории им можно порулить через Ole.

    Естественно нужен сам офис, и нужно будет печатные формы пересохранять в xls или doc…

    Reply
  12. Душелов
  13. Noy

    (12) упс…

    Reply
  14. Spartan

    (11),(12) Согласен, так оно конечно проще будет, но нужен офис 2007-й, а он не бесплатный… У наших юзеров он есть далеко не у всех.

    Reply
  15. megatrend

    Интересно, поучительно и перспективно! 💡

    А если кому-то чего-то не хватает в PDFCreator — добро пожаловать в его команду разработки!

    Programming Languages: Visual Basic

    License: GNU General Public License (GPL)
    Reply
  16. CheBurator

    Идем, берем Йоксель и сохраняем в ПДФ (по миниумму возможностей) безо всяких виртуальных принтеров и прочей шняги

    Reply
  17. Spartan

    (16) С удовольствием бы, только вот под 8-ку нету его пока… 😉

    Reply
  18. CheBurator

    Йоксель работает и под 8-ой

    Reply
  19. Spartan

    (18) Может конечно и так — я не пробовал… Только тогда автору стоило бы сделать свою страничку более информативной — я никакого упоминания о 8-ке там не нашел, и наоборот на глаза попадаются старые посты и комменты, в которых говорится, что компонента с 8-кой не работает или работает с извратом.

    Reply
  20. Трактор

    (14) Если ненравится платный МСофис, то можно пользовать бесплатный Опен офис. http://infostart.ru/public/20710/ Опенофисные ПДФки качественнее ПДФкреаторских.

    Но по большому счёту выбор инструмента определяется личными предпочтениями разработчика. Автору плюс за качественное описание.

    Reply
  21. Spartan

    (20) У нас почти у всех юзеров стоит мс офис, только у большинства он 2003-й, у некоторых — опен, но они категорически не желают с ним работать.. 😀 Держать его на компах в качестве конвертера как-то не айс, проще поставить небольшую утилиту.

    А вообще согласен полностью: вариантов решения задачи — масса, и в каждом конкретном случае, разработчик сам выбирает приемлемый. Но в любом случае, думаю, неплохо иметь пару альтернативных про запас… 😉

    Reply
  22. cool.dkf

    +Спс

    Кстати может кому пригодится — черновой вариант функции для печати через Universal Document Converter, прога платная правда(потому наверное буду юзать pdfcreator)

    Функция PDFСформироватьФайлыДляОтправки(Ссылка, Печатнаяформа, ИмяФай

    Reply
  23. son_v

    Спасибо за информацию. Как раз стоит такая задача ).

    Reply
  24. cool.dkf

    Забыл сказать, что профили для Universal Document Converter можно сделать в настройках самого виртуального принтера, сохранив затем в xml файл

    Reply
  25. ValeriTim

    Ай, молодца ! Отлично ! 😀

    Хотя сейчас такой задачи не стоит, но закладочка.

    Reply
  26. FERRO

    Да, всё хорошо, но только для клиентского варианта v8.х пользования — когда это надо одному или нескольким юзерам, т.е каждому на клиенте инсталим bullzip (или PDFCreator) и в путь……….а вот теперь представьте, если народу 30, 50, 100 или более человек и всё крутится например под 64 bit-ным Microsoft SQL Server 2003 SP2 R2 и задача стоит, не устанавливая виртуальный принтер на каждом компе (правда при условии, что хоть какой-то acrobat reader имеется в наличии у всех), преобразовывать табличный (или любой другой) документ в *.pdf на сервере, а клиенту выплевывать готовый файл (ну или хотя бы двоичные данные), да ещё и без использования какой-либо общедоступной шары……..???………..Ваш вариант, надеюсь понимаете, не прокатит. Мало того что «Напечатать()» — не доступен на сервере, так исчо и для 64 bit-ной 1С 32 bit-ный COM (а именно его использует bullzip даже с установленной 64 bit-ной примочкой, которая к нему прилагается) не виден…………. Так какой же вариант рулит……… 😉 (вобщем если кому интересно — могу поведать).

    Reply
  27. iov

    (26) поведай конечно. Интересно ж кто как с этим тра* работает то… Еще один вариант добавляет плюсы в карму.

    Reply
  28. Spartan

    (26) Конечно, понимаю и представляю… Делал сугубо под нужды своего предприятия — для меня этот вариант вполне приемлем. Ваш тоже интересно будет посмотреть… Чем больше вариантов будет, тем лучше.

    Reply
  29. cool.dkf

    Для большого числа клиентов нужен механизм, встроенный в саму 1С. Да наверное прокатит какая-нить внешняя компонента, наподобие yoksel.dll. Но версия выложенная на сайте прозрачность не поддерживает. Либо самому написать ВК — просто не у всех есть время и умение, да и задачи у всех разные. Но очень интересно услышать оригинальный способ решения этой проблемы.

    PS (26)опечатка — SQL Server 2005

    Reply
  30. mosAdm
  31. Spartan

    (30) Я, собственно, и не испытывал иллюзий по поводу того, что мне первому пришло в голову юзать COM-объект виртуального принтера. Кстати, мой код, извините, мне нравится больше — в указанном примере как раз присутствуют все те ситуации, которые я постарался учесть и обойти:

    — функция не будет работать, если виртуальный принтер будет удален или переименован;

    — все время меняется принтер в системе по-умолчанию;

    — имя файла указывается явно в настройках автосохранения (попробуйте использовать этот код при пакетной печати и посмотрите, что будет происходить с файлами);

    — непонятен смысл использования конструкции # Если Клиент, так как метод Напечатать() не работает на сервере;

    З.Ы. Да, и этой темы, я кстати, не видел: со всеми свойствами и методами классов разбирался самостоятельно. Думаю, что имею право поделиться собственными наработками…

    Reply
  32. Spartan

    + (31) Вот, что понравилось — это принудительный выход из цикла, на случай, если файл не сформировался, пожалуй, надо добавить в код…

    Reply
  33. Yashazz

    Баян, но может быть полезно… Я от PDFCreator’a отказался в пользу обычного пинания экселевского SaveAs, и нам хватило. Тоже накатал было для PDFCreator обработку, да бросил за ненадобностью. Ваш вариант хорош для тех, у кого MS Офис и не стоит вообще, и других конвертеров нету.

    Reply
  34. Ужас бухгалтера

    (29) > Но версия выложенная на сайте прозрачность не поддерживает.

    Кто это тебе такое сказал?

    Вот тема, где выложен XLS-файл с прозрачной картинкой и PDF, который был из него получен (естественно с прозрачностью): http://yoksel.net.ru/forum/topic.php?id=174

    И вообще, как можно, видеть в теме, Ёпрст (заказчик этого дела) специально интересовался прозрачностью.

    О работе из восьмерки и картинках с прозрачностью есть еще обсуждение здесь: http://yoksel.net.ru/forum/topic.php?id=211

    Reply
  35. cool.dkf

    (34)Виноват — действительно проблема оказалась не в yoksel-е, а в 1С, о чем собственно и свидетельствует http://yoksel.net.ru/forum/topic.php?id=211

    Reply
  36. CheBurator

    ну как обычно — Йоксель наиболее правильное решение…

    Reply
  37. Spartan

    (36) Вобщем, что хочу сказать… Сделал я аналогичную функцию с помощью Йокселя… Есть свои плюсы и свои минусы.

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

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

    В итоге добавил в свою обработку как дополнительную возможность, но от первоначального варианта не отказался — будем дальше в процессе использования пробовать оба.

    З.Ы. Да… с прозрачностью я не разбирался — мне не надо. Вобщем, только укрепился в своем мнении: каждый способ имеет право на существование, у каждого свои недостатки и свои преимущества.

    Reply
  38. Redokov

    Плюсую. Хороший пример, читаемый код.

    Reply
  39. iiceberg

    Добавил свойство для pdfcreator

    НастройкиПоУмолчанию. saveFileName = имяфайла;

    В профиле имя отразилось, настройки сохранились. Но при печати не подхватывает профиль «печать 1с»

    Как заставить принтер использовать выбранный профиль?

    Reply
  40. Spartan

    (39) Заставить принтер использовать профиль мне не удалось, у меня просто подменяются настройки по умолчанию:

    УтилитаПечати.cOptions = НастройкиПоУмолчанию;

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

    Reply
  41. lees

    твой рассказ мне очень помог разобраться с ковертацией в pdf! Естественно большой +.

    но вот непорядок, скачал yoksel_comserver_hotfix_2010_06_29.rar c http://yoksel.net.ru/Hotfixes, зарегил

    и во время выполнения кода

    Попытка

    ЗагрузитьВнешнююКомпоненту(КаталогПрограммы() + «Yoksel.dll»);

    Исключение

    Предупреждение(«Не удалось загрузить внешнюю компоненту Yoksel! Сообщите администратору системы!», 20);

    Возврат Неопределено;

    КонецПопытки;

    у меня выскакивает ошибка Runtime error:

    http://s1.ipicture.ru/Gallery/Viewfull/2636824.html (ошибка в демо-базе yoksel_demo_config_1cv81.rar)

    Может кто подскажет в чем подвох, поиск поюзал — проблем вподе подобных не возникает. Yoksel.dll лежит в каталоге bin.

    Reply
  42. cool.clo

    (41) тебе надо к разработчику yoksel (если не ошибаюсь ужасбухгалтера),

    ЗЫ Как вариант, ты скачал последнюю версию yoksel, совместима ли она с демо-конфой, попробуй на других использовать (напиши свой код, методы и свойства в справке есть) Тем более ты пишешь, что ошибка возникает во время выполнения кода, ну так найди это проблемное место в коде 1С и подумай.

    Reply
  43. lees

    (42) вот проблемное место

    ЗагрузитьВнешнююКомпоненту(КаталогПрограммы() + «Yoksel.dll»);

    Фишка в том, что если код заменить на следующий

    Попытка

    ЗагрузитьВнешнююКомпоненту(КаталогПрограммы() + «Yoksel111111111.dll»);

    Исключение

    Предупреждение(«Не удалось загрузить внешнюю компоненту Yoksel! Сообщите администратору системы!», 20);

    Возврат Неопределено;

    КонецПопытки;

    тогда ошибки Runtime Error не будет, будет лишь Предупреждение (т.е. нормальная обработка исключительной ситуации)

    Reply
  44. Spartan

    (41) Попробуй вот эту бросить в каталог программы…

    Хотя это похоже та же самая…

    Reply
  45. cool.vlad4

    (43) ну так блин естессно 😀

    даже я тебе больше скажу если ты напишешь вместо yoksel.dll зюзя.dll тоже самое будет

    А у тебя другие ВК нормально работают?

    Reply
  46. Spartan

    (41) Ну вообще в демо-базе йокселя компонента уже грузится при старте системы… Если никаких предупреждений при запуске не выдается, значит, библиотека загружена. Попробуй просто убрать код повторной загрузки.

    Reply
  47. cool.vlad4

    (46) А почему ты решил, что у него повторная загрузка? по моему одна…но он так описал, все, что угодно может быть (хоть в журнальчик бы взглянул) …даже вот так бывает http://support.microsoft.com/kb/884538

    Reply
  48. Spartan

    (47) Потому что у него приведен кусок кода из моей публикации… Но это было в контексте моей задачи и естественно другой базы (да и вообще это я так… баловался…), а в демо-базе йокселя компонента грузится ПриНачалеРаботыСистемы().

    Reply
  49. cool.vlad4

    😀 тогда ты прав, просто только из его комментов это сложно понять…

    Reply
  50. Spartan

    (49) Хотя по идее и повторная загрузка не должна давать ошибки… Но тут действительно хз, что за ситуация в целом… 🙂

    Reply
  51. lees

    (48) >Потому что у него приведен кусок кода из моей публикации…..

    Да, я сначала юзал кусок кода из публикации и подумал что возможно что-то делаю не так,

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

    Reply
  52. Spartan

    (51) Ну тогда тебе действительно лучше с разработчиком Йокселя на эту тему пообщаться… Какие-нить другие ВК пробовал загружать? Только йоксель падает?

    Reply
  53. lees

    (52) Только йоксель падает. Работает например ScanOpos.dll для считывания штрихкодов

    Reply
  54. lees

    вот что я делаю:

    1) копирую yoksel.dll в папку C:/Progmram Files/1Cv81/bin

    2) regsvr32 yoksel.dll и вижу предупреждение об удачной регистрации

    3) Запускаю демо-базу yoksel

    Далее, 8-ка вылетает ❓

    Версия платформы 1С 8.1.15.14

    Reply
  55. cool.vlad4

    Это только на твоем компе? посмотри журнал событий…

    Reply
  56. lees

    (55)это не только на моем, но и на 2 других смотрел

    Заработало! Оказалось, что за место метода

    ЗагрузитьВнешнююКомпоненту(КаталогПрограммы() + «Yoksel.dll»);

    мне нужно использовать

    ПодключитьВнешнююКомпоненту(«Йоксель»)

    😉

    Вот мой топик на мисте

    http://www.forum.mista.ru/topic.php?id=523437

    🙂

    Reply
  57. lees

    чтобы картинка вмещалась в pdf вероятно необходимо варьировать параметрами ШиринаСтраницы и КоличествоБитНаПексел. Так? (ПолеСверху, ПолеСлева,… — само собой)

    Reply
  58. Pavel777777

    Хорошая статья, в свое время тоже остановился на PDFCreator для сохранения печатных форм ) Пара дополнений (может пригодятся) :

    — Печатную форму из нескольких страниц можно сохранять в виде изображения в формате TIFF. Соответственно, «НастройкиПоУмолчанию.AutosaveFormat = 5;» В этом случае при просмотре стандартной программой просмотра изображений xp появляется внизу кнопочка перехода между страницами.

    — Не совсем понятна проблема с получением нужного имени файла. Может это только в 8-ке так? В 7-ке используя «НастройкиПоУмолчанию.AutosaveFileName = «Title»; // Здесь Title должно быть в угловых скобках, но редактор HTML воспринимает это как тег и сбивает разметку» и затем в процедуре печати 1с «ИсхТабл.Показать(«Счет_»+СокрЛП(Докум.НомерДок),,-1);» получалось нужное имя файла вида «Счет_[НомерДок].tif»

    Reply
  59. Spartan

    (58) Не заметил комментарий, но лучше поздно, чем никогда… С именем файла есть нюансы. Во-первых, чтобы получить имя таким образом, табличный документ нужно, как минимум, показать. Можно конечно потом скрыть, но мельтешение окон не есть гуд — мне нужно было выполнять все «тихо»: сформировать файл, добавить во вложения, открыть письмо. А, во-вторых, даже в таком случае пришлось бы прибегнуть к искусственной задержке времени, т.к. опции не успевали бы сохраняться. Короче, как я и написал в статье, пришел к такому варианту опытным путем.

    Reply
  60. idw

    К статье про Yoksel я бы еще добавил вот такой код, иначе получаются листы пдф, которые не умещаются на одном листе:

    Если ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт Тогда

    //ШиринаСтраницыВТвипах = ТабДок.ВысотаСтраницы * 567/10;

    //ВысотаСтраницыВТвипах = ТабДок.ШиринаСтраницы * 567/10;

    ШиринаСтраницыВТвипах = 16839;

    ВысотаСтраницыВТвипах = 11907;

    Иначе

    //ШиринаСтраницыВТвипах = ТабДок.ШиринаСтраницы * 567/10;

    //ВысотаСтраницыВТвипах = ТабДок.ВысотаСтраницы * 567/10;

    ШиринаСтраницыВТвипах = 11907;

    ВысотаСтраницыВТвипах = 16839;

    КонецЕсли;

    Это для формата А4

    Reply
  61. sash-ml

    Спасибо за обновление публикации.

    Я давно использую этот алгоритм и PDF creator для массовых рассылок инфы клиентам

    Для дополнительного удобства пользователей изменил немного общую форму «ПечатьДокументов»

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

    Главное юзеры довольны очень.

    Reply
  62. Alex Y

    Спасибо за идею

    Поменяйте ссылку PDFCreator на

    http://sourceforge.net/projects/pdfcreator/

    Reply
  63. Spartan

    (62) Поменял. Видимо с офсайтом проблемы…

    Reply
  64. rommario

    Спасибо, материал очень полезный.

    На мой взгляд единственным коммерчески приемлемым решением является Yoksel.

    Главное его преимущество, что он не требует установки никаких принтеров (скажем на 20 машинах), легко регистрируется и, проверено, работает без проблем.

    Для обхода проблемы с высотой страницы я искусственно бью свой большой xls на несколько файлов, все их преобразовываю в pdfы, которые потом объединяю в один файл.

    Хотя это конечно нельзя назвать нормальным решением.

    Недорогих и тем более бесплатных приемлемых решений для печати в pdf пока, к сожалению, нет.

    Reply
  65. Rustig

    (0) хочу отблагодарить 🙂

    может телефончик напишите?

    Reply
  66. Spartan

    (65) Что-то у меня с рассылкой, наверное… не вижу новые комментарии. Да бог с ним — пользуйтесь на здоровье! 😉

    Reply
  67. ARL

    У меня проблемы с отработкой строки:

    ПереместитьФайл(ФайлPDF.ПолноеИмя, НовоеПолноеИмя) ;

    Как понимаю, 1С не «отпускает» первый файл.

    Пришлось заменить на

    КопироватьФайл(ФайлPDF.ПолноеИмя, НовоеПолноеИмя) ;

    При этом не получается печатать массив файлов.

    Ни кто не знает, как обойти проблему?

    Автору однозначно, благодарность. Наши менеджеры порадовались.

    Reply
  68. Spartan

    (67) Если файл «захвачен», то скорее всего не 1С, а виртуальным принтером. Вообще странно — у меня после проверки размера файла таких проблем не возникало. Какие имена получаются при копировании? Можно конечно добавить еще принудительную задержку времени в несколько секунд, но это немного коряво получится. В общем, надо пробовать в конкретной ситуации…

    Вообще хорошо бы посмотреть, что блокирует файл… может с правами какие-то нюансы?

    Reply
  69. PGorlov

    Добрый день!

    Спасибо за такой пример, но есть одно но! Я совсем не понимаю почему происходит следующее:

    1. Все документы, нужные в бумажном виде, печатаем на HP 2727

    2. Когда надо в PDF, то запускают мою обработку, включающую ваш способ преобразования в PDF

    3. Выбирают необходимые документы

    4. Эти документы печатаются в PDF с синей печатью и подписью

    5. Отправляются архивом на указанные емейл

    6. Затем если снова надо печатать бумажные документы, то печать уходит на PDFCreator

    Собственно, правится это путем открытия перед печатью пункта меню: Файл-Параметры Страницы, выставляется нужный принтер и до следующего использования обработки все хорошо, после ее применения опять вместо нужного принтера стоит PDFCreator

    Непонятно сие по следующим причинам:

    1. Ни кто про это не писал

    2. Стоит ведь строка в коде: ТабДок.ИмяПринтера = СтароеИмяПринтера;

    3. Если после этой строки добавить: ТабДок.Напечатать(); то старый принтер «запоминается», иначе остается PDFCreator

    Буду благодарен, если кто-нибудь подскажет в чем может быть дело.

    Reply
  70. Spartan

    del

    Reply
  71. Spartan

    (69) Строка ТабДок.ИмяПринтера = СтароеИмяПринтера; была изначально или добавили позже? Если позже, то виртуальный принтер уже мог ранее сохраниться в настройках табличного документа внутри базы. В таком случае необходимо для таких печатных форм установить нужный принтер принудительно — у меня есть где-то для этого обработка. Позже поищу и выложу нужный код, если нужно.

    Reply
  72. PGorlov

    (71)Не, там раньше стоял наш HP 2727, строка уже была в обработке, т.е. по идее измениться ни чего не должно было.

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

    Reply
  73. Spartan
    Reply
  74. kolia

    Спасибо. Интересная статья. Очень помогла

    Reply
  75. Spartan

    Грабли с виртуальными принтерами более неактуальны — в новом релизе платформы 8.2.15.289 добавили поддержку pdf.

    Reply
  76. Seven2000

    (75) Спасибо, что открыл глаза!!!

    А как из 1С тогда програмно сохранить в ПДФ встроенными средствами?

    Reply
  77. Spartan

    (76)

    ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF);
    Reply
  78. boss_kuz

    Предлагаю поменять часть кода определения создания файла типа :

     ФайлPDF = Новый Файл(Путь + «Title.pdf»);
    НовоеПолноеИмя = Путь + ?(ЗначениеЗаполнено(ТабличныйДокумент.ИспользуемоеИмяФайла), ТабличныйДокумент.ИспользуемоеИмяФайла, «Табличный документ » + Строка(1)) + «.pdf»;
    ФайлСформирован = Ложь;
    Порог = ТекущаяДата() + 30;
    Пока ТекущаяДата()<Порог цикл
    ОбработкаПрерыванияПользователя();
    Попытка
    ПереместитьФайл(ФайлPDF.ПолноеИмя, НовоеПолноеИмя);
    ФайлСформирован = Истина;
    Break;
    Исключение
    Продолжить;
    КонецПопытки;
    КонецЦикла;
    
    Если Не ФайлСформирован Тогда
    Сообщить(«Ожидание отклика завершено. Файл не создан!»,СтатусСообщения.Важное);
    Попытка
    УтилитаПечати.cClose();
    Исключение
    Сообщить(«Нормальное завершение процесса печати невозможно!», СтатусСообщения.ОченьВажное);
    КонецПопытки;
    УтилитаПечати        = Неопределено;
    НастройкиПоУмолчанию = Неопределено;
    Состояние();
    Возврат ложь;
    КонецЕсли;
    

    Показать

    Reply
  79. BoryaMbi

    (77)

    Считаю публикацию снова актуальной, в связи с ошибкой 1С в кодировках при записи pdf файла:

    Известные ошибки версии 8.2.16, планируемые к исправлению в будущих версиях

    20006661 (SW707626) Сохранение табличного документа в формате PDF

    Проблема:

    При сохранении табличного документа в формате PDF, текст, написанный нестандартным шрифтом, сохраняется в PDF некорректно.

    Дата публикации:

    2012-08-02

    http://downloads.v8.1c.ru/content/Platform/8_2_16_362/ErrPlatform_8_2_16_362.htm

    Обсуждения:

    http://www.forum.mista.ru/topic.php?id=668893

    http://www.forum.mista.ru/topic.php?id=647214

    Есть ли мысли по этому поводу?

    Каким образом можно обходить ошибку?

    Или это говорит нам о том, что 1С в вопросах PDF нельзя доверять вообще?

    Reply
  80. Кошки рулят

    Какой-то дикий код для Йокселя у автора.

    Какие-то проблемы с регистрацией? У меня dll регистрации не требует. Что я делаю не правильно?

    ИсхТабл = СоздатьОбъект(«Таблица»);
    …
    …
    ИсхТабл.Вывести();
    
    ЗагрузитьВнешнююКомпоненту («SpreadSheet.dll»);
    
    Таб = СоздатьОбъект («ТабличныйДокумент»);
    Таб.ЗагрузитьИзТаблицы (ИсхТабл);
    Конвертер = СоздатьОбъект («Йоксель.ГрафическийКонвертер.PDF»);
    Конвертер.ВысотаСтраницы = 56.7*297;
    Конвертер.ШиринаСтраницы = 56.7*210;
    Конвертер.КоличествоБитНаПиксел = 24;
    Конвертер.Документ = Таб;
    Конвертер.ПолеСлева = 56.7*15;
    Конвертер.ПолеСверху = 56.7*10;
    Конвертер.ПолеСправа = 56.7*10;
    Конвертер.ПолеСнизу = 56.7*5;
    
    Данные = Конвертер.СтандартныеМетаданные;
    Данные.Автор = глПользователь;
    Данные.Заголовок = «шлю всем мой крутой документ»;
    Данные.Тема = «мой крутой документ»;
    Данные.КлючевыеСлова = «отчет, документ» ;
    Данные.ГенераторОригинальногоДокумента = «1С:Клюшки & Кошки рулят»;
    Данные.ГенераторДокументаPDF = «Йоксель — yoksel.net.ru»;
    
    Час=»»;
    Минута=»»;
    Секунда=»»;
    ТекущееВремя(Час,Минута,Секунда);
    
    Данные.УстановитьДатуСоздания (ДатаГод(ТекущаяДата()),ДатаМесяц(ТекущаяДата()),ДатаЧисло(ТекущаяДата()),Час,Минута,Секунда);
    Данные.УстановитьДатуМодификации (ДатаГод(ТекущаяДата()),ДатаМесяц(ТекущаяДата()),ДатаЧисло(ТекущаяДата()),Час,Минута,Секунда);
    
    Конвертер.ЗаписатьВФайл (КаталогВременныхФайлов()+»Мой крутой документ.pdf»);
    ЗапуститьПриложение(КаталогВременныхФайлов()+»Мой крутой документ.pdf»);
    //ФС.УдалитьФайл(КаталогВременныхФайлов()+»Мой крутой документ.pdf»);
    

    Показать

    Reply
  81. Spartan

    (79) Даже не знаю, а какие могут быть мысли? Платформа — это черный ящик.. Варианты: не использовать нестандартные шрифты, ждать пока 1С исправят ошибку или пользоваться нетиповыми методами.

    (80)

    Что я делаю не правильно?

    Наверное, пишете в 7-ке..

    Йоксель корректно поддерживает(-л) mxl только семерочного формата, поэтому для корректного отображения форм используется промежуточное сохранение в xls. Или что именно Вам кажется «диким»? Оформление кода через Попытку? Так регистрация тут не при чем.. Библиотеки банально может не оказаться на машине, или Вы предлагаете лично это проверить у каждого из 70 пользователей?

    Reply
  82. BoryaMbi

    (81)

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

    Можно подробнее, какие необходимо использовать штрифты в табличном документе, чтобы его можно было корректно записать в pdf?

    Я перепробовал парочку — ничего не вышло. Просто в итоговом документе — выделил всю таблицу и свойствах указал другой штрифт — Ариал, затем Таймс и т.д. Все тоже самое.

    Может еще какую-то кодировку необходимо указывать?

    Reply
  83. Spartan

    (82) Честно говоря, сам не сталкивался — узнал об этой ошибке из Вашего поста.. Так что не смогу ничего подсказать, к сожалению. Надо экспериментировать.

    Reply
  84. BoryaMbi

    (83)

    Ясно. Думаю, что это корректное место для обсуждения данной проблемы.

    Reply
  85. boss_kuz

    На основании этой статьи я сделал рабочую обработку.

    Ставьте плюсики 🙂 http://infostart.ru/public/146275/

    Reply
  86. N.Serg

    Добрый день, очень полезная публикация, но есть вопрос. А как заставить PDFCreator создавать один файл с документами печати, а не несколько?

    Reply
  87. Spartan

    (86) Формируйте один табличный документ нужного вида, чтобы все, что нужно, было в нем и передавайте на вход процедуры массив с этим документом.

    Reply
  88. N.Serg

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

    Reply
  89. Spartan

    (88) Тогда не знаю. Не уверен, что это вообще возможно с помощью PDFCreator. Копайте его настройки — я делал это сто лет назад, может чего добавилось/поменялось.

    Reply
  90. N.Serg

    а Вы не помните где брали документацию по работе с этим объектом (его свойства и методы)?

    Reply
  91. N.Serg

    может кому-то пригодится, т.к. у меня ушла куча времени

    Попытка
    ПринтерПДФ = Новый COMОбъект(«PDFCreator.clsPDFCreator»);
    Исключение
    Сообщить(«Не установлен драйвер принтера PDFCreator!», СтатусСообщения.Важное);
    Возврат Неопределено;
    КонецПопытки;
    
    ПринтерыPDF = ПринтерПДФ.cGetPDFCreatorPrinters();
    Если ПринтерыPDF.Count() = 0 Тогда
    ПринтерПДФ.cAddPDFCreatorPrinter(«PDFCreator»);
    ПринтерыPDF = ПринтерПДФ.cGetPDFCreatorPrinters();
    КонецЕсли;
    ИмяПринтераPDF = ПринтерыPDF.Item(1);
    
    ПринтерПДФ.cStart(«/NoProcessingAtStartup»);
    ПринтерПДФ.cClearcache();
    ПринтерПДФ.cPrinterStop = 1;
    
    НаборОпций = ПринтерПДФ.cOptions();
    НаборОпций.NoConfirmMessageSwitchingDefaultprinter   = 1;
    НаборОпций.UseAutosave                        = 1;
    НаборОпций.UseAutosaveDirectory                  = 1;
    НаборОпций.AutosaveFormat                     = 0; // PDF
    НаборОпций.AutosaveDirectory                  =  Путь;
    НаборОпций.AutosaveFilename                   = «111.PDF»;
    НаборОпций.AutosaveStartStandardProgram       = 0;
    
    ПринтерПДФ.cOptions = НаборОпций;
    
    Для Индекс = 0 По ТабличныеДокументы.Количество() — 1 Цикл
    ТабДок = ТабличныеДокументы[Индекс];
    ТабДок.ИмяПринтера = ИмяПринтераPDF;
    ТабДок.Напечатать();
    КонецЦикла;;
    
    ПринтерПДФ.cCombineAll();
    ПринтерПДФ.cPrinterStop = 0;
    
    Счетчик = 0;
    Пока ПринтерПДФ.cCountOfPrintjobs > 1 Цикл
    Счетчик = Счетчик + 1;
    ПринтерПДФ.cCombineAll();
    Старт = ТекущаяДата();
    Пока ТекущаяДата() <> Старт + 1 Цикл
    КонецЦикла;
    КонецЦикла;
    
    Старт = ТекущаяДата();
    Таймаут = 5;
    
    Пока НЕ ЗначениеЗаполнено(ПринтерПДФ.cOutputFileName) ИЛИ (ТекущаяДата() — Старт < Таймаут) Цикл
    КонецЦикла;
    
    ПринтерПДФ.cClearcache();
    ПринтерПДФ.cClose();
    ПринтерПДФ = Неопределено;
    
    Возврат Истина;
    

    Показать

    Reply
  92. farkhod

    Хороший листинг, пригодится может каждому

    Reply
  93. wondermaker

    (75) там актуальны другие грабли 🙂

    Как минимум до платформы 8.2.19.80 есть проблема — если поле «перенасыщено» форматированием (жирный, наклонный, подчеркивание), то при определенных обстоятельства может получиться проблема при сохранении в PDF — файл просто не читается.

    Я пока поймал эту ошибку, думал, что поседею.

    Причем поймать условия, при которых это происходит (т.е. условия знал, не знал что именно влияет) сложно.

    В итоге, убрал в строках подчеркивание из шрифта и всё заработало без проблем.

    Reply
  94. szhukov

    Не получается в один файл напечатать несколько печатных форм

    Подскажите как?

    (использую PDFCreator)

    там вроде есть, такая функция cCombineAll, но то ли не так пользую, то ли не для этого… 🙂

    Reply
  95. Spartan

    (94) От PDFCreator’а давно отказались. К сожалению, не помогу. Эксперименты с ним проводить некогда.

    Reply
  96. baikalpharm

    Установил принтер PDFCreator, но при выполнение выходит ошибка «Не установлен драйвер принтера PDFCreator!».

    Что необходимо еще установить?

    Reply
  97. jorelingo

    (96) baikalpharm, необходимо скачать более раннюю версию pdfcreator 1.7.3, тогда все ок

    Reply
  98. ironn

    Намучился с этим PDF Creator, понадобилось сохранять в jpg из 1С 8.2

    Оказывается, все зависит от версии.

    Для версий до 2.0

    УтилитаПечати = Новый COMОбъект(«PDFCreator.clsPDFCreator»);

    Для версий, начиная с 2.0 или 2.1 (у меня 2.1)

    PDFCreator= Новый COMОбъект(«PDFCreatorBeta.PDFCreatorObj»);
    PDFCreatorQueue= Новый COMОбъект(«PDFCreatorBeta.JobQueue»);

    А в версии 2.2 уже без Beta

    PDFCreator= Новый COMОбъект(«PDFCreator.PDFCreatorObj»);
    PDFCreatorQueue= Новый COMОбъект(«PDFCreator.JobQueue»);

    Методы тоже поменялись, примеры есть на оф. сайте

    Если кому интересно, могу подрихтовать и выложить. Сейчас работает для Бух. для Украины.

    Reply
  99. ironn

    (97) jorelingo, более ранние версии глючные сильно

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *