Разработка интерфейсов на обычных формах в платформе «1С:Предприятие 8» таит в себе множество нюансов, с которыми часто сталкиваются начинающие программисты. Один из классических сценариев — необходимость предоставить пользователю возможность выбора значения из ограниченного выпадающего списка в конкретной ячейке табличной части. На первый взгляд задача кажется тривиальной: достаточно получить нужные данные запросом и передать их в элемент управления колонки. Однако на практике разработчики часто сталкиваются с неожиданным поведением системы, когда выбранное значение визуально исчезает сразу после того, как пользователь переходит на другую строку или ячейку табличного поля. В этой статье мы подробно разберем, как правильно реализовать заполнение списка выбора и почему возникает проблема с «исчезновением» данных, а также предоставим готовые и эффективные решения.
Для начала проанализируем типичную ошибку, с которой столкнулся автор темы на форуме. При открытии формы он попытался использовать следующий код:
Штрих = Новый ТаблицаЗначений;
// ... выполнение запроса ...
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Штрих.ЗаполнитьЗначения("Штрихкод", РезультатЗапроса.ВыгрузитьКолонку("Штрихкод"));
ЭлементыФормы.МТД_Поставщики.Колонки.Штрихкод.ЭлементУправления.СписокВыбора = Штрих;
В данном фрагменте кода кроются сразу две серьезные методологические ошибки, которые приводят к аварийному завершению работы программы (падению на последних строчках):
СписокВыбора элемента управления (в данном случае это ПолеВвода в колонке табличного поля) ожидает объект типа СписокЗначений. Автор же создает объект типа ТаблицаЗначений и пытается присвоить его напрямую. Платформа 1С не может выполнить автоматическое преобразование таблицы в список, что приводит к ошибке несовместимости типов.ЗаполнитьЗначения() у объекта ТаблицаЗначений предназначен для заполнения всех строк определенной колонки таблицы одним фиксированным значением. Попытка передать туда массив (полученный методом ВыгрузитьКолонку()) некорректна и вызывает исключение "Метод объекта не обнаружен".Для того чтобы исправить падение кода, мы должны использовать специализированный объект СписокЗначений и его метод ЗагрузитьЗначения(), который отлично принимает массив, возвращаемый методом таблицы значений ВыгрузитьКолонку(). Рассмотрим исправленный и рабочий вариант кода инициализации при открытии формы:
// Создаем запрос для получения штрихкодов по владельцу
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Штрихкоды.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.Штрихкоды КАК Штрихкоды
|ГДЕ
| Штрихкоды.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец", Ссылка);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// Инициализируем СписокЗначений вместо ТаблицыЗначений
СписокШтрихкодов = Новый СписокЗначений;
СписокШтрихкодов.ЗагрузитьЗначения(РезультатЗапроса.ВыгрузитьКолонку("Штрихкод"));
// Присваиваем список выбора элементу управления колонки
ЭлементыФормы.МТД_Поставщики.Колонки.Штрихкод.ЭлементУправления.СписокВыбора = СписокШтрихкодов;
Этот код успешно отработает без ошибок, и при нажатии на кнопку выбора в ячейке "Штрихкод" пользователь действительно увидит выпадающий список со штрихкодами. Однако здесь мы сталкиваемся со следующей проблемой: при выборе значения из списка и последующем клике на любую другую ячейку выбранный штрихкод бесследно исчезает. Давайте разберемся, почему это происходит и как это исправить.
В обычных формах 1С поведение поля ввода регулируется набором взаимосвязанных свойств. Свойство РежимВыбораИзСписка (Choice list mode) накладывает на поле жесткое ограничение: значение в ячейке *обязательно* должно присутствовать в связанном списке выбора СписокВыбора.
Если этот флаг установлен в значение Истина, а список выбора по какой-то причине пуст, не инициализирован для конкретной строки или же содержит значения другого типа, то при потере фокуса ячейкой платформа принудительно очистит визуальное отображение значения, так как не сможет сопоставить его с элементами списка.
Решение проблемы:
Штрихкод.РежимВыбораИзСписка и установите его в значение Ложь.КнопкаСпискаВыбора и установите его в значение Истина.При такой комбинации настроек поле ввода сохранит кнопку выпадающего списка (стрелочку вниз), но платформа перестанет принудительно очищать ячейку при потере фокуса, даже если список выбора в какой-то момент окажется неактуальным.
Еще одна частая причина исчезновения выбранного значения — неявное несовпадение типов данных. Например, в базе данных штрихкод может храниться как строка (тип Строка), а реквизит вашей табличной части Штрихкод на форме имеет тип ссылки (например, СправочникСсылка.Штрихкоды), или наоборот.
Когда пользователь выбирает элемент из списка, платформа пытается записать выбранное значение в связанный реквизит табличной части. Если типы не совпадают (например, вы пытаетесь записать строку "4601234567890" в поле с типом значения Число или СправочникСсылка), трансляция типа завершается неудачей. Платформа не выдает явной ошибки, но значение в реквизит не записывается, и при обновлении строки ячейка снова становится пустой.
Решение проблемы: обязательно проверьте тип реквизита в табличной части вашего объекта (или реквизита формы, если ТЧ создана на форме программно) и тип значений, которые выгружаются из запроса. Они должны быть строго идентичны.
В обычных формах 1С табличное поле оптимизирует использование ресурсов: для редактирования всей колонки создается всего один общий элемент управления (в нашем примере — ПолеВвода). Когда вы пишете код заполнения списка выбора в обработчике ПриОткрытии формы, вы жестко задаете один статический список выбора для всей колонки.
Если логика вашей задачи подразумевает, что список штрихкодов должен зависеть от владельца (например, от номенклатуры в текущей строке), то заполнение списка при открытии формы работать не будет. Переходя на новую строку с другой номенклатурой, вы будете видеть либо пустой список, либо список от предыдущей строки, а старые выбранные значения в других строках будут визуально пропадать, так как платформа не найдет их в текущем (изменившемся или пустом) списке выбора элемента управления.
Решение проблемы: динамическое заполнение в событии «НачалоВыбораИзСписка»
Мы рекомендуем отказаться от заполнения списка выбора при открытии формы и перенести этот процесс в обработчик события элемента управления колонки табличной части. Это гарантирует актуальность списка в момент выбора для каждой конкретной строки.
Разберем по шагам, как это реализовать:
Штрихкод вашей табличной части МТД_Поставщики.НачалоВыбораИзСписка.
Процедура МТД_ПоставщикиШтрихкодНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
// Отменяем стандартную обработку, чтобы платформа не пыталась открыть свой список
СтандартнаяОбработка = Ложь;
// Получаем текущую строку табличной части
ТекущаяСтрока = ЭлементыФормы.МТД_Поставщики.ТекущаяСтрока;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Получаем владельца (например, Номенклатуру) из текущей строки
ТекущийВладелец = ТекущаяСтрока.Номенклатура;
Если Не ЗначениеЗаполнено(ТекущийВладелец) Тогда
Предупреждение("Сначала необходимо выбрать Номенклатуру в строке!");
Возврат;
КонецЕсли;
// Формируем запрос для получения штрихкодов конкретно для текущей номенклатуры
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Штрихкоды.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.Штрихкоды КАК Штрихкоды
|ГДЕ
| Штрихкоды.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец", ТекущийВладелец);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// Заполняем список выбора конкретного элемента управления
Элемент.СписокВыбора.Очистить();
Элемент.СписокВыбора.ЗагрузитьЗначения(РезультатЗапроса.ВыгрузитьКолонку("Штрихкод"));
КонецПроцедуры
При таком подходе список выбора будет формироваться индивидуально в момент клика по кнопке выбора в каждой конкретной строке табличной части, что полностью исключит конфликты данных между строками и предотвратит исчезновение ранее выбранных значений.
Иногда при ручной настройке формы разработчики забывают связать добавленную на форму колонку табличного поля с фактическим реквизитом табличной части объекта. Если у колонки не заполнено свойство Данные (Data):
Решение проблемы: проверьте свойства проблемной колонки на форме. Убедитесь, что в поле свойства Данные указан путь к соответствующему реквизиту табличной части (например, МТД_Поставщики.Штрихкод). Только при наличии этой связи значение будет успешно записываться в базу данных или в объектную структуру документа/справочника.
Мы подробно проанализировали процесс работы со списками выбора в табличных частях на обычных формах 1С. Для стабильной и корректной работы этого функционала всегда придерживайтесь следующих правил:
СписокВыбора используйте только объект типа СписокЗначений.РежимВыбораИзСписка и включайте КнопкаСпискаВыбора, чтобы избежать автоматического затирания ячеек платформой.Данные.НачалоВыбораИзСписка для динамического формирования списков в разрезе каждой строки табличной части.