Как выгрузить таблицу значений или результат СКД в файл DBF?

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

При интеграции 1С с внешними или унаследованными информационными системами часто возникает задача формирования и передачи данных в формате dBase (файлы с расширением .dbf). На практике разработчики нередко сталкиваются с ошибками при выгрузке таблицы значений в DBF: от неверного обхода строк коллекции до проблем с кодировкой и передачей ссылочных данных. Рассмотрим подробно, как правильно организовать выгрузку данных из системы компоновки данных (СКД) и таблицы значений в файл DBF с помощью встроенного объекта XBase.

Типичные ошибки при работе со структурой DBF и строками таблицы значений

Проанализируем типовую ситуацию: результат СКД был успешно выгружен в объект ТаблицаЗначений, после чего предпринимается попытка наполнить DBF-файл. Частая ошибка начинающих разработчиков — обращение к коллекции колонок вместо обращения к конкретным строкам в цикле:


// Ошибочный подход:
Для N = 1 По ТЗ.Количество() Цикл
    БД.UrLizo = ТЗ.Колонки.Получить(1); // Ошибка: обращение к объекту "КолонкаТаблицыЗначений", а не к данным строки
КонецЦикла;

Метод ТЗ.Колонки.Получить() возвращает описание колонки, а не значение в текущей строке. Для корректного заполнения файла базы данных необходимо обходить именно строки таблицы значений.

Пошаговый алгоритм выгрузки таблицы значений в DBF

Разберем процесс создания и наполнения DBF-файла по шагам:

  1. Инициализация объекта XBase и настройка кодировки. Свойство Кодировка следует задавать до создания или открытия файла. В 1С поддерживаются два формата: КодировкаXBase.ANSI (Windows-1251) и КодировкаXBase.OEM (DOS / CP866).
  2. Определение структуры полей. Поля создаются с помощью метода БД.Поля.Добавить(). Важно помнить об ограничениях формата dBase: имя поля не должно быть длиннее 10 символов и должно содержать только латиницу, цифры и знаки подчеркивания.
  3. Создание файла на диске. Метод БД.СоздатьФайл() физически формирует файл с заданной структурой.
  4. Обход строк и запись данных. Выполняем цикл по строкам таблицы значений. На каждой итерации вызываем БД.Добавить(), заполняем поля и фиксируем запись методом БД.Записать().
  5. Закрытие файла. Обязательно вызываем БД.ЗакрытьФайл(), чтобы освободить дескриптор в операционной системе. Рекомендуется использовать конструкцию Попытка ... Исключение, чтобы файл гарантированно закрывался даже в случае возникновения ошибки при записи.

Посмотрим на практический пример реализации:


Процедура ВыгрузитьТЗвDBF(ТЗ, ПутьКФайлу)
    БД = Новый XBase;
    
    // Указываем кодировку (ANSI для Windows или OEM для DOS)
    БД.Кодировка = КодировкаXBase.ANSI;
    
    // Добавляем поля в структуру (имя поля <= 10 символов)
    БД.Поля.Добавить("URLIZO", "S", 100);
    БД.Поля.Добавить("KONTRAGENT", "S", 100);
    БД.Поля.Добавить("SCHET", "S", 10);
    БД.Поля.Добавить("OSTATOKDT", "N", 15, 2);
    БД.Поля.Добавить("OSTATOKKT", "N", 15, 2);
    
    Попытка
        БД.СоздатьФайл(ПутьКФайлу);
        
        // Правильный обход строк таблицы значений
        Для Каждого СтрокаТЗ Из ТЗ Цикл
            // Проверяем заполненность ключевых полей при необходимости
            Если ЗначениеЗаполнено(СтрокаТЗ.Организация) И ЗначениеЗаполнено(СтрокаТЗ.Контрагент) Тогда
                БД.Добавить();
                
                // Присваиваем строковые и числовые значения
                БД.URLIZO     = Строка(СтрокаТЗ.Организация);
                БД.KONTRAGENT = Строка(СтрокаТЗ.Контрагент);
                БД.SCHET      = Строка(СтрокаТЗ.Счет);
                БД.OSTATOKDT  = СтрокаТЗ.ОстатокДт;
                БД.OSTATOKKT  = СтрокаТЗ.ОстатокКт;
                
                БД.Записать();
            КонецЕсли;
        КонецЦикла;
    Исключение
        Сообщить("Ошибка при выгрузке в DBF: " + ОписаниеОшибки());
    КонецПопытки;
    
    // Закрываем файл, если он открыт
    Если БД.Открыта() Тогда
        БД.ЗакрытьФайл();
    КонецЕсли;
КонецПроцедуры

Работа со ссылочными данными и оптимизация выборки

Объект XBase не работает со ссылочными типами 1С (такими как СправочникСсылка или ДокументСсылка), а также со значениями Null и Неопределено. Все ссылочные значения необходимо явно преобразовывать в строки или извлекать конкретные реквизиты.

Если в DBF-файл требуется выгрузить, например, ИНН контрагента или организации, можно обратиться к реквизиту напрямую: СтрокаТЗ.Контрагент.ИНН. Однако обращение через точку в цикле приводит к дополнительным неявным запросам к базе данных на каждой итерации. Чтобы оптимизировать быстродействие, добавьте поле Контрагент.ИНН непосредственно в набор данных СКД и выведите его отдельной колонкой в результирующую таблицу значений.

Универсальная функция генерации DBF по структуре ТаблицыЗначений

Рассмотрим универсальный алгоритм, который автоматически создает DBF-файл на основе колонок переданной таблицы значений с динамическим сопоставлением типов 1С и dBase:


Функция СоздатьНовыйФайлDBF(тз, ПолныйПутьКФайлуDBF, XB = Неопределено)
    Если НЕ XB = Неопределено Тогда
        Возврат XB;
    КонецЕсли;
    
    Файл = Новый XBase;
    Файл.Кодировка = КодировкаXBase.ANSI;
    
    Для Каждого Колонка Из тз.Колонки Цикл
        КолонкаТиповая = Ложь;
        Попытка
            Если Найти(Строка(Колонка.ТипЗначения), "Строка") > 0 Тогда
                Длина = Колонка.ТипЗначения.КвалификаторыСтроки.Длина;
                // В DBF максимальная длина строкового поля типа "S" составляет 254 символа
                ДлинаПоля = ?(Длина > 0 И Длина <= 254, Длина, 254);
                Файл.Поля.Добавить(Лев(Колонка.Имя, 10), "S", ДлинаПоля);
                КолонкаТиповая = Истина;
            ИначеЕсли Найти(Строка(Колонка.ТипЗначения), "Число") > 0 Тогда
                Файл.Поля.Добавить(Лев(Колонка.Имя, 10), "N", 15, 3);
                КолонкаТиповая = Истина;
            ИначеЕсли Найти(Строка(Колонка.ТипЗначения), "Дата") > 0 Тогда
                Файл.Поля.Добавить(Лев(Колонка.Имя, 10), "D");
                КолонкаТиповая = Истина;
            КонецЕсли;
            
            Если НЕ КолонкаТиповая Тогда
                // Для прочих типов создаем строковое поле ограниченной длины
                Файл.Поля.Добавить(Лев(Колонка.Имя, 10), "S", 254);
            КонецЕсли;
        Исключение
            Сообщить("Колонка """ + Колонка.Имя + """ не создана. Ошибка: " + ОписаниеОшибки());
        КонецПопытки;
    КонецЦикла;
    
    Файл.ОткрытьФайл(ПолныйПутьКФайлуDBF);
    Если Не Файл.Открыта() Тогда
        Файл.СоздатьФайл(ПолныйПутьКФайлуDBF);
    Иначе
        Файл.ОчиститьФайл();
    КонецЕсли;
    
    Возврат Файл;
КонецФункции

Особенности выгрузки результата СКД в ТаблицуЗначений

При получении таблицы значений через ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений важно учитывать следующие нюансы:

  1. Учет настроек пользователя. При формировании макета компоновки вместо прямого обращения к КомпоновщикНастроек.Настройки используйте вызов КомпоновщикНастроек.ПолучитьНастройки(). Это гарантирует, что установленные пользователем на форме отборы и параметры применятся к выгрузке.
  2. Структура группировок. Генератор макета для коллекции значений формирует строки в соответствии со структурой группировок схемы. Чтобы выгрузить плоскую таблицу без дублирующих итоговых строк, в настройках СКД должна быть настроена одна группировка «Детальные записи» без родительских группировок.
← На главную