Почему при выгрузке данных из 1С в Excel появляется запрос на замену файла resume.xlw и формируется пустой отчет?

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

При разработке внешних обработок выгрузки проводок или остатков ТМЦ в Microsoft Excel разработчики часто сталкиваются с ситуацией, когда процедура успешно отрабатывает за один период, но при смене дат формирует пустой файл и выдает диалоговое окно: «Файл resume.xlw уже существует, заменить да/нет». Кроме того, выполнение часто прерывается ошибками Значение не является значением объектного типа (Наименование), а в операционной системе остаются висеть фоновые процессы EXCEL.EXE.

Разберем детально, почему возникают эти проблемы, как исправить логику формирования файла и запроса к регистрам бухгалтерии, а также рассмотрим более надежный способ сохранения данных без использования COM-объектов.

Причина появления сообщения о файле resume.xlw

Проанализируем природу появления диалога о перезаписи resume.xlw. В объектной модели Microsoft Excel вызов метода Save() непосредственно у корневого COM-объекта приложения (например, Excel.Save()) трактуется как команда сохранения текущей рабочей области (Workspace). Файлом по умолчанию для такой рабочей области всегда выступает resume.xlw.

Чтобы исключить появление этого окна и корректно сохранить книгу с данными, необходимо вызывать метод сохранения у конкретного объекта книги (Workbook), указывая точный целевой путь к файлу:


// Неправильно: сохранение рабочей области Excel
Excel.Save();

// Правильно: сохранение конкретной рабочей книги
Книга.SaveAs(ПутьКФайлу);
// Либо через активную книгу
Excel.ActiveWorkbook.SaveAs(ПутьКФайлу);

Для подавления системных предупреждений Excel при перезаписи файла также следует временно отключить системные алерты свойством Excel.DisplayAlerts = 0 (или Ложь).

Ошибки в запросе и обращение к незаполненным субконто

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

{ВнешняяОбработка.Выгрузка.Форма(78)}: Значение не является значением объектного типа (Наименование)

Такое исключение возникает в момент обращения к реквизиту субконто, когда само субконто не заполнено (в выборку попадает значение NULL или Неопределено):


// Ошибка при отсутствии значения у субконто:
Лист.Cells(Строка, 19).Value = Выборка.СубконтоКт1.Наименование;

Если на счетах учета (например, 10, 41 или 08) по какой-либо проводке субконто не задано или субсчет имеет иную настройку субконто, цикл сразу прерывается, документ не успевает заполниться, а выгрузка завершается сбоем.

Для устранения этой проблемы применим два правила:

  1. Безопасное разыменование в тексте запроса: используем функцию ЕСТЬNULL, чтобы в результат выборки всегда возвращалась строка, даже если субконто отсутствует:
    
    ВЫБРАТЬ
        ЕСТЬNULL(ХозрасчетныйДвиженияССубконто.СубконтоКт1.Наименование, "") КАК СубконтоКт1Наименование
    ИЗ
        РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&НачалоПериода, &КонецПериода, ...)
    
  2. Проверка заполненности в коде: если разыменование выполняется в коде модуля, обязательно проверяем значение функцией ЗначениеЗаполнено():
    
    Если ЗначениеЗаполнено(Выборка.СубконтоКт1) Тогда
        Лист.Cells(Строка, 19).Value = Выборка.СубконтоКт1.Наименование;
    Иначе
        Лист.Cells(Строка, 19).Value = "";
    КонецЕсли;
    
  3. Корректная граница периода: дата конца периода обязательно должна включать время окончания дня. Используем функцию КонецДня() при передаче параметра в запрос, чтобы движения за последний день не отсекались:
    
    Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
    Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));
    

Управление процессами Excel и безопасное закрытие COM-соединения

Когда выгрузка падает с ошибкой, приложение EXCEL.EXE остается в памяти операционной системы в фоновом режиме. При повторных запусках эти процессы накапливаются, блокируют файлы на диске и приводят к непредсказуемым сбоям при записи.

Посмотрим на пример безопасной работы с COM-объектом с использованием блока Попытка ... Исключение:


Попытка
    Excel = Новый COMОбъект("Excel.Application");
    Excel.DisplayAlerts = Ложь;
    Книга = Excel.Workbooks.Add();
    Лист = Книга.Sheets(1);
    
    // Заполнение ячеек данными из выборки
    // ...
    
    // Корректное сохранение книги
    Книга.SaveAs(ПутьКФайлу);
    Книга.Close(Ложь);
    Excel.Quit();
Исключение
    // В случае ошибки гарантированно освобождаем ресурсы
    Если Excel <> Неопределено Тогда
        Excel.DisplayAlerts = Ложь;
        Excel.Quit();
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;

Excel = Неопределено;

Альтернативное решение: выгрузка через ТабличныйДокумент 1С

Обращение к ячейкам Excel через COM-соединение (OLE) имеет ряд существенных недостатков: медленная построчная запись, необходимость установленного MS Office, зависимость от разрядности платформы (32-bit / 64-bit) и невозможность стабильной работы на сервере 1С под Linux.

Наиболее надежным и быстрым стандартом платформы 1С является формирование отчета через ТабличныйДокумент с последующим прямым сохранением в формат XLSX.

Разберем по шагам, как реализовать этот подход:

  1. Формируем данные запросом и выводим строки в объект ТабличныйДокумент с использованием областей макета или программного заполнения ячеек.
  2. Вызываем встроенный метод платформы Записать(), передавая перечисление ТипФайлаТабличногоДокумента.XLSX:

ТабДок = Новый ТабличныйДокумент;

// Заполняем ТабДок данными отчета (через макет или напрямую)
// ...

// Сохраняем в файл XLSX штатными средствами платформы
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);

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

← На главную