Каталог решений - Печать в PDF в фоновом режиме через регламентные задания 1с 8.2 с помощью Yoksel.dll на х64 сервере

Печать в PDF в фоновом режиме через регламентные задания 1с 8.2 с помощью Yoksel.dll на х64 сервере

Печать в PDF в фоновом режиме через регламентные задания 1с 8.2 с помощью Yoksel.dll на х64 сервере

В наличии

Была поставлена задача автоматической рассылки документов на почтовые ящики ответственных лиц.
Был опробован виртуальный принтер PDFСreator — результат отрицательный.
Фоновый режим рассылки документов сервером осуществлен с помощью внешней компоненты Yoksel.dll, которая была зарегистрирована на х32 1с-сервере с помощью команды regsvr32 Yoksel.dll
Ниже приведенные процедуры созданы в общем модуле.
Ссылки на документы, печатные формы которых необходимо разослать ответственным лицам накапливаютя в регистре сведений рдУведомлениеГотовности.
В процедурах показана сама идея автоматического формирования PDF-документов на сервере 1с. Если 1с-сервер х64, то в кластер вносится х32 1с сервер и создается рабочий процесс, в который автоматически перекочевывает фоновое задание и Йоксель запускается и работает физически на х32 сервере.

Категория:

Описание

Процедура УведомлениеГотовности() Экспорт
    
    Запрос = Новый Запрос;
                   
    Запрос.Текст =  "ВЫБРАТЬ РАЗЛИЧНЫЕ
                    |    рдУведомлениеГотовности.ОтчетПроизводства КАК ОтчетПроизводства,
                    |    ЗаказНаПроизводствоПродукция.Заказ.Ссылка КАК ЗаказПокупателя
                    |ИЗ
                    |    РегистрСведений.рдУведомлениеГотовности КАК рдУведомлениеГотовности
                    |        ПОЛНОЕ СОЕДИНЕНИЕ РегистрНакопления.ВыпускПродукции КАК ВыпускПродукции
                    |            ПОЛНОЕ СОЕДИНЕНИЕ Документ.ЗаказНаПроизводство.Продукция КАК ЗаказНаПроизводствоПродукция
                    |            ПО ВыпускПродукции.Заказ.Ссылка = ЗаказНаПроизводствоПродукция.Ссылка
                    |        ПО рдУведомлениеГотовности.ОтчетПроизводства = ВыпускПродукции.Регистратор
                    |ГДЕ
                    |    рдУведомлениеГотовности.Отправлено = ЛОЖЬ
                    |    И рдУведомлениеГотовности.Обработано = ЛОЖЬ";
        
    ТЗ = Запрос.Выполнить().Выгрузить();
    ТЗ.Сортировать("ЗаказПокупателя Возр,ОтчетПроизводства Убыв");
    Заказ="";
    Для каждого Строчка из ТЗ Цикл
        Если Заказ <> Строчка.ЗаказПокупателя Тогда
            Заказ = Строчка.ЗаказПокупателя;
            Если НЕ ПустаяСтрока(Строчка.ОтчетПроизводства) Тогда 
                //ТЗ1 = Запрос.Выполнить().Выгрузить().ВыбратьСтроку();
                рдОбработкаПроведенияОтчетПроизводстваЗаСменуРассылкаУведомленийГотовности(Строчка.ОтчетПроизводства);
            КонецЕсли;
        КонецЕсли;    
    КонецЦикла;

КонецПроцедуры    

  
Процедура рдОбработкаПроведенияОтчетПроизводстваЗаСменуРассылкаУведомленийГотовности(Источник) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("Ссылка",Источник);
    Запрос.УстановитьПараметр("Услуга","Услуга");
    Запрос.УстановитьПараметр("ПустойОтчет",Документы.ОтчетПроизводстваЗаСмену.ПустаяСсылка());
    
    Запрос.Текст =  "ВЫБРАТЬ РАЗЛИЧНЫЕ
                    |    ЗаказНаПроизводствоПродукция.Заказ.Ссылка КАК ЗаказПокупателя
                    |ПОМЕСТИТЬ ТЕМП
                    |ИЗ
                    |    РегистрНакопления.ВыпускПродукции КАК ВыпускПродукции
                    |        ПОЛНОЕ СОЕДИНЕНИЕ Документ.ЗаказНаПроизводство.Продукция КАК ЗаказНаПроизводствоПродукция
                    |        ПО ВыпускПродукции.Заказ.Ссылка = ЗаказНаПроизводствоПродукция.Ссылка
                    |ГДЕ
                    |    ВыпускПродукции.Регистратор.Ссылка = &Ссылка
                    |;
                    |
                    |////////////////////////////////////////////////////////////////////////////////
                    |ВЫБРАТЬ РАЗЛИЧНЫЕ
                    |    ЗаказыПокупателей.Номенклатура КАК Номенклатура,
                    |    ЗаказыПокупателей.ХарактеристикаНоменклатуры КАК Характеристика,
                    |    ЗаказыПокупателей.Количество КАК КолЗаказ,
                    |    0 КАК КолВыпуск,
                    |    &ПустойОтчет КАК Выпуск,
                    |    ТЕМП.ЗаказПокупателя КАК Заказ
                    |ПОМЕСТИТЬ ТЗЗаказ
                    |ИЗ
                    |    РегистрНакопления.ЗаказыПокупателей КАК ЗаказыПокупателей
                    |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТЕМП КАК ТЕМП
                    |        ПО ЗаказыПокупателей.Регистратор = ТЕМП.ЗаказПокупателя
                    |ГДЕ
                    |    ЗаказыПокупателей.Номенклатура.ВидНоменклатуры.Наименование <> &Услуга
                    |;
                    |
                    |////////////////////////////////////////////////////////////////////////////////
                    |ВЫБРАТЬ РАЗЛИЧНЫЕ
                    |    ВыпускПродукции.Продукция,
                    |    ВыпускПродукции.ХарактеристикаПродукции,
                    |    0 КАК КолЗаказ,
                    |    ВыпускПродукции.Количество КАК КолВыпуск,
                    |    ВыпускПродукции.Регистратор КАК Выпуск,
                    |    ЗаказНаПроизводствоПродукция.Заказ.Ссылка КАК Заказ
                    |ПОМЕСТИТЬ ТЗВыпуск
                    |ИЗ
                    |    РегистрНакопления.ВыпускПродукции КАК ВыпускПродукции
                    |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказНаПроизводство.Продукция КАК ЗаказНаПроизводствоПродукция
                    |            ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТЕМП КАК ТЕМП
                    |            ПО ЗаказНаПроизводствоПродукция.Заказ.Ссылка = ТЕМП.ЗаказПокупателя.Ссылка
                    |        ПО ВыпускПродукции.Заказ.Ссылка = ЗаказНаПроизводствоПродукция.Ссылка
                    |;
                    |
                    |////////////////////////////////////////////////////////////////////////////////
                    |ВЫБРАТЬ
                    |    ТЗЗаказ.Номенклатура КАК Номенклатура,
                    |    ТЗЗаказ.Характеристика КАК Характеристика,
                    |    ТЗЗаказ.КолЗаказ КАК КолЗаказ,
                    |    ТЗВыпуск.КолВыпуск КАК КолВыпуск,
                    |    ТЗВыпуск.Выпуск КАК Выпуск,
                    |    ТЗЗаказ.Заказ КАК Заказ
                    |ИЗ
                    |    ТЗЗаказ КАК ТЗЗаказ
                    |        ЛЕВОЕ СОЕДИНЕНИЕ ТЗВыпуск КАК ТЗВыпуск
                    |            ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ОтчетПроизводстваЗаСмену КАК ОтчетПроизводстваЗаСмену
                    |            ПО ТЗВыпуск.Выпуск = ОтчетПроизводстваЗаСмену.Ссылка
                    |        ПО ТЗЗаказ.Номенклатура = ТЗВыпуск.Продукция
                    |            И ТЗЗаказ.Характеристика = ТЗВыпуск.ХарактеристикаПродукции";

           
    
    //ТЗ = Запрос.Выполнить().Выгрузить().ВыбратьСтроку();
//Возврат;
    Выборка = Запрос.Выполнить().Выбрать();

    Отсылать = Ложь;
    Пока Выборка.Следующий() Цикл
        Если (Выборка.КолВыпуск = Выборка.КолЗаказ) И (Выборка.КолЗаказ<>0) Тогда
            Отсылать = Истина;
        иначе    
            Отсылать = Ложь;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    Результат = Ложь;
    Если Отсылать Тогда
        //Результат = Истина;
        Результат = ОтправитьУведомление(Выборка.Заказ,Источник);
    КонецЕсли;
    
    СтрокаРегистра = РегистрыСведений.рдУведомлениеГотовности.СоздатьМенеджерЗаписи();
    СтрокаРегистра.ОтчетПроизводства = Источник;
    СтрокаРегистра.Отправлено = Результат;
    СтрокаРегистра.Обработано = Истина;

    Попытка
        СтрокаРегистра.Записать();
    Исключение    
    КонецПопытки;    

КонецПроцедуры

Функция ОтправитьУведомление(Документ,ОтчетПр)
    
    ДокОбъект = Документ.ПолучитьОбъект();
    
    //Удалим pdf и flg оставшийся с прошлого раза
    ИмяФайла = "1c_notify.pdf";
    ПолноеИмяФайла = КаталогВременныхФайлов() + ИмяФайла;
    УдалитьФайлы(ПолноеИмяФайла);
    
    ИмяФлага = "1c_notify.flg";
    ПолноеИмяФлага = КаталогВременныхФайлов() + ИмяФлага;
    УдалитьФайлы(ПолноеИмяФлага);
        
    ПрофильЭлектроннойПочты = ПолучитьПрофильЭлектроннойПочты();
    Если ПрофильЭлектроннойПочты = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;    
    
    АдресНазначения = ксОбщийМодуль.ПолучитьПочтуПоСотруднику(ДокОбъект.ксОсновнойИнженерКонсультант);
    Если ПустаяСтрока(АдресНазначения) Тогда 
        ЗаписьЖурналаРегистрации("Не указан email у " + ДокОбъект.ксОсновнойИнженерКонсультант + ". Отправка сообщений указанному получателю не возможна!", УровеньЖурналаРегистрации.Ошибка, , ,"Уведомление");
        Возврат Ложь;
    КонецЕсли;
        
    //Создадим новое письмо на указаный адрес
    Письмо = Новый ИнтернетПочтовоеСообщение;
    Письмо.Отправитель = "1c@ridan.ru";
    Письмо.ИмяОтправителя = "ЗАО Ридан (отдел отгрузки)";
    Письмо.Получатели.Добавить(АдресНазначения);
    Письмо.Получатели.Добавить("ryuchin_a@ridan.ru");
        
    Письмо.Тема = "Уведомление о готовности";
    Письмо.Тексты.Добавить(Строка(ОтчетПр) + "
        |Уведомление об готовности выпуска для " + ДокОбъект.Контрагент + " по счету " + СокрЛП(ДокОбъект.Ссылка.Номер) + " от " + Формат(ДокОбъект.Ссылка.Дата, "ДФ=dd.MM.yy") + " находится во вложении");
    ПолноеИмяФайла = ФайлВложенияЙоксель(ДокОбъект,ОтчетПр);
    Письмо.Вложения.Добавить(ПолноеИмяФайла, "Уведомление о готовности");
    ИПочта = Новый ИнтернетПочта;
    
    Попытка
        ИПочта.Подключиться(ПрофильЭлектроннойПочты);
        ИПочта.Послать(Письмо);
        ИПочта.Отключиться();
        ЗаписьЖурналаРегистрации("Уведомление об готовности выпуска для " + ДокОбъект.Контрагент + " по счету " + СокрЛП(ДокОбъект.Ссылка.Номер) + " от " + Формат(ДокОбъект.Ссылка.Дата, "ДФ=dd.MM.yy") + " отправлено " + ДокОбъект.ксОсновнойИнженерКонсультант, УровеньЖурналаРегистрации.Информация, , ,"Уведомление");
        
        //ЗаписьЖурналаРегистрации("Удалить "+ПолноеИмяФайла, УровеньЖурналаРегистрации.Информация, , ,"Уведомление");
        //УдалитьФайлы(ПолноеИмяФайла);        
        Возврат Истина;
    Исключение
        ЗаписьЖурналаРегистрации("Необходимо проверить настройки электронной почты! Отправка невозможна! (" + ОписаниеОшибки() + ")", УровеньЖурналаРегистрации.Ошибка, , ,"Уведомление");
        Возврат Ложь;
    КонецПопытки;
    
КонецФункции

Функция ПолучитьПрофильЭлектроннойПочты()
    
    ПрофильПочты = Новый ИнтернетПочтовыйПрофиль;
    
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("УчетнаяЗапись", Константы.ксУчетнаяЗаписьЭлектроннойПочты.Получить());
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    УчетныеЗаписиЭлектроннойПочты.SMTPСервер,
    |    УчетныеЗаписиЭлектроннойПочты.ПортSMTP,
    |    УчетныеЗаписиЭлектроннойПочты.ЛогинSMTP,
    |    УчетныеЗаписиЭлектроннойПочты.ПарольSMTP,
    |    УчетныеЗаписиЭлектроннойПочты.ТребуетсяSMTPАутентификация,
    |    УчетныеЗаписиЭлектроннойПочты.АдресЭлектроннойПочты,
    |    УчетныеЗаписиЭлектроннойПочты.Логин,
    |    УчетныеЗаписиЭлектроннойПочты.Пароль,
    |    УчетныеЗаписиЭлектроннойПочты.ВремяОжиданияСервера
    |ИЗ
    |    Справочник.УчетныеЗаписиЭлектроннойПочты КАК УчетныеЗаписиЭлектроннойПочты
    |ГДЕ
    |    УчетныеЗаписиЭлектроннойПочты.Ссылка = &УчетнаяЗапись";
    Результат = Запрос.Выполнить();
    
    ЭлектроннаяПочта = Результат.Выбрать();
    Если ЭлектроннаяПочта.Следующий() Тогда
        
        Если ЭлектроннаяПочта.ТребуетсяSMTPАутентификация Тогда
            
            ПрофильПочты.АутентификацияSMTP = СпособSMTPАутентификации.Login;
            ПрофильПочты.ПользовательSMTP = ЭлектроннаяПочта.ЛогинSMTP;
            ПрофильПочты.ПарольSMTP = ЭлектроннаяПочта.ПарольSMTP;
            
        Иначе
            
            ПрофильПочты.АутентификацияSMTP = СпособSMTPАутентификации.ПоУмолчанию;
            
        КонецЕсли;
        
        ПрофильПочты.АдресСервераSMTP = ЭлектроннаяПочта.SMTPСервер;
        ПрофильПочты.ПортSMTP = ЭлектроннаяПочта.ПортSMTP;
        ПрофильПочты.ВремяОжидания = ЭлектроннаяПочта.ВремяОжиданияСервера;
        
        Возврат ПрофильПочты;
        
    Иначе
        
        ЗаписьЖурналаРегистрации("Не удалось получить учетную запись электронной почты - Отправка сообщений не возможна!", УровеньЖурналаРегистрации.Ошибка, , ,"Уведомление");
                 
        Возврат Неопределено;
        
    КонецЕсли;
    
КонецФункции

Функция ПечатьУведомления(СсылкаНаОбъект,ОтчетПр)
    
    НомерПечать = ОбщегоНазначения.ПолучитьНомерНаПечать(СсылкаНаОбъект);
    
    ТабДокумент = Новый ТабличныйДокумент;
    ТабДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_УВЕДОМЛЕНИЕ_ОБ_ОТГРУЗКЕ";
    
    Макет = ПолучитьОбщийМакет("УведомлениеГотовности");
    Обл   = Макет.ПолучитьОбласть("Шапка");
    
    Обл.Параметры.Заголовок = "Уведомление о готовности к отгрузке " + НомерПечать + " от " + Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy");
    Обл.Параметры.Плательщик = "Плательщик: " + СсылкаНаОбъект.Контрагент.Наименование;
    Обл.Параметры.Уведомление = "Информируем Вас, что оборудование по Счету №" + НомерПечать + " от " + Формат(СсылкаНаОбъект.Дата, "ДФ=dd.MM.yyyy") + Символы.ПС + "готово к отгрузке по следующим позициям:";
    ТабДокумент.Вывести(Обл);
    
    НомерСтроки = 1;
    Обл = Макет.ПолучитьОбласть("Строка");
    Для Каждого ТекСтрока ИЗ СсылкаНаОбъект.Товары Цикл
        
        Обл.Параметры.НомерСтроки = НомерСтроки;
        Обл.Параметры.Товар = ТекСтрока.Номенклатура.НаименованиеПолное + ", расчет " + ТекСтрока.ксРасчет;
        Обл.Параметры.Единица = ТекСтрока.ЕдиницаИзмерения;
        Обл.Параметры.Количество = ТекСтрока.Количество;
        Обл.Параметры.ДатаОтгрузки =  Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy");
        //Обл.Параметры.ДатаОтгрузки =  Формат(ОтчетПр.Дата, "ДФ=dd.MM.yyyy");
        ТабДокумент.Вывести(Обл);
        НомерСтроки = НомерСтроки + 1;
        
    КонецЦикла;
    
    Обл = Макет.ПолучитьОбласть("Подвал");
    Обл.Параметры.УсловияПоставки = СсылкаНаОбъект.ДополнениеКАдресуДоставки;
    ТабДокумент.Вывести(Обл);
    
    ТабДокумент.АвтоМасштаб = Истина;
    ТабДокумент.ИмяПринтера = "1c_notifyer";

    Возврат ТабДокумент;
    
КонецФункции

Функция ФайлВложенияЙоксель(пСтр,ОтчетПр)
    
    ИмяФайла = "1c_notify.pdf";
    ПолноеИмяФайла = КаталогВременныхФайлов() + ИмяФайла;
    ИмяФлага = "1c_notify.flg";
    ПолноеИмяФлага = КаталогВременныхФайлов() + ИмяФлага;

    //СтруктураПараметров = новый структура("ИмяФайла",ПолноеИмяФайла);
    
    ТабДокумент = ПечатьУведомления(пСтр.Ссылка,ОтчетПр);
    ПолноеИмяФайла = Йоксель_СохранитьОтчётВПДФ(ТабДокумент,ПолноеИмяФайла);
    
    УдалитьФайлы(ПолноеИмяФлага);
    
    Возврат ПолноеИмяФайла;
    
КонецФункции
// Функция формирует файлы для отправки по электронной почте с помощью внешней компоненты Yoksel.dll
//
Функция Йоксель_СохранитьОтчётВПДФ(ТабДок, ИмяФайла)//Путь)
    Попытка
        //ЗагрузитьВнешнююКомпоненту(КаталогПрограммы() + "Yoksel.dll");
        Йоксель      = ПолучитьCOMОбъект("","Йоксель");
        КонвертерPDF = Йоксель.СоздатьГрафическийКонвертерPDF();
    Исключение
        ЗаписьЖурналаРегистрации(ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка, , ,"Уведомление");
        //Предупреждение("Не удалось загрузить внешнюю компоненту Yoksel! Сообщите администратору системы!", 20);
        Возврат Неопределено;
    КонецПопытки;
    ТабДок.Записать(КаталогВременныхФайлов()+ "1c_notify.xls", ТипФайлаТабличногоДокумента.XLS97);
    
    // Конвертируем временный файл в формат pdf
    Попытка
        Таб = Йоксель.СоздатьТабличныйДокумент();
        Таб.Открыть(КаталогВременныхФайлов()+ "1c_notify.xls", "2");
        КонвертерPDF.Документ = Таб;
        КонвертерPDF.КоличествоБитНаПиксел = 24; //1, 4, 8, 24
        //КонвертерPDF.ПолеСлева = 1134; // в твипах (1 твип = 1/567 см)
        КонвертерPDF.ЗаписатьВФайл(ИмяФайла);
    Исключение
        УдалитьФайлы(КаталогВременныхФайлов()+ "1c_notify.xls");
        ЗаписьЖурналаРегистрации(ОписаниеОшибки(), УровеньЖурналаРегистрации.Ошибка, , ,"Уведомление");
        //Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
        Возврат Неопределено;
    КонецПопытки;
has been added to your cart:
Оформление заказа