К статье
Практический материал

Разработка и Конфигурация · 12 мин

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

Как получить строку динамического списка в 1С: ТекущиеДанные, ТекущаяСтрока, ДанныеСтроки, поиск по ключу. Примеры кода, ошибки и ограничения методов.

Динамический список в управляемых формах 1С — это не таблица значений, а механизм чтения данных по запросу, поэтому привычные способы обхода строк здесь не работают. Разработчики, привыкшие к обычным формам, часто пытаются обратиться к строке списка напрямую по индексу и получают ошибку или неопределённое значение. Чтобы получить данные текущей или произвольной строки динамического списка, используются специальные свойства расширения формы и методы работы с ключами строк.

Основных сценария четыре: получить данные текущей (выделенной) строки, получить данные строки по её идентификатору, получить выделенные строки при множественном выборе и программно найти строку по значению поля. Каждый сценарий решается своим инструментом, и смешивать их нельзя: например, ТекущаяСтрока возвращает не сами данные, а ключ строки, из которого данные ещё нужно извлечь.

Ниже разобраны рабочие приёмы с примерами кода на встроенном языке, ограничения платформы и типичные ошибки, из-за которых код «не видит» строку списка.

Что такое строка динамического списка и почему к ней особый подход

Динамический список — это реквизит формы, который отображает результат запроса с автоматической постраничной подгрузкой. В памяти клиента одновременно находится только видимая часть данных, остальные строки подгружаются при прокрутке. Поэтому у динамического списка нет коллекции строк, которую можно перебрать циклом, как у таблицы значений или табличной части.

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

Из этого следуют два практических вывода. Во-первых, «получить строку» обычно означает получить либо ключ (ссылку), либо структуру с данными колонок. Во-вторых, если нужны все строки результата, работать надо не со списком на форме, а с запросом, который этот список формирует.

Получение текущей строки через ТекущиеДанные

Самый частый сценарий — прочитать данные строки, на которой стоит курсор. Для этого у таблицы формы, связанной с динамическим списком, есть свойство ТекущиеДанные. Оно возвращает объект с полями, соответствующими колонкам списка:

&НаКлиенте

Процедура ПоказатьДанныеСтроки(Команда)

ТекущиеДанные = Элементы.Список.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

ПоказатьПредупреждение(, "Строка не выбрана");

Возврат;

КонецЕсли;

Сообщить("Номенклатура: " + ТекущиеДанные.Наименование);

Сообщить("Цена: " + ТекущиеДанные.Цена);

КонецПроцедуры

Обязательна проверка на Неопределено: если в списке нет ни одной строки или курсор не установлен, обращение к полям вызовет ошибку. Это самая частая причина падения обработчиков команд, привязанных к списку.

Важное ограничение: ТекущиеДанные содержит только те поля, которые реально выведены в колонки таблицы формы или добавлены в список полей динамического списка. Если поле есть в запросе, но не выбрано в настройках списка, прочитать его из строки не получится — нужно либо добавить поле в список, либо получать значение отдельным запросом по ссылке.

Получение ключа строки через ТекущаяСтрока

Свойство ТекущаяСтрока возвращает не данные, а ключ строки. Для списка с основной таблицей это ссылка, и её можно передать в серверную процедуру, открыть объект или использовать в запросе:

&НаКлиенте

Процедура ОбработатьСтроку(Команда)

КлючСтроки = Элементы.Список.ТекущаяСтрока;

Если КлючСтроки = Неопределено Тогда

Возврат;

КонецЕсли;

ОбработатьСтрокуНаСервере(КлючСтроки);

КонецПроцедуры

&НаСервереБезКонтекста

Процедура ОбработатьСтрокуНаСервере(Ссылка)

Объект = Ссылка.ПолучитьОбъект();

// ... действия с объектом ...

Объект.Записать();

КонецПроцедуры

Множественный выбор: ВыделенныеСтроки

Если у таблицы формы включён множественный выбор, массив ключей выделенных строк возвращает свойство ВыделенныеСтроки. Типичный пример — групповая обработка документов:

&НаКлиенте

Процедура ПровестиВыделенные(Команда)

Для Каждого КлючСтроки Из Элементы.Список.ВыделенныеСтроки Цикл

ПровестиДокументНаСервере(КлючСтроки);

КонецЦикла;

Элементы.Список.Обновить();

КонецПроцедуры

После серверных изменений данных вызывайте Элементы.Список.Обновить(), иначе пользователь увидит устаревшие значения до ручного обновления списка.

Порядок действий для текущей строки
  1. 1
    Определите имя таблицы формы, связанной с динамическим списком (Элементы.ИмяСписка)
  2. 2
    Получите Элементы.ИмяСписка.ТекущиеДанные и проверьте на Неопределено
  3. 3
    Если нужны данные на сервере — возьмите Элементы.ИмяСписка.ТекущаяСтрока (ссылку) и передайте в серверную процедуру
  4. 4
    После изменений вызовите Элементы.ИмяСписка.Обновить() и проверьте результат в форме

Данные произвольной строки: метод ДанныеСтроки

Если известен ключ строки, а курсор стоит на другой позиции, данные получают методом ДанныеСтроки() расширения таблицы формы динамического списка:

ДанныеСтроки = Элементы.Список.ДанныеСтроки(КлючСтроки);

Если ДанныеСтроки <> Неопределено Тогда

Сообщить(ДанныеСтроки.Наименование);

КонецЕсли;

Метод вернёт Неопределено, если строка с таким ключом не загружена на клиент (например, находится далеко за пределами прокрутки и ещё не подгружалась) либо не соответствует текущим отборам. Это принципиальное ограничение: ДанныеСтроки работает только в рамках данных, которые список уже получил.

Метод полезен в обработчиках событий таблицы — например, в ПриАктивизацииСтроки или Выбор, где ключ строки приходит в параметрах, а нужны значения конкретных колонок без переключения контекста на сервер.

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

Обойти динамический список циклом нельзя — у него нет такого программного интерфейса. Если задача требует всех данных (экспорт, пакетная обработка, проверка условий), правильный путь — выполнить тот же запрос программно. Текст запроса доступен в свойстве ТекстЗапроса реквизита формы:

&НаСервере

Функция ПолучитьВсеСтроки()

Запрос = Новый Запрос(Список.ТекстЗапроса);

// при необходимости передать параметры из Список.Параметры

Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Учтите, что ТекстЗапроса не содержит отборы, которые пользователь наложил интерактивно, и настройки компоновки. Если нужен результат с учётом пользовательских отборов, используют схему компоновки данных из свойства КомпоновщикНастроек списка и программно формируют итоговый запрос через КомпоновщикМакетаКомпоновкиДанных. Это заметно сложнее, но даёт точное совпадение с тем, что видит пользователь.

Для небольших списков допустим и другой приём: программно установить Элементы.Список.ТекущаяСтрока по очереди на каждый ключ из заранее полученного массива ссылок и читать ТекущиеДанные. Однако это медленно, вызывает перерисовку формы и считается плохой практикой — используйте запрос.

Сравнение вариантов

ТекущиеДанные

Данные строки под курсором, только на клиенте, только выведенные поля. Подходит для команд и обработчиков событий

ТекущаяСтрока / ВыделенныеСтроки

Ключи (ссылки) строк для передачи на сервер и групповых операций. Данных колонок не содержат

ДанныеСтроки(Ключ)

Данные любой загруженной строки по ключу. Не работает для неподгруженных строк

Запрос по ТекстЗапроса

Все данные списка на сервере. Требует отдельного учёта пользовательских отборов

Программное позиционирование на нужной строке

Обратная задача — не прочитать, а найти и показать строку. Для списка с основной таблицей достаточно присвоить ссылку свойству ТекущаяСтрока:

Элементы.Список.ТекущаяСтрока = НайденнаяСсылка;

Если ссылка не соответствует текущим отборам списка, платформа либо спозиционируется на ближайшей доступной строке, либо покажет вопрос о сбросе отбора — поведение зависит от настроек. Поэтому перед позиционированием полезно проверить, проходит ли объект под установленные отборы.

Для произвольного динамического списка без основной таблицы позиционирование по ссылке недоступно: ключи там служебные. Выход — найти объект запросом, а список отфильтровать так, чтобы нужная строка в него попала, либо использовать стандартную команду поиска по строке.

Типичные ошибки и их признаки

Первая ошибка — обращение к ТекущиеДанные из серверной процедуры формы. Свойство существует только на клиенте; на сервере получите ошибку обращения к свойству. Решение — передавать ключ строки параметром.

Вторая ошибка — попытка перебрать список циклом Для Каждого Строка Из Список Цикл. Динамический список не является коллекцией, такой код не скомпилируется или не даст ожидаемого результата. Нужен запрос по ТекстЗапроса.

Третья ошибка — чтение поля, которого нет среди колонок списка. ТекущиеДанные.НекоеПоле вернёт ошибку, если поле не добавлено в выбранные поля динамического списка. Добавьте поле в запрос и в настройки списка (его можно сделать невидимым для пользователя).

Четвёртая ошибка — использование ДанныеСтроки для строки, которая не загружена. Метод молча вернёт Неопределено, и логика «тихо» не сработает. Всегда проверяйте результат.

Типичные ошибки
01
Обращение к ТекущиеДанные без проверки на Неопределено — ошибка при пустом списке
02
Чтение поля, не добавленного в колонки списка — ошибка обращения к свойству
03
Попытка обойти динамический список циклом — нет такого интерфейса, нужен запрос
04
ДанныеСтроки для неподгруженной строки — возвращает Неопределено без сообщения
05
Забытый Элементы.Список.Обновить() после серверных изменений — пользователь видит старые данные

Проверка результата

После внедрения кода проверьте три сценария: список с данными и выбранной строкой, пустой список и список с активными пользовательскими отборами. В первом случае команда должна отработать и показать корректные значения, во втором — корректно завершиться без ошибки, в третьем — не потерять строки из-за отборов.

Для серверной обработки по ключу строки дополнительно проверьте поведение при удалённом объекте: ссылка может стать «битой» между чтением ключа и обращением к базе. Оборачивайте ПолучитьОбъект() в попытку и проверяйте результат на Неопределено.

Контрольные точки

Как проверить результат

Команда при выбранной строке
Норма

Возвращаются значения именно той строки, где курсор

Тревожный признак

Данные другой строки или ошибка обращения к полю

Команда при пустом списке
Норма

Сообщение о невыбранной строке, ошибок нет

Тревожный признак

Исключение «Поле объекта не обнаружено»

После серверных изменений
Норма

Список обновился, видны новые значения

Тревожный признак

Старые данные до ручного обновления

Частые вопросы

Можно ли получить строку динамического списка по номеру (индексу)?

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

Почему ТекущиеДанные возвращает Неопределено, хотя строки в списке есть?

Курсор не установлен ни на одной строке — например, форма только открылась или применён отбор, скрывший текущую позицию. Всегда проверяйте значение на Неопределено перед обращением к полям.

Как получить поле, которое есть в запросе, но не выведено в колонки?

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

Работает ли ДанныеСтроки на сервере?

Нет, это метод расширения таблицы формы и доступен только в клиентском контексте формы. На сервер передавайте ключ строки и читайте данные запросом или через объект.

Как получить строки с учётом отборов, которые наложил пользователь?

Напрямую из списка — никак. Используйте схему компоновки данных списка и настройки из КомпоновщикНастроек: сформируйте макет компоновки программно и извлеките итоговый запрос с параметрами отборов.

Чем ТекущаяСтрока отличается от ТекущиеДанные?

ТекущаяСтрока — это ключ строки (для списка с основной таблицей — ссылка), пригодный для передачи на сервер. ТекущиеДанные — объект со значениями колонок, доступный только на клиенте.

Итог

Что важно запомнить

ТекущиеДанные — данные строки под курсором на клиенте, ТекущаяСтрока и ВыделенныеСтроки — ключи для серверной обработки, ДанныеСтроки — данные по известному ключу. Обход всех строк динамического списка невозможен — используйте запрос. Всегда проверяйте результат на Неопределено и обновляйте список после изменений.