В практике интеграции 1С со сторонними системами часто встречается неприятная ситуация: файл формата XLSX, выгруженный с сайта или из другой программы, прекрасно открывается в Microsoft Excel, но при попытке прочитать его программно в 1С (через ТабличныйДокумент.Прочитать()) или просто открыв через меню "Файл — Открыть", мы видим абсолютно пустые ячейки. При этом никаких ошибок не возникает, а простое пересохранение файла вручную в самом Excel магическим образом решает проблему. Разберем подробно, почему так происходит и как автоматизировать процесс "исправления" таких файлов, особенно если сервер 1С работает под управлением Linux.
Проанализируем структуру XLSX. Этот формат представляет собой ZIP-архив, внутри которого находятся XML-файлы с данными и описанием структуры. Проблема чаще всего кроется в том, как именно формируется этот архив сторонними библиотеками (например, популярной библиотекой Excelize на языке Go).
Выясним основные технические причины "пустого" открытия:
sharedStrings.xml, а в ячейках стоят индексы. Второй (Inline Strings) — когда текст пишется прямо в описании листа. Внутренний парсер 1С во многих релизах настроен на работу преимущественно с Shared Strings. Если библиотека-генератор использует Inline Strings для оптимизации скорости, 1С может просто проигнорировать эти данные.dimension, указывающий на диапазон заполненных ячеек (например, A1:E10). Некоторые генераторы ошибочно ставят там A1:A1 или вовсе пропускают его. Excel при открытии игнорирует этот тег и сканирует файл целиком, а 1С доверяет ему и, видя пустой диапазон, прекращает чтение.Если ваш сервер 1С или клиентское рабочее место работают под управлением ОС Windows, самым простым и надежным способом будет программное пересохранение файла. Это заставит движок Microsoft Excel привести структуру файла к стандартному виду, который 1С понимает без проблем.
Рассмотрим пример кода для обработки файла перед загрузкой:
// Функция исправляет структуру XLSX файла через COM
Функция ИсправитьФайлЭксель(ПутьКФайлу)
Попытка
Эксель = Новый COMОбъект("Excel.Application");
Эксель.Visible = Ложь;
Эксель.DisplayAlerts = Ложь;
Книга = Эксель.Workbooks.Open(ПутьКФайлу);
// Пересохраняем в том же формате, Excel сам пересоберет XML-структуру
Книга.Save();
Книга.Close();
Эксель.Quit();
Возврат Истина;
Исключение
Сообщить("Ошибка при вызове Excel: " + ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
После выполнения этой процедуры метод ТабличныйДокумент.Прочитать() отработает корректно и данные появятся в 1С. Однако помните, что на стороне сервера 1С должен быть установлен Microsoft Excel, и у пользователя, под которым запущен поток сервера, должны быть права на запуск COM-объектов.
Проанализируем ситуацию, когда сервер 1С работает на Linux. Использовать COM-объекты здесь невозможно. В этом случае мы можем воспользоваться консольными возможностями LibreOffice, который часто устанавливается на Linux-серверах как замена MS Office.
Разберем по шагам, как выполнить конвертацию "на лету":
libreoffice.--headless для запуска конвертации без графического интерфейса.Пример кода на стороне сервера 1С:
Процедура ИсправитьФайлНаLinux(ПутьКФайлу)
// Формируем команду для конвертации файла самого в себя
// libreoffice --headless --convert-to xlsx --outdir /путь/к/папке /путь/к/файлу.xlsx
КаталогФайла = Файл.Путь; // Получаем путь к папке
ИмяФайла = ПутьКФайлу;
КомандаСистемы = "libreoffice --headless --convert-to xlsx --outdir " + КаталогФайла + " " + ИмяФайла;
// Запускаем приложение и ждем завершения
ЗапуститьПриложение(КомандаСистемы, , Истина);
КонецПроцедуры
Этот метод полностью имитирует ручное пересохранение. LibreOffice пересоберет структуру ZIP-архива и корректно заполнит таблицу общих строк (Shared Strings), после чего 1С сможет прочитать данные.
Если мы не хотим зависеть от установленного офисного ПО, мы можем рассмотреть вариант прямого парсинга данных. Поскольку XLSX — это архив, мы можем распаковать его средствами 1С и прочитать нужные данные напрямую из XML-файлов листов.
Посмотрим на пример логики работы с объектом ЧтениеZipФайла:
// Пример распаковки и чтения данных напрямую
Архив = Новый ЧтениеZipФайла(ПутьКФайлу);
КаталогРаспаковки = КаталогВременныхФайлов() + "excel_data\";
Архив.ИзвлечьВсе(КаталогРаспаковки, РежимВосстановленияПутейФайловZIP.Восстанавливать);
Архив.Закрыть();
// Основные данные листа обычно лежат здесь:
ПутьКXML = КаталогРаспаковки + "xl/worksheets/sheet1.xml";
// Далее используем ЧтениеXML для обхода узлов
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКXML);
Пока ЧтениеXML.Прочитать() Цикл
// Здесь мы можем вручную выцеплять теги <v> (значение) или <t> (текст)
// Даже если они записаны как Inline Strings (<is><t>текст</t></is>)
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "t" Тогда
Сообщить("Найдено значение: " + ЧтениеXML.ПрочитатьСодержимое());
КонецЕсли;
КонецЦикла;
ЧтениеXML.Закрыть();
Важный нюанс: Этот способ требует написания собственного парсера, который будет сопоставлять индексы строк и колонок, но зато он является самым быстрым и не зависит от операционной системы или установленного стороннего софта.
Выяснив причину проблемы (нестандартная генерация файлов библиотеками типа Excelize), мы можем выбрать наиболее подходящую стратегию:
Excel.Application.LibreOffice в headless-режиме.ЧтениеXML, так как это избавит от необходимости запускать тяжелые внешние приложения.Совет: Всегда проверяйте исходные файлы на наличие тега dimension и формат хранения строк. Это поможет вам заранее спрогнозировать, возникнут ли проблемы при загрузке данных в 1С.