При разработке в среде 1С часто возникает архитектурная дилемма: необходимо передать дополнительное значение (например, рассчитанную сумму, количество строк или статус) из формируемого отчета обратно в вызывающую обработку. Ситуация осложняется тем, что этот отчет может вызываться из десятков других мест конфигурации. Прямое добавление новых параметров в экспортную функцию формирования отчета нарушит обратную совместимость, и система начнет выдавать ошибки компиляции во всех остальных модулях.
В этой статье мы подробно разберем несколько безопасных и элегантных практических методов решения данной задачи. Мы изучим как подход с использованием временного хранилища и необязательных параметров, так и метод передачи данных непосредственно внутри возвращаемого объекта ТабличныйДокумент.
Давайте проанализируем наиболее надежный способ с точки зрения платформенных механизмов 1С. Если вызов отчета осуществляется через передачу единой структуры параметров, мы можем динамически добавлять в эту структуру новые ключи. Другие объекты, вызывающие этот же отчет, просто не будут знать о существовании нового ключа, что полностью исключает возникновение ошибок обратной совместимости.
Суть метода заключается в том, что в вызывающей обработке мы генерируем новый адрес во временном хранилище, помещаем его в структуру параметров и передаем в отчет. Отчет проверяет наличие этого параметра и записывает туда числовое значение.
Рассмотрим по шагам реализацию этого механизма.
Шаг 1. Код в вызывающей обработке:
// 1. Создаем структуру параметров для отчета
ПараметрыОтчета = Новый Структура;
ПараметрыОтчета.Вставить("АдресХранилищаТабДок", АдресТабДок); // Основной параметр
// 2. Генерируем уникальный идентификатор и новый адрес во временном хранилище
АдресСуммы = ПоместитьВоВременноеХранилище(Неопределено, Новый УникальныйИдентификатор);
// Добавляем адрес в структуру параметров
ПараметрыОтчета.Вставить("АдресХранилищаСуммы", АдресСуммы);
// 3. Вызываем экспортную процедуру формирования отчета
Отчеты.МойОтчет.СформироватьОтчет(ПараметрыОтчета);
// 4. Извлекаем возвращенное числовое значение после выполнения отчета
НужноеЧисло = ПолучитьИзВременногоХранилища(АдресСуммы);
Шаг 2. Код в модуле отчета:
Процедура СформироватьОтчет(ПараметрыОтчета) Экспорт
// ... Вычисления и формирование Табличного Документа ...
ТабДок = Новый ТабличныйДокумент;
// (Код заполнения отчета)
// Помещаем основной табличный документ в его хранилище
ПоместитьВоВременноеХранилище(ТабДок, ПараметрыОтчета.АдресХранилищаТабДок);
// Вычисляем нужное числовое значение
ИтоговаяСумма = 150250.45;
// БЕЗОПАСНАЯ ПРОВЕРКА: Проверяем, передан ли дополнительный параметр
Если ПараметрыОтчета.Свойство("АдресХранилищаСуммы") Тогда
// Записываем значение по переданному адресу
ПоместитьВоВременноеХранилище(ИтоговаяСумма, ПараметрыОтчета.АдресХранилищаСуммы);
КонецЕсли;
КонецПроцедуры
Этот подход идеален, так как функция Свойство() защищает выполнение кода от падения, если отчет вызывается из старых обработок, где ключ АдресХранилищаСуммы не передается.
Давайте рассмотрим альтернативный вариант, который вообще не требует модификации передаваемых параметров. Поскольку отчет в любом случае возвращает объект ТабличныйДокумент, мы можем использовать сам этот документ в качестве «транспорта» для метаданных.
Каждая ячейка табличного документа имеет свойство Расшифровка. В это свойство можно поместить абсолютно любой тип данных, включая числа, соответствия или целые структуры. При этом пользователь при просмотре отчета ничего не заметит, если мы не включим признак интерактивного действия для этой ячейки.
Выясним, как реализовать этот подход на практике.
Запись значения на стороне отчета:
// Формируем табличный документ
ТабДок = Новый ТабличныйДокумент;
// Выбираем ячейку, которая гарантированно присутствует в документе (например, R1C1)
// Или создаем отдельную невидимую техническую область
ТехническаяЯчейка = ТабДок.Область("R1C1");
// Записываем числовое значение в свойство Расшифровка
ТехническаяЯчейка.Расшифровка = ВычисленноеЧисловоеЗначение;
Если нам нужно вернуть из отчета не одно число, а целый набор различных показателей, мы можем упаковать их в структуру и передать её аналогичным образом:
ДанныеДляВозврата = Новый Структура;
ДанныеДляВозврата.Вставить("ИтоговаяСумма", ИтоговаяСумма);
ДанныеДляВозврата.Вставить("КоличествоСтрок", КоличествоСтрок);
ТабДок.Область("R1C1").Расшифровка = ДанныеДляВозврата;
Чтение значения на стороне вызывающей обработки:
// Получаем табличный документ из временного хранилища
ТабДок = ПолучитьИзВременногоХранилища(АдресТабДок);
// Извлекаем данные из расшифровки первой ячейки
ДанныеИзОтчета = ТабДок.Область("R1C1").Расшифровка;
Если ТипЗнч(ДанныеИзОтчета) = Тип("Структура") Тогда
Сумма = ДанныеИзОтчета.ИтоговаяСумма;
Количество = ДанныеИзОтчета.КоличествоСтрок;
ИначеЕсли ТипЗнч(ДанныеИзОтчета) = Тип("Число") Тогда
Сумма = ДанныеИзОтчета;
КонецЕсли;
Данный метод является наиболее элегантным, так как интерфейс взаимодействия (параметры вызова) остается абсолютно нетронутым.
Еще один надежный способ передачи данных внутри табличного документа — это создание скрытой именованной ячейки. Этот метод особенно удобен, если вызывающая программа должна прочитать значение, ориентируясь на конкретное уникальное имя области, чтобы избежать путаницы с реальными данными отчета.
Проанализируем пример реализации данного метода.
Шаг 1. Создание именованной области в отчете:
// Выбираем ячейку за пределами стандартной области видимости (например, в 1000-й строке)
ТехническаяОбласть = ТабДок.Область(1000, 1, 1000, 1);
ТехническаяОбласть.Имя = "ТехническиеДанные_СуммаОтчета";
// Указываем, что ячейка содержит значение, и записываем его
ТехническаяОбласть.СодержитЗначение = Истина;
ТехническаяОбласть.Значение = ВычисленнаяСумма;
ТехническаяОбласть.ТипЗначения = Новый ОписаниеТипов("Число");
// Скрываем строку, чтобы она не отображалась пользователю при выводе на печать
ТабДок.Область("R1000").Видимость = Ложь;
Шаг 2. Получение значения в обработке:
ТабДок = ПолучитьИзВременногоХранилища(АдресТабДок);
// Безопасно пытаемся прочитать значение из именованной области
Попытка
Сумма = ТабДок.Область("ТехническиеДанные_СуммаОтчета").Значение;
Исключение
// Обработка ситуации, если отчет сформирован старой версией кода без этой области
Сумма = 0;
КонецПопытки;
Каждое из рассмотренных решений имеет свои области применения:
Применяя данные подходы, вы сможете легко модернизировать механизмы обмена данными между объектами конфигурации 1С, сохраняя при этом стабильность работы всей системы в целом.