Как передать параметр и предотвратить перезапись реквизитов при открытии обычной формы в 1С?

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

При программном создании и открытии документов в обычных формах 1С:Предприятие (например, в конфигурации «Управление производственным предприятием 1.3») разработчики часто сталкиваются с ситуацией, когда заполненные программно реквизиты сбрасываются или перезаписываются значениями по умолчанию. Это происходит из-за того, что в модуле формы документа в процедуре ПриОткрытии срабатывают типовые механизмы заполнения шапки.

Рассмотрим подробно, почему возникает эта проблема, почему попытка использовать системное свойство ПараметрОснование может приводить к ошибке «Несоответствие типов», и какие существуют способы для правильной передачи параметров в обычную форму.

Причина перезаписи реквизитов и особенности свойства ПараметрОснование

Проанализируем порядок выполнения событий при программном открытии формы. Когда мы вызываем метод ПолучитьФорму(), платформа создает объект формы в памяти, но события формы еще не запускаются. Затем, при вызове метода Открыть(), платформой последовательно вызываются обработчики ПередОткрытием и ПриОткрытии.

В типовых конфигурациях на обычных формах внутри процедуры ПриОткрытии выполняется код следующего вида:


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

Если документ новый, а свойства ПараметрОбъектКопирования и ПараметрОснование равны Неопределено, стандартный алгоритм подставляет значения по умолчанию для текущего пользователя, затирая ранее введенные программно данные.

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

Способ 1. Установка значений реквизитов после вызова метода Открыть()

Разберем самый простой подход, который не требует изменения кода самой открываемой формы. Так как процедура ПриОткрытии выполняется строго в момент вызова Форма.Открыть(), мы можем перезаписать нужные реквизиты сразу после открытия формы.

Посмотрим на пример кода:


// Создаем объект и получаем форму
ЗаказПокупателяОбъект = Документы.ЗаказПокупателя.СоздатьДокумент();
ФормаЗаказаПокупателя = ЗаказПокупателяОбъект.ПолучитьФорму("ФормаДокумента");

// Открываем форму (в этот момент срабатывает ПриОткрытии и заполняет СкладГруппа значением по умолчанию)
ФормаЗаказаПокупателя.Открыть();

// Перезаписываем реквизит формы или объекта нужным значением
ФормаЗаказаПокупателя.СкладГруппа = Константы.ччч.Получить();

При таком подходе значение по умолчанию будет подставлено при открытии, но сразу же заменено на необходимое нам значение.

Способ 2. Использование экспортной переменной в модуле формы

Если у нас есть возможность редактировать форму открываемого документа, мы можем объявить экспортную переменную в самом верху модуля формы. Это позволит передать любой флаг или параметр до вызова метода Открыть().

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

Способ 3. Использование механизма «Заполнить» и настройки «Ввод на основании»

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

  1. В конфигураторе для создаваемого документа (например, ЗаказПокупателя) на вкладке «Ввод на основании» указываем документ-источник (например, ЗаказПоставщику).
  2. В модуле объекта заполняемого документа прописываем логику в процедуре ОбработкаЗаполнения.
  3. В вызывающем коде передаем ссылку записанного документа-основания:
    
    // Документ-источник должен быть записан в базе и иметь ссылку
    ЗаказПокупателяОбъект = Документы.ЗаказПокупателя.СоздатьДокумент();
    ЗаказПокупателяОбъект.Заполнить(СсылкаНаЗаказПоставщику);
    
    Форма = ЗаказПокупателяОбъект.ПолучитьФорму("ФормаДокумента");
    Форма.ПараметрОснование = СсылкаНаЗаказПоставщику;
    Форма.Открыть();
    

В этом случае платформа корректно примет значение в ПараметрОснование, а проверка на ПараметрОснование = Неопределено в процедуре ПриОткрытии вернет Ложь, что предотвратит перезапись реквизитов базовыми значениями по умолчанию.

← На главную