Как исправить ошибку "Значение не является значением объектного типа (ВысотаТаблицы)" при выводе внешней печатной формы в 1С:ЗУП?

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

При разработке и внедрении внешних печатных форм в конфигурациях 1С, таких как 1С:Зарплата и Управление Персоналом (ЗУП), мы можем столкнуться с различными сложностями. Одной из распространенных проблем является ошибка "Значение не является значением объектного типа (ВысотаТаблицы)". Давайте рассмотрим эту проблему подробно, выясним ее причины и найдем эффективные способы решения. В качестве альтернативы самостоятельной разработке можно использовать готовый сборник внешних печатных форм для 1С:ЗУП.

Анализируем контекст возникновения ошибки

Представим ситуацию, когда мы создали внешнюю печатную форму для документа "Прием на работу" в ЗУП. При попытке ее распечатать, после ввода необходимых данных в форме настроек, система выдает ошибку:

Значение не является значением объектного типа (ВысотаТаблицы) {ОбщаяФорма.ПечатьДокументов.Форма(675)}:ЕстьТабличныеДокументы = ЕстьТабличныеДокументы Или ПечатнаяФорма.ТабличныйДокумент.ВысотаТаблицы <> 0; {ОбщаяФорма.ПечатьДокументов.Форма(67)}:ИсключитьОфисныеДокументыИзКомплектов(КоллекцияПечатныхФорм); {ОбщийМодуль.УправлениеПечатьюКлиент.Модуль(198)}:ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия, ВладелецФормы, КлючУникальности); {ВнешняяОбработка.ДоговорПоставкоДем.Форма.ФормаНастроек.Форма(34)}:УправлениеПечатьюКлиент.ПечатьДокументов(МассивПечатныхФорм, ОбъектыПечати, ЭтаФорма); [ОшибкаВоВремяВыполненияВстроенногоЯзыка, ОшибкаИспользованияВстроенногоЯзыка]

Этот стек вызова ошибки очень показателен. Он указывает, что проблема возникает в общей форме ОбщаяФорма.ПечатьДокументов при попытке обратиться к свойству ВысотаТаблицы у объекта ПечатнаяФорма.ТабличныйДокумент. Судя по ошибке "Значение не является значением объектного типа", это означает, что ПечатнаяФорма.ТабличныйДокумент в этот момент является Неопределено или каким-то другим типом, который не имеет свойства ВысотаТаблицы.

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

Код формы настроек внешней печатной формы

Начнем с кода формы настроек, который инициирует процесс печати:


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

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

В этом коде мы видим стандартный вызов серверной функции ПечатьНаСервере, которая, в свою очередь, вызывает метод Печать модуля внешней обработки. Затем результат передается на клиент в УправлениеПечатьюКлиент.ПечатьДокументов. Здесь все выглядит достаточно стандартно.

Код модуля внешней печатной формы

Теперь обратимся к модулю самой внешней печатной формы. Нас интересует процедура Печать и функция СформироватьПечатнуюФорму:


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

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

Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати)
КонецФункции

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

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

Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати) КонецФункции

В 1С, если функция не содержит оператор Возврат, она неявно возвращает значение Неопределено. Именно это и является основной причиной ошибки. Разберем цепочку событий:

  1. Из процедуры ПечатьТрудовогоДоговора вызывается функция СформироватьПечатнуюФорму.
  2. Поскольку функция СформироватьПечатнуюФорму пуста, она возвращает Неопределено.
  3. Это Неопределено передается в процедуру УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию в качестве табличного документа.
  4. Процедура ВывестиТабличныйДокументВКоллекцию добавляет в коллекцию печатных форм строку, в которой поле для табличного документа содержит Неопределено.
  5. Когда общая форма ПечатьДокументов пытается обработать эту коллекцию, она обнаруживает, что вместо табличного документа там Неопределено. При попытке обратиться к свойству ВысотаТаблицы у Неопределено возникает ошибка "Значение не является значением объектного типа".

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

Как правильно исправить проблему: шаги к решению

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

Шаг 1: Инициализация ТабличногоДокумента

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


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

Шаг 2: Реализация логики формирования печатной формы

Внутри функции СформироватьПечатнуюФорму нам необходимо реализовать всю логику по получению данных, загрузке макета, заполнению областей и выводу их в ТабДок. Если у вас уже был готовый код, убедитесь, что он раскомментирован и корректно работает. Мы должны использовать методы объекта ТабличныйДокумент, такие как Вывести(), ОтображатьСетку(), ОтображатьЗаголовки() и т.д.

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


Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати) Экспорт
    // 1. Создаем табличный документ
    ТабДок = Новый ТабличныйДокумент;
    ТабДок.Очистить(); // Очищаем на всякий случай
    ТабДок.ИмяПараметровПечати = "ПараметрыПечати_ТрудовойДоговорДалини";

    // 2. Получаем объект документа "Прием на работу"
    ДокументОбъект = СсылкаНаОбъект[0].ПолучитьОбъект(); // СсылкаНаОбъект - это массив ссылок

    // 3. Получаем макет печатной формы
    Макет = ПолучитьМакет("ТрудовойДоговорДалини"); // Предполагается, что макет добавлен в обработку
    
    // 4. Определяем области макета
    ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
    ОбластьДанные = Макет.ПолучитьОбласть("Данные");
    ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");

    // 5. Заполняем параметры макета данными из документа и ПараметровПечати
    // Например, для заголовка:
    ОбластьЗаголовок.Параметры.Заполнить(ДокументОбъект);
    ОбластьЗаголовок.Параметры.ДатаПечати = ТекущаяДата();
    
    // Заполнение параметров из СтруктураДанных, переданной из формы настроек
    ОбластьДанные.Параметры.СерияПаспорта      = ПараметрыПечати.Серия;
    ОбластьДанные.Параметры.НомерПаспорта      = ПараметрыПечати.Номер;
    ОбластьДанные.Параметры.КемВыдан           = ПараметрыПечати.КемВыдан;
    ОбластьДанные.Параметры.ДатаВыдачи         = ПараметрыПечати.ДатаВыдачи;
    ОбластьДанные.Параметры.КодПодразделения   = ПараметрыПечати.КодПодразделения;
    ОбластьДанные.Параметры.ДатаНачалаРаботы   = ПараметрыПечати.ДатаНачалаРаботы;
    ОбластьДанные.Параметры.РазмерТарифнойСтавки = ПараметрыПечати.РазмерТарифнойСтавкий; // Опечатка в названии, исправим на РазмерТарифнойСтавки
    ОбластьДанные.Параметры.ЗаработнаяПлата    = ПараметрыПечати.ЗаработнаяПлата;
    
    // Также заполняем данные из самого документа
    ОбластьДанные.Параметры.НомерДокумента = ДокументОбъект.Номер;
    ОбластьДанные.Параметры.ДатаДокумента = ДокументОбъект.Дата;
    ОбластьДанные.Параметры.Сотрудник = ДокументОбъект.Сотрудник;
    // ... и так далее для всех необходимых полей ...

    // 6. Выводим области в табличный документ
    ТабДок.Вывести(ОбластьЗаголовок);
    ТабДок.Вывести(ОбластьДанные);
    ТабДок.Вывести(ОбластьПодвал);

    // 7. Настраиваем параметры вывода (если необходимо)
    ТабДок.ПараметрыСтраницы.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
    ТабДок.ПараметрыСтраницы.МасштабПечати = 100;

    // 8. Возвращаем заполненный табличный документ
    Возврат ТабДок;
КонецФункции

Обратите внимание на то, что СсылкаНаОбъект в параметрах функции СформироватьПечатнуюФорму является массивом ссылок. Если вы ожидаете только один объект, как в данном случае с документом "Прием на работу", то обращайтесь к первому элементу массива: СсылкаНаОбъект[0].ПолучитьОбъект().

Дополнительные причины и как их предотвратить

Даже если мы раскомментируем код или напишем его заново, могут возникнуть другие нюансы, приводящие к аналогичным ошибкам:

  1. Не все ветви кода возвращают табличный документ. Часто разработчики используют условные операторы (Если ... Тогда ... Иначе ... КонецЕсли;) внутри функции формирования. Если оператор Возврат ТабДок; находится только в одной из ветвей, а другие ветви не достигают его выполнения, функция все равно может вернуть Неопределено.

    Решение: Всегда инициализируйте ТабличныйДокумент в начале функции и помещайте Возврат ТабДок; в самый конец функции, чтобы гарантировать его выполнение.

  2. Возвращается неверный тип данных. По ошибке или из-за неправильной логики функция может вернуть не ТабличныйДокумент, а, например, Структуру, Массив или результат запроса. Механизм печати не сможет обработать такой объект, что приведет к той же ошибке "Значение не является значением объектного типа".

    Решение: Всегда проверяйте тип возвращаемого значения в отладчике. Убедитесь, что это именно ТабличныйДокумент.

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

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

Эффективная отладка для выявления подобных проблем

Для точного определения места и причины ошибки мы рекомендуем использовать отладчик 1С:

  1. Установите точки останова.
    • Первую точку останова поставьте в процедуре ПечатьПродолжить на клиенте, на строке МассивПечатныхФорм = ПечатьНаСервере(ОбъектыПечати, СтруктураДанных);.
    • Вторую точку останова поставьте в серверной функции ПечатьНаСервере, на строке
      
      ОбработкаОбъект.Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода, ПараметрыПечати);
      
      .
    • Третью, и самую важную, точку останова установите в модуле внешней обработки, в процедуре Печать (или ПечатьТрудовогоДоговора), перед вызовом СформироватьПечатнуюФорму и после него.
    • Четвертую точку останова поставьте внутри самой функции СформироватьПечатнуюФорму: в самом начале и непосредственно на строке Возврат ТабДок;.
  2. Запустите отладку. Воспроизведите действия, которые приводят к ошибке (печать формы).
  3. Пошаговое выполнение. Используйте клавиши F10 (шаг через) и F11 (шаг внутрь) для пошагового прохождения кода.
    • Дойдя до вызова ПечатьНаСервере, войдите в нее (F11).
    • Далее, дойдя до вызова ОбработкаОбъект.Печать, снова войдите в нее (F11), чтобы попасть в модуль вашей внешней обработки.
    • Пройдите по процедуре Печать и ПечатьТрудовогоДоговора, пока не дойдете до вызова СформироватьПечатнуюФорму. Войдите в эту функцию (F11).
    • Внутри СформироватьПечатнуюФорму выполняйте код пошагово. Проверяйте значения всех переменных, особенно ТабДок.
  4. Проверка возвращаемого значения.

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

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

    Если РезультатФормирования окажется Неопределено, то мы точно знаем, что проблема в функции СформироватьПечатнуюФорму.

Заключение

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

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

← На главную