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