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