Почему не выводится дата в документ MS Word из 1С и как это исправить?

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

При выгрузке данных из 1С в офисные документы MS Word через COM-объект Word.Application разработчики часто сталкиваются с ситуацией, когда вместо ожидаемой даты в шаблоне остается пустая строка или заменяемый параметр вовсе пропадет. Рассмотрим подробно, почему возникают такие ошибки в коде 1С, проанализируем частые причины сбоя при вызове функции Формат() и научимся правильно передавать реквизиты в макет Word.

Основные причины отсутствия даты при выводе в MS Word

Разберем ключевые проблемы, с которыми сталкиваются при формировании печатных форм через механизмы COM-взаимодействия:

  1. Незаполненное значение даты в 1С: Если реквизит Дата содержит значение по умолчанию (пустая дата вида 01.01.0001 0:00:00), то функция Формат(Шапка.Дата, "ДФ=dd.MM.yyyy") возвращает пустую строку "". При поиске и замене метки в Word подставляется пустой текст, из-за чего создается ощущение, что дата не выводится.
  2. Ошибки перезаписи переменных и структур: Часто при заполнении структуры данных допускается синтаксическая ошибка, когда вся переменная структуры случайно перезаписывается одним значением. Например, запись РеквизитыДокумента = Шапка.Номер превращает структуру в обычную строку, после чего обращение к свойству РеквизитыДокумента.Дата приводит к ошибке выполнения.
  3. Некорректное обращение к контексту объекта: Использование обращений вроде ЭтотОбъект.СсылкаНаОбъект внутри серверных функций или внешних обработок без проверки на заполненность реквизитов может возвращать пустые значения.
  4. Ограничения метода Find в MS Word: Команда Find.Execute ищет метки только в основной области текста (Content). Если тег даты расположен в таблице, надписи или колонтитуле, замена стандартным вызовом не произойдет.

Анализ ошибки на конкретном примере

Проанализируем ситуацию из практики. Разработчик пытается извлечь номер и дату документа с помощью запроса и передать их в замену меток [Дата] и [Номер] в шаблоне Word.

Посмотрим на ошибочный фрагмент кода получения данных:


Функция ПолучитьРеквизитыДокумента() 
    РеквизитыДокумента = Новый Структура ("Номер","Дата");
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                   |    ПриемНаРаботуВОрганизацию.Номер,
                   |    ПриемНаРаботуВОрганизацию.Дата
                   |ИЗ
                   |    Документ.ПриемНаРаботуВОрганизацию КАК ПриемНаРаботуВОрганизацию
                   |ГДЕ
                   |    ПриемНаРаботуВОрганизацию.Ссылка = &ТекущийДокумент";
    Запрос.УстановитьПараметр("ТекущийДокумент", СсылкаНаОбъект);
    Шапка = Запрос.Выполнить().Выбрать();
    Шапка.Следующий();

    // Ошибка 1: Перезапись всей структуры значением Номера!
    РеквизитыДокумента = Шапка.Номер; 
    // Ошибка 2: Попытка обратиться к свойству "Дата" у строки:
    РеквизитыДокумента.Дата = Формат(Шапка.Дата,"ДФ=dd.MM.yyyy");

    Возврат РеквизитыДокумента;
КонецФункции

В данном фрагменте строка РеквизитыДокумента = Шапка.Номер полностью уничтожает ранее созданную структуру РеквизитыДокумента. Последующая попытка присвоения РеквизитыДокумента.Дата вызывает сбой.

Кроме того, при проверке через отладчик значение поля Шапка.Дата или ЭтотОбъект.Дата может оказаться незаполненным: 01.01.0001 0:00:00. Если дата в документе-источнике не установлена, метод Формат() вернет пустую строку, и Word подставит пустое место на место текстового маркера.

Исправление кода и правильный вывод реквизитов в Word

Исправим ошибки в коде. Сформируем структуру реквизитов корректно, организуем проверку даты на заполненность и реализуем надежную замену в документе Word через COM.


Функция ПолучитьРеквизитыДокумента() 
    
    РеквизитыДокумента = Новый Структура("Номер, Дата, Организация");
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ПриемНаРаботу.Номер КАК Номер,
        |   ПриемНаРаботу.Дата КАК Дата,
        |   ПриемНаРаботу.Организация КАК Организация
        |ИЗ
        |   Документ.ПриемНаРаботуВОрганизацию КАК ПриемНаРаботу
        |ГДЕ
        |   ПриемНаРаботу.Ссылка = &ТекущийДокумент";
        
    Запрос.УстановитьПараметр("ТекущийДокумент", СсылкаНаОбъект);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        РеквизитыДокумента.Номер = СокрЛП(Выборка.Номер);
        
        // Проверяем заполненность даты перед форматированием
        Если ЗначениеЗаполнено(Выборка.Дата) Тогда
            РеквизитыДокумента.Дата = Формат(Выборка.Дата, "ДФ=dd.MM.yyyy");
        Иначе
            РеквизитыДокумента.Дата = "_____г.";
        КонецЕсли;
        
        РеквизитыДокумента.Организация = СокрЛП(Строка(Выборка.Организация));
    КонецЕсли;
    
    Возврат РеквизитыДокумента;
    
КонецФункции

Процедура ПечатьВWord() Экспорт

    Данные = ПолучитьРеквизитыДокумента();
    ПутьКМакету = МакетПолучить(); // Получаем путь к временному doc-файлу
    
    Если Не ЗначениеЗаполнено(ПутьКМакету) Тогда
        Возврат;
    КонецЕсли;

    Попытка
        Word = Новый COMОбъект("Word.Application");
    Исключение
        Сообщить("Не удалось запустить MS Word. Проверьте установку программы.");
        Возврат;
    КонецПопытки;

    NewDoc = Word.Documents.Add(ПутьКМакету);
    
    // Выполняем замену меток в документе
    Замена = NewDoc.Content.Find;
    
    // Замена даты
    Замена.Execute("[Дата]", , , , , , , , , Данные.Дата, 2);
    // Замена номера
    Замена.Execute("[Номер]", , , , , , , , , Данные.Номер, 2);
    // Замена организации
    Замена.Execute("[Организация]", , , , , , , , , Данные.Организация, 2);

    Word.Visible = Истина;
    
    // Удаляем временный файл макета
    УдалитьФайлы(ПутьКМакету);

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

Альтернативные способы работы с шаблонами Word

Помимо прямого поиска текста с помощью Find.Execute, существуют более надежные способы заполнения шаблонов MS Word из 1С:

  1. Закладки (Bookmarks): В макете Word в местах вставки данных создаются закладки. Из 1С передача значения выполняется напрямую в область закладки: NewDoc.Bookmarks("ДатаДокумента").Range.Text = Данные.Дата; Этот подход предотвращает случайное удаление меток или сбой поиска из-за форматирования текста.
  2. Переменные документа (DocVariables): В макет вставляются специальные поля DOCVARIABLE "ИмяПеременной". Из кода 1С значения присваиваются коллекции переменных:
    
    NewDoc.Variables.Item("ДатаДокумента").Value = Данные.Дата;
    NewDoc.Fields.Update(); // Обновление всех полей в документе
    
  3. Формирование файлов DOCX без COM: Для работы на серверах под управлением Linux или для повышения производительности рекомендуется использовать встроенные средства работы с ZIP-архивами и XML в 1С (так как файл .docx представляет собой ZIP-архив с XML-структурой) либо использовать механизмы Библиотеки Стандартных Подсистем (БСП) для генерации офисных документов.
← На главную