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