При разработке отчетов в 1С:Предприятие 8.2 и 8.3 на обычных формах часто возникает задача выгрузки сформированного результата в формат Excel. Начинающие разработчики нередко сталкиваются с ситуацией, когда файл вроде бы записывается на диск с расширением .xls или .xlsx, но при попытке его открыть Microsoft Excel выдает предупреждение: "Файл поврежден или имеет неверное расширение". Разберем подробно, почему это происходит и как правильно реализовать программное сохранение табличного документа.
Рассмотрим ситуацию, с которой столкнулся автор темы. Программный код выполняет запрос, заполняет макет данными и выводит их в объект ТабличныйДокумент. Однако при вызове метода Записать() указывается только путь к файлу с расширением .xlsx, но не указывается формат самого документа. В системе 1С по умолчанию метод Записать() сохраняет данные во внутреннем формате .mxl. Если вы просто переименуете mxl-файл в xlsx, Excel не сможет его распознать, так как внутренняя структура файла осталась прежней. Чтобы решить эту задачу, нам необходимо явно указать платформе, в какой формат нужно конвертировать данные.
Для начала проанализируем базовый код формирования отчета. Чтобы наш ТабличныйДокумент был доступен для сохранения в другой процедуре, он должен быть объявлен как реквизит формы или передан как параметр. Посмотрим на правильную реализацию формирования документа:
Процедура ПолучитьОтчетНажатие(Элемент)
Макет = ПолучитьМакет("МакетТаблицы");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗначенияСвойствТоварныхКатегорий.Номенклатура.Наименование,
| ЗначенияСвойствТоварныхКатегорий.Свойство.Код,
| ЗначенияСвойствТоварныхКатегорий.Значение
|ИЗ
| РегистрСведений.ЗначенияСвойствТоварныхКатегорий КАК ЗначенияСвойствТоварныхКатегорий
|ГДЕ
| ЗначенияСвойствТоварныхКатегорий.Номенклатура.ПометкаУдаления = ЛОЖЬ
| И ЗначенияСвойствТоварныхКатегорий.Свойство.Код = ""00050""
| И ЗначенияСвойствТоварныхКатегорий.Значение = ИСТИНА";
РезультатЗапроса = Запрос.Выполнить();
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы");
ОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("Детали");
// Очищаем и подготавливаем табличный документ
ТабДок.Очистить();
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьШапкаТаблицы);
// Включаем группировки, если они предусмотрены в отчете
ТабДок.НачатьАвтогруппировкуСтрок();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ОбластьДетальныхЗаписей.Параметры.Заполнить(ВыборкаДетальныеЗаписи);
ТабДок.Вывести(ОбластьДетальныхЗаписей, ВыборкаДетальныеЗаписи.Уровень());
КонецЦикла;
ТабДок.ЗакончитьАвтогруппировкуСтрок();
КонецПроцедуры
Теперь перейдем к самому важному этапу — процедуре сохранения. Разберем, как использовать ДиалогВыбораФайла и метод Записать() с правильными параметрами.
Выясним причину ошибки: методу Записать() вторым параметром нужно передать значение из перечисления ТипФайлаТабличногоДокумента. Если мы хотим получить современный формат Excel, используем ТипФайлаТабличногоДокумента.XLSX. Рассмотрим исправленный код:
Процедура СохранитьНажатие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отключаем стандартные действия, если это необходимо
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.ПолноеИмяФайла = "МойОтчет.xlsx";
Диалог.Заголовок = "Выберите путь для сохранения отчета";
Диалог.Фильтр = "Файлы Excel (*.xlsx)|*.xlsx|Все файлы (*.*)|*.*";
Если Диалог.Выбрать() Тогда
Попытка
// Явно указываем тип файла вторым параметром
ТабДок.Записать(Диалог.ПолноеИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
Сообщить("Файл успешно сохранен в: " + Диалог.ПолноеИмяФайла);
Исключение
Сообщить("Ошибка при сохранении файла! Возможно, файл открыт в другой программе.");
Сообщить(ОписаниеОшибки());
КонецПопытки;
Иначе
Сообщить("Сохранение отменено пользователем.");
КонецЕсли;
КонецПроцедуры
Проанализируем дополнительные аспекты, которые помогут сделать выгрузку более профессиональной и надежной:
XLS (Excel 97-2003) ограничен 65 536 строками. Если ваш отчет потенциально может быть больше, всегда используйте XLSX, который поддерживает более миллиона строк.ТабДок.ОтображатьСетку = Ложь;.ТабДок.АвтоМасштаб = Истина;. Это заставит Excel подогнать ширину отчета под лист бумаги.НачатьАвтогруппировкуСтрок() и Вывести(Область, Уровень), то при сохранении в XLSX платформа автоматически создаст в Excel аналогичную структуру группировок (сворачиваемые строки).ДиалогВыбораФайла работает только на клиенте, а ТабличныйДокумент обычно формируется на сервере. В этом случае схему работы нужно изменить: сформировать документ на сервере, сохранить его во временный файл через ПолучитьИмяВременногоФайла("xlsx"), вернуть путь на клиент и там уже предложить пользователю сохранить файл в выбранное место.При выгрузке данных в Excel полезно также проверять наличие установленных прав на запись в выбранный каталог. Использование блока Попытка...Исключение при вызове метода Записать() является обязательным, так как файл может быть заблокирован антивирусом или открыт самим пользователем в приложении Excel в момент сохранения.
Подведем итог: для корректного сохранения табличного документа 1С в Excel достаточно правильно указать расширение в диалоге выбора файла и обязательно передать соответствующий тип файла в метод Записать(). Это гарантирует, что структура данных будет правильно конвертирована платформой, и пользователь не увидит ошибок при открытии документа.