Как исправить ошибку «Индекс находится за границами массива» при печати и сохранить акт сверки в Excel в 1С 8.3?

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

При разработке внешних обработок и доработке механизмов групповой печати в конфигурациях на базе Библиотеки стандартных подсистем (например, «Бухгалтерия предприятия 3.0») разработчики нередко сталкиваются с ошибкой «Индекс находится за границами массива». Дополнительно возникает вопрос: как перевести логику вывода документов в файл Excel из режима обычных форм (1С 8.2) на стандарты управляемого приложения 1С 8.3.

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

Анализ причин ошибки «Индекс находится за границами массива»

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


Если МассивАктов.Количество Тогда
    СтрСпПечФормАкт = СоздатьСпиокЗначенийДляВыбора("АктСверкиВзаиморасчетов", Истина, ЭтаФорма.НастройкаПечатиАкт);
    Если ТабПечФорм[0].Обработчик = "" Тогда
        //Внешняя форма
        ПечатьВнешнейПечатнойФормы(МассивАктов);
    Иначе
        //Встроенная
        УправлениеПечатьюКлиент.ВыполнитьКомандуПечати(
            ТабПечФорм[0].МенеджерПечати,
            ТабПечФорм[0].Идентификатор,
            МассивАктов,
            Неопределено,
            ПараметрыПечати
        );
    КонецЕсли;
КонецЕсли;

В этом участке кода присутствуют сразу две критические ошибки:

  1. Обращение к несуществующей строке коллекции: Ошибка генерируется в строке с проверкой Если ТабПечФорм[0].Обработчик = "" Тогда. Коллекция ТабПечФорм на момент вызова пуста или не инициализирована. Обращение по индексу [0] к пустой таблице значений или массиву всегда вызывает исключение выхода за границы. Кроме того, результат функции СоздатьСпиокЗначенийДляВыбора присваивается переменной СтрСпПечФормАкт, а проверка выполняется над ТабПечФорм, что указывает на рассинхронизацию переменных.
  2. Некорректный синтаксис проверки количества: Выражение Если МассивАктов.Количество Тогда содержит синтаксическую ошибку встроенного языка 1С. Во-первых, Количество() у массива — это метод, а не свойство, поэтому требуются круглые скобки. Во-вторых, в конструкции Если ожидается строго булево значение. Платформа 1С не выполняет неявное приведение чисел к булеву типу, поэтому необходимо явное сравнение: Если МассивАктов.Количество() > 0 Тогда.

Рассмотрим, как обеспечить безопасный доступ к элементам коллекции. Перед получением нулевого элемента всегда следует выполнять проверку на заполненность:


Если ТабПечФорм.Количество() > 0 Тогда
    Если ТабПечФорм[0].Обработчик = "" Тогда
        ПечатьВнешнейПечатнойФормы(МассивАктов);
    Иначе
        УправлениеПечатьюКлиент.ВыполнитьКомандуПечати(
            ТабПечФорм[0].МенеджерПечати,
            ТабПечФорм[0].Идентификатор,
            МассивАктов,
            Неопределено,
            ПараметрыПечати
        );
    КонецЕсли;
КонецЕсли;

Программное формирование печатной формы и сохранение в Excel

Метод УправлениеПечатьюКлиент.ВыполнитьКомандуПечати предназначен исключительно для интерактивного вывода печатных форм пользователю на экран. Если стоит задача автоматически выгрузить акты сверки в файл Excel, этот метод не подходит.

Разберем правильные способы программного формирования табличного документа на сервере и его последующего сохранения.

Способ 1. Вызов универсального механизма через «УправлениеПечатью» (рекомендуемый)

Рассмотрим использование стандартной серверной функции БСП УправлениеПечатью.СформироватьПечатныеФормы. Этот метод берет на себя создание всех служебных структур и гарантирует корректную работу со встроенными макетами документов.


&НаСервере
Функция ПолучитьТабличныйДокументАктаСверки(МассивАктов)
    ПараметрыПечати = Новый Структура;
    ПечатныеФормы = УправлениеПечатью.СформироватьПечатныеФормы(
        "Документ.АктСверкиВзаиморасчетов",
        "АктСверки",
        МассивАктов,
        ПараметрыПечати,
        Неопределено
    );
    
    Если ПечатныеФормы.КоллекцияПечатныхФорм.Количество() > 0 Тогда
        Возврат ПечатныеФормы.КоллекцияПечатныхФорм[0].ТабличныйДокумент;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Способ 2. Прямой вызов процедуры печати из модуля менеджера

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

Обратите внимание на параметр ОбъектыПечати: он представляет собой коллекцию типа СписокЗначений. Данный список связывает ссылки на документы с областями табличного документа для постраничной разбивки и нумерации. При прямом вызове мы передаем в него пустой список, который будет заполнен внутри процедуры печати.


&НаСервере
Функция СформироватьПечатьНапрямую(МассивАктов)
    КоллекцияПечатныхФорм = УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм("АктСверки");
    ОбъектыПечати = Новый СписокЗначений;
    ПараметрыВывода = УправлениеПечатью.ПодготовитьСтруктуруПараметровВывода();
    
    Документы.АктСверкиВзаиморасчетов.Печать(
        МассивАктов,
        Новый Структура,
        КоллекцияПечатныхФорм,
        ОбъектыПечати,
        ПараметрыВывода
    );
    
    СтрокаТаблицы = КоллекцияПечатныхФорм.Найти("АктСверки", "ИмяМакета");
    Если СтрокаТаблицы <> Неопределено Тогда
        Возврат СтрокаТаблицы.ТабличныйДокумент;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Сохранение табличного документа в файл Excel

Посмотрим, как сохранить полученный табличный документ в файл на диске. В 1С 8.3 для указания формата файла используется системное перечисление ТипФайлаТабличногоДокумента.

Важные особенности форматов:

  1. Для современного формата Excel используется ТипФайлаТабличногоДокумента.XLSX (поддерживает более 1 млн строк).
  2. Для устаревшего формата Excel 97–2003 используется ТипФайлаТабличногоДокумента.XLS (имеет жесткое ограничение в 65 536 строк).

Пример сохранения табличного документа на стороне сервера:


&НаСервере
Процедура СохранитьТабличныйДокументВФайл(ТабличныйДокумент, ПолноеИмяФайла)
    Если ТабличныйДокумент <> Неопределено Тогда
        ТабличныйДокумент.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
    КонецЕсли;
КонецПроцедуры

Помните, что выполнение метода Записать на сервере сохраняет файл в файловую систему сервера. Если файл необходимо передать на рабочий компьютер пользователя, поместите сформированный файл или двоичные данные во временное хранилище и используйте стандартные клиентские методы получения файлов (например, ПолучитьФайл или НачатьПолучениеФайловССервера).

← На главную