Почему возникает ошибка «Итератор для значения не определен» при печати документа в 1С?

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

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

Анализ проблемы и механизма возникновения ошибки

Рассмотрим структуру типовой процедуры формирования печатных форм, используемой в Библиотеке стандартных подсистем (БСП) и отраслевых решениях (например, в 1C:CRM):


Процедура СформироватьПечатныеФормы(ИмяМенеджераПечати, Знач ИменаМакетов, МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати = Неопределено, ПараметрыВывода) Экспорт
    
    СписокПолучателей = Новый СписокЗначений;
    Для Каждого Док Из МассивОбъектов Цикл   // Ошибка: Итератор для значения не определен
        // формирование данных
    КонецЦикла;
    ...
КонецПроцедуры

Конструкция Для Каждого ... Из ... Цикл в платформе 1С:Предприятие рассчитана исключительно на работу с коллекциями, поддерживающими итератор (например, Массив, СписокЗначений, ТаблицаЗначений, Структура). Если в переменную цикла передается простой тип — например, одиночная ссылка вида ДокументСсылка или Неопределено, платформа генерирует исключение.

Посмотрим на типовую функцию формирования печатной формы в модуле менеджера:


Функция СформироватьПечатнуюФормуБСО(МассивОбъектов, ОбъектыПечати) Экспорт
    
    УстановитьПривилегированныйРежим(Истина);
    
    ТабДок = Новый ТабличныйДокумент;
    ТабДок.АвтоМасштаб = Истина;
    ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_БСО";
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ПКО.Дата,
    |    ПКО.Номер,
    |    ПКО.НомерЗаказа КАК Заказ,
    |    ПКО.Плательщик КАК Клиент,
    |    ПКО.Сумма
    |ИЗ
    |    Документ.ПКО КАК ПКО
    |ГДЕ
    |    ПКО.Ссылка В(&МассивОбъектов)";
    
    Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
    Макет = УправлениеПечатью.ПолучитьМакет("Документ.ПКО.БСО");
    Выборка = Запрос.Выполнить().Выбрать();
    ...
КонецФункции

Обратим внимание на интересную особенность языка запросов 1С: оператор В (&МассивОбъектов) одинаково успешно отрабатывает как со списком/массивом значений, так и с одиночной ссылкой. Из-за этого запрос выполняется без ошибок, что часто сбивает разработчика с толку. Однако дальнейшая передача параметра в цикл общего модуля приводит к аварийному завершению работы.

Поиск источника проблемы с помощью отладчика

Разберем по шагам, как локализовать место подмены типа данных:

  1. Установим точку останова в процедуре СформироватьПечатныеФормы непосредственно на строке с циклом Для Каждого Док Из МассивОбъектов Цикл.
  2. Запустим печать проблемного документа и перейдем в окно вычисления выражений (Shift+F9), чтобы проверить тип параметра: вызовем ТипЗнч(МассивОбъектов).
  3. Если тип значения оказывается ДокументСсылка вместо Массив, откроем окно Стек вызовов.
  4. Переместимся назад по цепочке вызовов до момента первичной инициализации переменной или нажатия кнопки команды печати.

Как правило, выясняется одна из двух причин:

  1. Неправильный режим команды: для нового документа была добавлена команда печати с некорректно настроенными свойствами. В палитре свойств команды параметр Режим использования данных установлен в Одиночный вместо Множественный. В этом случае платформа при нажатии кнопки передает в параметр команды одиночную ссылку, а не массив.
  2. Ручной вызов печати из формы: разработчик добавил вызов печати вручную и передал в метод подсистемы напрямую Объект.Ссылка, забыв упаковать значение в массив.

Варианты решения

В зависимости от архитектуры конфигурации и требований к сопровождению рассмотрим два способа исправления ошибки.

Способ 1. Исправление источника вызова (рекомендуемый)

Если для вывода документа на печать используется команда метаданных:

  1. Найдем в дереве конфигурации команду печати созданного документа.
  2. В палитре свойств найдем параметр Режим использования данных.
  3. Изменим его со значения Одиночный на Множественный. В этом случае платформа гарантированно передаст в процедуру ОбработкаКоманды(ПараметрКоманды, ...) массив ссылок, даже если пользователь выбрал один документ.

Если печать вызывается программно из модуля формы или внешней обработки, проверим передаваемые параметры и принудительно обернем ссылку в массив:


// Инициализация массива перед вызовом подсистемы печати
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(Объект.Ссылка);

// Либо с использованием функции БСП:
// МассивОбъектов = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Объект.Ссылка);

Способ 2. Защита в коде модуля печати

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


Процедура СформироватьПечатныеФормы(ИмяМенеджераПечати, Знач ИменаМакетов, МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати = Неопределено, ПараметрыВывода) Экспорт

    // Проверяем тип входящего параметра и приводим его к массиву
    Если ТипЗнч(МассивОбъектов) <> Тип("Массив") Тогда
        ОдиночныйОбъект = МассивОбъектов;
        МассивОбъектов = Новый Массив;
        Если ЗначениеЗаполнено(ОдиночныйОбъект) Тогда
            МассивОбъектов.Добавить(ОдиночныйОбъект);
        КонецЕсли;
    КонецЕсли;

    СписокПолучателей = Новый СписокЗначений;
    Для Каждого Док Из МассивОбъектов Цикл
        // Штатная обработка элементов коллекции
    КонецЦикла;
    ...
КонецПроцедуры

Такая проверка гарантирует, что даже при передаче единичной ссылки исполнение кода не будет прервано аварийным завершением, а печатная форма сформируется штатно.

← На главную