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

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

Переход с платформы 1С 7.7 на 1С 8.3 (Управляемые формы) часто сопровождается трудностями в понимании того, как взаимодействуют данные объекта, элементы формы и клиент-серверная архитектура. Одной из классических задач является групповой пересчет колонок в табличной части (ТЧ) — например, увеличение цены всех товаров на определенное значение, введенное пользователем. Рассмотрим подробнее, с какими подводными камнями можно столкнуться при реализации этой задачи и как их правильно обойти.

Различие между данными формы и данными объекта

Проанализируем типичную ситуацию: на управляемой форме создано поле ввода НовоеЗначение. Это поле не является реквизитом документа, оно существует только «в памяти» открытого окна. В 1С 8.3 крайне важно понимать, где именно хранятся данные, к которым мы обращаемся. Если мы напишем простой цикл &НаКлиенте, обращаясь к переменной напрямую, система может не понять, откуда брать это значение.

Разберем по шагам: когда вы создаете реквизит формы (не путать с реквизитом объекта Объект), обращение к нему в коде клиентской процедуры должно идти напрямую по имени, если это реквизит формы. Однако, если вы пытаетесь обращаться к нему как ТекущаяСтрока.Цена + НовоеЗначение, а НовоеЗначение не инициализировано или определено неверно, результатом сложения может стать пустое значение (Null или Неопределено). Это и приводит к тому, что поле в табличной части визуально очищается.

Корректный обход табличной части на клиенте

Рассмотрим пример кода, который часто используют разработчики, привыкшие к старым версиям платформы. Основная ошибка здесь заключается в том, что изменение данных в строке ТЧ на клиенте может конфликтовать с серверными механизмами системы.


&НаКлиенте
Процедура ПересчитатьДокумент(Команда)
    // Предположим, НовоеЗначение — это реквизит формы (число)
    Для каждого ТекущаяСтрока Из Объект.Товары Цикл
        // Важно убедиться, что НовоеЗначение заполнено
        Если ЗначениеЗаполнено(НовоеЗначение) Тогда
            ТекущаяСтрока.Цена = ТекущаяСтрока.Цена + НовоеЗначение;
            
            // После изменения цены обычно требуется пересчитать сумму строки
            // В типовых конфигурациях для этого вызываются специальные процедуры
            СтруктураДействий = Новый Структура("ПересчитатьСумму", Истина);
            // ОбработкаРедактированияСтроки(ТекущаяСтрока, СтруктураДействий); 
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

В этом примере мы видим, что изменение ТекущаяСтрока.Цена происходит непосредственно в коллекции Объект.Товары. Поскольку Объект на управляемой форме является производным от ДанныеФормыСтруктура, изменения сразу отображаются в интерфейсе. Однако здесь кроется главная проблема: если в модуле формы или в обработчиках событий ТЧ прописаны дополнительные зависимости (например, при изменении цены должна пересчитываться сумма или скидка), простой цикл их не запустит.

Выясним причину очистки данных: влияние типовых механизмов

Проанализируем ситуацию, когда код кажется верным, значение в отладчике считается правильно, но в самой таблице после завершения процедуры стоят нули или старые значения. Выясним причину: в современных конфигурациях (УТ 11, БП 3.0, ERP) табличные части защищены сложной логикой пересчета.

Если внутри вашего цикла или сразу после него вызывается типовая процедура вроде РассчитатьИтогиТЧ() или ОбновитьДанныеСтроки(), она может брать данные из других связанных реквизитов, которые вы не обновили. Например, если вы изменили цену, но не изменили сумму или не вызвали серверный метод пересчета, система может решить, что данные некорректны, и «откатить» их к состоянию, рассчитанному на основе сохраненных в базе данных или зависимых полей.

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

Где хранить временные данные: реквизит формы или реквизит объекта?

Рассмотрим вопрос сохранения значения НовоеЗначение. Посмотрим на два сценария:

  1. Значение нужно только для разовой операции: В этом случае достаточно реквизита формы. Чтобы пользователь не вводил его каждый раз заново при открытии этого же документа, можно использовать свойство «Автоматическое сохранение данных в настройках» (флаг «Сохранение» в свойствах реквизита формы). Но помните: эти настройки сохраняются для пользователя, а не для документа. Если вы введете «10» в одном документе, закроете его и откроете другой — там тоже появится «10».
  2. Значение должно быть уникальным для каждого документа: Если бизнес-логика требует, чтобы мы знали, какой коэффициент был применен именно к этому заказу, необходимо создавать реквизит в самом объекте (в дереве метаданных конфигурации). Только так данные будут записаны в таблицу базы данных и привязаны к конкретной ссылке.

Оптимизация: Перенос расчетов на сервер

Работа с большими табличными частями (более 100 строк) &НаКлиенте может приводить к «подтормаживанию» интерфейса. Правильнее выполнять тяжелые расчеты &НаСервере. Рассмотрим, как это выглядит в архитектуре управляемого приложения:


&НаКлиенте
Процедура Пересчитать(Команда)
    // Передаем управление на сервер, чтобы расчет был быстрее
    ПересчитатьНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПересчитатьНаСервере()
    // Здесь мы работаем с данными формы "Объект" напрямую
    Для каждого СтрокаТЧ Из Объект.Товары Цикл
        СтрокаТЧ.Цена = СтрокаТЧ.Цена + НовоеЗначение;
        // На сервере нам доступны методы общих модулей для пересчета сумм
        // ОбработкаТабличныхЧастей.РассчитатьСуммуТабЧасти(СтрокаТЧ, Объект);
    КонецЦикла;
КонецПроцедуры

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

Итоги и рекомендации

Подводя итог, выделим основные правила работы с табличными частями в 1С 8.3:

Соблюдение этих принципов позволит создавать надежный и предсказуемый код, который не будет «радовать» пользователей внезапным обнулением цен или сумм в ответственных документах.

← На главную