В типовых конфигурациях на управляемых формах «1С Бухгалтерия предприятия 8», «1С Зарплата и управление персоналом 8», «1С Управление Торговлей 8» и т.д., которые реализованы с использованием БСП (библиотека стандартных подсистем) – есть такая замечательная вещь, как регистр сведений «Пользовательские макеты печати». Помимо своего прямого предназначения - дать пользователю возможность самостоятельно редактировать печатные формы (конечно в разумных пределах), его можно использовать и по другому назначению. А именно - хранить в нём некоторую информацию. Бывают ситуации, когда поставленная задача казалось бы не даёт возможности её выполнить, не внеся изменений в типовую конфигурацию. А менять типовую без крайней необходимости – ой, как не хочется. На мой взгляд - с помощью регистра сведений "Пользовательские макеты" - можно решать некоторые задачи. Регистр сведений "ПользовательскиеМакетыПечати" - имеет два измерения: "Объект" и "ИмяМакета", которые имеют тип "Строка" и один ресурс "Макет" с типом "ХранилищеЗначений", где можно хранить что угодно. Почему бы этим не воспользоваться. Ниже примеры из моей практики, где применял.
Пример для «1С Зарплата и управление персоналом 8»:
Необходимо из внешней торговой системы загружать данные о продажах и на основании этих данных рассчитывать премии продавцам. Продавцы имеют процент в зависимости от должности («стажер», «консультант» и т.д) и от места расположения магазина. Никакой линейной зависимости нет: одна и та же должность в разных магазинах имеет разный процент. В прежней редакции Зарплаты 2.5 был заведен «регистр сведений» в разрезе должность/подразделение со ставкой процента. При переходе на 3.1 – было решено использовать макет. Это позволило оставить конфигурацию полностью типовой. Использовать дополнительные реквизиты не получалось, т.к. тогда пришлось бы прописывать для каждого магазина должности и ставки процентов. Оставался бы открытым вопрос с хранением истории изменения ставок, да и забивать форму кучей дополнительных реквизитов тоже не хотелось.
Пример использования при печати:
Необходимо разработать внешнюю печатную форму (неважно что это будет, например трудовой договор по форме принятой в организации). При печати должно «всплывать» окно, в котором дополнительно указываются некоторые сведения, которые также выводятся в печатную форму. При этом должна сохранятся возможность повторной печати с этими же самыми сведениями: у одного сотрудника это одни условия, у другого – другие. В прежней версии использовался непериодический регистр сведений. Я сделал с использованием макета. При первичной печати данные в макет записываются, при повторной – считываются.
Конечно использование макетов - регистр сведений никогда не заменит, но в каких-то случаях очень даже полезен.
Ниже пример реализации по примеру с записью ставок процентов продаж:
Создаем внешнюю обработку, форму с табличной частью, которую должен заполнить пользователь и макет, который потом будет считывать. После заполнения – записываем данные. Простая табличная часть в три колонки "Подразделение", "Должность", "Процент" и "Дата сведений" на форме обработки.
С записью всё просто:
&НаКлиенте
Процедура ЗаписатьПользовательскийМакет()
ЗаписатьПользовательскийМакетНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаписатьПользовательскийМакетНаСервере()
ТаблДокумент = Новый ТабличныйДокумент;
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Макет = ОбработкаОбъект.ПолучитьМакет("Макет");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для каждого стр из ПроцентыПродаж цикл
ОбластьСтрока.Параметры.КодПодразделения = стр.Подразделение.Код;
ОбластьСтрока.Параметры.Подразделение = стр.Подразделение.Наименование;
ОбластьСтрока.Параметры.Должность = стр.Должность.Наименование;
ОбластьСтрока.Параметры.Процент = стр.Процент;
ОбластьСтрока.Параметры.ПечДатаСведений = ДатаСведений;
ТаблДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
ИмяВладельца = "Справочник.Организации";
ИмяМакета = "Процент_продаж";
Запись = РегистрыСведений.ПользовательскиеМакетыПечати.СоздатьМенеджерЗаписи();
Запись.Объект = ИмяВладельца;
Запись.ИмяМакета = ИмяМакета;
Запись.Использование = Истина;
Запись.Макет = Новый ХранилищеЗначения(ТаблДокумент, Новый СжатиеДанных(9));
Запись.Записать();
КонецПроцедуры
«ИмяВладельца» и «ИмяМакета» - большой роли не играют. Главное чтобы потом при считывании макета они были такими же.
Считываем макет и выводим на печать:
&НаКлиенте
Процедура ПечатьСписка(Команда)
ТабличныйДок = ПечатьСпискаНаСервере();
//========= эта конструция нужна, чтобы открыть общую форму "Печать документов"
КоллекцияПечатныхФорм.Очистить();
МассивОбъектов=Новый Массив;
МассивОбъектов.Добавить(ТабличныйДок);
Стр=КоллекцияПечатныхФорм.Добавить();
Стр.ИмяМакета="Процент_продаж";
Стр.ИмяВРЕГ="ПРОЦЕНТ_ПРОДАЖ";
Стр.ТабличныйДокумент=ТабличныйДок;
Стр.СинонимМакета="Процент продаж";
Стр.Экземпляров=1;
Стр.ОфисныеДокументы = "";
ПараметрыОткрытия = Новый Структура("ИмяМенеджераПечати,ИменаМакетов,ПараметрКоманды,ПараметрыПечати");
ПараметрыОткрытия.ИмяМенеджераПечати="Справочник.Организации";
ПараметрыОткрытия.ПараметрКоманды = Новый Массив;
ПараметрыОткрытия.ПараметрыПечати = Новый Структура;
ПараметрыОткрытия.Вставить("КоллекцияПечатныхФорм", КоллекцияПечатныхФорм);
ПараметрыОткрытия.Вставить("ОбъектыПечати", МассивОбъектов);
ПараметрыОткрытия.Вставить("ОфисныеДокументы","");
ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия, ЭтаФорма.ВладелецФормы);
КонецПроцедуры
&НаСервере
Функция ПечатьСпискаНаСервере()
//============ получение макета из регистра сведений
ТекстЗапроса =
"ВЫБРАТЬ
| ПользовательскиеМакетыПечати.Макет КАК Макет,
| ПользовательскиеМакетыПечати.ИмяМакета КАК ИмяМакета
|ИЗ
| РегистрСведений.ПользовательскиеМакетыПечати КАК ПользовательскиеМакетыПечати
|ГДЕ
| ПользовательскиеМакетыПечати.Объект = &Объект
| И ПользовательскиеМакетыПечати.ИмяМакета ПОДОБНО &ИмяМакета
| И ПользовательскиеМакетыПечати.Использование";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.Параметры.Вставить("Объект", "Справочник.Организации");
Запрос.Параметры.Вставить("ИмяМакета", "Процент_продаж");
Выборка = Запрос.Выполнить().Выгрузить();
Если Выборка.Количество()=1 Тогда
МакетВХранилище = Выборка[0].Макет;
МакетСоставаПоказателей = МакетВХранилище.Получить();
КонецЕсли;
Таб = Новый ТабличныйДокумент;
Если МакетСоставаПоказателей = Неопределено Тогда
СообщитьПользователю("Ставки не загружены в программу!");
Возврат Таб;
КонецЕсли;
//===========заполнение таблицы значений.Для вывода на печать она не нужна, можно сразу заполнять табличный документ
//=========== ТЗ нужна, чтобы прочитанные данные из макета использовать для дальнейших расчетов.
//=========== Например в какой-нибудь обработке по расчету премий - уже на основании полученных ставок из макета.
Табл = Новый ТаблицаЗначений;
Табл.Колонки.Добавить("Подразделение", Новый ОписаниеТипов("СправочникСсылка.ПодразделенияОрганизаций"));
Табл.Колонки.Добавить("Должность", Новый ОписаниеТипов("СправочникСсылка.Должности"));
Табл.Колонки.Добавить("Процент",Новый ОписаниеТипов("Число"));
Табл.Колонки.Добавить("ПечДатаСведений",Новый ОписаниеТипов("Дата"));
Для а = 1 по МакетСоставаПоказателей.ВысотаТаблицы Цикл
КодПодразделения = МакетСоставаПоказателей.Область(а,1,а,1).Текст;
Подразделение = МакетСоставаПоказателей.Область(а,2,а,2).Текст;
Должность = МакетСоставаПоказателей.Область(а,3,а,3).Текст;
Процент = МакетСоставаПоказателей.Область(а,4,а,4).Текст;
ПечДатаСведений = МакетСоставаПоказателей.Область(а,5,а,5).Текст;
Если Процент = "" Тогда
Процент = 0;
КонецЕсли;
НовСтрока = Табл.Добавить();
НовСтрока.Подразделение = Справочники.ПодразделенияОрганизаций.НайтиПоКоду(КодПодразделения);
НовСтрока.Должность = Справочники.Должности.НайтиПоНаименованию(СокрЛП(Должность));
НовСтрока.Процент = Число(Процент);
НовСтрока.ПечДатаСведений = Дата(ПечДатаСведений);
КонецЦикла;
//========= вывод на печать
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Макет = ОбработкаОбъект.ПолучитьМакет("Макет");
Шапка = Макет.ПолучитьОбласть("Шапка");
Таб.Вывести(Шапка);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для каждого стр из Табл цикл
ОбластьСтрока.Параметры.КодПодразделения = стр.Подразделение.Код;
ОбластьСтрока.Параметры.Подразделение = стр.Подразделение.Наименование;
ОбластьСтрока.Параметры.Должность = стр.Должность.Наименование;
ОбластьСтрока.Параметры.Процент = стр.Процент;
ОбластьСтрока.Параметры.ПечДатаСведений = Формат(стр.ПечДатаСведений,"ДФ=dd.MM.yyyy");
Таб.Вывести(ОбластьСтрока);
КонецЦикла;
Возврат Таб;
КонецФункции
Для вывода на печать, чтобы использовать общую форму "Печать документов", нужно будет ещё в реквизиты формы добавить Таблицу значений с колонками произвольного типа "ИмяМакета", "ТабличныйДокумент", "ИмяВРЕГ", "СинонимМакета", "Экземпляров", "ПолныйПутьКМакету", "ИмяФайлаПечатнойФормы", "ОфисныеДокументы".
Есть ещё один момент который я считаю плюсом: если пользователь зайдёт в регистр сведений "Пользовательские макеты печати", то данный макет он не увидит. С одной стороны сохраняется конфиденциальность, а с другой не будет лишних вопросов.
Пример с обработкой прилагаю: работает и "1С Зарплатой 8" и с "1СБухгалтерией 8". В "1С Управлении торговлей 8" не сработает по причине отсутствия справочников "Должности" и "Подразделения", но сам принцип рабочий.
Обработка тестировалась на релизах "1С Зарплата 8" 3.1.7.144, 3.1.8.216; "1С Бухгалтерия 8" 3.0.67.54.