Как исправить ошибку «Поле объекта не обнаружено (КоличествоЭкземпляров)» при печати в Word из 1С 8.3?

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

Разработка внешних печатных форм в среде 1С:Предприятие 8.3 — одна из самых частых задач программиста. Использование шаблонов Microsoft Word (файлов формата docx) позволяет создавать красивые, легко редактируемые договоры, соглашения и акты. Однако при интеграции таких форм в типовые конфигурации, работающие на базе Библиотеки стандартных подсистем (БСП), разработчики часто сталкиваются с неприятным поведением системы. Программа успешно формирует и открывает документ Word, но сразу после этого выдает ошибку: «Поле объекта не обнаружено (КоличествоЭкземпляров)».

В этой статье мы подробно разберем, почему возникает данная ошибка, как работает механизм вывода печатных форм в БСП и какими способами можно обойти это ограничение — от простых «костылей» до правильного современного использования механизмов БСП без привлечения COM-объектов.

Выясняем причину возникновения ошибки

Давайте проанализируем, что происходит в недрах БСП, когда мы нажимаем кнопку «Печать». Стандартный механизм БСП спроектирован в первую очередь для работы с объектом ТабличныйДокумент (стандартный печатный лист 1С). Системные модули печати ожидают, что результатом выполнения процедуры печати будет коллекция печатных форм, содержащая именно табличные документы.

Когда управление возвращается в общий модуль БСП, система пытается настроить параметры печати для полученных макетов. В коде это выглядит примерно так:


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

Если в качестве печатной формы мы передали COM-объект Word (или структуру, в которой вместо табличного документа находится ссылка на приложение Word), БСП пытается обратиться к свойству КоличествоЭкземпляров у этого объекта. Разумеется, у COM-объекта Microsoft Word такого свойства нет, из-за чего платформа генерирует исключение и аварийно завершает работу обработчика печати.

Если же мы вообще ничего не возвращаем в структуру печатных форм, БСП выдает другую ошибку — о том, что печатная форма не была сформирована вовсе.

Ниже мы рассмотрим три способа решения этой проблемы.

Способ 1. Использование «заглушки» в виде пустого табличного документа

Это самое быстрое и простое решение, которое обсуждалось на форуме. Оно идеально подходит, если ваша печатная форма уже написана с использованием COM-объекта Word.Application, отлично работает, и вам нужно лишь избавиться от назойливой ошибки БСП, не переписывая весь код генерации файла.

Суть метода заключается в том, чтобы обмануть БСП: мы формируем и открываем документ Word самостоятельно через COM, а в вызывающую процедуру БСП возвращаем абсолютно чистый, пустой объект ТабличныйДокумент. Система видит, что документ возвращен, успешно считывает у него свойство КоличествоЭкземпляров и завершает работу без ошибок.

Рассмотрим пример реализации этого обхода в модуле внешней печатной формы:


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

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

КонецПроцедуры

Плюсы метода: простота внедрения, минимальные изменения в существующем коде.

Минусы метода: у пользователя на долю секунды может мелькать пустое окно предварительного просмотра 1С (хотя при правильной настройке параметров вывода этого можно избежать). Кроме того, сохраняются все недостатки работы с COM-объектами.

Способ 2. Регистрация в качестве «Обработки заполнения»

Если мы регистрируем внешнюю обработку в справочнике «Дополнительные отчеты и обработки» с видом «Печатная форма», БСП жестко контролирует возвращаемые типы данных. Но мы можем пойти другим путем.

Если в сведениях о внешней обработке (функция СведенияОВнешнейОбработке) указать вид «Заполнение объекта» или «Дополнительная обработка», то БСП не будет ожидать возврата табличного документа. В таком сценарии мы можем повесить формирование Word-документа прямо на команду выполнения обработки.

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

Способ 3. Современное и правильное решение средствами БСП (без COM)

Использование COM-технологии (Новый COMОбъект("Word.Application")) в современных реалиях считается устаревшим подходом и «плохим тоном» разработки. Оно имеет критические недостатки:

  1. Код не кроссплатформенный — он принципиально не будет работать, если сервер 1С работает под управлением ОС Linux.
  2. Требует обязательной установки MS Word на сервере (при фоновом формировании) или на каждом клиентском компьютере.
  3. Процессы winword.exe часто «зависают» в памяти сервера, забивая оперативную память и снижая производительность системы.

Современные версии БСП (начиная с версии 3.0) предоставляют мощный штатный механизм для работы с офисными документами напрямую, без использования COM. Документ формируется на сервере путем работы с XML-структурой zip-архива docx. Для этого используется встроенное свойство структуры печатной формы — ОфисныеДокументы.

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

Шаг 1. Подготовка шаблона. Создайте обычный документ в MS Word (docx). Вместо заполняемых полей вставьте параметры в фигурных скобках, например: {v8 НомерДоговора}, {v8 ДатаДоговора}. Сохраните файл и загрузите его во внешнюю обработку как макет с типом Двоичные данные. По стандартам БСП имя макета должно начинаться префиксом ПФ_DOC_.

Шаг 2. Код формирования документа. В процедуре печати мы используем программный интерфейс общего модуля УправлениеПечатью. Мы инициализируем макет, заполняем параметры и помещаем готовый файл во временное хранилище 1С. Адрес этого хранилища мы передаем в специальное соответствие ОфисныеДокументы.

Посмотрим на пример правильного кода:


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

    // Получаем пустую структуру для нашей печатной формы
    ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ИдентификаторКоманды");
    
    // БСП все еще требует инициализации ТабличногоДокумента (оставляем пустой как заглушку)
    ПечатнаяФорма.ТабличныйДокумент = Новый ТабличныйДокумент;
    
    // Создаем соответствие для хранения двоичных данных файлов Word
    ОфисныеДокументы = Новый Соответствие;
    
    Для Каждого СсылкаИзМассива Из МассивОбъектовНазначения Цикл
        
        // 1. Получаем двоичные данные нашего макета-шаблона .docx
        ДвоичныеДанныеМакета = ПолучитьМакет("ПФ_DOC_Договор");
        
        // 2. Инициализируем макет средствами БСП
        Макет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, Неопределено);
        
        // 3. Создаем объект печатной формы
        ПечатнаяФормаWord = УправлениеПечатью.ИнициализироватьПечатнуюФорму(Неопределено, Макет.НастройкиСтраницыМакета, Макет);
        
        // 4. Описываем области шаблона
        СтруктураОбластей = Новый Структура;
        УправлениеПечатью.ДобавитьОписаниеОбласти(СтруктураОбластей, "ТелоДоговора", "Общая");
        
        // 5. Заполняем параметры данными из информационной базы 1С
        ДанныеЗаполнения = Новый Структура;
        ДанныеЗаполнения.Вставить("НомерДоговора", СсылкаИзМассива.Номер);
        ДанныеЗаполнения.Вставить("ДатаДоговора",  Формат(СсылкаИзМассива.Дата, "ДЛФ=DD"));
        ДанныеЗаполнения.Вставить("Контрагент",    Строка(СсылкаИзМассива.Контрагент));
        
        ОбластьТело = УправлениеПечатью.ОбластьМакета(Макет, СтруктураОбластей.ТелоДоговора);
        УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаWord, ОбластьТело, ДанныеЗаполнения);
        
        // 6. Получаем адрес сформированного docx-файла во временном хранилище
        АдресХранилища = УправлениеПечатью.СформироватьДокумент(ПечатнаяФормаWord);
        
        // 7. Помещаем файл в соответствие (АдресХранилища - ключ, ИмяФайла - значение)
        ИмяФайла = "Договор_" + СокрЛП(СсылкаИзМассива.Номер) + ".docx";
        ОфисныеДокументы.Вставить(АдресХранилища, ИмяФайла);
        
        // Очищаем занятые ресурсы сервера
        УправлениеПечатью.ОчиститьСсылки(ПечатнаяФормаWord);
        УправлениеПечатью.ОчиститьСсылки(Макет);
        
    КонецЦикла;
    
    // Передаем коллекцию готовых файлов Word в БСП
    ПечатнаяФорма.ОфисныеДокументы = ОфисныеДокументы;

КонецПроцедуры

При использовании этого метода БСП видит заполненное свойство ОфисныеДокументы, понимает, что печать производится в офисный формат, автоматически скачивает временный файл на клиентский компьютер и открывает его в локальном текстовом редакторе пользователя (MS Word, LibreOffice, OpenOffice, в зависимости от того, что установлено по умолчанию для файлов .docx).

При этом никаких ошибок о количестве экземпляров не возникает, а на экране 1С не открываются пустые раздражающие окна просмотра табличных документов!

Резюме

Мы рассмотрели три способа борьбы с ошибкой инициализации реквизитов печатной формы БСП. Если вам нужно быстро исправить старый код, используйте Способ 1 с возвратом пустого табличного документа в качестве заглушки. Если вы проектируете новую печатную форму под современную конфигурацию 1С, настоятельно рекомендуем использовать Способ 3 — это спасет вас от проблем производительности COM-соединений, обеспечит стабильную работу на веб-клиенте и под операционными системами семейства Linux.

← На главную