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

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

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

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

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

Если в модуле объекта в процедуре ОбработкаПроведения программа встречает условие, при котором переменная Отказ устанавливается в значение Истина, происходит откат транзакции. Проблема очистки полей чаще всего кроется в том, как именно данные привязаны к форме:

  1. Реквизиты формы: Эти данные существуют только в памяти открытого окна. Они не сохраняются в таблицах базы данных.
  2. Реквизиты объекта (документа): Эти данные прописаны в конфигураторе в структуре документа и сохраняются в базу данных при записи.

Если ваши колонки «Авторы» и «Издательство» являются только реквизитами формы и заполняются программно в процессе работы, то при неудачном проведении форма «перечитывает» данные из объекта. Поскольку в объекте этих данных нет (они не сохранены), поля на форме становятся пустыми. Посмотрим, как решить эту задачу правильно.

Решение 1: Превращение реквизитов формы в реквизиты объекта

Самый простой и надежный способ, который мы рассмотрим — это добавление необходимых полей непосредственно в табличную часть документа в дереве метаданных конфигуратора. Разберем по шагам, почему это работает:

Когда мы добавляем реквизит в табличную часть (например, Автор с типом СправочникСсылка.Авторы), этот реквизит становится частью данных самого документа. При нажатии «Провести» сначала выполняется запись объекта. Если запись прошла успешно, но проведение (проверка остатков) завершилось отказом, документ все равно остается в базе в статусе «Записан», и данные в колонках никуда не исчезают.

Преимущества этого метода:

Решение 2: Динамическое заполнение через «ПриЧтенииНаСервере»

Иногда мы не хотим хранить лишние данные в базе. Например, если «Автор» уже указан в карточке книги, дублировать его в каждой строке документа кажется избыточным. В этом случае мы используем реквизиты формы. Чтобы они не очищались, нам нужно научить форму «вспоминать» их каждый раз, когда она обновляется.

Проанализируем ситуацию: после ошибки проведения форма выполняет чтение данных объекта. Нам нужно подключиться к этому процессу через обработчик ПриЧтенииНаСервере в модуле формы. Рассмотрим пример кода:


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

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

Решение 3: Ранняя проверка остатков в модуле формы

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

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


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

Использование этого подхода в сочетании с проверкой в модуле объекта обеспечивает «двойной контур» защиты: удобство для пользователя и надежность данных для системы.

Решение 4: Использование коллекции «ДополнительныеСвойства»

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

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

Важные рекомендации при работе с Учебной версией

Поскольку вы используете учебную версию 1С:Предприятие 8.3.19, важно помнить о некоторых ограничениях и особенностях:

  1. Типизация колонок: Убедитесь, что у колонок на форме (даже если это только реквизиты формы) правильно указан тип данных. Если вы пытаетесь записать ссылку в колонку с типом Строка, 1С может очистить её при обновлении интерфейса из-за несоответствия типов.
  2. Событие ПриИзменении: Обязательно заполняйте зависимые поля («Автор», «Формат») сразу при выборе книги. Код должен выглядеть примерно так:

&НаКлиенте
Процедура ТоварыКнигаПриИзменении(Элемент)
    СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
    // Получаем данные книги серверным вызовом или через кэш
    ДанныеКниги = ПолучитьДанныеКниги(СтрокаТаблицы.Книга);
    СтрокаТаблицы.Автор = ДанныеКниги.Автор;
    СтрокаТаблицы.ИздательствоФормат = ДанныеКниги.Формат;
КонецПроцедуры

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

← На главную