Как правильно выгрузить данные из 1С в формат DBF и передать их для загрузки?

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

Формат DBF (Database File) — это один из старейших форматов хранения табличных данных, который до сих пор активно применяется для интеграции информационных систем. Особенно часто с ним приходится сталкиваться при обмене данными между современными конфигурациями на платформе «1С:Предприятие 8» и устаревшими базами на платформе «1С:Предприятие 7.7». Несмотря на кажущуюся простоту формата, процесс выгрузки скрывает в себе множество подводных камней: от жестких ограничений на длину наименований колонок до проблем со структурированием иерархических данных.

В этой статье мы подробно рассмотрим, как правильно спроектировать архитектуру выгрузки документов и их табличных частей в формат DBF, разберем технические ограничения встроенного объекта 1С XBase, решим проблему с кодировками и подготовим данные так, чтобы принимающая сторона смогла загрузить их без ошибок.

Правила именования полей в файлах DBF

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

  1. Ограничение по длине: Имя поля (колонки) не должно превышать 10 символов. Все, что выходит за рамки этого лимита, будет безвозвратно обрезано драйвером базы данных, что может привести к дублированию имен колонок и ошибкам создания файла.
  2. Разрешенные символы: Допускается использовать только латинские буквы (A-Z, a-z), цифры (0-9) и символ подчеркивания «_». Кириллица в именах полей не поддерживается большинством СУБД и драйверов.
  3. Первый символ: Имя поля должно обязательно начинаться с латинской буквы. Использование цифры или подчеркивания в качестве первого символа недопустимо.
  4. Отказ от транслитерации: Рекомендуется использовать понятные английские термины вместо транслитерации русских слов. Например, вместо нечитаемого KOLICH_TOV лучше использовать лаконичное QTY (Quantity), а вместо NOMENKL — ITEM. Это упростит работу программисту, который будет писать загрузчик на принимающей стороне.

Обязательно подготовьте сопроводительный файл (спецификацию в формате Excel или текстовом файле), в котором детально распишите соответствие ваших латинских полей реквизитам 1С. Например: DOC_NUM — Номер документа, DOC_DATE — Дата документа, PRICE — Цена номенклатуры.

Архитектура выгрузки: «Шапка + Табличная часть» в плоском формате

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

Подход А: Один DBF-файл с денормализацией (дублированием) данных

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

Рассмотрим структуру такого файла на примере:

Преимущества: Простота реализации выгрузки. Все данные находятся в одном месте.

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

Подход Б: Два связанных DBF-файла (Реляционный подход)

Этот подход более профессиональный и чистый. Мы выгружаем данные в два раздельных файла, например, HEAD.DBF (для шапки документов) и LINES.DBF (для строк табличных частей).

Связующим звеном между файлами выступает уникальный идентификатор (ID). В качестве ID можно использовать уникальный идентификатор ссылки 1С (GUID), преобразованный в строку, либо простой инкрементный счетчик, генерируемый в процессе выгрузки.

Разберем по шагам, как это работает:

  1. В файле HEAD.DBF создаем поля: ID (строка, 36 символов), DOC_NUM, DOC_DATE, PARTNER.
  2. В файле LINES.DBF создаем поля: ID_HEAD (ссылка на шапку, строка, 36 символов), ITEM, QTY, PRICE, SUM.
  3. При чтении принимающая сторона сначала импортирует HEAD.DBF, создает документы и кэширует связь между внутренним документом и ID. Затем читает LINES.DBF и быстро добавляет строки в соответствующие документы по ключу ID_HEAD.

Технические ограничения встроенного объекта 1С XBase

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

Проблема кодировки: OEM против ANSI

Одной из наиболее частых проблем при обмене через DBF является появление нечитаемых символов («кракозябр») при загрузке. Это происходит из-за несовпадения кодировок при записи и чтении файла.

Формат DBF не хранит внутри себя жестких метаданных о используемой кодировке, поэтому программисты на обеих сторонах должны договориться об этом «на берегу». Существует два основных стандарта:

  1. OEM (кодировка CP866 / DOS): Исторический стандарт для операционной системы DOS. Очень часто базы данных «1С:Предприятие 7.7» (особенно файловые версии) используют именно кодировку OEM для работы с таблицами.
  2. ANSI (кодировка CP1251 / Windows): Стандартная кодировка для русскоязычной операционной системы Windows. Используется большинством современных приложений.

В платформе 1С при создании файла через XBase крайне важно явно задавать кодировку перед вызовом метода создания. Посмотрим на пример инициализации кодировки в коде:


НовыйДБФ = Новый XBase;
// Явно указываем кодировку Windows
НовыйДБФ.Кодировка = КодировкаXBase.ANSI; 
// Если принимающая сторона требует DOS-кодировку, используем:
// НовыйДБФ.Кодировка = КодировкаXBase.OEM;

Как принимающая сторона будет читать файл?

Для того чтобы облегчить жизнь коллеге, который будет писать загрузчик (особенно на платформе «1С:Предприятие 7.7»), рассмотрим, как именно происходит процесс чтения файлов DBF на стороне получателя:

Практический пример: Выгрузка документов в DBF на 1С 8.3

Рассмотрим подробный пример кода, реализующий выгрузку документов «Поступление товаров» во внешний файл DBF по реляционному принципу (один файл с шапкой, второй — с табличной частью). Будем использовать латинские имена полей, явно зададим типы колонок и кодировку ANSI.


Процедура ВыгрузитьДокументыВDBF(МассивДокументов, ПутьКПапке) Экспорт

    // 1. Создаем файл шапки HEAD.DBF
    ФайлШапки = Новый XBase;
    ФайлШапки.Кодировка = КодировкаXBase.ANSI;
    
    // Описываем структуру колонок HEAD.DBF
    ФайлШапки.Поля.Добавить("ID", "S", 36); // Уникальный идентификатор документа
    ФайлШапки.Поля.Добавить("NUM", "S", 10); // Номер документа
    ФайлШапки.Поля.Добавить("DATE", "D");    // Дата документа
    ФайлШапки.Поля.Добавить("CONTR", "S", 100); // Наименование контрагента
    ФайлШапки.Поля.Добавить("INN", "S", 12);   // ИНН контрагента для поиска
    
    // Создаем физический файл на диске
    ИмяФайлаШапки = ПутьКПапке + "head.dbf";
    ФайлШапки.СоздатьФайл(ИмяФайлаШапки);
    
    // 2. Создаем файл строк табличной части LINES.DBF
    ФайлСтрок = Новый XBase;
    ФайлСтрок.Кодировка = КодировкаXBase.ANSI;
    
    // Описываем структуру колонок LINES.DBF
    ФайлСтрок.Поля.Добавить("ID_HEAD", "S", 36); // Связь с файлом шапки
    ФайлСтрок.Поля.Добавить("ITEM_CODE", "S", 20); // Код номенклатуры (для поиска)
    ФайлСтрок.Поля.Добавить("ITEM_NAME", "S", 150); // Наименование номенклатуры
    ФайлСтрок.Поля.Добавить("QTY", "N", 15, 3); // Количество (точность 3 знака)
    ФайлСтрок.Поля.Добавить("PRICE", "N", 15, 2); // Цена
    ФайлСтрок.Поля.Добавить("SUM", "N", 15, 2); // Сумма
    
    ИмяФайлаСтрок = ПутьКПапке + "lines.dbf";
    ФайлСтрок.СоздатьФайл(ИмяФайлаСтрок);
    
    // 3. Заполняем файлы данными из документов
    Для Каждого ДокСсылка Из МассивДокументов Цикл
        
        // Получаем уникальный идентификатор для связывания таблиц
        УникальныйИдентификатор = Строка(ДокСсылка.УникальныйИдентификатор());
        
        // Записываем шапку документа
        ФайлШапки.Добавить();
        ФайлШапки.ID = УникальныйИдентификатор;
        ФайлШапки.NUM = ДокСсылка.Номер;
        ФайлШапки.DATE = ДокСсылка.Дата;
        ФайлШапки.CONTR = СокрЛП(ДокСсылка.Контрагент.Наименование);
        ФайлШапки.INN = СокрЛП(ДокСсылка.Контрагент.ИНН);
        ФайлШапки.Записать();
        
        // Записываем строки табличной части "Товары"
        Для Каждого СтрокаТЧ Из ДокСсылка.Товары Цикл
            ФайлСтрок.Добавить();
            ФайлСтрок.ID_HEAD = УникальныйИдентификатор;
            ФайлСтрок.ITEM_CODE = СокрЛП(СтрокаТЧ.Номенклатура.Код);
            ФайлСтрок.ITEM_NAME = Лев(СокрЛП(СтрокаТЧ.Номенклатура.Наименование), 150); // Ограничиваем длину строки
            ФайлСтрок.QTY = СтрокаТЧ.Количество;
            ФайлСтрок.PRICE = СтрокаТЧ.Цена;
            ФайлСтрок.SUM = СтрокаТЧ.Сумма;
            ФайлСтрок.Записать();
        EndDo;
        
    КонецЦикла;
    
    // Закрываем файлы, освобождая ресурсы ОС
    ФайлШапки.ЗакрытьФайл();
    ФайлСтрок.ЗакрытьФайл();
    
    ПоказатьПредупреждение(, "Выгрузка в DBF успешно завершена!");

КонецПроцедуры

В данном примере мы использовали функцию Лев() для жесткого ограничения длины наименования номенклатуры до 150 символов. Это гарантирует, что при выгрузке длинных названий система не выдаст ошибку переполнения строкового буфера DBF-файла. Также обратите внимание на обязательный вызов метода Записать() после заполнения полей новой строки и метод ЗакрытьФайл() в конце процедуры для предотвращения блокировки файлов операционной системой.

← На главную