Как сохранить и автоматически подставлять комментарий из последнего документа при создании нового в 1С?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

При интенсивной работе с документами, такими как ПеремещениеТоваров в конфигурации «1С:Бухгалтерия предприятия 3.0», часто возникает практическая задача: автоматически переносить текстовый комментарий из последнего созданного документа в каждый вновь создаваемый. При этом значение должно быть общим для всех пользователей системы и периодически обновляться по мере ввода новых документов.

Попытки реализовать такое поведение через расширение конфигурации нередко приводят к ошибкам, из-за которых данные не сохраняются или не отображаются на форме. Разберем типичные ошибки, проанализируем причины некорректной работы кода и подробно рассмотрим несколько надежных способов решения задачи.

Почему не работают стандартные наивные подходы

Проанализируем типовые ошибки, которые чаще всего допускаются при попытке решить данную задачу:

  1. Ошибки в вызове ХранилищеОбщихНастроек: сигнатура метода ХранилищеОбщихНастроек.Загрузить() принимает параметры: (КлючОбъекта, КлючНастроек, НастройкиПоУмолчанию, ИмяПользователя). Передача строки с описанием вместо настроек по умолчанию приводит к некорректной работе механизма. Кроме того, если имя пользователя не указано явно, настройки по умолчанию привязываются к текущему пользователю сеанса, а не становятся общими для всех.
  2. Использование временных файлов: сохранение данных через КаталогВременныхФайлов() на сервере привязывается к контексту операционной системы и учетной записи службы сервера 1С. В клиент-серверном варианте файлы во временном каталоге могут удаляться при очистке, недоступны с других рабочих процессов кластера или блокироваться правами доступа.
  3. Некорректная аннотация обработчиков в расширении: объявление серверной процедуры формы без явного перехвата события типовой формы (например, отсутствие директивы &После("ПриСозданииНаСервере")) приводит к тому, что платформа просто игнорирует добавленный код, и реквизит Объект.Комментарий не заполняется.

Рассмотрим рабочие и архитектурно правильные способы реализации механизма.

Способ 1. Получение комментария из последнего документа через «ОбработкуЗаполнения» (рекомендуемый)

Если цель состоит в том, чтобы каждый новый документ получал комментарий из предыдущего документа в базе, наиболее лаконичным решением является обращение к данным последнего созданного документа в обработчике инициализации объекта. В этом случае нам не требуется создавать дополнительные хранилища настроек или константы.

Разберем реализацию в модуле объекта документа ПеремещениеТоваров в расширении конфигурации:


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

Преимущества данного подхода:

  1. Механизм работает на уровне модуля объекта: комментарий заполнится корректно вне зависимости от того, из какой именно формы или обработки создается документ.
  2. Не используются сторонние файлы и кэши, данные всегда актуальны для всех пользователей базы данных.
  3. Код легко переносится между конфигурациями через расширение без изменения структуры метаданных.

Способ 2. Использование объекта «ХранилищеСистемныхНастроек»

Если мы хотим явно сохранять комментарий только при записи проведенного документа и делать его доступным для всей системы, применим объект платформы ХранилищеСистемныхНастроек. В отличие от ХранилищеОбщихНастроек, системные настройки предназначены для хранения параметров всей информационной базы и не требуют привязки к конкретному пользователю.

Посмотрим на пример сохранения комментария при записи документа в модуле объекта расширения:


&После("ПриЗаписи")
Процедура Расш1_ПриЗаписи(Отказ)
    
    Если Не Отказ И ЗначениеЗаполнено(ЭтотОбъект.Комментарий) Тогда
        ХранилищеСистемныхНастроек.Сохранить(
            "Документ_ПеремещениеТоваров", 
            "ПоследнийКомментарий", 
            ЭтотОбъект.Комментарий
        );
    КонецЕсли;
    
КонецПроцедуры

Теперь добавим чтение сохраненного значения при создании нового объекта:


&После("ОбработкаЗаполнения")
Процедура Расш1_ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
    
    Если ДанныеЗаполнения = Неопределено И ЭтотОбъект.ЭтоНовый() Тогда
        СохраненныйКомментарий = ХранилищеСистемныхНастроек.Загрузить(
            "Документ_ПеремещениеТоваров", 
            "ПоследнийКомментарий"
        );
        
        Если ЗначениеЗаполнено(СохраненныйКомментарий) Тогда
            ЭтотОбъект.Комментарий = СохраненныйКомментарий;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Реализация через форму документа в расширении

Если логика заполнения требуется исключительно при интерактивном открытии формы пользователем, задействуем модуль формы документа ФормаДокумента в расширении. Важно использовать правильные директивы перехвата событий управляемой формы.

Разберем по шагам перехват события ПриСозданииНаСервере:


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

Важное примечание: при работе в расширении управляемой формы всегда необходимо проверять правильность указания директивы (&После, &Вместо или &Перед) с точным именем перехватываемого события в кавычках. Обычное объявление процедуры без аннотации не связывает ее с жизненным циклом формы 1С.

Итоги

Для реализации задачи автозаполнения комментария наиболее устойчивым решением является использование обработчика ОбработкаЗаполнения в модуле объекта через расширение. Оно не загромождает конфигурацию лишними метаданными, стабильно работает в клиент-серверном режиме и обеспечивает одинаковое поведение системы для всех пользователей.

← На главную