Загрузка данных
Привет! Ссылку не открывал, она не нужна: задача понятная, напишем свою обработку. Ниже полный код и порядок сборки.
Как это будет работать
Это дополнительная внешняя обработка для подсистемы «Дополнительные отчеты и обработки» (она есть в УНФ). В ней три части:
Форма настроек: тип цен, группа номенклатуры, учетная запись почты, получатели, тема, формат (xlsx/pdf).
Формирование прайса запросом к регистру цен и отправка письмом через стандартную почту БСП.
Серверные команды «Прайс 1/2/3». Для таких команд в карточке доп. обработки можно настроить расписание, то есть регламентное задание. Так получаются до трех разных рассылок с разными настройками.
Шаг 1. Создайте обработку в конфигураторе
Файл → Новый → Внешняя обработка. Имя: ПрайсЛистыПоРасписанию.
Реквизиты обработки:
Имя Тип
НомерПрофиля Число (1 знак)
ТипЦен СправочникСсылка.ТипыЦен
Группа СправочникСсылка.Номенклатура
УчетнаяЗапись СправочникСсылка.УчетныеЗаписиЭлектроннойПочты
Получатели Строка (500)
Тема Строка (200)
ТекстПисьма Строка (0, неограниченная)
Формат Строка (4)
Добавьте форму Форма и сделайте ее основной.
Шаг 2. Модуль объекта
#Область ПрограммныйИнтерфейс
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Ложь;
ПараметрыРегистрации.Информация = "Отправка прайс-листов по e-mail по расписанию";
// Команда открытия настроек
Команда = ПараметрыРегистрации.Команды.Добавить();
Команда.Представление = "Настройка рассылки прайс-листов";
Команда.Идентификатор = "Форма";
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
Команда.ПоказыватьОповещение = Ложь;
// Команды для расписания (три независимых профиля)
Для Номер = 1 По 3 Цикл
Команда = ПараметрыРегистрации.Команды.Добавить();
Команда.Представление = "Отправить прайс-лист (профиль " + Номер + ")";
Команда.Идентификатор = "Прайс" + Номер;
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
Команда.ПоказыватьОповещение = Истина;
КонецЦикла;
Возврат ПараметрыРегистрации;
КонецФункции
// Вызывается БСП при выполнении серверной команды (в т.ч. из регламентного задания).
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения = Неопределено) Экспорт
Номер = Число(СтрЗаменить(ИдентификаторКоманды, "Прайс", ""));
ОтправитьПрайс(ПолучитьНастройки(Номер));
КонецПроцедуры
Функция ПолучитьНастройки(НомерПрофиля) Экспорт
Результат = Новый Структура;
Результат.Вставить("ТипЦен", Справочники.ТипыЦен.ПустаяСсылка());
Результат.Вставить("Группа", Справочники.Номенклатура.ПустаяСсылка());
Результат.Вставить("УчетнаяЗапись", Справочники.УчетныеЗаписиЭлектроннойПочты.ПустаяСсылка());
Результат.Вставить("Получатели", "");
Результат.Вставить("Тема", "Прайс-лист от [Дата]");
Результат.Вставить("ТекстПисьма", "Добрый день! Актуальный прайс-лист во вложении.");
Результат.Вставить("Формат", "xlsx");
Сохраненные = ХранилищеОбщихНастроек.Загрузить("ПрайсЛистыПоРасписанию",
"Профиль" + НомерПрофиля, , ИмяПользователяХранилища());
Если ТипЗнч(Сохраненные) = Тип("Структура") Тогда
ЗаполнитьЗначенияСвойств(Результат, Сохраненные);
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура СохранитьНастройки(НомерПрофиля, Настройки) Экспорт
ХранилищеОбщихНастроек.Сохранить("ПрайсЛистыПоРасписанию",
"Профиль" + НомерПрофиля, Настройки, , ИмяПользователяХранилища());
КонецПроцедуры
Процедура ОтправитьПрайс(Настройки) Экспорт
Если Не ЗначениеЗаполнено(Настройки.ТипЦен) Тогда
ВызватьИсключение "Не указан тип цен";
КонецЕсли;
Если Не ЗначениеЗаполнено(Настройки.УчетнаяЗапись) Тогда
ВызватьИсключение "Не указана учетная запись электронной почты";
КонецЕсли;
Если ПустаяСтрока(Настройки.Получатели) Тогда
ВызватьИсключение "Не указаны получатели";
КонецЕсли;
Попытка
ТабДок = СформироватьПрайс(Настройки);
Если Настройки.Формат = "pdf" Тогда
ТипФайла = ТипФайлаТабличногоДокумента.PDF;
Расширение = "pdf";
Иначе
ТипФайла = ТипФайлаТабличногоДокумента.XLSX;
Расширение = "xlsx";
КонецЕсли;
ДатаСтрока = Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy");
ВремФайл = ПолучитьИмяВременногоФайла(Расширение);
ТабДок.Записать(ВремФайл, ТипФайла);
Данные = Новый ДвоичныеДанные(ВремФайл);
УдалитьФайлы(ВремФайл);
Адрес = ПоместитьВоВременноеХранилище(Данные, Новый УникальныйИдентификатор);
Вложение = Новый Структура;
Вложение.Вставить("Представление", "Прайс-лист " + ДатаСтрока + "." + Расширение);
Вложение.Вставить("АдресВоВременномХранилище", Адрес);
Вложения = Новый Массив;
Вложения.Добавить(Вложение);
ПараметрыПисьма = Новый Структура;
ПараметрыПисьма.Вставить("Кому", Настройки.Получатели);
ПараметрыПисьма.Вставить("Тема", СтрЗаменить(Настройки.Тема, "[Дата]", ДатаСтрока));
ПараметрыПисьма.Вставить("Тело", Настройки.ТекстПисьма);
ПараметрыПисьма.Вставить("Вложения", Вложения);
РаботаСПочтовымиСообщениями.ОтправитьПочтовоеСообщение(Настройки.УчетнаяЗапись, ПараметрыПисьма);
ЗаписьЖурналаРегистрации("Прайс-листы по расписанию", УровеньЖурналаРегистрации.Информация, ,
, "Отправлено: " + Настройки.Получатели);
Исключение
ЗаписьЖурналаРегистрации("Прайс-листы по расписанию", УровеньЖурналаРегистрации.Ошибка, ,
, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Функция СформироватьПрайс(Настройки) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЕСТЬNULL(Номенклатура.Родитель.Наименование, """") КАК Группа,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.Наименование КАК Наименование,
| ЕСТЬNULL(Цены.Характеристика.Наименование, """") КАК Характеристика,
| ЕСТЬNULL(Номенклатура.ЕдиницаИзмерения.Наименование, """") КАК Единица,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ТипЦен = &ТипЦен) КАК Цены
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО Цены.Номенклатура = Номенклатура.Ссылка
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления
| И НЕ Номенклатура.ЭтоГруппа
| И Цены.Цена > 0";
Если ЗначениеЗаполнено(Настройки.Группа) Тогда
Запрос.Текст = Запрос.Текст + "
| И Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)";
Запрос.УстановитьПараметр("Группа", Настройки.Группа);
КонецЕсли;
Запрос.Текст = Запрос.Текст + "
|УПОРЯДОЧИТЬ ПО
| Группа,
| Наименование";
Запрос.УстановитьПараметр("Дата", ТекущаяДата());
Запрос.УстановитьПараметр("ТипЦен", Настройки.ТипЦен);
Выборка = Запрос.Выполнить().Выбрать();
ТабДок = Новый ТабличныйДокумент;
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДок.ПолеСлева = 10;
ТабДок.ПолеСправа = 10;
ТабДок.АвтоМасштаб = Истина;
Строка = 1;
ТабДок.Область(Строка, 1).Текст = "Прайс-лист на " + Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy")
+ " (" + Настройки.ТипЦен + ")";
ТабДок.Область(Строка, 1).Шрифт = Новый Шрифт(, 12, Истина);
Строка = Строка + 2;
Заголовки = Новый Массив;
Заголовки.Добавить("Артикул");
Заголовки.Добавить("Наименование");
Заголовки.Добавить("Характеристика");
Заголовки.Добавить("Ед.");
Заголовки.Добавить("Цена");
Для Колонка = 1 По Заголовки.Количество() Цикл
Ячейка = ТабДок.Область(Строка, Колонка);
Ячейка.Текст = Заголовки[Колонка - 1];
Ячейка.Шрифт = Новый Шрифт(, , Истина);
Ячейка.ЦветФона = Новый Цвет(220, 220, 220);
Ячейка.Обвести(Линия, Линия, Линия, Линия);
КонецЦикла;
ТабДок.ФиксацияСверху = Строка;
Строка = Строка + 1;
ТекущаяГруппа = Неопределено;
Пока Выборка.Следующий() Цикл
Если Выборка.Группа <> ТекущаяГруппа Тогда
ТекущаяГруппа = Выборка.Группа;
Область = ТабДок.Область(Строка, 1, Строка, 5);
Область.Объединить();
Область.Текст = ?(ПустаяСтрока(ТекущаяГруппа), "Без группы", ТекущаяГруппа);
Область.Шрифт = Новый Шрифт(, , Истина);
Область.ЦветФона = Новый Цвет(240, 240, 240);
Строка = Строка + 1;
КонецЕсли;
ТабДок.Область(Строка, 1).Текст = Выборка.Артикул;
ТабДок.Область(Строка, 2).Текст = Выборка.Наименование;
ТабДок.Область(Строка, 3).Текст = Выборка.Характеристика;
ТабДок.Область(Строка, 4).Текст = Выборка.Единица;
ТабДок.Область(Строка, 5).Текст = Формат(Выборка.Цена, "ЧДЦ=2; ЧРГ=' '");
ТабДок.Область(Строка, 5).ГоризонтальноеПоложение = ГоризонтальноеПоложение.Право;
Строка = Строка + 1;
КонецЦикла;
ТабДок.Область(, 1, , 1).ШиринаКолонки = 15;
ТабДок.Область(, 2, , 2).ШиринаКолонки = 55;
ТабДок.Область(, 3, , 3).ШиринаКолонки = 20;
ТабДок.Область(, 4, , 4).ШиринаКолонки = 6;
ТабДок.Область(, 5, , 5).ШиринаКолонки = 14;
Возврат ТабДок;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ИмяПользователяХранилища()
// Фиксированное имя, чтобы настройки читались и из регламентного задания
Возврат "ПрайсЛистыПоРасписанию_Общие";
КонецФункции
#КонецОбласти
В СформироватьПрайс переменная Линия не объявлена. Добавьте в начало функции:
bsl
Линия = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная, 1);
Шаг 3. Форма
В форме разместите поля: Объект.НомерПрофиля (поле выбора со списком 1, 2, 3), Объект.ТипЦен, Объект.Группа, Объект.УчетнаяЗапись, Объект.Получатели, Объект.Тема, Объект.ТекстПисьма (многострочное), Объект.Формат (список «xlsx» и «pdf»). Добавьте две команды: Сохранить и ОтправитьСейчас. Для поля НомерПрофиля создайте обработчик ПриИзменении.
Модуль формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.НомерПрофиля = 1;
ЗагрузитьНастройкиНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура НомерПрофиляПриИзменении(Элемент)
ЗагрузитьНастройкиНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура Сохранить(Команда)
СохранитьНаСервере();
ПоказатьОповещениеПользователя("Настройки сохранены");
КонецПроцедуры
&НаКлиенте
Процедура ОтправитьСейчас(Команда)
СохранитьНаСервере();
ОтправитьНаСервере();
ПоказатьОповещениеПользователя("Прайс-лист отправлен");
КонецПроцедуры
&НаСервере
Функция НастройкиИзФормы()
Результат = Новый Структура("ТипЦен, Группа, УчетнаяЗапись, Получатели, Тема, ТекстПисьма, Формат");
ЗаполнитьЗначенияСвойств(Результат, Объект);
Возврат Результат;
КонецФункции
&НаСервере
Процедура ЗагрузитьНастройкиНаСервере()
Настройки = РеквизитФормыВЗначение("Объект").ПолучитьНастройки(Объект.НомерПрофиля);
ЗаполнитьЗначенияСвойств(Объект, Настройки);
КонецПроцедуры
&НаСервере
Процедура СохранитьНаСервере()
РеквизитФормыВЗначение("Объект").СохранитьНастройки(Объект.НомерПрофиля, НастройкиИзФормы());
КонецПроцедуры
&НаСервере
Процедура ОтправитьНаСервере()
РеквизитФормыВЗначение("Объект").ОтправитьПрайс(НастройкиИзФормы());
КонецПроцедуры
Шаг 4. Подключение в УНФ
Сохраните обработку в файл .epf.
В УНФ: Администрирование → Печатные формы, отчеты и обработки → Дополнительные отчеты и обработки. Если пункта нет, включите флажок «Дополнительные отчеты и обработки».
Нажмите «Создать», выберите файл, подтвердите работу в небезопасном режиме (нужны права администратора).
В карточке на вкладке команд для «Отправить прайс-лист (профиль N)» нажмите Расписание и задайте время рассылки. Нужно, чтобы был выбран пользователь, от имени которого задание будет работать, и чтобы у него были права на почту.
Откройте «Настройка рассылки прайс-листов», заполните параметры и нажмите «Отправить сейчас» для теста.
Что может не совпасть с вашей конфигурацией
Я писал по памяти, а имена в разных релизах УНФ иногда отличаются. Проверьте в конфигураторе:
Справочник.ТипыЦен;
РегистрСведений.ЦеныНоменклатуры с измерениями ТипЦен, Номенклатура, Характеристика и ресурсом Цена;
Справочник.УчетныеЗаписиЭлектроннойПочты;
реквизиты номенклатуры Артикул и ЕдиницаИзмерения.
Если что-то отличается, исправьте имя в запросе. При ошибке пришлите мне текст, подправлю код.
В регистре цен в УНФ может быть флаг актуальности цены. Если он есть, добавьте в условие ГДЕ отбор по нему. Валюту можно взять из типа цен, добавив в запрос соответствующее поле.
Что можно добавить дальше: фильтр по остаткам на складе, отправка нескольким получателям с разными типами цен, архивирование вложения, прикрепление картинок. Скажите, что из этого нужно.
Всё делается в Конфигураторе вашей базы УНФ. Саму конфигурацию вы не меняете: обработка получается отдельным файлом .epf, поэтому УНФ она не сломает. Если хочется подстраховаться, перед началом скопируйте базу.
Часть 1. Открываем Конфигуратор
Запустите 1С, выберите вашу базу УНФ и нажмите кнопку «Конфигуратор», не «1С:Предприятие».
Обработку нужно создавать именно здесь. Тогда Конфигуратор знает справочники вашей УНФ и не ругается на Справочники.ТипыЦен и подобное.
Часть 2. Создаём обработку
Меню Файл → Новый… → Внешняя обработка.
Слева появится дерево с названием «Обработка1». Выделите его и нажмите Alt+Enter, откроется окно свойств.
В поле Имя впишите ПрайсЛистыПоРасписанию.
Часть 3. Добавляем реквизиты
В дереве слева раскройте обработку, щёлкните правой кнопкой по «Реквизиты» → «Добавить».
В свойствах впишите имя и выберите тип в поле «Тип» (кнопка с тремя точками). Всего нужно добавить 8 реквизитов:
Имя Тип Как выбрать
НомерПрофиля Число длина 1, точность 0
ТипЦен СправочникСсылка.ТипыЦен раскройте «СправочникСсылка», поставьте галочку
Группа СправочникСсылка.Номенклатура так же
УчетнаяЗапись СправочникСсылка.УчетныеЗаписиЭлектроннойПочты так же
Получатели Строка длина 500
Тема Строка длина 200
ТекстПисьма Строка длина 0 (без ограничения)
Формат Строка длина 4
Если какого-то справочника нет в списке типов, назовите мне его. Скорее всего, он называется чуть иначе в вашем релизе, и я поправлю код.
Часть 4. Вставляем код обработки
Правой кнопкой по самой обработке в дереве → «Открыть модуль объекта».
Вставьте весь код из блока «Шаг 2. Модуль объекта» моего прошлого сообщения.
Найдите строку Функция СформироватьПрайс(Настройки) Экспорт и сразу под ней добавьте строку:
bsl
Линия = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная, 1);
Нажмите Ctrl+F7, это проверка синтаксиса. Если выдаст ошибку, скопируйте её текст и пришлите мне.
Часть 5. Создаём форму
В дереве правой кнопкой по «Формы» → «Добавить».
В мастере оставьте всё по умолчанию. Имя должно быть именно Форма. Нажмите «Готово».
Откроется редактор формы. Слева сверху окно «Элементы», снизу окно «Реквизиты». Раскройте в нём «Объект», там будут ваши 8 реквизитов.
Перетащите мышкой из «Реквизиты» в «Элементы» эти 8 штук: НомерПрофиля, ТипЦен, Группа, УчетнаяЗапись, Получатели, Тема, ТекстПисьма, Формат.
Настройте поля. Щёлкните по полю в «Элементы», свойства откроются справа или по Alt+Enter:
НомерПрофиля: найдите «Список выбора», добавьте значения 1, 2, 3 и включите «Режим выбора из списка».
Формат: то же самое, значения xlsx и pdf.
ТекстПисьма: включите «Многострочный режим».
Событие для НомерПрофиля: в его свойствах откройте вкладку «События», у «ПриИзменении» нажмите значок лупы и выберите «Создать на клиенте». Откроется модуль формы. Пока просто закройте его.
Команды: вкладка «Команды» в редакторе формы, нажмите «Добавить» (зелёный плюс) и создайте две команды:
имя Сохранить, заголовок «Сохранить настройки»;
имя ОтправитьСейчас, заголовок «Отправить сейчас».
У каждой нажмите на лупу у поля «Действие» → «Создать на клиенте». Затем перетащите обе команды в окно «Элементы», чтобы появились кнопки.
Откройте модуль формы: правой кнопкой по форме в дереве → «Открыть модуль» (или вкладка «Модуль» внизу редактора). Удалите всё, что там есть, и вставьте код из «Шаг 3. Модуль формы» из прошлого сообщения.
Снова Ctrl+F7.
Часть 6. Сохраняем файл
Файл → Сохранить, выберите папку и имя, например ПрайсЛисты.epf.
Часть 7. Подключаем к УНФ
Закройте Конфигуратор и запустите базу в режиме «1С:Предприятие» под администратором.
Перейдите в Администрирование → Печатные формы, отчёты и обработки → Дополнительные отчёты и обработки. Если не найдёте, ищите по слову «Дополнительные» в поиске по меню. Если раздел скрыт, включите там галочку «Дополнительные отчёты и обработки».
Нажмите «Создать», выберите ваш .epf и нажмите «Выполнить». На вопрос о небезопасном режиме ответьте «Продолжить».
В карточке обработки сохраните её.
Часть 8. Настраиваем и тестируем
Почта должна быть настроена заранее. В УНФ в разделе настроек электронной почты должна существовать рабочая учётная запись (с адресом, SMTP-сервером и паролем). Если её нет, сначала создайте.
В карточке обработки откройте команду «Настройка рассылки прайс-листов». Выберите профиль 1, тип цен, учётную запись, впишите получателей (несколько адресов через ;) и нажмите «Сохранить настройки».
Нажмите «Отправить сейчас». Письмо с прайсом должно прийти получателю. Это тест.
Когда тест прошёл, вернитесь в карточку обработки, на вкладку команд. Выберите строку «Отправить прайс-лист (профиль 1)» и нажмите кнопку «Расписание» над таблицей. Задайте время, например «по будням в 8:00», и сохраните.
Важное про расписание
Если у вас клиент-серверная база (SQL или PostgreSQL), регламентные задания работают сами.
Если у вас файловая база (просто папка с файлом 1Cv8.1CD), задания выполняются только пока на одном из компьютеров открыта 1С с включённой обработкой регламентных заданий. Если так, скажите мне, и я объясню, как это настроить.
Если что-то не работает
Что видите Что делать
Ошибка в запросе, «поле не найдено» Пришлите текст ошибки, поправлю имена
Письмо не уходит Проверьте, что в УНФ тестовое письмо через эту учётную запись отправляется
Нет кнопки «Расписание» Проверьте, что у команды тип «Вызов серверного метода» и обработка включена
Пустой прайс Проверьте выбранный тип цен и что цены у номенклатуры заполнены
Если застрянете на любом шаге, напишите номер шага и что именно на экране, помогу.