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