При автоматизации загрузки данных из внешних файлов программисты 1С часто сталкиваются с ситуацией, когда при чтении колонки с датами из файла CSV или Excel программный код возвращает строку из символов решетки "##########". Это происходит несмотря на то, что при визуальном открытии файла данные выглядят корректно. Разберем подробно, почему возникает эта ошибка, как ее быстро исправить и какие альтернативные (более эффективные) методы чтения данных существуют в платформе 1С.
Проанализируем ситуацию, представленную в коде автора. Для получения данных используется COM-объект Excel и обращение к ячейке через свойство Text:
НоваяСтрока.ДатаОтгрузки = СокрЛП(Excel.Cells(СтрокаЭксель, 4).Text);
Выясним причину такого поведения системы. Свойство Text в объектной модели Microsoft Excel возвращает строковое представление значения ячейки именно в том виде, в котором оно отображается на экране. В Excel существует старое правило: если ширина столбца недостаточна для отображения числового значения или даты в заданном формате, программа заменяет содержимое визуальными символами "#".
Поскольку при программном открытии файла через COM-объект графическая оболочка Excel может инициализироваться с настройками по умолчанию, колонки часто оказываются слишком узкими. В итоге свойство Text честно считывает эти самые решетки вместо реальной даты.
Самый простой и быстрый способ решить проблему — изменить используемое свойство ячейки. Рассмотрим разницу между ними:
Дата (или COM-объект, который 1С преобразует в дату).Value, но не поддерживает типы данных «Дата» и «Валюта». В Excel даты хранятся как числовые значения (количество дней с начала эпохи). Использование Value2 считается наиболее быстрым и надежным способом при работе с большими массивами данных, так как исключает дополнительные преобразования на стороне COM-сервера.Исправленный код будет выглядеть следующим образом:
// Вместо .Text используем .Value
НоваяСтрока.ДатаОтгрузки = Excel.Cells(СтрокаЭксель, 4).Value;
Важно помнить: при использовании Value 1С получит полноценный тип Дата, и вам не потребуется использовать дополнительные функции преобразования строк. Если же вы используете Value2, то полученное число нужно будет конвертировать в дату по формуле, учитывающей начало отсчета времени в Excel (30.12.1899).
Если по каким-то причинам вам критически важно получить именно строковое представление даты (например, если в файле используются специфические форматы, которые сложно парсить вручную), можно применить метод автоматического подбора ширины. Проанализируем, как это сделать:
// Раздвигаем четвертый столбец перед чтением данных
Excel.Columns(4).AutoFit();
// Теперь свойство .Text вернет корректную строку
НоваяСтрока.ДатаОтгрузки = СокрЛП(Excel.Cells(СтрокаЭксель, 4).Text);
Этот метод заставляет Excel пересчитать визуальное представление ячеек, после чего символы решетки исчезают, уступая место реальным данным.
Рассмотрим более глубокую проблему. Использование COM-объекта Excel.Application для чтения простых текстовых файлов, коими являются файлы CSV, — это крайне ресурсоемкая операция. Каждый запуск процесса excel.exe потребляет значительный объем оперативной памяти и процессорного времени. Более того, на стороне сервера 1С (в клиент-серверном варианте) Microsoft Office может быть не установлен вовсе.
Для эффективной работы с CSV в 1С (начиная с версии 8.3.9) предусмотрен объект ЧтениеCSV. Разберем по шагам, как переписать чтение файла на этот объект:
ПутьКФайлу = "C:\temp\data.csv";
Разделитель = ";"; // Укажите разделитель, используемый в вашем файле
Текст = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);
Чтение = Новый ЧтениеCSV(Текст, Разделитель);
// Пропускаем заголовок, если он есть
Чтение.ПрочитатьСтроку();
Пока Истина Цикл
МассивДанных = Чтение.ПрочитатьСтроку();
Если МассивДанных = Неопределено Тогда
Прервать;
КонецЕсли;
НоваяСтрока = Таблица.Добавить();
// Предположим, дата во второй колонке (индекс 1)
// CSV — это текст, поэтому дату нужно преобразовать функцией Дата()
// или использовать методы парсинга строк
НоваяСтрока.ДатаОтгрузки = МассивДанных[3]; // Обращение по индексу колонки
КонецЦикла;
Чтение.Закрыть();
Преимущества этого метода:
Если файл имеет сложную структуру или вы привыкли работать с визуальными таблицами 1С, можно воспользоваться методом Прочитать объекта ТабличныйДокумент. Посмотрим на этот пример:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
НоваяСтрока = Таблица.Добавить();
// Получаем именно значение ячейки
НоваяСтрока.ДатаОтгрузки = ТабДок.Область(НомерСтроки, 4).Текст;
КонецЦикла;
Этот способ также значительно легче использования COM-объекта и позволяет избежать проблем с форматированием, если указать правильный параметр СпособЧтенияЗначенийТабличногоДокумента.
При работе с CSV через Excel важно учитывать следующие нюансы, которые могут исказить ваши данные:
"00123", Excel при открытии может автоматически преобразовать их в число 123, потеряв нули. Прямое чтение файла как текста через ЧтениеCSV сохраняет данные в исходном виде.UTF-8 или Windows-1251. При использовании COM-объекта Excel может неверно определить кодировку, если в файле нет метки BOM (Byte Order Mark)..Text сильно зависит от настроек даты и времени в самой операционной системе Windows. Если формат даты в системе изменится, ваш код парсинга строки может «сломаться». Использование .Value или прямого чтения текста защищает от таких сюрпризов.Подведем итог: если вам нужно быстрое исправление в существующем коде — замените .Text на .Value. Если же вы проектируете надежную систему импорта данных — откажитесь от использования Excel в пользу объекта ЧтениеCSV.