Как заполнить данные макета из двух структур с проверкой на пустое значение?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки печатных форм в 1С часто возникает ситуация, когда данные для заполнения параметров макета могут находиться в разных источниках. Типичный пример: в документе есть две колонки, и если первая не заполнена, необходимо взять значение из второй. Рассмотрим, как эффективно реализовать механизм «приоритетного заполнения», когда макет сначала пытается получить данные из основной структуры, а при их отсутствии — из вспомогательной.

Постановка задачи и анализ ситуации

Представим, что у нас есть две структуры: СтруктураДоп (основная) и СтруктураДоп2 (вспомогательная). Нам нужно обойти параметры и сформировать итоговый набор данных так, чтобы выполнялось условие: если значение в первой структуре пустое (или равно нулю, или неопределено — в зависимости от логики), мы подставляем значение из второй. Проанализируем несколько способов реализации этой задачи.

Способ 1: Использование тернарного оператора в цикле

Самый быстрый и очевидный способ — это перебор ключей одной структуры и получение соответствующих значений из другой с помощью тернарного оператора ?(). Разберем этот метод на конкретном примере кода:


СтруктураДоп = Новый Структура;
СтруктураДоп.Вставить("МО", 0); // Допустим, значение не заполнено
СтруктураДоп.Вставить("КТП", 2);
СтруктураДоп.Вставить("КТК", 3);

СтруктураДоп2 = Новый Структура;
СтруктураДоп2.Вставить("МО", 11);
СтруктураДоп2.Вставить("КТП", 22);
СтруктураДоп2.Вставить("КТК", 33);

Для Каждого Элемент Из СтруктураДоп Цикл
    // Используем тернарный оператор для выбора значения
    // Если значение в основной структуре не заполнено, берем из второй по тому же ключу
    ИтоговоеЗначение = ?(ЗначениеЗаполнено(Элемент.Значение), 
                         Элемент.Значение, 
                         СтруктураДоп2[Элемент.Ключ]);
    
    Сообщить("Ключ: " + Элемент.Ключ + " -> Значение: " + ИтоговоеЗначение);
КонецЦикла;

Важный нюанс: при использовании прямого обращения через квадратные скобки СтруктураДоп2[Элемент.Ключ], мы должны быть на 100% уверены, что данный ключ существует во второй структуре. Если уверенности нет, программа выдаст ошибку.

Способ 2: Безопасное слияние структур через метод Свойство()

Чтобы избежать фатальных ошибок при отсутствии ключей во второй структуре, рекомендуется использовать метод Свойство(). Этот метод не только проверяет наличие ключа, но и позволяет сразу выгрузить значение в переменную. Рассмотрим более надежный вариант кода:


ИтоговаяСтруктура = Новый Структура;

Для Каждого Элемент Из СтруктураДоп Цикл
    ЗначениеИзВторой = Неопределено;
    // Проверяем, есть ли такой ключ во второй структуре
    Если СтруктураДоп2.Свойство(Элемент.Ключ, ЗначениеИзВторой) Тогда
        // Если основное значение пустое, а во второй структуре что-то есть
        Если Не ЗначениеЗаполнено(Элемент.Значение) И ЗначениеЗаполнено(ЗначениеИзВторой) Тогда
            ИтоговаяСтруктура.Вставить(Элемент.Ключ, ЗначениеИзВторой);
        Иначе
            ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
        КонецЕсли;
    Иначе
        // Если во второй структуре ключа нет, просто берем из первой
        ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
    КонецЕсли;
КонецЦикла;

Способ 3: Метод «Слоев» (оптимизация заполнения)

Вместо того чтобы проверять каждое поле в цикле, мы можем пойти «от противного». Проанализируем логику: сначала заполним итоговый набор данных всеми значениями из «запасной» структуры, а затем «наложим» сверху только те значения из основной, которые заполнены. Это сделает код чище и удобнее для работы с параметрами макета.

  1. Создаем ИтоговаяСтруктура как копию второй (запасной) структуры.
  2. Обходим первую (основную) структуру.
  3. Если значение в первой структуре заполнено, перезаписываем его в итоговой.
  4. Передаем итоговую структуру в макет.

// Предположим, ПараметрыМакета — это наша область.Параметры
ИтоговаяСтруктура = Новый Структура;

// 1. Сначала копируем все из "запасной" структуры
Для Каждого Элемент Из СтруктураДоп2 Цикл
    ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;

// 2. Накладываем "основную" структуру (только заполненные поля)
Для Каждого Элемент Из СтруктураДоп Цикл
    Если ЗначениеЗаполнено(Элемент.Значение) Тогда
        ИтоговаяСтруктура.Вставить(Элемент.Ключ, Элемент.Значение);
    КонецЕсли;
КонецЦикла;

// 3. Заполняем область макета одной командой
Область.Параметры.Заполнить(ИтоговаяСтруктура);

Различие между проверками на «Пусто» и «Существует»

При реализации подобных алгоритмов важно четко разделять два состояния данных, с которыми мы работаем в 1С:

1. Ключ отсутствует в структуре: Если вы попытаетесь обратиться к Структура["Ключ"], которого нет, система вызовет исключение. Поэтому для динамических структур всегда используйте Свойство().

2. Значение пустое: Функция ЗначениеЗаполнено() возвращает Ложь для нуля, пустой строки, пустой ссылки, Неопределено и Null. Однако будьте осторожны: если в вашем бизнес-процессе «0» является значащим числом (например, количество товара), то стандартная проверка сочтет его «пустым» и заменит на значение из второй структуры. В таких случаях используйте явное сравнение: Элемент.Значение <> Неопределено.

Рекомендации по производительности и архитектуре

Если вы работаете в конфигурации на базе БСП (Библиотека стандартных подсистем), обратите внимание на общий модуль ОбщегоНазначения. Там часто присутствуют вспомогательные функции для копирования и дополнения структур, что позволяет избежать написания лишних циклов и снижает вероятность ошибок.

Также помним, что если данные берутся напрямую из Табличной Части, то обращение к колонке всегда вернет какое-то значение (хотя бы пустую ссылку). В этом случае проверка на Неопределено не сработает, и нужно использовать либо ЗначениеЗаполнено(), либо сравнивать с пустой ссылкой конкретного типа через ПредопределенноеЗначение().

Выяснив все нюансы, мы можем сделать вывод: наиболее изящным решением является предварительная подготовка одной итоговой структуры-посредника. Это позволяет отделить логику обработки данных от логики вывода печатной формы, делая код более читаемым и легким в поддержке.

← На главную