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