Почему не удается установить ДополнительныеСвойства объекту 1С и как это сделать правильно?

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

В практике разработки на платформе 1С:Предприятие часто возникает задача передать какой-либо специфический параметр (флаг) из программного кода в обработчики событий объекта или в подписки на события. Самым удобным инструментом для этого является свойство ДополнительныеСвойства. Однако начинающие разработчики часто сталкиваются с тем, что установленные свойства "не доходят" до адресата или вовсе не присваиваются. Рассмотрим подробно, почему это происходит, и как правильно реализовать передачу данных.

Разбор типичной ошибки: Свойство() против Вставить()

Проанализируем ситуацию, представленную в вопросе. Автор пытался использовать следующий код для установки признака группового перепроведения:


Документ = Строка.Ссылка.ПолучитьОбъект();
Документ.ДополнительныеСвойства.Свойство("ГрупповоеПерепроведение", Истина);

Выясним причину, почему этот код не работает. Дело в том, что ДополнительныеСвойства — это объект типа Структура. В языке 1С у структуры есть два метода, которые часто путают: Свойство() и Вставить(). Рассмотрим их различия подробнее:

  1. Метод Свойство(Ключ, НайденноеЗначение) предназначен исключительно для чтения. Он проверяет, существует ли в структуре элемент с указанным ключом. Если ключ найден, метод возвращает Истина, а само значение записывает во второй параметр (в нашем примере — в переменную, где была константа Истина, что вообще бессмысленно).
  2. Метод Вставить(Ключ, Значение) предназначен для записи. Он добавляет новый элемент в структуру или обновляет существующий.

Таким образом, для установки свойства необходимо использовать метод Вставить. Посмотрим на правильный вариант кода:


// Правильная установка значения в структуру
Документ.ДополнительныеСвойства.Вставить("ГрупповоеПерепроведение", Истина);

Жизненный цикл объекта и оперативная память

Вторая важная причина, по которой "пропадают" дополнительные свойства, заключается в непонимании жизненного цикла объекта ДокументОбъект. Важно помнить: ДополнительныеСвойства существуют только в оперативной памяти и только пока "жив" конкретный экземпляр объекта.

Проанализируем типичный ошибочный сценарий:

  1. Вы вызываете ПолучитьОбъект().
  2. Устанавливаете в нем ДополнительныеСвойства.
  3. Процедура завершается, и переменная, хранящая объект, уничтожается.
  4. Данные потеряны, так как в базу данных ДополнительныеСвойства не записываются.

Разберем, как это работает на практике. Если вы хотите, чтобы эти свойства сработали в подписке на события или в модуле объекта, вы должны установить их перед вызовом метода Записать(). Именно в момент выполнения метода Записать() платформа передает текущий экземпляр объекта (со всеми заполненными свойствами в памяти) во все обработчики: ПередЗаписью, ПриЗаписи и в соответствующие подписки.

Рассмотрим пример правильного цикла обработки:


Для каждого Строка Из МассивСтрок Цикл
    // Получаем объект из ссылки
    ДокументОбъект = Строка.Ссылка.ПолучитьОбъект();
    
    // Передаем контекст: сообщаем системе, что это программная обработка
    ДокументОбъект.ДополнительныеСвойства.Вставить("ГрупповоеПерепроведение", Истина);
    
    // Вызываем запись. В этот момент подписка на событие увидит наш флаг
    ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецЦикла;

Как обработать ДополнительныеСвойства в подписке на события

Теперь выясним, как правильно прочитать переданное значение на "другой стороне" — например, в подписке на событие ПередЗаписью. Проанализируем безопасный способ извлечения данных:


Процедура ОбработкаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    ПризнакГрупповойОбработки = Ложь;
    
    // Безопасно проверяем наличие свойства
    Если Источник.ДополнительныеСвойства.Свойство("ГрупповоеПерепроведение", ПризнакГрупповойОбработки) Тогда
        Если ПризнакГрупповойОбработки = Истина Тогда
            // Здесь ваша логика: например, пропустить изменение реквизита
            Возврат; 
        КонецЕсли;
    КонецЕсли;
    
    // Стандартная логика для одиночного проведения...
КонецПроцедуры

Обратите внимание: здесь мы используем метод Свойство() именно по назначению — для проверки наличия ключа и получения его значения в переменную.

Архитектурный совет: метод "от обратного"

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

Рассмотрим, как это реализовать:

  1. В модуле формы документа в обработчике ПередЗаписьюНаСервере пишем:
    
    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
        ТекущийОбъект.ДополнительныеСвойства.Вставить("ИнтерактивнаяЗапись", Истина);
    КонецПроцедуры
    
  2. В модуле объекта или подписке проверяем этот флаг. Если его нет — значит, документ записывается программно (в том числе и при групповой обработке).
    
    Если НЕ Источник.ДополнительныеСвойства.Свойство("ИнтерактивнаяЗапись") Тогда
        // Это групповое перепроведение или любая другая фоновая операция
        // Блокируем изменение "капризных" реквизитов
    КонецЕсли;
    

Технические нюансы и производительность

Проанализируем ситуацию с точки зрения производительности. Использование ПолучитьОбъект() в цикле по списку документов — это тяжелая операция. Каждый вызов создает полноценный объект в памяти и делает запрос к базе данных.

Рекомендации:

Подводя итог, использование ДополнительныеСвойства требует соблюдения трех правил: использовать Вставить() для записи, вызывать Записать() для передачи контекста и проверять наличие ключа через Свойство() в принимающем коде. Это обеспечит надежную работу ваших алгоритмов при любой сложности проведения документов.

← На главную