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