Как прочитать формат ячейки и получить значение с валютой при загрузке Excel через LibreOffice в 1С

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

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

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

Причина проблемы: разница между Value и String

Разберем ситуацию: в ячейке Excel записано число 100, но благодаря денежному формату пользователь видит 100 грн.. При использовании метода getDataArray(), который часто применяется для ускорения загрузки, 1С получает массив чистых значений типа Double. Система LibreOffice Calc разделяет внутреннее содержимое ячейки и её визуальное представление. Для решения задачи нам необходимо обратиться к объектам, которые отвечают за рендеринг текста.

Способ №1: Использование свойства String для получения отображаемого текста

Самый простой способ получить значение вместе с «грн.» или «евро» — это обращение к свойству String каждой конкретной ячейки. В отличие от Value, это свойство возвращает строку именно в том виде, в котором она отображается в интерфейсе Calc.

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


// Вместо пакетного получения данных через Range.getDataArray()
// используем поочередное обращение к ячейкам
Для НомерСтроки = begRow По endRow Цикл
    НовСтрока = локТабЗнач.Добавить();
    Для НомерКолонки = begCol По endCol Цикл
        // Получаем объект конкретной ячейки
        ТекущаяЯчейка = Sheet.getCellByPosition(НомерКолонки, НомерСтроки);
        
        // Читаем именно строковое представление (с валютой, знаками и т.д.)
        ОтображаемыйТекст = ТекущаяЯчейка.getString();
        
        НовСтрока[НомерКолонки] = ОтображаемыйТекст;
    КонецЦикла;
КонецЦикла;

Важно: Обращение к каждой ячейке через COM-соединение работает медленнее, чем получение всего массива данных сразу. Однако это единственный надежный способ «увидеть» текст так, как его видит пользователь.

Способ №2: Анализ числового формата через NumberFormat

Если нам нужно не просто получить строку, а программно понять, что это именно валюта (чтобы, например, разделить число 100 и валюту грн. в разные колонки), мы должны проанализировать идентификатор формата ячейки. Каждая ячейка в LibreOffice имеет свойство NumberFormat.

Рассмотрим алгоритм получения маски формата:

  1. Получим объект всех форматов документа через Document.getNumberFormats().
  2. Для конкретной ячейки узнаем её NumberFormat (это целочисленный индекс).
  3. С помощью метода getByKey() выгрузим структуру формата и проанализируем свойство FormatStr.

Пример кода для реализации этой логики:


// Получаем доступ к библиотеке форматов документа
ВсеФорматы = Document.getNumberFormats();

ТекущаяЯчейка = Sheet.getCellByPosition(0, 10); // Пример для конкретной ячейки
ИндексФормата = ТекущаяЯчейка.NumberFormat;

// Извлекаем настройки формата по индексу
СтруктураФормата = ВсеФорматы.getByKey(ИндексФормата);
МаскаФормата = СтруктураФормата.FormatStr;

// Теперь мы можем проверить, содержится ли в маске обозначение валюты
Если Найти(МаскаФормата, "грн") > 0 Тогда
    Сообщить("Это денежный формат в гривнах");
ИначеЕсли Найти(МаскаФормата, "€") > 0 Тогда
    Сообщить("Это денежный формат в евро");
КонецЕсли;

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

Способ №3: Нативное чтение средствами 1С (без COM и LibreOffice)

Выясним важную техническую деталь: начиная с версии платформы 8.3.6, компания 1С добавила возможность нативного чтения файлов .xls и .xlsx на уровне платформы. Это работает даже на Linux-серверах и не требует установленного офисного пакета. Этот метод часто является самым стабильным и быстрым.

Рассмотрим, как это реализовать через объект ТабличныйДокумент:


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

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

Использование ТабличныйДокумент позволяет избежать проблем с правами доступа к COM-объектам на сервере и значительно упрощает поддержку кода, так как вы перестаете зависеть от версии установленного LibreOffice.

Подведем итоги

Выбор метода зависит от ваших конкретных условий:

Помните, что при работе с форматом .xls (старый бинарный формат) могут возникать специфические ошибки интерпретации спецсимволов, поэтому всегда проверяйте результат загрузки на тестовых данных с различными валютными знаками.

← На главную