При разработке и внедрении внешних печатных форм в конфигурациях 1С, таких как 1С:Зарплата и Управление Персоналом (ЗУП), мы можем столкнуться с различными сложностями. Одной из распространенных проблем является ошибка "Значение не является значением объектного типа (ВысотаТаблицы)". Давайте рассмотрим эту проблему подробно, выясним ее причины и найдем эффективные способы решения. В качестве альтернативы самостоятельной разработке можно использовать готовый сборник внешних печатных форм для 1С:ЗУП.
Представим ситуацию, когда мы создали внешнюю печатную форму для документа "Прием на работу" в ЗУП. При попытке ее распечатать, после ввода необходимых данных в форме настроек, система выдает ошибку:
Значение не является значением объектного типа (ВысотаТаблицы) {ОбщаяФорма.ПечатьДокументов.Форма(675)}:ЕстьТабличныеДокументы = ЕстьТабличныеДокументы Или ПечатнаяФорма.ТабличныйДокумент.ВысотаТаблицы <> 0; {ОбщаяФорма.ПечатьДокументов.Форма(67)}:ИсключитьОфисныеДокументыИзКомплектов(КоллекцияПечатныхФорм); {ОбщийМодуль.УправлениеПечатьюКлиент.Модуль(198)}:ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия, ВладелецФормы, КлючУникальности); {ВнешняяОбработка.ДоговорПоставкоДем.Форма.ФормаНастроек.Форма(34)}:УправлениеПечатьюКлиент.ПечатьДокументов(МассивПечатныхФорм, ОбъектыПечати, ЭтаФорма); [ОшибкаВоВремяВыполненияВстроенногоЯзыка, ОшибкаИспользованияВстроенногоЯзыка]
Этот стек вызова ошибки очень показателен. Он указывает, что проблема возникает в общей форме ОбщаяФорма.ПечатьДокументов при попытке обратиться к свойству ВысотаТаблицы у объекта ПечатнаяФорма.ТабличныйДокумент. Судя по ошибке "Значение не является значением объектного типа", это означает, что ПечатнаяФорма.ТабличныйДокумент в этот момент является Неопределено или каким-то другим типом, который не имеет свойства ВысотаТаблицы.
Давайте посмотрим на предоставленный код, чтобы выявить причину.
Начнем с кода формы настроек, который инициирует процесс печати:
&НаКлиенте
Процедура ПечатьПродолжить(Команда)
// ... сбор данных из формы ...
ОбъектыПечати = Новый СписокЗначений;
ОбъектыПечати.Добавить(Объект.СсылкаНаОбъект,"Трудовая договор");
МассивПечатныхФорм = ПечатьНаСервере(ОбъектыПечати, СтруктураДанных);
УправлениеПечатьюКлиент.ПечатьДокументов(МассивПечатныхФорм, ОбъектыПечати, ЭтаФорма);
Закрыть;
КонецПроцедуры
&НаСервере
Функция ПечатьНаСервере(ОбъектыПечати, ПараметрыПечати)
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(ОбъектыПечати[0].Значение);
КоллекцияПечатныхФорм = УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм("ТрудовойДоговорДалини");
ПараметрыВывода = УправлениеПечатью.ПодготовитьСтруктуруПараметровВывода;
ОбработкаОбъект.Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода, ПараметрыПечати);
МассивПечатныхФорм = ОбщегоНазначения.ТаблицаЗначенийВМассив(КоллекцияПечатныхФорм);
Возврат МассивПечатныхФорм;
КонецФункции
В этом коде мы видим стандартный вызов серверной функции ПечатьНаСервере, которая, в свою очередь, вызывает метод Печать модуля внешней обработки. Затем результат передается на клиент в УправлениеПечатьюКлиент.ПечатьДокументов. Здесь все выглядит достаточно стандартно.
Теперь обратимся к модулю самой внешней печатной формы. Нас интересует процедура Печать и функция СформироватьПечатнуюФорму:
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода, ПараметрыПечати) Экспорт
//УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ПФ_Трудовой_Договор_Внешний", "Трудовой договор с водителями", СформироватьПечатнуюФормуДоговора(МассивОбъектов, ОбъектыПечати, ПараметрыВывода));
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ТрудовойДоговорДалини") Тогда
ПечатьТрудовогоДоговора (МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода)
КонецЕсли;
КонецПроцедуры
Процедура ПечатьТрудовогоДоговора (МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода)
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ТрудовойДоговорДалини",
НСтр("ru='Трудовой договор с водителями'"),
СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати, ПараметрыВывода));
КонецПроцедуры
Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати)
КонецФункции
При внимательном рассмотрении представленного кода мы замечаем очень важную деталь. Функция СформироватьПечатнуюФорму в модуле внешней печатной формы, которая должна возвращать сформированный табличный документ, является абсолютно пустой:
Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати) КонецФункции
В 1С, если функция не содержит оператор Возврат, она неявно возвращает значение Неопределено. Именно это и является основной причиной ошибки. Разберем цепочку событий:
ПечатьТрудовогоДоговора вызывается функция СформироватьПечатнуюФорму.СформироватьПечатнуюФорму пуста, она возвращает Неопределено.Неопределено передается в процедуру УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию в качестве табличного документа.ВывестиТабличныйДокументВКоллекцию добавляет в коллекцию печатных форм строку, в которой поле для табличного документа содержит Неопределено.ПечатьДокументов пытается обработать эту коллекцию, она обнаруживает, что вместо табличного документа там Неопределено. При попытке обратиться к свойству ВысотаТаблицы у Неопределено возникает ошибка "Значение не является значением объектного типа".Пользователь подтвердил это, указав, что код в этой функции был закомментирован или не дописан, и после раскомментирования/добавления логики формирования печатной формы, проблема была решена.
Для исправления этой ошибки нам необходимо гарантировать, что функция СформироватьПечатнуюФорму всегда возвращает объект типа ТабличныйДокумент.
В самом начале функции СформироватьПечатнуюФорму мы должны создать новый экземпляр объекта ТабличныйДокумент. Это обеспечит, что даже если в процессе формирования возникнут другие ошибки, мы всегда вернем хотя бы пустой табличный документ, который имеет свойство ВысотаТаблицы.
Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати)
ТабДок = Новый ТабличныйДокумент; // Инициализируем табличный документ
// ... здесь будет код по заполнению макета ...
Возврат ТабДок; // Обязательный возврат табличного документа
КонецФункции
Внутри функции СформироватьПечатнуюФорму нам необходимо реализовать всю логику по получению данных, загрузке макета, заполнению областей и выводу их в ТабДок. Если у вас уже был готовый код, убедитесь, что он раскомментирован и корректно работает. Мы должны использовать методы объекта ТабличныйДокумент, такие как Вывести(), ОтображатьСетку(), ОтображатьЗаголовки() и т.д.
Приведем пример структуры функции формирования:
Функция СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати, ПараметрыПечати) Экспорт
// 1. Создаем табличный документ
ТабДок = Новый ТабличныйДокумент;
ТабДок.Очистить(); // Очищаем на всякий случай
ТабДок.ИмяПараметровПечати = "ПараметрыПечати_ТрудовойДоговорДалини";
// 2. Получаем объект документа "Прием на работу"
ДокументОбъект = СсылкаНаОбъект[0].ПолучитьОбъект(); // СсылкаНаОбъект - это массив ссылок
// 3. Получаем макет печатной формы
Макет = ПолучитьМакет("ТрудовойДоговорДалини"); // Предполагается, что макет добавлен в обработку
// 4. Определяем области макета
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьДанные = Макет.ПолучитьОбласть("Данные");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
// 5. Заполняем параметры макета данными из документа и ПараметровПечати
// Например, для заголовка:
ОбластьЗаголовок.Параметры.Заполнить(ДокументОбъект);
ОбластьЗаголовок.Параметры.ДатаПечати = ТекущаяДата();
// Заполнение параметров из СтруктураДанных, переданной из формы настроек
ОбластьДанные.Параметры.СерияПаспорта = ПараметрыПечати.Серия;
ОбластьДанные.Параметры.НомерПаспорта = ПараметрыПечати.Номер;
ОбластьДанные.Параметры.КемВыдан = ПараметрыПечати.КемВыдан;
ОбластьДанные.Параметры.ДатаВыдачи = ПараметрыПечати.ДатаВыдачи;
ОбластьДанные.Параметры.КодПодразделения = ПараметрыПечати.КодПодразделения;
ОбластьДанные.Параметры.ДатаНачалаРаботы = ПараметрыПечати.ДатаНачалаРаботы;
ОбластьДанные.Параметры.РазмерТарифнойСтавки = ПараметрыПечати.РазмерТарифнойСтавкий; // Опечатка в названии, исправим на РазмерТарифнойСтавки
ОбластьДанные.Параметры.ЗаработнаяПлата = ПараметрыПечати.ЗаработнаяПлата;
// Также заполняем данные из самого документа
ОбластьДанные.Параметры.НомерДокумента = ДокументОбъект.Номер;
ОбластьДанные.Параметры.ДатаДокумента = ДокументОбъект.Дата;
ОбластьДанные.Параметры.Сотрудник = ДокументОбъект.Сотрудник;
// ... и так далее для всех необходимых полей ...
// 6. Выводим области в табличный документ
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьДанные);
ТабДок.Вывести(ОбластьПодвал);
// 7. Настраиваем параметры вывода (если необходимо)
ТабДок.ПараметрыСтраницы.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДок.ПараметрыСтраницы.МасштабПечати = 100;
// 8. Возвращаем заполненный табличный документ
Возврат ТабДок;
КонецФункции
Обратите внимание на то, что СсылкаНаОбъект в параметрах функции СформироватьПечатнуюФорму является массивом ссылок. Если вы ожидаете только один объект, как в данном случае с документом "Прием на работу", то обращайтесь к первому элементу массива: СсылкаНаОбъект[0].ПолучитьОбъект().
Даже если мы раскомментируем код или напишем его заново, могут возникнуть другие нюансы, приводящие к аналогичным ошибкам:
Если ... Тогда ... Иначе ... КонецЕсли;) внутри функции формирования. Если оператор Возврат ТабДок; находится только в одной из ветвей, а другие ветви не достигают его выполнения, функция все равно может вернуть Неопределено.
Решение: Всегда инициализируйте ТабличныйДокумент в начале функции и помещайте Возврат ТабДок; в самый конец функции, чтобы гарантировать его выполнение.
ТабличныйДокумент, а, например, Структуру, Массив или результат запроса. Механизм печати не сможет обработать такой объект, что приведет к той же ошибке "Значение не является значением объектного типа".
Решение: Всегда проверяйте тип возвращаемого значения в отладчике. Убедитесь, что это именно ТабличныйДокумент.
СформироватьПечатнуюФорму может происходить другая ошибка (например, деление на ноль, обращение к несуществующему реквизиту объекта, неправильный путь к макету). Это прервет выполнение функции до того, как будет создан и возвращен ТабличныйДокумент.
Решение: Используйте отладчик для пошагового выполнения кода внутри функции СформироватьПечатнуюФорму. Отслеживайте значения переменных и контролируйте поток выполнения, чтобы выявить и исправить любые внутренние ошибки.
Для точного определения места и причины ошибки мы рекомендуем использовать отладчик 1С:
ПечатьПродолжить на клиенте, на строке МассивПечатныхФорм = ПечатьНаСервере(ОбъектыПечати, СтруктураДанных);.ПечатьНаСервере, на строке
ОбработкаОбъект.Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода, ПараметрыПечати);
Печать (или ПечатьТрудовогоДоговора), перед вызовом СформироватьПечатнуюФорму и после него.СформироватьПечатнуюФорму: в самом начале и непосредственно на строке Возврат ТабДок;.F10 (шаг через) и F11 (шаг внутрь) для пошагового прохождения кода.
ПечатьНаСервере, войдите в нее (F11).ОбработкаОбъект.Печать, снова войдите в нее (F11), чтобы попасть в модуль вашей внешней обработки.Печать и ПечатьТрудовогоДоговора, пока не дойдете до вызова СформироватьПечатнуюФорму. Войдите в эту функцию (F11).СформироватьПечатнуюФорму выполняйте код пошагово. Проверяйте значения всех переменных, особенно ТабДок.После выхода из функции СформироватьПечатнуюФорму, но до вызова УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию, проверьте тип и значение возвращенного результата. Для этого можно добавить временную переменную для отладки, как мы показывали ранее:
Процедура ПечатьТрудовогоДоговора (МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода)
РезультатФормирования = СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати, ПараметрыВывода);
// Здесь поставьте точку останова и в окне "Табло" проверьте "РезультатФормирования".
// Его тип должен быть "ТабличныйДокумент".
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ТрудовойДоговорДалини",
НСтр("ru='Трудовой договор с водителями'"),
РезультатФормирования);
КонецПроцедуры
Если РезультатФормирования окажется Неопределено, то мы точно знаем, что проблема в функции СформироватьПечатнуюФорму.
Ошибка "Значение не является значением объектного типа (ВысотаТаблицы)" при выводе внешней печатной формы в 1С чаще всего указывает на то, что функция, ответственная за формирование табличного документа, либо не возвращает никакого значения (Неопределено), либо возвращает значение некорректного типа. Внимательный анализ кода, особенно функции СформироватьПечатнуюФорму, и использование отладчика помогут нам быстро выявить и устранить эту проблему.
Всегда помните о необходимости явного создания объекта ТабличныйДокумент и его гарантированного возврата из функции формирования печатной формы. Это ключевой принцип при работе с внешними печатными формами в системе 1С. В качестве основы для разработки можно использовать готовый шаблон внешней печатной формы.