Как реализовать интерактивное редактирование строки динамического списка в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с динамическими списками (ДС) в 1С:Предприятии — это стандарт де-факто для отображения больших массивов данных. Однако разработчики часто сталкиваются с задачей превратить этот список в интерактивный инструмент, например, для реализации подбора товара, где пользователь должен прямо в списке указать количество или цену. В этой статье мы подробно разберем, почему «из коробки» это сделать сложно, как работает идентификация строк и какие существуют обходные пути для реализации бизнес-логики.

Природа динамического списка и ограничения редактирования

Для начала проанализируем ситуацию: почему обычную таблицу на форме редактировать легко, а динамический список — нет? Динамический список не является хранилищем данных в памяти сервера приложений. Это, по сути, курсор к базе данных. Платформа считывает данные порциями (порционный вывод), чтобы обеспечить высокую скорость работы при миллионах записей. Если список построен на произвольном запросе (особенно с объединениями и вычисляемыми полями), база данных не «понимает», в какую именно физическую таблицу и строку нужно записать измененное значение Количество, введенное пользователем в ячейку.

Рассмотрим два сценария работы платформы:

  1. С установленной «Основной таблицей»: В этом случае 1С знает, что данные принадлежат, например, справочнику Номенклатура. Платформа позволяет вызывать стандартные команды (создать, изменить), но редактирование чаще всего происходит в отдельной форме объекта.
  2. Без основной таблицы (произвольный запрос): Редактирование в строках полностью заблокировано на уровне ядра платформы, так как отсутствует однозначная связь с объектом БД.

Идентификация строки в динамическом списке

Разберем вопрос автора об идентификаторе строки. Многие начинающие разработчики путают индекс строки в массиве и ТекущуюСтроку в списке. В динамическом списке нет понятия «номер строки 5», так как состав строк постоянно меняется из-за фильтров и фонового обновления.

Проанализируем свойство ТекущаяСтрока. Значение этого свойства зависит от настроек ДС:

Чтобы программно получить данные текущей строки, мы используем метод Элементы.ИмяСписка.ДанныеСтроки(Идентификатор). Рассмотрим пример:


&AtClient
Процедура ДинамическийСписокПриАктивизацииСтроки(Элемент)
    ИдентификаторСтроки = Элемент.ТекущаяСтрока;
    Если ИдентификаторСтроки <> Неопределено Тогда
        ДанныеСтроки = Элемент.ДанныеСтроки(ИдентификаторСтроки);
        // Теперь в переменной ДанныеСтроки доступны все колонки запроса
        ТекущийТовар = ДанныеСтроки.Ссылка;
    КонецЕсли;
КонецПроцедуры

Методы имитации редактирования в динамическом списке

Если нам всё же крайне необходимо позволить пользователю вводить данные (например, количество для подбора), рассмотрим следующие варианты решения.

Вариант 1. Использование событий начала редактирования

Мы можем перехватить попытку пользователя изменить строку. Для этого используются события ПриНачалеРедактирования (OnStartEdit) или ПередНачаломИзменения (BeforeRowChange). Посмотрим на логику работы:

  1. Пользователь дважды кликает по ячейке.
  2. Срабатывает событие.
  3. Вместо открытия формы объекта мы программно открываем маленькое окно для ввода значения или активируем скрытое поле ввода.

Однако помните: записать введенное значение обратно «в ячейку» динамического списка невозможно, если это поле не привязано к реальному реквизиту в БД. Если вы вводите данные во временную таблицу или коллекцию в памяти, список их не отобразит без обновления через параметры.

Вариант 2. Подмена на «Статический список» (Таблицу Значений)

Это самый надежный способ, который часто применяется в типовых конфигурациях 1С (например, в формах подбора товаров). Вместо динамического списка мы используем Таблицу Значений (ТЗ), размещенную на форме.

Преимущества этого метода:

Как это реализовать? Разберем по шагам:

  1. При открытии формы или нажатии кнопки «Найти» выполняем запрос к базе данных.
  2. Выгружаем результат запроса в таблицу значений на форме.
  3. У колонок Количество и Цена устанавливаем признак редактирования.

&AtServer
Процедура ЗаполнитьТаблицуОстатков()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Остатки.Номенклатура КАК Номенклатура,
        |   Остатки.ВНаличии КАК Остаток,
        |   0 КАК Количество,
        |   0 КАК Цена
        |ИЗ
        |   РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки";
    
    Результат = Запрос.Выполнить().Выгрузить();
    // Загружаем в реквизит формы типа ТаблицаЗначений
    ОстаткиНаФорме.Загрузить(Результат);
КонецПроцедуры

Вариант 3. Использование параметров динамического списка для отображения данных

Если вы категорически хотите оставить динамический список (например, из-за удобных встроенных фильтров и поиска), можно использовать «гибридный» метод. Суть его заключается в том, что введенные пользователем данные хранятся в отдельной Таблице Значений (в памяти), а в динамическом списке они только отображаются через механизм левого соединения в запросе с временной таблицей.

Алгоритм действий:

  1. Пользователь вводит количество в отдельном поле или через всплывающее окно.
  2. Программа записывает это количество в скрытую ТЗ на форме, где ключом является Ссылка на товар.
  3. Программа передает эту ТЗ в параметры динамического списка.
  4. Запрос ДС пересчитывается и показывает введенное число в колонке.

Этот путь сложен в реализации, так как требует частого вызова метода Обновить() для динамического списка, что может привести к «мерцанию» интерфейса и нагрузке на сервер.

Выводы и рекомендации

Проанализировав все способы, мы можем сделать следующие выводы:

Для задачи автора (связка таблицы остатков и таблицы отгрузки) лучше всего подойдет использование обычной таблицы значений для остатков. Это позволит связать строки двух таблиц по внутреннему идентификатору или ссылке номенклатуры и обеспечит пользователю комфортную работу без лишних модальных окон.

← На главную