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