Почему очищаются добавленные колонки формы после выполнения команды и как это исправить?

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

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

Разберем механику проблемы: почему данные исчезают?

Проанализируем поведение платформы в контексте управляемых форм. Проблема обычно возникает при следующем сценарии:

  1. На форму вынесена объектная команда (команда, определенная в дереве конфигурации для конкретного объекта).
  2. Параметром этой команды является ДокументСсылка или ссылка на другой объект.
  3. Пользователь изменяет данные на форме (появляется «звездочка» модифицированности).
  4. При нажатии на кнопку команды платформа видит, что форма модифицирована, и автоматически записывает объект перед выполнением команды. Это необходимо, чтобы серверный код команды работал с актуальными данными из базы.
  5. После выполнения команды платформа инициирует обновление контекста формы, чтобы отобразить возможные изменения.

Именно на последнем этапе происходит «магия» обнуления. Поскольку колонка СуммаПлатежаТекущая существует только на уровне формы и отсутствует в структуре таблицы объекта в базе данных, при стандартном цикле чтения данных из базы (который инициирует платформа) это поле просто инициализируется значением по умолчанию (например, 0). Процедуры типа ПослеЗаписиНаСервере могут отрабатывать, но последующее завершение выполнения команды часто вызывает повторную синхронизацию, которая перекрывает ваши изменения.

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

Рассмотрим подробнее порядок событий. Когда вы нажимаете кнопку команды, происходит следующее:

  1. Вызов ПередЗаписью (на клиенте и сервере).
  2. Физическая запись объекта в БД.
  3. Вызов ПослеЗаписиНаСервере.
  4. Выполнение основного кода команды в модуле команды.
  5. Обновление данных формы (Read) — вот ключевой момент.

Если логика заполнения вашей «виртуальной» колонки находится только в ОбработкеОповещения или ПослеЗаписиНаСервере, она может быть затерта финальным обновлением данных, которое делает платформа, чтобы гарантировать соответствие формы состоянию объекта в базе данных. Платформа буквально делает ЭтаФорма.Прочитать(), что сбрасывает все программные доработки, не сохраненные в БД.

Решение №1: Использование обработчика ПриЧтенииНаСервере

Самый надежный и правильный способ сохранить данные в колонках формы, не привязанных к объекту — это использовать процедуру ПриЧтенииНаСервере. Многие ошибочно полагают, что она вызывается только один раз при открытии формы. На самом деле, платформа вызывает её каждый раз, когда данные объекта перечитываются из базы, в том числе после выполнения команд, изменяющих состояние данных.

Рассмотрим пример кода, который позволит нам «закрепить» данные в колонке:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    // Вызываем общую процедуру заполнения расчетных данных
    ЗаполнитьРасчетныеКолонкиФормы(ТекущийОбъект);
КонецПроцедуры

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

Важный нюанс: В процедуре ПриЧтенииНаСервере нам доступен параметр ТекущийОбъект. Это именно тот объект, который был прочитан из базы. Использование этой точки входа гарантирует, что даже после «тихой» записи платформой данные в форме будут восстановлены.

Решение №2: Проверка флага «Изменяет данные»

Проанализируем настройки самой команды. У каждой команды (как в дереве метаданных, так и у команд формы) есть свойство «Изменяет данные». Если этот флаг установлен, платформа ведет себя более агрессивно в плане обновления интерфейса.

Если ваша команда по логике не должна приводить к перечитыванию всего объекта (например, она просто отправляет оповещение или выполняет внешнее действие), попробуйте снять этот флаг. Однако помните, что для объектных команд с параметром «Ссылка» автоматическая запись всё равно может произойти, если объект был изменен. В этом случае ПриЧтенииНаСервере остается единственным стабильным решением.

Решение №3: Обработка оповещения и клиентская логика

Если заполнение колонки должно происходить строго после какого-то интерактивного действия, можно использовать механизм оповещений. Но здесь важно понимать порядок выполнения. Если вы вызываете Оповестить() из модуля команды, обработчик в форме сработает после того, как команда завершится.

Посмотрим на пример правильной организации кода в форме:


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

Почему это иногда не работает? Если после вашего Оповестить платформа всё еще выполняет какие-то внутренние серверные вызовы по завершению команды, данные могут обнулиться снова. Поэтому метод с ПриЧтенииНаСервере считается эталонным для Управляемого Приложения.

Подведем итоги и выводы

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

Основные рекомендации:

Следуя этим правилам, мы добьемся стабильной работы интерфейса, и наши данные не будут «магическим» образом исчезать при действиях пользователя.

← На главную