Выгрузка ТабличногоДокумента в XLSX кодом: сервер, клиент, поток
Содержание
Чтобы программно сохранить табличный документ 1С в Excel, вызовите у него метод Записать с типом файла ТипФайлаТабличногоДокумента.XLSX: ТабДок.Записать("C:\Выгрузка\Остатки.xlsx", ТипФайлаТабличногоДокумента.XLSX). Excel на компьютере для этого не нужен: файл формирует сама платформа 1С:Предприятие 8.3, в том числе на сервере под Linux.
Вся сложность не в одной строке кода, а вокруг неё. Где физически появится файл — на сервере или у пользователя. Как отдать его в браузер. Почему суммы в Excel легли текстом и не суммируются.
Метод Записать: базовая запись файла Excel
Метод принимает два параметра: путь к файлу и тип файла. Расширение в имени ни на что не влияет — формат задаёт только второй параметр. Если тип не указать, платформа запишет внутренний формат MXL, и Excel такой файл не откроет.
Минимальный пример в серверной процедуре обработки:
&НаСервере
Процедура СохранитьВExcelНаСервере(ПутьКФайлу)
ТабДок = Новый ТабличныйДокумент;
Макет = РеквизитФормыВЗначение("Объект").ПолучитьМакет("Макет");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Дата = Формат(ТекущаяДатаСеанса(), "ДЛФ=D");
ТабДок.Вывести(ОбластьШапка);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
КонецПроцедуры
Если документ уже лежит на форме — например, реквизит Результат в отчёте на СКД, — строить его заново не нужно. Достаточно вызвать Записать у этого реквизита.
Где работает метод
| Где выполняется код | Записать в файл | Что учесть |
|---|---|---|
Сервер (&НаСервере, общий модуль) | ✅ | Путь — на сервере 1С, права — у пользователя службы |
| Тонкий клиент | ✅ | Путь — на компьютере пользователя |
| Веб-клиент | ❌ | Только через временное хранилище и получение файла |
| Фоновое и регламентное задание | ✅ | Только серверные пути, диалогов нет |
Если конфигурация открывается и в тонком клиенте, и в браузере, сразу пишите вариант «сервер → двоичные данные → клиент». Он работает везде, и второй код поддерживать не придётся.
XLS или XLSX: какой тип файла выбрать
У перечисления ТипФайлаТабличногоДокумента для Excel есть несколько значений. На практике выбор сводится к двум.
| Тип | Формат | Предел строк на лист | Предел колонок | Когда брать |
|---|---|---|---|---|
XLSX | Office Open XML (Excel 2007 и новее) | 1 048 576 | 16 384 | По умолчанию для любых новых выгрузок |
XLS | Двоичный формат Excel 97–2003 | 65 536 | 256 | Только если файл читает старая программа, которая не понимает XLSX |
XLS95 | Excel 95 | 16 384 | 256 | Практически не нужен |
ODS | OpenDocument (LibreOffice) | — | — | Когда получатель работает не в Excel |
Главная причина выбрать XLSX — лимит строк. Реестр документов за год легко перевалит за 65 тысяч строк, и в XLS хвост просто не поместится в лист.
📌 Ещё два довода за XLSX:
- 📦 файл в 3–5 раз меньше: внутри это сжатый ZIP-архив с XML;
- 🔤 нет проблем с кодировкой кириллицы в старых просмотрщиках.
Расширение в пути должно совпадать с типом. Файл Отчет.xls, записанный с типом XLSX, Excel откроет с предупреждением «формат файла не соответствует расширению». Пользователь решит, что файл повреждён.
Подготовка табличного документа к сохранению в Excel
Сохранить файл
— полдела. Чтобы получатель мог с ним работать, документ готовят ещё до вызова Записать.
Числа, а не текст
Самая частая жалоба: суммы в Excel выровнены по левому краю, СУММ по колонке даёт ноль. Причина — в ячейку попала строка. Так бывает, если параметр макета заполнили уже отформатированным значением, например Формат(Сумма, "ЧДЦ=2").
Чтобы в Excel ушло число, ячейка должна содержать значение, а не текст:
Область = ТабДок.Область(НомерСтроки, 5, НомерСтроки, 5);
Область.СодержитЗначение = Истина;
Область.ТипЗначения = Новый ОписаниеТипов("Число");
Область.Значение = 15340.50;
Область.Формат = "ЧДЦ=2";
В макете то же самое настраивается в свойствах ячейки: флажок «Содержит значение», тип значения «Число» и формат. Параметр при этом заполняют числом, без Формат().
Что ещё проверить перед записью
- 📏 Ширина колонок. Задайте
ШиринаКолонкиу колонок с длинными наименованиями, иначе текст обрежется по границе ячейки. - 🔒 Защита. Свойство
Защитаи флагТолькоПросмотротносятся к работе в 1С; не рассчитывайте, что они превратятся в защиту листа Excel. - 🧹 Пустые строки шаблона. Если вывели область «Итого» до цикла, а потом удалили, проверьте, что лишние строки не остались внизу листа.
- 🔢 Длинные коды. ИНН, штрихкоды и номера счетов выводите как текст. Иначе Excel покажет штрихкод
4601234567890как4,60123E+12.
Для отчёта на СКД ничего из этого делать вручную не нужно: компоновщик выводит числовые поля как значения, и после Записать они в Excel остаются числами.
Пути и временные файлы при выгрузке
Строка ТабДок.Записать("C:\Выгрузка\...") в серверной процедуре создаёт файл на сервере 1С, а не на компьютере пользователя. В файловой базе это часто один и тот же компьютер, поэтому ошибку замечают только после перехода на клиент-серверный вариант.
Временный файл на сервере
Если файл нужен только как промежуточный шаг — например, чтобы получить двоичные данные или приложить к письму, — пишите его во временный каталог:
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ТабДок.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLSX);
ДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
ЗаписьЖурналаРегистрации("Выгрузка в Excel",
УровеньЖурналаРегистрации.Предупреждение, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
ПолучитьИмяВременногоФайла только придумывает уникальное имя во временном каталоге, файл не создаёт. Удаление — ваша обязанность. Без УдалитьФайлы каталог Temp сервера за полгода регулярных выгрузок разрастается на гигабайты.
Постоянный каталог на сервере
Для регламентной выгрузки в общую папку используйте сетевой путь вида \\fileserver\Обмен\Остатки.xlsx, а не букву диска. Буква подключённого диска видна только в сеансе пользователя Windows, а служба сервера 1С работает под своей учётной записью и такого диска не видит.
Правила для каталога:
- Дайте учётной записи службы сервера 1С (часто это
USR1CV8) права на запись в папку. - Проверьте существование каталога через
Новый Файл(Путь).Существует()и создайте его функциейСоздатьКаталог, если нужно. - Добавляйте в имя файла дату и время:
"Остатки_" + Формат(ТекущаяДатаСеанса(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx". Так новая выгрузка не упрётся в файл, который кто-то держит открытым.
Двоичные данные: выгрузка без файла и передача пользователю
Чтобы отдать Excel пользователю, правильная схема выглядит так: на сервере получить двоичные данные, положить их во временное хранилище, на клиенте сохранить файл.
Шаг 1. Двоичные данные на сервере
В актуальных версиях платформы 8.3 метод Записать принимает не только имя файла, но и поток. Тогда временный файл на диске вообще не нужен:
&НаСервере
Функция ПодготовитьФайлExcel()
ТабДок = СформироватьТабличныйДокумент();
Поток = Новый ПотокВПамяти;
ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.XLSX);
ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
КонецФункции
Если платформа старая и запись в поток не поддерживается, используйте вариант с временным файлом из предыдущего раздела. Результат тот же — объект ДвоичныеДанные.
УникальныйИдентификатор формы в ПоместитьВоВременноеХранилище привязывает данные к форме: хранилище очистится, когда форму закроют.
Шаг 2. Сохранение на клиенте
В конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11 и большинство отраслевых) есть готовая процедура, которая сама покажет диалог и работает в веб-клиенте:
&НаКлиенте
Процедура ВыгрузитьВExcel(Команда)
Адрес = ПодготовитьФайлExcel();
ФайловаяСистемаКлиент.СохранитьФайл(Неопределено, Адрес, "Остатки.xlsx");
КонецПроцедуры
Без БСП используйте асинхронное получение файлов платформы — НачатьПолучениеФайлов с описанием передаваемого файла. Синхронный ПолучитьФайл с диалогом сработает только там, где разрешены модальные вызовы, а в современных конфигурациях режим модальности обычно выключен.
Excel во вложении письма или в архиве
Те же двоичные данные пригодятся без клиента вообще:
- 📧 добавить во вложения
ИнтернетПочтовоеСообщениеи отправить отчёт по расписанию; - 🗂 положить во вложения справочника файлов;
- 🗜 упаковать несколько отчётов в один архив через
ЗаписьZipФайла: записать каждый табличный документ во временный файл, добавить его методомДобавить, затем вызватьЗаписатьу архива.
Сравнение способов: Записать или COM-объект Excel
Иногда предлагают формировать Excel через Новый COMОбъект("Excel.Application") и заполнять ячейки по одной. Для выгрузки табличного документа это почти всегда хуже.
| Способ | Нужен Excel | Linux-сервер | Скорость на 10 000 строк | Когда оправдан |
|---|---|---|---|---|
ТабличныйДокумент.Записать | Нет | Да | Секунды | Обычная выгрузка отчёта или печатной формы |
COM Excel.Application | Да, на машине, где выполняется код | Нет | Минуты | Нужны формулы, сводные таблицы, макросы в готовом файле |
| Запись в поток + почта/хранилище | Нет | Да | Секунды | Регламентные рассылки, веб-клиент |
COM-объект на сервере 1С вдобавок требует лицензии Office на сервере и регулярно оставляет в памяти зависшие процессы EXCEL.EXE. Если формулы всё же нужны, сначала сохраните файл через Записать, а затем откройте его через COM только для доработки.
Ошибки при записи файла и как их перехватить
Вызов Записать оборачивайте в Попытка … Исключение. Иначе одна занятая папка обрушит всё регламентное задание, и пользователь увидит системное окно без подсказки, что делать.
Попытка
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Исключение
ТекстОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("Выгрузка в Excel",
УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение СтрШаблон(
"Не удалось сохранить файл %1. Проверьте, что он не открыт в Excel и папка доступна.",
ПутьКФайлу);
КонецПопытки;
Пользователю — короткое понятное сообщение, в журнал регистрации — полный текст с номером строки модуля. Так администратор найдёт причину, не воспроизводя ошибку.
Большие документы
На табличном документе в несколько сотен тысяч строк запись идёт долго и съедает память рабочего процесса. Для таких выгрузок:
- Запускайте формирование в фоновом задании, чтобы не блокировать интерфейс.
- Разбивайте выгрузку на несколько файлов — например, по месяцам или организациям.
- Не держите на форме одновременно табличный документ и его двоичные данные: после записи присвойте переменной с документом
Неопределено.