Как при создании нового документа 1С открыть уже существующий на основании?

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

Часто в процессе разработки на управляемых формах возникает задача: пользователь пытается создать новый документ на основании существующего (например, «Карточка ремонта» на основании «Карточки приема»), но в системе такой документ уже был создан ранее. В этом случае вместо открытия пустой формы создания нового объекта нам необходимо найти уже существующий документ и открыть его.

Рассмотрим, почему реализация этой задачи в процедуре ОбработкаЗаполнения является ошибкой и как правильно настроить логику открытия формы.

Почему ОбработкаЗаполнения не подходит для открытия форм

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

Реализация через событие ПриСозданииНаСервере

Для решения задачи мы будем использовать событие ПриСозданииНаСервере модуля формы того документа, который мы пытаемся создать. Именно здесь у нас есть доступ к параметрам открытия, включая параметр Основание.

Рассмотрим пошаговый алгоритм действий:

  1. Перехватываем процесс создания формы в событии ПриСозданииНаСервере.
  2. Проверяем, существует ли уже документ, созданный на основании переданного параметра.
  3. Если документ найден, мы должны «отказаться» от создания текущей пустой формы, установить признак модифицированности в Ложь и инициировать открытие найденного объекта.

Посмотрим на пример реализации такого кода в модуле формы документа:


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

КонецПроцедуры

Разбор ключевых моментов решения

Давайте проанализируем, что именно происходит в приведенном коде:

Альтернативный подход: использование метода Закрыть()

Иногда логика поиска может быть реализована на клиенте в процедуре ПередОткрытием. Хотя серверный вариант предпочтительнее, так как он работает быстрее и не отрисовывает форму «впустую», клиентский подход также возможен. В этом случае вы проверяете наличие документа, открываете его, а текущую форму закрываете командой ЭтаФорма.Закрыть().

Однако помните: ЭтаФорма.Модифицированность = Ложь обязательна к исполнению перед закрытием, чтобы система не задавала пользователю лишних вопросов о сохранении изменений, которые он не успел внести.

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

← На главную