При разработке в среде 1С программисты часто сталкиваются с задачей расчета производных величин в табличных частях документов, таких как общий вес или объем товаров. На первый взгляд задача кажется простой, но она таит в себе подводные камни: от критических ошибок производительности до проблем с обновлением интерфейса. В данной статье мы разберем, как правильно извлекать данные из справочников, оптимизировать расчеты и настраивать условное оформление так, чтобы оно не «слетало» в типовых конфигурациях.
Рассмотрим ситуацию, когда при переборе строк табличной части попытка получить вес товара через конструкцию Строка.Вес возвращает 0, хотя в карточке номенклатуры значение заполнено. Это происходит потому, что поле Вес отсутствует в самой табличной части документа, а программа пытается обратиться к реквизиту, которого нет в текущем контексте строки.
Часто начинающие разработчики допускают ошибку, пытаясь обратиться к данным следующим образом:
// Ошибочный код
Для Каждого Строка Из Объект.Товары Цикл
Объем1 = Объем1 + Строка.Количество * Объект.Товары.Номенклатура.ОбъемЧислитель;
КонецЦикла;
Проанализируем ошибку: обращение Объект.Товары.Номенклатура является некорректным, так как Товары — это коллекция строк (табличная часть), и у нее нет свойства Номенклатура. Свойство Номенклатура есть у конкретной строки. Однако даже исправление на Строка.Номенклатура.ОбъемЧислитель является плохой практикой.
Почему обращение через точку — это плохо? Каждый раз, когда система встречает точку после ссылки (например, Номенклатура.Вес), она выполняет отдельный неявный запрос к базе данных. Если в документе 100 строк, система сделает 100 лишних запросов, что существенно замедлит работу сервера.
Для однократного получения значения реквизита в типовых конфигурациях (УТ 11, ERP, КА) рекомендуется использовать функции общих модулей. Это позволяет избежать ошибок и делает код более читаемым. Рассмотрим пример использования стандартной функции:
ВесТовара = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Строка.Номенклатура, "ВесЧислитель");
Если же необходимо рассчитать данные для всей таблицы, правильнее всего будет использовать запрос. Мы заранее выгрузим все нужные весовые характеристики для списка номенклатуры из документа одним махом, а затем применим их в расчетах. Это самый производительный метод.
Другой важный аспект — обновление данных в интерфейсе. Если вы рассчитали вес только в коде, пользователь может не увидеть изменений до тех пор, пока не переоткроет форму или не выполнит принудительное действие. Чтобы СуммаОбъема или ИтогоВес обновлялись мгновенно при изменении количества, необходимо использовать клиентские события формы.
Выясним алгоритм действий:
ПриИзменении для колонки Количество.Элементы.Товары.Обновить() или пересчитаем итог программно в реквизит формы, выведенный в «подвал» таблицы.Часто возникает задача выделить цветом строки, где не указан вес или объем. Разработчик настраивает условное оформление в конструкторе формы, но при запуске программы оно не работает. Проанализируем причину: в типовых конфигурациях 1С (например, в УТ 11) часто существует процедура УстановитьУсловноеОформление, которая вызывается при открытии формы и программно очищает все настройки, заданные вручную, чтобы установить свои собственные.
Чтобы ваше оформление работало, его нужно добавить программно. Разберем по шагам, как это сделать через расширение конфигурации:
УстановитьУсловноеОформление и создадим для нее перехват с аннотацией &После.Посмотрим на пример кода для выделения красным фоном пустых значений веса:
&НаСервере
Процедура Расш_УстановитьУсловноеОформлениеПосле()
// Добавляем новый элемент условного оформления
Элемент = УсловноеОформление.Элементы.Добавить();
// 1. Указываем, что именно мы меняем (Цвет фона)
Элемент.Оформление.УстановитьЗначениеПараметра("ЦветФона", ЦветаСтиля.ЦветТекстаОшибки);
// 2. Указываем условие: если Вес равен 0
ЭлементОтбора = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Вес");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.МеньшеИлиРавно;
ЭлементОтбора.ПравоеЗначение = 0;
// 3. Указываем поля, которые будут окрашены
ПолеОформления = Элемент.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыВес");
КонецПроцедуры
При работе с весогабаритными характеристиками (ВГХ) обязательно учитывайте следующее:
ВесЧислитель и ВесЗнаменатель). Это сделано для того, чтобы избежать погрешностей округления. Итоговый вес одной единицы равен Числитель / Знаменатель.Номенклатура, а из справочника УпаковкиЕдиницыИзмерения, привязанного к этой номенклатуре.Проанализировав ситуацию, мы видим, что залог стабильной работы программы — это отказ от избыточных обращений через точку в пользу запросов и правильное использование программных механизмов настройки интерфейса, таких как УсловноеОформление в связке с расширениями. Это не только ускорит работу системы, но и сделает ваш код соответствующим стандартам разработки 1С.