Как программно сохранить табличный документ 1С в Excel с текстовым форматом ячеек?

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

Часто при программном сохранении прайс-листов или отчетов из 1С в формат XLSX через метод Записать() табличного документа разработчики сталкиваются с неприятной особенностью. При открытии итогового файла Excel присваивает всем ячейкам формат «Общий». Из-за этого строковые значения, похожие на числа, искажаются: пропадают ведущие нули (например, артикул "0001" превращается в "1"), а длинные цифровые коды (штрихкоды, номера счетов) могут преобразоваться в экспоненциальный вид вроде "1.24Е18".

Разберем подробнее, почему возникает эта проблема, и проанализируем несколько способов ее решения — от стандартных средств платформы 1С до более сложных вариантов, подходящих для фоновых заданий.

Способ 1. Использование свойств ячейки в Табличном документе 1С

Самый простой подход, не требующий сторонних средств, заключается в явном указании типа значения для конкретных ячеек перед сохранением. Платформа 1С позволяет задать для области табличного документа свойство СодержитЗначение и явно указать тип Строка. При экспорте в Excel формат ячейки формально останется «Общим», но само значение не будет сконвертировано в число, сохранив ведущие нули и предотвратив появление экспоненциального формата.

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


ТипСтрока = Новый ОписаниеТипов("Строка");
Для НомерСтроки = 1 По ТабличныйДокумент.ВысотаТаблицы Цикл
    Для НомерСтолбца = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
        Ячейка = ТабличныйДокумент.Область(НомерСтроки, НомерСтолбца, НомерСтроки, НомерСтолбца);
        ТекТекст = Ячейка.Текст;
        
        // Анализируем текст: если начинается с "0" или содержит длинное число
        Если ТребуетсяПреобразованиеВСтроку(ТекТекст) Тогда
            Ячейка.СодержитЗначение = Истина;
            Ячейка.ТипЗначения = ТипСтрока;
            Ячейка.Текст = ТекТекст; // Обязательно переприсваиваем текст
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

ТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);

Важное замечание: в некоторых случаях (особенно со сложными артикулами) требуется принудительно переприсвоить свойство Текст после установки типа, иначе выгрузка может сработать некорректно. Однако этот метод не задает жесткий «Текстовый» формат в самом интерфейсе Excel — для некоторых требовательных систем автоматической загрузки у клиентов этого может быть недостаточно.

Способ 2. Установка формата через COM-объект Excel.Application

Если заказчику принципиально важно, чтобы в свойствах ячейки в самом Excel стоял формат «Текстовый», можно воспользоваться COM-соединением. Мы открываем уже сохраненный файл через приложение Excel и меняем формат NumberFormat на @.

Проанализируем пример кода для такой постобработки:


Excel = Новый COMОбъект("Excel.Application");
Excel.WorkBooks.Open(ИмяФайла); 
Excel.Visible = 0;
Excel.Cells.Select();
Excel.Selection.NumberFormat = "@"; // Устанавливаем текстовый формат
Excel.DisplayAlerts = Ложь;

// Сохраняем файл в нужном формате
Если Расширение = "XLSX" Тогда
    Excel.ActiveWorkbook.SaveAs(ИмяФайла, 51); // 51 - xlsx 2007-2013
Иначе
    Excel.ActiveWorkbook.SaveAs(ИмяФайла, 18); // 18 - xls 97-2003
КонецЕсли;

Excel.Application.Quit();
Excel = Неопределено;

Недостатки метода:

  1. Метод работает очень медленно на больших объемах данных.
  2. Для его работы на сервере (или в фоновом задании) должен быть установлен MS Office, что часто запрещено политиками безопасности или невозможно на Linux-серверах.
  3. При зависании COM-объекта в памяти сервера будут копиться «мертвые» процессы EXCEL.EXE.

Способ 3. Прямая модификация структуры XLSX (ZIP + XML)

Так как файл формата XLSX по своей сути является ZIP-архивом с набором XML-документов, мы можем отредактировать этот архив средствами самой платформы 1С. Этот метод идеален для фоновых заданий, не требует установленного Excel и работает предельно быстро.

Разберем по шагам алгоритм действий:

  1. Сохраняем табличный документ стандартным методом в формат XLSX.
  2. С помощью объекта ЧтениеZipФайла распаковываем сохраненный файл во временный каталог на сервере.
  3. Находим файл листа (обычно xl/worksheets/sheet1.xml) и файл стилей (xl/styles.xml).
  4. Используя объекты ЧтениеXML и ЗаписьXML (или ПостроительDOM), модифицируем XML-разметку. Мы можем присвоить нужным ячейкам атрибут текстового типа (t="str") или добавить новый текстовый стиль в файл стилей.
  5. Упаковываем модифицированные файлы обратно в архив с помощью объекта ЗаписьZipФайла и меняем расширение на .xlsx.

Данный подход является самым технически грамотным для высоконагруженных серверных систем.

Способ 4. Формирование файла в формате XML Spreadsheet 2003

Если клиенту важен не сам контейнер XLSX, а факт успешного импорта данных в сторонние системы (без потери нулей), можно генерировать отчет в текстовом формате Microsoft XML Spreadsheet (сохраняется с расширением .xml или .xls).

Создавая файл напрямую через конкатенацию строк или ЗаписьXML, мы получаем полный контроль над форматированием. В таком файле можно жестко прописать тег:

<NumberFormat ss:Format="@"/>

При открытии такого файла MS Excel гарантированно распознает колонку как текстовую, и никакие числа не будут усечены.

Способ 5. Использование ADO

Еще один серверный вариант, не требующий установки самого пакета Office. Достаточно установить бесплатный провайдер Access Database Engine. Подключившись к файлу Excel через объект ADODB.Connection, можно создавать листы как таблицы базы данных (CREATE TABLE) и вставлять строки через INSERT INTO.

При выполнении SQL-запроса на создание таблицы мы можем явно определить тип проблемных колонок как VARCHAR или TEXT. При записи в такие колонки Excel не будет применять автоматическую конвертацию в числа, сохранив данные в исходном виде.

Резюме

Выбор конкретного решения зависит от архитектуры вашей базы. Если вы формируете прайсы небольшого объема интерактивно на клиенте, может быть достаточно COM-объекта. Если же рассылка отчетов работает на сервере через регламентные задания РегламентныеЗадания, лучше использовать метод корректировки свойств СодержитЗначение в самом ТабличныйДокумент или применять продвинутые подходы с модификацией структуры XLSX-архива.

← На главную