Как программно изменить значение в одной ячейке табличного поля при изменении другой в 1С?

Программист 1С v8.3 (Обычные формы)
← На главную

При разработке внешних обработок или доработке существующих конфигураций на обычных формах часто возникает задача: организовать автоматический расчет одного поля на основании данных другого. Классический пример — пересчет колонки Всего при изменении Количества или Цены. Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с ошибкой «Поле объекта не обнаружено» при попытке обратиться к данным строки.

В этой статье мы подробно разберем, как правильно получить доступ к данным текущей строки, какие свойства объектов использовать и как избежать типичных ошибок производительности.

Разберем причину ошибки «Поле объекта не обнаружено»

Проанализируем ситуацию: когда вы создаете обработчик события ПриИзменении для колонки табличного поля, платформа передает в процедуру параметр Элемент. Многие ошибочно полагают, что Элемент — это и есть строка таблицы. На самом деле, Элемент — это объект типа ТабличноеПоле.

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

Способ 1. Использование свойства ТекущиеДанные

Самый универсальный и правильный способ получить доступ к строке в обычных формах — это использование свойства ТекущиеДанные. Оно возвращает объект строки (это может быть строка таблицы значений или строка табличной части документа).

Рассмотрим пример кода в обработчике события:


Процедура ТабличноеПоле1КоличествоПриИзменении(Элемент)
    // Получаем строку, в которой произошло изменение
    СтрокаДанных = Элемент.ТекущиеДанные;
    
    // Выполняем расчет
    Если СтрокаДанных <> Неопределено Тогда
        СтрокаДанных.Всего = СтрокаДанных.Количество * СтрокаДанных.Цена;
    КонецЕсли;
КонецПроцедуры

Здесь Элемент.ТекущиеДанные возвращает нам контекст конкретной строки. Важно всегда проверять результат на Неопределено, чтобы избежать ошибок в пустых таблицах.

Способ 2. Обращение через ЭлементыФормы

Иногда удобнее обращаться к табличному полю не через параметр процедуры, а напрямую через коллекцию элементов формы. Это особенно полезно, если вы вызываете пересчет из другой процедуры, куда Элемент не передается.

Посмотрим на пример:


Процедура РассчитатьСумму()
    // Обращаемся напрямую к табличному полю на форме
    Строка = ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные;
    
    Если Строка <> Неопределено Тогда
        Строка.Всего = Строка.Количество * Строка.Цена;
    КонецЕсли;
КонецПроцедуры

Разница между ТекущиеДанные и ТекущаяСтрока

Выясним причину, почему стоит предпочитать ТекущиеДанные. В обычных формах объект ТабличноеПоле может вести себя по-разному в зависимости от источника данных:

  1. Если источником является Таблица значений, то ТекущаяСтрока вернет саму строку, и разницы практически нет.
  2. Если источником является Табличная часть документа или справочника, ТекущаяСтрока может вернуть индекс строки или ссылку, что затруднит прямой доступ к колонкам.

Поэтому использование ТекущиеДанные является стандартом де-факто, так как это свойство всегда возвращает объект с доступными колонками-реквизитами.

Как обновить итоги в подвале таблицы

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


Процедура ТабличноеПоле1КоличествоПриИзменении(Элемент)
    Строка = Элемент.ТекущиеДанные;
    Строка.Всего = Строка.Количество * Строка.Цена;
    
    // Заставляем форму пересчитать итоги в колонках
    ЭлементыФормы.ТабличноеПоле1.ОбновитьСтроки();
КонецПроцедуры

Важные рекомендации по реализации расчетов

При написании логики пересчета придерживайтесь следующих правил, чтобы ваша обработка работала стабильно:

  1. Проверка на пустые значения: Если пользователь очистит поле Цена, программа может попытаться умножить число на Null или Неопределено. Используйте приведение к числу: Число(Строка.Цена).
  2. Вынос логики в отдельную процедуру: Если формул много (НДС, скидки, валюты), лучше создать отдельную процедуру в модуле, которая принимает строку как параметр.

Пример правильной структуры кода:


Процедура ПересчитатьСтроку(СтрокаТаблицы) Экспорт
    СтавкаНДС = 20;
    СтрокаТаблицы.Сумма = СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;
    СтрокаТаблицы.СуммаНДС = (СтрокаТаблицы.Сумма * СтавкаНДС) / 100;
    СтрокаТаблицы.Всего = СтрокаТаблицы.Сумма + СтрокаТаблицы.СуммаНДС;
КонецПроцедуры

Процедура ТабличноеПоле1КоличествоПриИзменении(Элемент)
    ПересчитатьСтроку(Элемент.ТекущиеДанные);
КонецПроцедуры

Чего делать категорически нельзя

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

Также убедитесь, что у колонки Всего в свойствах заполнено поле Данные. Если колонка создана просто «для красоты» и не привязана к реквизиту таблицы, то программно присвоенное значение исчезнет, как только строка уйдет из фокуса видимости.

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

← На главную