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