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