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

Программист 1С v8.3 (Управляемые формы)
← К списку

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

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

В чем заключается проблема: Неразрывный пробел и другие разделители

Проанализируем ситуацию подробнее. Когда мы читаем числовые данные из ячейки Excel, которая отформатирована с разделителями групп разрядов (например, "1 000 000"), 1С может прочитать это значение как строку, содержащую особый символ – неразрывный пробел. Этот символ имеет код 160 и может быть представлен в 1С как Символ(160) или Символы.НПП.

Попытка напрямую преобразовать такую строку, как "1 000", в число с помощью функции Число(), приведет к ошибке, поскольку для 1С это уже не является чистым числовым представлением. Эта особенность 1С, использующей неразрывный пробел в качестве разделителя по умолчанию, порой доставляет немало хлопот разработчикам.

Важно отметить, что разделитель групп разрядов может быть настроен индивидуально для каждого пользователя в параметрах программы 1С (через «Настройки» -> «Параметры» -> «Общие» -> «Разделители»). Это означает, что под разными пользователями в одной и той же базе один и тот же код может работать по-разному, если он не учитывает эту особенность.

Решение 1: Прямое удаление неразрывного пробела

Один из самых простых и часто используемых способов — это удаление неразрывного пробела из строки перед ее преобразованием в число. Мы можем использовать функцию СтрЗаменить() для замены всех вхождений неразрывного пробела на пустую строку.

Давайте посмотрим на пример: допустим, мы прочитали значение из Excel в переменную СтрокаИзExcel, и знаем, что там может быть неразрывный пробел.

Шаги по реализации:

  1. Сначала убедимся, что наше значение имеет строковый тип. Если оно уже строка, этот шаг можно пропустить.
  2. Используем функцию СтрЗаменить() для удаления символа.
  3. Преобразуем очищенную строку в число.

Вот как это будет выглядеть в коде:


ПеременнаяИзExcel = "1 234 567"; // Пример строки, прочитанной из Excel
// Или, если значение прочитано как число, но при форматировании в строку получился пробел:
// ЧисловоеЗначение = 1234567;
// ПеременнаяИзExcel = Строка(ЧисловоеЗначение); // Результат может быть "1 234 567"

// Удаляем неразрывный пробел
СтрокаБезРазделителя = СтрЗаменить(ПеременнаяИзExcel, Символ(160), "");

// Теперь можно преобразовать в число
ЧисловоеЗначение = Число(СтрокаБезРазделителя);

Сообщить("Исходная строка: " + ПеременнаяИзExcel);
Сообщить("Строка без разделителя: " + СтрокаБезРазделителя);
Сообщить("Преобразованное число: " + ЧисловоеЗначение);

Вместо Символ(160) мы также можем использовать константу Символы.НПП, что делает код более читаемым:


СтрокаБезРазделителя = СтрЗаменить(ПеременнаяИзExcel, Символы.НПП, "");

Этот подход доказал свою эффективность и был подтвержден пользователями форума как рабочее решение.

Решение 2: Использование функции Формат() для контроля вывода

Если мы хотим получить строковое представление числа без каких-либо разделителей групп разрядов, или если мы работаем с числом и хотим быть уверенными, что при его строковом представлении не появятся неразрывные пробелы, нам на помощь приходит функция Формат().

Функция Формат() в 1С является мощным инструментом для управления представлением значений различных типов (чисел, дат, булевых) в строковом виде. Для наших целей нас интересует параметр форматной строки ЧГ=0 (Числовая Группировка = 0).

Как это работает:

  1. Если у нас уже есть числовое значение, и мы хотим получить его строковое представление без разделителей, используем Формат() с параметром ЧГ=0.
  2. Если же у нас строка, но мы хотим стандартизировать ее, мы можем сначала попытаться преобразовать ее в число (используя предыдущий метод для очистки, если необходимо), а затем отформатировать это число в строку без разделителей.

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


ИсходноеЧисло = 1234567.89;

// Форматируем число в строку без разделителей групп разрядов
СтрокаБезРазделителей = Формат(ИсходноеЧисло, "ЧГ=0");

Сообщить("Исходное число: " + ИсходноеЧисло);
Сообщить("Строка без разделителей (через Формат): " + СтрокаБезРазделителей);

Результатом будет строка "1234567.89". Обратите внимание, что Формат() с ЧГ=0 предотвращает *появление* разделителей при формировании строки из числа, в то время как СтрЗаменить() *удаляет* их, если они уже присутствуют в исходной строке.

Также можно использовать параметр ЧГ= (пустое значение) для отключения группировки. Параметр ЧРГ (Числовой Разделитель Групп) позволяет задать символ-разделитель групп целой части числа. Если указать ЧРГ='', то разделителем будет символ неразрывного пробела, поэтому ЧГ=0 является более надежным вариантом для полного удаления разделителей.

Дополнительные рекомендации и лучшие практики

Чтобы ваш код был максимально надежным и универсальным, рассмотрим несколько важных моментов:

  1. Региональные настройки информационной базы:

    Настройки 1С влияют на то, как числа отображаются и интерпретируются. В конфигураторе (раздел Администрирование -> Региональные установки информационной базы) можно найти свойства "Разделитель дробной части" и "Разделитель групп". Если вы меняете эти настройки, учитывайте, что это повлияет на всю базу. При импорте из Excel всегда лучше явно управлять форматом, не полагаясь только на общие настройки.

  2. Обработка ошибок при преобразовании:

    При работе с внешними данными всегда есть риск, что строка не будет корректным числом, даже после удаления разделителей. Чтобы избежать аварийного завершения работы программы, всегда используйте конструкцию Попытка...Исключение при преобразовании строк в числа.

    Пример:

    
    СтрокаДляПреобразования = "1234567"; // Или "abc"
    
    Попытка
        ЧисловоеЗначение = Число(СтрокаДляПреобразования);
        Сообщить("Значение успешно преобразовано: " + ЧисловоеЗначение);
    Исключение
        Сообщить("Ошибка преобразования строки '" + СтрокаДляПреобразования + "' в число. " + ОписаниеОшибки());
        ЧисловоеЗначение = 0; // Устанавливаем значение по умолчанию или пропускаем
    КонецПопытки;
    
  3. Разделитель дробной части:

    Помимо неразрывного пробела, проблемой может быть и разделитель дробной части. В разных региональных настройках и в разных файлах Excel в качестве разделителя может использоваться как точка, так и запятая. В русских настройках 1С по умолчанию ожидается запятая. Если в Excel используется точка, возможно, потребуется дополнительная замена СтрЗаменить(СтрокаИзExcel, ".", ",") перед преобразованием в число.

  4. Чтение больших файлов Excel:

    Хотя основная проблема этой страницы — преобразование чисел, при работе с большими XLS-файлами мы также должны помнить о производительности. Использование COMОбъект("Excel.Application") может быть медленным и ресурсоемким. Для очень больших объемов данных рассмотрите альтернативные методы, такие как чтение табличного документа по ячейкам, использование построителя запросов или технологии ADO, а также специализированные методы для XLSX-файлов средствами 1С (например, ПостроительDOM или ЧтениеXML), которые могут быть более эффективными.

Мы рассмотрели основные подходы к решению проблемы некорректного чтения числовых данных из Excel в 1С, вызванной разделителями групп разрядов. Используя функции СтрЗаменить() для удаления неразрывного пробела или Формат() с параметром ЧГ=0 для контроля вывода, а также применяя общие рекомендации по обработке ошибок, мы сможем сделать наш код надежным и устойчивым к различным форматам исходных данных.

← К списку