Почему при загрузке из Excel в 1С искажаются числовые данные и как это исправить?

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

При интеграции 1С с электронными таблицами Microsoft Excel разработчики нередко сталкиваются с ситуацией, когда текстовые поля переносятся корректно, а числовые значения (цены, количества, суммы) считываются с ошибками: дробная часть отсекается, числа становятся неожиданно маленькими либо вовсе превращаются в ноль. Разберем детально, почему это происходит при работе через COM-объект, проанализируем типичные ошибки в исходном коде и рассмотрим правильные варианты загрузки данных.

Анализ проблемы: почему искажаются числа

Рассмотрим типовой фрагмент кода, который часто приводит к ошибкам при загрузке:


Excel = Новый COMОбъект("Excel.Application");
Excel.Workbooks.Open("c:\nomen.xls");
Книга = Excel.ActiveWorkbook;
строкадокумента.Цена = СокрЛП((Excel.Cells(Строка, 3).Value));

В этой конструкции кроется сразу несколько критических уязвимостей, приводящих к порче числовых данных:

  1. Неявное строковое преобразование с помощью СокрЛП: функция СокрЛП ожидает на входе строку и возвращает строку. Когда числовое значение из свойства Value оборачивается в СокрЛП, а затем присваивается числовой колонке строкадокумента.Цена, платформа 1С выполняет обратное неявное преобразование строки в число. Если в операционной системе разделителем разрядов выступает пробел, а десятичным разделителем является запятая, 1С преобразует строку только до первого недопустимого символа. В результате строка вида "1 250" превращается в 1.
  2. Неразрывные пробелы и разделители групп разрядов: часто числа в Excel форматируются с разделением групп разрядов. При чтении текста ячейки в строку попадает не обычный пробел, а неразрывный пробел (Символы.НПП), который стандартная функция СокрЛП не удаляет.
  3. Специфика свойства Value в COM-модели Excel: свойство Value преобразует финансовые форматы в COM-тип Currency, который округляет значение до четырех знаков после запятой и зависит от региональных настроек Windows.
  4. Отсутствие указания конкретного листа: вызов Excel.Cells(...) обращается к текущему активному листу глобального приложения. Если при открытии файла активным оказался другой лист или пользователь переключил окно, считывание произойдет из непредвиденной ячейки.

Способ 1. Прямое присвоение числового значения без строковых функций

Если ячейка в Excel действительно содержит числовой формат, то свойство ячейки уже возвращает значение числового типа. Применение функций СокрЛП к числу избыточно и вредно. Посмотрим на корректный вариант считывания:


Лист = Книга.Sheets(1);
строкадокумента.Цена = Лист.Cells(Строка, 3).Value;

Чтобы избежать искажения вещественных чисел и валютных форматов, на уровне COM-объекта Excel рекомендуется использовать свойство Value2 вместо Value. Свойство Value2 возвращает значение базового типа Double без применения регионального форматирования валют:

строкадокумента.Цена = Лист.Cells(Строка, 3).Value2;

Способ 2. Очистка строкового представления от неразрывных пробелов

В некоторых файлах числа хранятся как отформатированный текст либо считываются через свойство Text (которое возвращает именно видимое отображение числа в ячейке). В этом случае перед преобразованием строки в число необходимо обязательно удалить все невидимые разделители групп разрядов, включая неразрывный пробел, и привести десятичный разделитель к системному стандарту.

Разберем по шагам, как обработать такую строку:


Лист = Книга.Sheets(1);
СтроковоеЗначение = Лист.Cells(Строка, 3).Text;

// Удаляем обычные пробелы и неразрывные пробелы (Символы.НПП)
СтроковоеЗначение = СтрЗаменить(СтроковоеЗначение, Символы.НПП, "");
СтроковоеЗначение = СтрЗаменить(СтроковоеЗначение, " ", "");

// Приводим точку к запятой, если в региональных настройках 1С разделителем является запятая
СтроковоеЗначение = СтрЗаменить(СтроковоеЗначение, ".", ",");

// Безопасно преобразуем очищенную строку в число
Попытка
    строкадокумента.Цена = Число(СтроковоеЗначение);
Исключение
    строкадокумента.Цена = 0;
КонецПопытки;

Способ 3. Использование встроенного объекта ТабличныйДокумент (без COM)

Использование COM-объекта Excel.Application имеет существенные недостатки: требуется установленный MS Office на рабочей станции или сервере, возникают конфликты разрядности (32 и 64 бит), а поячеечное чтение выполняется крайне медленно. Платформа 1С:Предприятие позволяет читать файлы Excel напрямую с помощью объекта ТабличныйДокумент.

Рассмотрим, как прочитать файл и получить точные числовые значения без искажений:


ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать("c:\nomen.xls");

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

Использование ТабличныйДокумент гарантирует правильное распознавание встроенных типов данных ячеек и полностью исключает зависимость от установленных в операционной системе офисных пакетов.

← На главную