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