Почему файлы Excel формата .xls не открываются при программной загрузке в 1С?

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

Часто при разработке механизмов загрузки данных из Excel в 1С разработчики сталкиваются с ситуацией, когда код успешно обрабатывает современные файлы .xlsx, но полностью игнорирует или выдает ошибку при попытке прочитать старые файлы формата .xls. Давайте вместе разберем, почему это происходит и как построить универсальное решение.

Разбор причины ошибки

Основное заблуждение кроется в понимании того, как работает метод ПолучитьИмяВременногоФайла(). Многие полагают, что указание расширения в параметрах этого метода как-то влияет на внутренние механизмы конвертации или распознавания формата файла. Это не так.

Метод ПолучитьИмяВременногоФайла() просто создает в операционной системе путь к файлу с заданным расширением. Если вы принудительно задаете ПолучитьИмяВременногоФайла("xlsx"), система создает пустой файл с расширением .xlsx. Если затем вы пытаетесь записать в него двоичные данные файла формата .xls, содержимое не меняется — внутри остается старый бинарный формат BIFF, а расширение у файла теперь «ложное». Когда 1С пытается прочитать такой файл методом ТабличныйДокумент.Прочитать(), она ожидает структуру XML (для формата .xlsx), но получает бинарные данные, что приводит к ошибке.

Шаг 1: Правильная передача файла с клиента на сервер

Чтобы избежать этой проблемы, необходимо передавать на сервер не просто двоичные данные, но и метаданные файла, в частности — его исходное расширение. На стороне клиента при использовании метода НачатьПомещениеФайлаНаСервер мы можем получить всю необходимую информацию об объекте.

Рассмотрим пример кода на клиенте:


&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
    ОкончаниеПомещения = Новый ОписаниеОповещения("ОбработчикОкончанияПомещения", ЭтотОбъект);
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
    ПараметрыДиалога.Фильтр = "Excel файлы(*.xls;*.xlsx)|*.xls;*.xlsx";
    НачатьПомещениеФайлаНаСервер(ОкончаниеПомещения,,, АдресВХ, ПараметрыДиалога, ЭтотОбъект.УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ОбработчикОкончанияПомещения(ОписаниеПомещенногоФайла, ДополнительныеПараметры) Экспорт
    Если ОписаниеПомещенногоФайла <> Неопределено Тогда
        АдресФайла = ОписаниеПомещенногоФайла.Адрес;
        Расширение = ОписаниеПомещенногоФайла.СсылкаНаФайл.Расширение;
        ПрочитатьДанныеНаСервере(АдресФайла, Расширение);
    КонецЕсли;
КонецПроцедуры

Шаг 2: Корректная обработка на стороне сервера

Теперь, когда расширение корректно передано на сервер, мы не должны жестко прописывать «xlsx» в коде. Мы будем использовать динамическое значение, полученное от пользователя. Это позволит методу ПолучитьИмяВременногоФайла() создавать временный файл с тем же расширением, которое было у исходного документа.

Разберем пример серверной процедуры:


&НаСервере
Процедура ПрочитатьДанныеНаСервере(АдресВХ, Расширение)
    // Генерируем временный файл с оригинальным расширением
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла(Расширение);
    
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХ);
    ДвоичныеДанные.Записать(ИмяВременногоФайла);
    
    ТабДок = Новый ТабличныйДокумент;
    Попытка
        ТабДок.Прочитать(ИмяВременногоФайла);
        // Далее работаем с данными ТабличногоДокумента
    Исключение
        Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Почему это решение является наиболее надежным?

  1. Соответствие форматов: Система всегда работает с файлом, имеющим корректное расширение для своего типа данных.
  2. Гибкость: Если в будущем вы решите поддерживать дополнительные форматы (например, .csv или .ods), код не потребует изменений — он будет просто «подхватывать» нужное расширение.
  3. Отсутствие «костылей»: Нет необходимости использовать перебор вариантов через Попытка...Исключение, так как мы точно знаем, какой файл собираемся открывать.

Мы проанализировали ситуацию и выяснили, что ключ к успеху — это сохранение метаданных файла при передаче в хранилище. Используя ОписаниеПомещенногоФайла.СсылкаНаФайл.Расширение, вы обеспечиваете стабильную работу механизма импорта независимо от версии Excel, в которой был сохранен документ. Теперь вы можете смело применять этот подход в своих разработках!

← На главную