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