Как правильно прочитать данные из Excel в 1С 7.7 без потери ведущих нулей и символов решетки?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Работа с внешними данными — одна из самых частых задач разработчика 1С. Однако при чтении файлов Excel (особенно в среде 1С 7.7) программисты часто сталкиваются с неприятными особенностями движка Microsoft Excel. Типичная ситуация: в ячейке записан код товара или номер документа с ведущими нулями (например, 0000195804), но после загрузки в 1С мы получаем обычное число 195804. Другая проблема — получение строки из символов решетки ### вместо реальных данных. В этой статье мы подробно разберем, почему это происходит и как правильно настроить чтение данных, чтобы результат в 1С полностью соответствовал тому, что вы видите в файле.

Разбираем проблему: почему Excel искажает данные?

Прежде чем переходить к коду, давайте проанализируем ситуацию. Когда мы обращаемся к ячейке Excel через COM-объект (используя Excel.Application), у нас есть несколько способов извлечь информацию. Чаще всего используются свойства Value и Text. Разберем их отличия:

Решение 1: Правильное использование свойства Text и автоподбор ширины

Если нам критично получить данные именно в виде строки (с нулями), использование Text оправдано. Чтобы избежать появления решеток, мы должны программно "раздвинуть" колонки перед чтением. Рассмотрим пример кода на языке 1С 7.7:


// Создаем объект Excel
Попытка
    Эксель = СоздатьОбъект("Excel.Application");
Исключение
    Сообщить("Excel не установлен!");
    Возврат;
КонецПопытки;

Книга = Эксель.Workbooks.Open(ИмяФайла);
Лист = Книга.Worksheets(1);

// Выполняем автоподбор ширины для всех колонок, 
// чтобы свойство .Text возвращало данные без решеток
Лист.Cells.EntireColumn.AutoFit();

// Теперь читаем данные
КодТовара = Лист.Cells(Строка, Колонка).Text;
Сообщить("Полученный код: " + КодТовара);

Этот метод прост, но имеет свои минусы. Чтение через Text работает медленнее, чем через Value, особенно на больших файлах, так как Excel тратит ресурсы на отрисовку и форматирование строк.

Решение 2: Форматирование ячеек через NumberFormat

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


// Устанавливаем текстовый формат для всей колонки (например, первой)
Лист.Columns(1).NumberFormat = "@";

// Теперь даже при обращении к Value Excel может вернуть строку, 
// если он успеет пересчитать формат данных
Значение = Лист.Cells(р, 1).Value;

Важное замечание: Установка формата "@" (текстовый) после того, как файл уже открыт, не всегда помогает вернуть уже "потерянные" нули, если Excel уже преобразовал их во внутреннее число. Поэтому этот метод лучше всего комбинировать с предварительной подготовкой файла.

Решение 3: Использование технологии ADO (самый надежный метод)

Для платформы 1С 7.7 использование ADO (ActiveX Data Objects) часто является более предпочтительным, чем работа через COM-объект Excel.Application. ADO работает значительно быстрее и не требует запуска самого Excel в памяти (хотя драйверы должны быть установлены). Но здесь есть свой нюанс с типами данных.

Посмотрим на параметр IMEX=1 в строке соединения. По умолчанию драйвер анализирует первые несколько строк (обычно 8) и определяет тип данных в колонке. Если там числа, он будет игнорировать ведущие нули в последующих строках. Установка IMEX=1 заставляет драйвер переходить в "смешанный режим" и читать данные как текст.


// Пример строки соединения для ADO
СтрокаСоединения = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ИмяФайла + ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1;""";
Connection = СоздатьОбъект("ADODB.Connection");
Connection.Open(СтрокаСоединения);

// Чтение данных через SQL-запрос
Recordset = Connection.Execute("SELECT * FROM [Лист1$]");
Пока Recordset.EOF() = 0 Цикл
    НужныйКод = Recordset.Fields(0).Value; // Здесь нули должны сохраниться благодаря IMEX=1
    Recordset.MoveNext();
КонецЦикла;

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

Решение 4: Программная обработка в 1С (функция дополнения нулями)

Если вы точно знаете длину кода (например, 10 символов), и данные все равно приходят без нулей, проще всего восстановить их средствами встроенного языка 1С. Это избавит вас от борьбы с настройками Excel.


Функция ВосстановитьНули(Значение, НужнаяДлина)
    Перем Результат;
    Результат = СокрЛП(Значение);
    Пока СтрДлина(Результат) < НужнаяДлина Цикл
        Результат = "0" + Результат;
    КонецЦикла;
    Возврат Результат;
КонецФункции

// Применение
ЧислоИзЭкселя = Лист.Cells(1, 1).Value; // получили 195804
ПравильныйКод = ВосстановитьНули(ЧислоИзЭкселя, 10); // получили 0000195804

Этот способ — самый быстрый в реализации и не зависит от версии Excel или установленных драйверов. Выясним причину потери нулей: если это просто автоматическое приведение типов, то математическая функция дополнения строки решит проблему на 100%.

Решение 5: Сторонние компоненты (Yoksel)

Для разработчиков на 1С 7.7 существует легендарное решение — компонента Yoksel (Йоксель). Она позволяет работать с файлами .xls напрямую на уровне двоичной структуры, не используя Microsoft Excel вообще. Выясним преимущества этого метода:

  1. Высокая скорость: Чтение происходит в десятки раз быстрее, чем через COM.
  2. Точность: Вы получаете доступ к типам ячеек напрямую. Если ячейка помечена как текстовая, вы гарантированно получите её строковое значение без искажений.
  3. Независимость: Программа будет работать даже на сервере, где Excel не установлен.

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

Мы проанализировали ситуацию и выяснили, что проблема "решеток" решается методом AutoFit(), а проблема ведущих нулей — выбором правильного свойства (Text), настройкой строки соединения ADO (IMEX=1) или ручным форматированием строки в самой 1С. Выбор метода зависит от ваших задач: для разовой загрузки небольшого прайс-листа достаточно Text с автошириной, а для регулярного обмена данными лучше использовать ADO или компоненту Yoksel.

← На главную