При выгрузке отчетов и печатных форм из 1С в форматы Microsoft Excel разработчики часто сталкиваются со странным поведением системы. В режиме предварительного просмотра в 1С (при вызове метода Показать()) табличный документ выглядит идеально, но после сохранения на диск и открытия в Excel начинается «мистика»: пропадает часть строк, а сам Excel ругается на то, что файл поврежден или заблокирован.
В этой статье мы подробно разберем, почему так происходит, проанализируем внутренние ограничения форматов XLS и XLSX, выясним роль версии платформы 1С и напишем правильный код для гарантированного сохранения тяжелых табличных документов.
Обычно ситуация развивается по следующему сценарию. Программист формирует отчет программно, заполняя ТабличныйДокумент вручную. После этого выполняется стандартный код сохранения:
ИмяФайла = ПолучитьИмяВременногоФайла("xls");
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLS97);
При открытии файла в MS Excel пользователь видит предупреждение: "Файл поврежден, так как его расширение не соответствует формату" или предложение восстановить содержимое книги. После согласия на восстановление открывается таблица, в которой визуально всё в порядке, но при детальном анализе обнаруживается, что исчезла ровно половина данных (или всё, что шло после определенной строки).
Рассмотрим две главные технические причины такого поведения.
Главная причина «исчезновения» строк — это фундаментальные ограничения самого формата, разработанного Microsoft еще в прошлом веке:
XLS и XLS97 (двоичный формат BIFF8) существует жесткий лимит на размер одного листа книги: максимум 65 536 строк и 256 колонок.Записать() с параметром ТипФайлаТабличногоДокумента.XLS97 (или просто XLS) движок платформы запишет только первые 65 536 строк. Остальные данные будут просто отброшены.В современном формате XLSX (который основан на XML-структурах и упакован в ZIP-архив) лимит увеличен до 1 048 576 строк и 16 384 колонок на один лист. Переход на этот формат мгновенно решает проблему усечения данных.
Почему же Excel сообщает о повреждении файла, даже если количество строк не превышает лимит?
Начиная с версии Microsoft Office 2010, корпорация Microsoft внедрила строгие механизмы безопасности. Функция Extension Hardening проверяет структуру открываемого файла на соответствие его расширению. Платформа 1С использует собственный генератор файлов (движок Moxel) для сборки бинарных XLS-файлов. Если в отчете присутствуют сложные элементы оформления, Excel расценивает структуру файла как некорректную:
Бинарный конвертер 1С для формата XLS97 не всегда может корректно упаковать эти элементы по спецификациям Microsoft. В результате Excel видит логические несоответствия и заявляет о потенциальной угрозе безопасности или повреждении структуры. Формат XLSX устроен прозрачнее, и 1С генерирует его структуру гораздо чище, что исключает появление подобных предупреждений.
Существует распространенное заблуждение, что для сохранения файлов в формате Excel на компьютере (или на сервере, если код выполняется в фоновом задании) обязательно должен быть установлен сам Microsoft Office. Проанализируем, как обстоят дела на самом деле:
ТабДок.Записать() работает автономно. Платформе 1С не требуются сторонние библиотеки или установленный Excel, чтобы сформировать бинарный XLS или упаковать XML-структуру XLSX.XLSX без использования COM-объектов появился в платформе 1С начиная с версии 8.3.6. Если вы работаете на устаревших версиях платформы (например, 8.2 или ранних релизах 8.3), метод Записать() с типом XLSX может отсутствовать или работать некорректно.Новый COMОбъект("Excel.Application") для программного формирования отчетов. При таком подходе **наличие лицензионного MS Excel на машине, где выполняется код, строго обязательно**, так как фактически управление передается внешнему приложению через OLE/COM. Это медленный, нестабильный метод, который часто приводит к зависанию процессов на сервере.Разберем по шагам правильный алгоритм сохранения табличного документа. Мы добавим проверку количества строк и колонки, а также предусмотрим обработку возможных ошибок.
Посмотрим на пример кода, который гарантирует корректную выгрузку отчета:
Процедура СохранитьТабличныйДокументВExcel(ТабДок, ПутьКФайлу) Экспорт
// Проверяем количество строк в документе
КоличествоСтрок = ТабДок.ВысотаТаблицы;
КоличествоКолонок = ТабДок.ШиринаТаблицы;
// Выясняем, какой формат использовать в зависимости от объема данных
Если КоличествоСтрок > 65535 Или КоличествоКолонок > 255 Тогда
// Для больших таблиц используем только XLSX
ТипСохранения = ТипФайлаТабличногоДокумента.XLSX;
РасширениеФайла = ".xlsx";
Иначе
// Если таблица небольшая, можно использовать XLSX по умолчанию для безопасности
ТипСохранения = ТипФайлаТабличногоДокумента.XLSX;
РасширениеФайла = ".xlsx";
КонецЕсли;
// Скорректируем имя файла, если у него неверное расширение
Если Не Прав(НРег(ПутьКФайлу), 5) = ".xlsx" И Не Прав(НРег(ПутьКФайлу), 4) = ".xls" Тогда
ПолныйПуть = ПутьКФайлу + РасширениеФайла;
Иначе
ПолныйПуть = ПутьКФайлу;
КонецЕсли;
Попытка
// Записываем табличный документ средствами платформы
ТабДок.Записать(ПолныйПуть, ТипСохранения);
Сообщить("Файл успешно сохранен по пути: " + ПолныйПуть, СтатусСообщения.Информация);
Исключение
ВызватьИсключение "Не удалось сохранить файл Excel. Причина: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Если в силу обстоятельств вы вынуждены работать на платформе ниже версии 8.3.6 (где нет штатной поддержки `XLSX`), но вам жизненно необходимо выгружать документы объемом более 65 тысяч строк, рассмотрите следующие альтернативные варианты:
Для создания отказоустойчивых систем интеграции 1С и Excel придерживайтесь простых правил:
ТипФайлаТабличногоДокумента.XLSX в качестве стандарта разработки по умолчанию.ТабДок.Записать() работает быстрее в десятки раз, не требует лицензий Microsoft Office на сервере и не оставляет «зависших» процессов в диспетчере задач.