При доработке обычных форм списков документов часто возникает задача вывести дополнительные вычисляемые данные или значения из табличных частей. Нередко разработчики сталкиваются с ситуацией, когда числовое поле начинает вести себя как обычный текст: данные прижимаются к левому краю, игнорируют формат разрядности и не реагируют на настройки типа колонки. Разберем причины такого поведения, выясним правильные способы установки числовых значений, а также рассмотрим важные вопросы оптимизации и обработки ошибок.
Проанализируем типовую ошибку в обработчике ПриВыводеСтроки. Когда для ячейки вызывается метод УстановитьТекст(), платформа принудительно переопределяет представление данных в ячейке как текстовую строку. Даже если в свойствах колонки элемента управления указан тип Число, переданный через этот метод текст отображается «как есть» — с выравниванием по левому краю и без автоматического разделения триад цифр или отображения незначащих нулей.
Рассмотрим исходный фрагмент кода с проблемой:
Процедура ДокументСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
Попытка
Ячейка = ОформлениеСтроки.Ячейки.СуммаЭквайринга;
Ячейка.УстановитьТекст(ДанныеСтроки.Ссылка.ОплатаПлатежнымиКартами.Получить(0).Сумма);
Исключение
КонецПопытки;
КонецПроцедуры
В данном примере метод УстановитьТекст() получает значение, неявно приводит его к строковому типу и отключает стандартное числовое форматирование ячейки.
Чтобы элемент управления распознавал переданные данные как число и автоматически применял к ним правила форматирования (выравнивание по правому краю, точность, разделители групп), у объекта ОформлениеЯчейки следует задавать именно значение, а не текст. Разберем, как это сделать правильно.
Значение или вызовем метод УстановитьЗначение().Число (при необходимости используем функцию Число()).Посмотрим на исправленный вариант:
Ячейка = ОформлениеСтроки.Ячейки.СуммаЭквайринга;
ЗначениеСуммы = ДанныеСтроки.Ссылка.ОплатаПлатежнымиКартами.Получить(0).Сумма;
Ячейка.УстановитьЗначение(Число(ЗначениеСуммы));
При таком подходе колонка списка корректно отобразит число по правому краю в соответствии с настройками разрядности.
Если по логике задачи необходимо оставить именно метод УстановитьТекст(), а также принудительно выровнять текст, выполним явное форматирование числа функцией Формат() и установим горизонтальное положение ячейки:
Ячейка = ОформлениеСтроки.Ячейки.СуммаЭквайринга;
СуммаЧислом = Число(ДанныеСтроки.Ссылка.ОплатаПлатежнымиКартами.Получить(0).Сумма);
Ячейка.УстановитьТекст(Формат(СуммаЧислом, "ЧДЦ=2; ЧГ=3,0"));
Ячейка.ГоризонтальноеПоложение = ПоложениеТекстаЭлектронногоДокумента.Право;
Обратим внимание на критическую проблему производительности в исходном коде: обращение вида ДанныеСтроки.Ссылка.ОплатаПлатежнымиКартами. При построчной отрисовке списка документов платформа для каждой отдельной строки выполняет неявное считывание всего объекта документа из базы данных. Это порождает так называемую проблему N+1 запросов: при отображении 30 строк на экране платформа сделает 30 отдельных тяжелых обращений к базе, что приведет к сильным зависаниям формы при прокрутке.
Для вычисляемых колонок в обычных формах штатным и производительным решением является событие списка ПриПолученииДанных. Разберем его реализацию по шагам:
ОформленияСтрок сразу для всей видимой пачки документов.Посмотрим на пример правильного обработчика ПриПолученииДанных:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
МассивСсылок = Новый Массив;
СоответствиеСтрок = Новый Соответствие;
Для Каждого Оформление Из ОформленияСтрок Цикл
МассивСсылок.Добавить(Оформление.ДанныеСтроки.Ссылка);
СоответствиеСтрок.Вставить(Оформление.ДанныеСтроки.Ссылка, Оформление);
КонецЦикла;
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТабЧасть.Ссылка КАК Ссылка,
| ТабЧасть.Сумма КАК СуммаЭквайринга
|ИЗ
| Документ.РеализацияТоваровУслуг.ОплатаПлатежнымиКартами КАК ТабЧасть
|ГДЕ
| ТабЧасть.Ссылка В(&МассивСсылок)
| И ТабЧасть.НомерСтроки = 1";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ТекОформление = СоответствиеСтрок[Выборка.Ссылка];
Если ТекОформление <> Неопределено Тогда
ТекОформление.Ячейки.СуммаЭквайринга.УстановитьЗначение(Выборка.СуммаЭквайринга);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В исходном коде использовалась конструкция Попытка...Исключение КонецПопытки для перехвата ситуации, когда табличная часть пуста. Подобное «глушение» исключений считается грубой ошибкой разработки по следующим причинам:
ОписаниеОшибки() или ЗаписьЖурналаРегистрации().Пример корректной обработки непредвиденных ошибок:
Попытка
// Потенциально опасная операция
ВыполнитьДействие();
Исключение
ТекстОшибки = "Ошибка при обработке списка: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("ОформлениеСписка", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
Сообщить(ТекстОшибки);
КонецПопытки;
Таким образом, для корректного отображения чисел в списке необходимо передавать данные через УстановитьЗначение(), выносить запросы к данным в событие ПриПолученииДанных и избегать пустых блоков перехвата исключений.