Как выгрузить все данные из файла DBF в массив или таблицу значений в 1С 8.3?

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

Интеграция со сторонними информационными системами часто ставит перед разработчиком 1С задачу импорта данных из файлов устаревших форматов, таких как DBF. Несмотря на возраст стандарта, таблицы DBF активно используются для обмена данными в различных отраслях. В этой статье мы подробно разберем, как прочитать данные из файла DBF и оптимально перенести их в коллекции 1С — массивы, структуры или таблицы значений. Мы также проанализируем скрытые технические проблемы, с которыми вы гарантированно столкнетесь на практике, и найдем пути их решения.

Способ №1: Использование встроенного объекта XBase

Платформа 1С:Предприятие предоставляет стандартный встроенный объект XBase, специально предназначенный для прямой работы с файлами баз данных dBase. Это наиболее быстрый и кроссплатформенный инструмент, не требующий установки дополнительных драйверов в операционной системе.

Рассмотрим по шагам классический пример считывания данных. Допустим, у нас есть файл DBF, содержащий три колонки (например, "Колонка1", "Колонка2", "Колонка3"), и нам необходимо выгрузить эти данные в массив структур для последующего сравнения со строками табличной части документа.

Применим следующий эффективный алгоритм:


// Создаем объект для работы с файлом DBF
ДБФ = Новый XBase;

// Открываем файл по указанному пути
ДБФ.ОткрытьФайл(ПутьКФайлу);

Если Не ДБФ.Открыта() Тогда
    ВызватьИсключение "Не удалось открыть файл DBF. Проверьте правильность пути и права доступа.";
КонецЕсли;

// Подготовим массив для хранения результатов
МассивРезультатов = Новый Массив;

// Переходим к первой записи файла
ДБФ.Первая();

// Запускаем цикл обхода всех записей файла
Пока Не ДБФ.ВКонце() Цикл
    
    // Для удобства последующей обработки строки создаем Структуру
    СтрокаДанных = Новый Структура;
    СтрокаДанных.Вставить("Колонка1", ДБФ.Колонка1);
    СтрокаДанных.Вставить("Колонка2", ДБФ.Колонка2);
    СтрокаДанных.Вставить("Колонка3", ДБФ.Колонка3);
    
    // Добавляем заполненную структуру в результирующий массив
    МассивРезультатов.Добавить(СтрокаДанных);
    
    // Переходим к следующей записи
    ДБФ.Следующая();
    
КонецЦикла;

// Закрываем файл после завершения операции, чтобы освободить системные ресурсы
ДБФ.ЗакрытьФайл();

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

Способ №2: Оптимальная выгрузка через Таблицу Значений

Если вам нужно получить массив значений только по одной определенной колонке файла, ручной обход в цикле может оказаться избыточным и медленным. В таком случае гораздо рациональнее сначала считать всю таблицу DBF во временную ТаблицаЗначений, а затем выгрузить нужную колонку в одно действие с помощью встроенного высокопроизводительного метода платформы.

Разберем этот вариант реализации:


// Создаем Таблицу Значений и описываем её структуру
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Колонка1");
ТаблицаДанных.Колонки.Добавить("Колонка2");
ТаблицаДанных.Колонки.Добавить("Колонка3");

ДБФ = Новый XBase;
ДБФ.ОткрытьФайл(ПутьКФайлу);

Если ДБФ.Открыта() Тогда
    ДБФ.Первая();
    Пока Не ДБФ.ВКонце() Цикл
        НоваяСтрока = ТаблицаДанных.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ДБФ);
        ДБФ.Следующая();
    КонецЦикла;
    ДБФ.ЗакрытьФайл();
КонецЕсли;

// Быстрое получение плоского массива значений по конкретной колонке
МассивЭлементов = ТаблицаДанных.ВыгрузитьКолонку("Колонка1");

Метод ВыгрузитьКолонку() реализован на уровне платформы на языке C++ и выполняется значительно быстрее, чем ручное наполнение массива поэлементно в цикле на встроенном языке 1С.

Критическая проблема: Ограничение длины имени файла (DOS 8.3)

При использовании стандартного объекта XBase программисты часто сталкиваются со следующей неочевидной ошибкой: метод ОткрытьФайл() возвращает ложь, хотя файл гарантированно существует на диске и права доступа к нему открыты.

Выясним причину проблемы: Внутренний движок встроенного объекта XBase в 1С унаследовал логику работы устаревших DOS-библиотек СУБД dBase. Из-за этого он критически зависит от ограничений файловой системы на длину имен папок и файлов. Формат DOS 8.3 требует, чтобы имя файла содержало не более 8 символов, а его расширение — не более 3 символов. Длина путей к файлу также может вызывать сбои.

Решать проблему обрезкой длины имени сгенерированного временного файла до 8 символов (например, через Лев(Новый УникальныйИдентификатор(), 8)) небезопасно, так как при многопоточной работе на сервере возрастает риск коллизии имен файлов.

Разберем наиболее стабильное и безопасное решение этой проблемы:

  1. Создаем изолированную временную директорию во временном каталоге операционной системы. Платформа 1С нормально воспринимает длинные пути к каталогам.
  2. Внутри этой папки копируем исходный DBF-файл, присваивая ему строго фиксированное короткое имя, например, data.dbf (всего 4 символа в имени).
  3. Выполняем чтение из этого скопированного файла.
  4. После прочтения закрываем файл, удаляем его и саму временную папку.

Посмотрим на программную реализацию этого обхода ограничений:


// Формируем путь к уникальной временной папке
ИмяВременнойПапки = КаталогВременныхФайлов() + Новый УникальныйИдентификатор() + "\";
СоздатьКаталог(ИмяВременнойПапки);

// Копируем исходный файл в эту папку под коротким именем "data.dbf"
ВременныйФайлDBF = ИмяВременнойПапки + "data.dbf";
КопироватьФайл(ИсходныйПутьКФайлу, ВременныйФайлDBF);

// Теперь безопасно открываем XBase
ДБФ = Новый XBase;
ДБФ.ОткрытьФайл(ВременныйФайлDBF);

// [Здесь выполняется ваш алгоритм чтения данных]

ДБФ.ЗакрытьФайл();

// Обязательно наводим за собой порядок на диске
Попытка
    УдалитьФайлы(ИмяВременнойПапки);
Исключение
    ЗаписьЖурналаРегистрации("УдалениеВременныхФайлов", УровеньЖурналаРегистрации.Предупреждение,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

Особенности работы с MEMO-полями в 1С

Многие разработчики ошибочно полагают, что встроенный объект 1С XBase вообще не умеет работать со специальными текстовыми неограниченными MEMO-полями. Проанализируем эту ситуацию детальнее.

На самом деле, встроенный XBase поддерживает чтение MEMO-полей, но накладывает жесткие ограничения на их форматы:

Если же ваша таблица DBF создана СУБД Microsoft FoxPro (или Visual FoxPro), то MEMO-поля там хранятся в формате .fpt. Этот формат встроенным объектом XBase платформы 1С **не поддерживается**. Попытка прочитать такое поле приведет либо к ошибке выполнения, либо к чтению пустых значений. Если вы столкнулись именно с этой проблемой, вам поможет переход на технологию ADO.

Способ №3: Альтернативное чтение через ADO (ActiveX Data Objects)

Использование технологии ADO позволяет обойти абсолютно все системные ограничения встроенного 1С-объекта XBase. При работе через COM-объект ADODB.Connection вы получаете следующие преимущества:

Рассмотрим по шагам программный пример чтения данных через ADO:


// Создаем COM-объект подключения
Connection = Новый COMОбъект("ADODB.Connection");

// Обратите внимание: Источником данных (Data Source) для провайдера DBF 
// является именно каталог (папка), в котором лежит файл, а не сам файл!
РазделительПути = "/";
Если Найти(ПутьКФайлу, "\") > 0 Тогда
    РазделительПути = "\";
КонецЕсли;

ПозицияПоследнегоСлэша = СтрНайти(ПутьКФайлу, РазделительПути, НаправлениеПоиска.ОтКонца);
КаталогФайла = Лев(ПутьКФайлу, ПозицияПоследнегоСлэша);
ИмяФайлаDBF  = Сред(ПутьКФайлу, ПозицияПоследнегоСлэша + 1);

// Формируем строку подключения для провайдера Jet OLEDB
СтрокаПодключения = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + КаталогФайла + ";Extended Properties=dBASE IV;";

Попытка
    Connection.Open(СтрокаПодключения);
Исключение
    ВызватьИсключение "Не удалось установить соединение через ADO: " + ОписаниеОшибки();
КонецПопытки;

// Выполняем SQL-запрос к файлу, имя файла выступает в роли имени таблицы в БД
ТекстЗапроса = "SELECT Колонка1, Колонка2, Колонка3 FROM [" + ИмяФайлаDBF + "]";
Recordset = Новый COMОбъект("ADODB.Recordset");

Попытка
    Recordset.Open(ТекстЗапроса, Connection, 3, 1); // CursorType: adOpenStatic, LockType: adLockReadOnly
Исключение
    Connection.Close();
    ВызватьИсключение "Ошибка выполнения SQL-запроса к DBF: " + ОписаниеОшибки();
КонецПопытки;

МассивРезультатов = Новый Массив;

// Обходим полученный набор записей
Пока Recordset.EOF = 0 Цикл
    
    СтрокаДанных = Новый Структура;
    СтрокаДанных.Вставить("Колонка1", Recordset.Fields("Колонка1").Value);
    СтрокаДанных.Вставить("Колонка2", Recordset.Fields("Колонка2").Value);
    СтрокаДанных.Вставить("Колонка3", Recordset.Fields("Колонка3").Value);
    
    МассивРезультатов.Добавить(СтрокаДанных);
    
    Recordset.MoveNext();
КонецЦикла;

// Закрываем соединения
Recordset.Close();
Connection.Close();

Кроссплатформенность и серверы под управлением Linux

В современных реалиях построения ИТ-архитектуры серверная часть платформы 1С:Предприятие очень часто функционирует под управлением операционных систем семейства Linux. Это накладывает серьезный отпечаток на выбор способа интеграции.

Важное предупреждение: Использование технологии ADO (COM-объектов Windows) на сервере Linux принципиально невозможно. Попытка вызова Новый COMОбъект("ADODB.Connection") на Linux-сервере приведет к немедленному аварийному завершению работы программы с системной ошибкой.

Напротив, встроенный объект 1С XBase начиная с платформы 8.3 полностью переписан разработчиками 1С и нативно поддерживается как в Windows, так и во всех поддерживаемых 64-битных дистрибутивах Linux.

Однако при работе с XBase на Linux-сервере возникает другая критически важная деталь — чувствительность к регистру символов (case-sensitivity) в именах файлов и путей. Если в ОС Windows вы могли передать в метод ОткрытьФайл() путь /temp/MyData.dbf, а сам файл на диске назывался /temp/mydata.DBF, Windows успешно проигнорирует разницу регистров и откроет файл. В среде Linux такое обращение вызовет неустранимую ошибку "Файл не найден". Всегда строго контролируйте регистр написания имен файлов и расширений в коде вашей конфигурации!

← На главную