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