Почему при чтении CSV через Excel вместо даты считываются решетки и как это исправить?

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

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

Причина возникновения проблемы: Особенности свойства Text

Проанализируем ситуацию, представленную в коде автора. Для получения данных используется COM-объект Excel и обращение к ячейке через свойство Text:

НоваяСтрока.ДатаОтгрузки = СокрЛП(Excel.Cells(СтрокаЭксель, 4).Text);

Выясним причину такого поведения системы. Свойство Text в объектной модели Microsoft Excel возвращает строковое представление значения ячейки именно в том виде, в котором оно отображается на экране. В Excel существует старое правило: если ширина столбца недостаточна для отображения числового значения или даты в заданном формате, программа заменяет содержимое визуальными символами "#".

Поскольку при программном открытии файла через COM-объект графическая оболочка Excel может инициализироваться с настройками по умолчанию, колонки часто оказываются слишком узкими. В итоге свойство Text честно считывает эти самые решетки вместо реальной даты.

Решение №1: Использование свойства Value или Value2

Самый простой и быстрый способ решить проблему — изменить используемое свойство ячейки. Рассмотрим разницу между ними:

  1. Свойство Value: Возвращает содержимое ячейки с учетом типа данных. Если в ячейке дата, Excel передаст в 1С объект типа Дата (или COM-объект, который 1С преобразует в дату).
  2. Свойство Value2: Работает аналогично Value, но не поддерживает типы данных «Дата» и «Валюта». В Excel даты хранятся как числовые значения (количество дней с начала эпохи). Использование Value2 считается наиболее быстрым и надежным способом при работе с большими массивами данных, так как исключает дополнительные преобразования на стороне COM-сервера.

Исправленный код будет выглядеть следующим образом:


// Вместо .Text используем .Value
НоваяСтрока.ДатаОтгрузки = Excel.Cells(СтрокаЭксель, 4).Value;

Важно помнить: при использовании Value 1С получит полноценный тип Дата, и вам не потребуется использовать дополнительные функции преобразования строк. Если же вы используете Value2, то полученное число нужно будет конвертировать в дату по формуле, учитывающей начало отсчета времени в Excel (30.12.1899).

Решение №2: Программное расширение столбцов (AutoFit)

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


// Раздвигаем четвертый столбец перед чтением данных
Excel.Columns(4).AutoFit();
// Теперь свойство .Text вернет корректную строку
НоваяСтрока.ДатаОтгрузки = СокрЛП(Excel.Cells(СтрокаЭксель, 4).Text);

Этот метод заставляет Excel пересчитать визуальное представление ячеек, после чего символы решетки исчезают, уступая место реальным данным.

Решение №3: Переход на встроенные механизмы чтения CSV (Рекомендуемое)

Рассмотрим более глубокую проблему. Использование COM-объекта Excel.Application для чтения простых текстовых файлов, коими являются файлы CSV, — это крайне ресурсоемкая операция. Каждый запуск процесса excel.exe потребляет значительный объем оперативной памяти и процессорного времени. Более того, на стороне сервера 1С (в клиент-серверном варианте) Microsoft Office может быть не установлен вовсе.

Для эффективной работы с CSV в 1С (начиная с версии 8.3.9) предусмотрен объект ЧтениеCSV. Разберем по шагам, как переписать чтение файла на этот объект:


ПутьКФайлу = "C:\temp\data.csv";
Разделитель = ";"; // Укажите разделитель, используемый в вашем файле

Текст = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);
Чтение = Новый ЧтениеCSV(Текст, Разделитель);

// Пропускаем заголовок, если он есть
Чтение.ПрочитатьСтроку(); 

Пока Истина Цикл
    МассивДанных = Чтение.ПрочитатьСтроку();
    Если МассивДанных = Неопределено Тогда
        Прервать;
    КонецЕсли;
    
    НоваяСтрока = Таблица.Добавить();
    // Предположим, дата во второй колонке (индекс 1)
    // CSV — это текст, поэтому дату нужно преобразовать функцией Дата()
    // или использовать методы парсинга строк
    НоваяСтрока.ДатаОтгрузки = МассивДанных[3]; // Обращение по индексу колонки
КонецЦикла;

Чтение.Закрыть();

Преимущества этого метода:

Решение №4: Чтение через Табличный документ

Если файл имеет сложную структуру или вы привыкли работать с визуальными таблицами 1С, можно воспользоваться методом Прочитать объекта ТабличныйДокумент. Посмотрим на этот пример:


ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);

Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
    НоваяСтрока = Таблица.Добавить();
    // Получаем именно значение ячейки
    НоваяСтрока.ДатаОтгрузки = ТабДок.Область(НомерСтроки, 4).Текст;
КонецЦикла;

Этот способ также значительно легче использования COM-объекта и позволяет избежать проблем с форматированием, если указать правильный параметр СпособЧтенияЗначенийТабличногоДокумента.

Важные замечания по формату CSV

При работе с CSV через Excel важно учитывать следующие нюансы, которые могут исказить ваши данные:

Подведем итог: если вам нужно быстрое исправление в существующем коде — замените .Text на .Value. Если же вы проектируете надежную систему импорта данных — откажитесь от использования Excel в пользу объекта ЧтениеCSV.

← На главную