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