Почему во внешней печатной форме возникает ошибка «Поле объекта не обнаружено (КоличествоЭкземпляров)»

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

При разработке внешних печатных форм (ВПФ) для конфигураций на базе БСП (Библиотека стандартных подсистем), таких как 1С:Зарплата и управление персоналом 3.1, разработчики часто сталкиваются с ошибками типизации объектов. Одной из наиболее запутанных ситуаций является ошибка обращения к полю КоличествоЭкземпляров. Проблема усугубляется, когда форма готовится для публикации в Личном кабинете сотрудника (ЛК), так как это накладывает дополнительные требования к структуре кода.

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

Анализ исходной ситуации

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


ПечатнаяФорма.ТабличныйДокумент.КоличествоЭкземпляров = ПечатнаяФорма.Экземпляров;

При этом отладчик показывает, что объект ПечатнаяФорма.ТабличныйДокумент имеет тип ОбластьЯчеекТабличногоДокумента, хотя ожидается тип ТабличныйДокумент. Именно в этом кроется причина: у «Области» нет и не может быть свойства КоличествоЭкземпляров, так как оно относится ко всему листу целиком.

Выясняем причину: коварство метода Вывести()

Проанализируем функцию, которая формирует документ в коде автора:


Функция ТабличныйДокументНаПечать(ПараметрыПечати, МассивОбъектовДляПечати, ОбъектыПечати, ПараметрыВывода)
    ТабДокумент = Новый ТабличныйДокумент;
    // ... заполнение параметров макета ...
    ТабДокумент.КоличествоЭкземпляров = 1;
    Возврат ТабДокумент.Вывести(Обходной);  
КонецФункции

Обратим внимание на последнюю строку: Возврат ТабДокумент.Вывести(Обходной);. Рассмотрим подробнее, как работает метод платформы Вывести():

  1. Метод Вывести() добавляет указанную область в табличный документ.
  2. Важный момент: результатом выполнения этого метода является объект типа ОбластьЯчеекТабличногоДокумента (та область, которая только что была выведена в документ).
  3. Следовательно, функция возвращает не сам ТабличныйДокумент, а лишь его часть.

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

Шаг 1: Исправление возвращаемого значения

Для решения проблемы нам необходимо разделить процесс вывода области в документ и процесс возврата самого объекта из функции. Перепишем финал функции следующим образом:


// Правильный вариант завершения формирования документа
ТабДокумент.Вывести(Обходной); 
Возврат ТабДокумент; // Возвращаем именно объект типа ТабличныйДокумент

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

Шаг 2: Обеспечение совместимости с Личным кабинетом сотрудника

Поскольку автор темы готовит форму для ЛК, важно правильно выполнить интеграцию с библиотекой «Зарплата и кадры». Рассмотрим, какие действия необходимы для того, чтобы кнопка «Опубликовать в ЛК» стала доступна и работала корректно.

Во-первых, необходимо использовать процедуру ЗарплатаКадры.ПриОпределенииОбъектовПечатнойФормы. Она инициализирует структуру ПараметрыПечати, добавляя в неё информацию о том, к какому сотруднику привязана форма. Без этого ЛК не поймет, в чьем кабинете должен появиться документ.


// В процедуре Печать()
ПараметрыПечати = Новый Структура;
ПараметрыПечати.Вставить("РеквизитыДетализации", "Сотрудник"); // Указываем поле, по которому идет связка

// Подготовка данных для БЗК
ЗарплатаКадры.ПриОпределенииОбъектовПечатнойФормы(МассивОбъектовДляПечати, "ТДОбходнойЛист", "", ПараметрыПечати);

Во-вторых, после формирования табличного документа, его нужно зарегистрировать в коллекции и передать управление подсистеме «Зарплата и кадры»:


// Выводим документ в коллекцию БСП
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ТДОбходнойЛист", "Обходной лист", ТабДокумент);

// Вызываем обработчик БЗК для подготовки публикации
ЗарплатаКадры.ПриПечати(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода);

// Передаем параметры внешней печатной формы в параметры вывода
ПараметрыВывода.Вставить("ПараметрыПечатиВнешнейПечатнойФормы", ПараметрыПечати);

Полный пример исправленного кода

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


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

    МассивОбъектовДляПечати = ОбщегоНазначения.СкопироватьРекурсивно(МассивОбъектов);
    ПараметрыПечати = Новый Структура;
    ПараметрыПечати.Вставить("РеквизитыДетализации", "Сотрудник");
    
    // Подготовка структуры для Личного кабинета
    ЗарплатаКадры.ПриОпределенииОбъектовПечатнойФормы(МассивОбъектовДляПечати, "ТДОбходнойЛист", "", ПараметрыПечати);
    
    // Формируем сам документ
    ТабДокумент = ТабличныйДокументНаПечать(ПараметрыПечати, МассивОбъектовДляПечати, ОбъектыПечати, ПараметрыВывода);
    
    // Регистрация в коллекции
    УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ТДОбходнойЛист", "Обходной лист", ТабДокумент);
    
    // Финализация процесса для БЗК
    ЗарплатаКадры.ПриПечати(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода);
    ПараметрыВывода.Вставить("ПараметрыПечатиВнешнейПечатнойФормы", ПараметрыПечати);
    
КонецПроцедуры

Функция ТабличныйДокументНаПечать(ПараметрыПечати, МассивОбъектовДляПечати, ОбъектыПечати, ПараметрыВывода)
    ТабДокумент = Новый ТабличныйДокумент;
    ТабДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ОбходнойЛист";
    
    // Работаем с данными документа (на примере первого объекта)
    СсылкаНаДокумент = МассивОбъектовДляПечати[0];
    Сотрудник = СсылкаНаДокумент.Сотрудник;
    
    МакетикОЛ = ПолучитьОбщийМакет("ОбходнойЛист");
    Обходной = МакетикОЛ.ПолучитьОбласть("Обходной");
    
    // Заполнение параметров
    Обходной.Параметры.ФИОРаботника = Сотрудник.ФизическоеЛицо.Наименование;
    Обходной.Параметры.ДатаРождения = Формат(Сотрудник.ФизическоеЛицо.ДатаРождения, "ДФ=dd.MM.yyyy");
    Обходной.Параметры.ДатаДок = Формат(СсылкаНаДокумент.Дата, "ДЛФ=DD");
    Обходной.Параметры.Подразделение = СсылкаНаДокумент.Подразделение;
    Обходной.Параметры.Должность = СсылкаНаДокумент.Должность;
    Обходной.Параметры.ДатаПриема = Формат(СсылкаНаДокумент.ДатаПриема, "ДЛФ=DD");
    
    // Выводим область
    ТабДокумент.Вывести(Обходной);
    
    // Устанавливаем свойства документа
    ТабДокумент.КоличествоЭкземпляров = 1;
    
    // Возвращаем полноценный ТабличныйДокумент
    Возврат ТабДокумент;
КонецФункции

Заключение и рекомендации

Подведем итоги нашего исследования. Ошибка «Поле объекта не обнаружено (КоличествоЭкземпляров)» — это классический пример нарушения типизации. Программист ожидал ТабличныйДокумент, но из-за особенностей метода Вывести() передал ОбластьЯчеекТабличногоДокумента.

Основные правила, которые помогут избежать подобных проблем в будущем:

Соблюдение этих простых правил сделает ваш код стабильным, а процесс разработки внешних печатных форм — предсказуемым и быстрым.

← На главную