В процессе разработки печатных форм в 1С часто возникает ситуация, когда данные для заполнения параметров макета могут находиться в разных источниках. Типичный пример: в документе есть две колонки, и если первая не заполнена, необходимо взять значение из второй. Рассмотрим, как эффективно реализовать механизм «приоритетного заполнения», когда макет сначала пытается получить данные из основной структуры, а при их отсутствии — из вспомогательной.
Представим, что у нас есть две структуры: СтруктураДоп (основная) и СтруктураДоп2 (вспомогательная). Нам нужно обойти параметры и сформировать итоговый набор данных так, чтобы выполнялось условие: если значение в первой структуре пустое (или равно нулю, или неопределено — в зависимости от логики), мы подставляем значение из второй. Проанализируем несколько способов реализации этой задачи.
Самый быстрый и очевидный способ — это перебор ключей одной структуры и получение соответствующих значений из другой с помощью тернарного оператора ?(). Разберем этот метод на конкретном примере кода:
СтруктураДоп = Новый Структура;
СтруктураДоп.Вставить("МО", 0); // Допустим, значение не заполнено
СтруктураДоп.Вставить("КТП", 2);
СтруктураДоп.Вставить("КТК", 3);
СтруктураДоп2 = Новый Структура;
СтруктураДоп2.Вставить("МО", 11);
СтруктураДоп2.Вставить("КТП", 22);
СтруктураДоп2.Вставить("КТК", 33);
Для Каждого Элемент Из СтруктураДоп Цикл
// Используем тернарный оператор для выбора значения
// Если значение в основной структуре не заполнено, берем из второй по тому же ключу
ИтоговоеЗначение = ?(ЗначениеЗаполнено(Элемент.Значение),
Элемент.Значение,
СтруктураДоп2[Элемент.Ключ]);
Сообщить("Ключ: " + Элемент.Ключ + " -> Значение: " + ИтоговоеЗначение);
КонецЦикла;
Важный нюанс: при использовании прямого обращения через квадратные скобки СтруктураДоп2[Элемент.Ключ], мы должны быть на 100% уверены, что данный ключ существует во второй структуре. Если уверенности нет, программа выдаст ошибку.
Чтобы избежать фатальных ошибок при отсутствии ключей во второй структуре, рекомендуется использовать метод Свойство(). Этот метод не только проверяет наличие ключа, но и позволяет сразу выгрузить значение в переменную. Рассмотрим более надежный вариант кода:
ИтоговаяСтруктура = Новый Структура;
Для Каждого Элемент Из СтруктураДоп Цикл
ЗначениеИзВторой = Неопределено;
// Проверяем, есть ли такой ключ во второй структуре
Если СтруктураДоп2.Свойство(Элемент.Ключ, ЗначениеИзВторой) Тогда
// Если основное значение пустое, а во второй структуре что-то есть
Если Не ЗначениеЗаполнено(Элемент.Значение) И ЗначениеЗаполнено(ЗначениеИзВторой) Тогда
ИтоговаяСтруктура.Вставить(Элемент.Ключ, ЗначениеИзВторой);
Иначе
ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЕсли;
Иначе
// Если во второй структуре ключа нет, просто берем из первой
ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЕсли;
КонецЦикла;
Вместо того чтобы проверять каждое поле в цикле, мы можем пойти «от противного». Проанализируем логику: сначала заполним итоговый набор данных всеми значениями из «запасной» структуры, а затем «наложим» сверху только те значения из основной, которые заполнены. Это сделает код чище и удобнее для работы с параметрами макета.
ИтоговаяСтруктура как копию второй (запасной) структуры.
// Предположим, ПараметрыМакета — это наша область.Параметры
ИтоговаяСтруктура = Новый Структура;
// 1. Сначала копируем все из "запасной" структуры
Для Каждого Элемент Из СтруктураДоп2 Цикл
ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;
// 2. Накладываем "основную" структуру (только заполненные поля)
Для Каждого Элемент Из СтруктураДоп Цикл
Если ЗначениеЗаполнено(Элемент.Значение) Тогда
ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЕсли;
КонецЦикла;
// 3. Заполняем область макета одной командой
Область.Параметры.Заполнить(ИтоговаяСтруктура);
При реализации подобных алгоритмов важно четко разделять два состояния данных, с которыми мы работаем в 1С:
1. Ключ отсутствует в структуре: Если вы попытаетесь обратиться к Структура["Ключ"], которого нет, система вызовет исключение. Поэтому для динамических структур всегда используйте Свойство().
2. Значение пустое: Функция ЗначениеЗаполнено() возвращает Ложь для нуля, пустой строки, пустой ссылки, Неопределено и Null. Однако будьте осторожны: если в вашем бизнес-процессе «0» является значащим числом (например, количество товара), то стандартная проверка сочтет его «пустым» и заменит на значение из второй структуры. В таких случаях используйте явное сравнение: Элемент.Значение <> Неопределено.
Если вы работаете в конфигурации на базе БСП (Библиотека стандартных подсистем), обратите внимание на общий модуль ОбщегоНазначения. Там часто присутствуют вспомогательные функции для копирования и дополнения структур, что позволяет избежать написания лишних циклов и снижает вероятность ошибок.
Также помним, что если данные берутся напрямую из Табличной Части, то обращение к колонке всегда вернет какое-то значение (хотя бы пустую ссылку). В этом случае проверка на Неопределено не сработает, и нужно использовать либо ЗначениеЗаполнено(), либо сравнивать с пустой ссылкой конкретного типа через ПредопределенноеЗначение().
Выяснив все нюансы, мы можем сделать вывод: наиболее изящным решением является предварительная подготовка одной итоговой структуры-посредника. Это позволяет отделить логику обработки данных от логики вывода печатной формы, делая код более читаемым и легким в поддержке.