Мы часто сталкиваемся с задачей программного доступа к данным информационных баз 1С:Предприятия 7.7, которые хранятся в формате DBF. Если нам требуется не просто построчное чтение, а выполнение сложных запросов, фильтрации или агрегации данных, стандартные средства 1С могут оказаться не самыми эффективными. В этой статье мы подробно разберем, как установить соединение с такой базой данных, используя OLE DB провайдер FoxPro, и как выполнять к ней SQL-запросы, в том числе с учетом специфики метаданных 1С, при помощи внешней компоненты 1С++. Мы рассмотрим несколько подходов: от простого прямого чтения DBF-файлов до продвинутого использования SQL-запросов, позволяющих значительно ускорить обработку данных.
Начнем с самого простого и встроенного в 1С v7 механизма для работы с DBF-файлами – это объект XBASE. Этот подход позволяет нам напрямую открывать DBF-файлы, читать их содержимое и работать с полями записей.
Разберем по шагам, как использовать объект XBASE:
1. Создание объекта: Мы создаем экземпляр объекта XBASE.
2. Установка кодовой страницы: Очень важно правильно указать кодовую страницу файла, чтобы избежать проблем с отображением кириллицы. Для Windows-кодировки (CP1251) обычно используется значение 0.
3. Открытие файла: Указываем полный путь к DBF-файлу, который хотим открыть.
4. Проверка открытия: Всегда проверяем, успешно ли файл был открыт.
5. Чтение данных: Используем методы Первая() для перехода к первой записи и Следующая() для последовательного перебора всех записей.
6. Доступ к полям: Поля записи доступны как свойства объекта XBASE (например, ДБФ.Code, ДБФ.Descr).
7. Закрытие файла: После завершения работы обязательно закрываем файл.
Посмотрим на пример кода, демонстрирующий этот подход:
ДБФ = СоздатьОбъект("XBASE");
ДБФ.КодоваяСтраница(0); // Кодовая страница Windows (CP1251)
ДБФ.ОткрытьФайл("c:\export.dbf");
Если ДБФ.Открыта() = 0 Тогда
Сообщить("Файл DBF не открыт !", "!");
Возврат;
КонецЕсли;
КолСтр = ДБФ.КоличествоЗаписей();
н = 0;
ДБФ.Первая();
// Доступ к полям текущей записи
ПризнакГруппы = ДБФ.IsGroup;
ТекУровень = ДБФ.Level;
ТекКодРодителя = ДБФ.ParentCode;
ТекКод = ДБФ.Code;
ТекНаименоване = ДБФ.Descr;
н = н + 1;
Состояние("В файле прочитано записей " + н + " из " + КолСтр);
Пока ДБФ.Следующая() = 1 Цикл
// Доступ к полям следующей записи
ПризнакГруппы = ДБФ.IsGroup;
ТекУровень = ДБФ.Level;
ТекКодРодителя = ДБФ.ParentCode;
ТекКод = ДБФ.Code;
ТекНаименоване = ДБФ.Descr;
н = н + 1;
Состояние("В файле прочитано записей " + н + " из " + КолСтр);
КонецЦикла;
ДБФ.ЗакрытьФайл();
Преимущества объекта XBASE: Он встроен в 1С и не требует дополнительных компонентов. Он хорошо подходит для простых задач чтения или записи небольших объемов данных, когда требуется прямой доступ к структуре DBF-файла.
Ограничения: Для записи данных объект XBASE часто требует монопольного доступа к файлу, что может быть проблемой в многопользовательской среде. Кроме того, построчный перебор записей может быть очень медленным при работе с большими объемами данных или при необходимости сложных выборок и фильтрации.
Если нам нужна более высокая производительность, возможность выполнения сложных SQL-запросов и работа с метаданными 1С, мы можем использовать внешнюю компоненту 1С++ (файл 1cpp.dll) в связке с OLE DB провайдером для Visual FoxPro. Этот подход значительно расширяет наши возможности, позволяя обращаться к DBF-базе данных 1С как к полноценной реляционной базе.
Прежде чем использовать объекты, предоставляемые компонентой 1С++, нам необходимо ее загрузить. Мы всегда рекомендуем использовать конструкцию Попытка...Исключение для надежной загрузки.
Попытка
ЗагрузитьВнешнююКомпоненту("1cpp.dll");
Сообщить("Компонента 1С++ загружена!");
Исключение
Сообщить("Не удалось загрузить компоненту 1С++ :(");
КонецПопытки;
Важный момент: Компонента 1cpp.dll должна находиться в каталоге с базой 1С, в каталоге BIN платформы 1С или быть зарегистрированной в системе.
Компонента 1С++ предоставляет объект OLEDBData, который позволяет нам устанавливать OLE DB соединение с различными источниками данных, включая DBF-файлы через провайдер VFPOLEDB.1.
Рассмотрим подробнее строку соединения и ее параметры:
* Provider=VFPOLEDB.1: Это обязательный параметр, указывающий на использование OLE DB провайдера для Visual FoxPro.
* Data Source=<ПутьКБазе>: Здесь мы указываем путь к каталогу информационной базы 1С. Для 1С v7.7 это обычно путь к папке, содержащей файлы 1Cv7.MD, 1SJOURN.DBF и другие.
* Exclusive=Yes или Exclusive=No: Определяет, будет ли соединение монопольным. Для операций записи часто требуется Yes, но провайдер VFPOLEDB.1 позволяет работать и в режиме совместного доступа.
* Mode=ReadWrite: Задает режим доступа к данным (чтение и запись).
* Collating Sequence=MACHINE: Указывает на использование машинной сортировки. Этот параметр важен для корректной работы с данными, особенно при выполнении запросов с сортировкой.
* Deleted=Yes: Позволяет видеть записи, помеченные как удаленные в DBF-файле.
Посмотрим на пример установки соединения:
// ПутьИБ - это переменная, содержащая полный путь к каталогу информационной базы 1С
ПутьИБ = КаталогИБ(); // Или указываем конкретный путь, например, "C:\1C_Base\"
СоединениеСтрока = "Provider=VFPOLEDB.1;Data Source=" + ПутьИБ + ";Exclusive=No;Mode=ReadWrite;Collating Sequence=MACHINE;Deleted=Yes";
БД = СоздатьОбъект("OLEDBData");
Рез = БД.Соединение(СоединениеСтрока);
Если Рез = 0 Тогда
Сообщить("Ошибка соединения с базой данных OLE DB!", "!");
Возврат;
Иначе
Сообщить("Соединение с базой данных OLE DB установлено успешно!");
КонецЕсли;
Важные нюансы и рекомендации:
* Установка провайдера: Для работы VFPOLEDB.1 на компьютере должен быть установлен OLE DB провайдер Visual FoxPro. Если полная версия Visual FoxPro не установлена, его нужно установить отдельно (обычно это VFP 9.0 OLE DB Provider).
* Разрядность: Провайдер VFPOLEDB.1 является 32-разрядным. Если вы пытаетесь использовать его в 64-разрядной среде (например, в 64-разрядном процессе сервера приложений), могут возникнуть проблемы совместимости. Убедитесь, что ваше приложение запускается в 32-разрядном режиме.
* Обновление драйверов: В некоторых случаях обновление драйверов FoxPro может решить проблемы с подключением.
* Проверка соединения: Перед выполнением запросов всегда проверяйте, что соединение установлено корректно.
Один из самых мощных методов объекта OLEDBData – это ПрисоединитьИБ(). Он позволяет не просто подключиться к DBF-файлам, но и "понять" структуру информационной базы 1С, преобразуя метаимена (например, "Журнал.DOCNO", "ТМЦ.DESCR") в реальные имена полей и таблиц DBF-файлов (например, "1SJOURN.DOCNO", "SC148.DESCR"). Это критически важно для выполнения SQL-запросов к данным 1С с использованием привычных нам имен объектов метаданных.
Изначально у некоторых пользователей возникали сложности с этим методом, однако выяснилось, что проблема часто заключалась в синтаксисе вызова.
Правильный вызов метода ПрисоединитьИБ() выглядит так:
// ПутьИБ - это переменная, содержащая полный путь к каталогу информационной базы 1С
ПутьИБ = КаталогИБ();
// СоединениеСтрока - это строка OLE DB соединения, которую мы сформировали ранее
СоединениеСтрока = "Provider=VFPOLEDB.1;Data Source=" + ПутьИБ + ";Exclusive=No;Mode=ReadWrite;Collating Sequence=MACHINE;Deleted=Yes";
БД = СоздатьОбъект("OLEDBData");
// Присоединяем информационную базу, передавая путь и строку соединения
// Этот метод не только подключается, но и загружает метаданные 1С
Рез = БД.ПрисоединитьИБ(ПутьИБ, СоединениеСтрока);
Если Рез = 0 Тогда
Сообщить("Ошибка присоединения информационной базы 1С через OLE DB!", "!");
Возврат;
Иначе
Сообщить("Информационная база 1С присоединена успешно!");
КонецЕсли;
Что происходит внутри ПрисоединитьИБ(): Этот метод выполняет несколько ключевых действий:
1. Он устанавливает OLE DB соединение, используя переданную строку соединения.
2. Он загружает файл метаданных 1Cv7.MD из указанного пути.
3. Он инициализирует внутренние механизмы для преобразования метаимен 1С в физические имена таблиц и полей DBF, что делает возможным выполнение SQL-запросов с использованием метаимен.
После успешного вызова БД.ПрисоединитьИБ() мы можем выполнять SQL-запросы, используя привычные имена объектов метаданных 1С. Объект OLEDBData автоматически преобразует эти имена в соответствующие имена таблиц и полей в DBF-файлах.
Рассмотрим пример SQL-запроса, который использует метаимена 1С:
ТекстЗапроса = "
|SELECT
| Журнал.DOCNO AS Документ_ном,
| Журнал.DATE AS Дата,
| ТМЦ.DESCR AS Товар,
| ТМЦ.sp14604 AS КодТрейд,
| РасходнаяНакладнаяСтроки.sp1033 AS Количество,
| ROUND(РасходнаяНакладнаяСтроки.sp1036/5*6, 2) AS Цена,
| РасходнаяНакладнаяСтроки.sp1040 AS Сумма
|FROM
| 1SJOURN AS Журнал
|INNER JOIN dh1011 AS РасходнаяНакладная ON Журнал.IDDOC = РасходнаяНакладная.IDDOC
|INNER JOIN dt1011 AS РасходнаяНакладнаяСтроки ON Журнал.IDDOC = РасходнаяНакладнаяСтроки.IDDOC
|INNER JOIN sc148 AS ТМЦ ON РасходнаяНакладнаяСтроки.sp1031 = ТМЦ.ID
|WHERE
| (Журнал.sp960 LIKE '%РасходнаяНакладная № 15294 от 03.07.25%')
";
// Выполняем запрос
// Результат запроса обычно возвращается в виде объекта RecordSet или ТаблицыЗначений
РезультатЗапроса = БД.ВыполнитьИнструкцию(ТекстЗапроса);
Если РезультатЗапроса = 0 Тогда
Сообщить("Ошибка выполнения SQL-запроса!", "!");
Иначе
Сообщить("SQL-запрос выполнен успешно. Получено " + РезультатЗапроса.КоличествоСтрок() + " записей.");
// Далее можно работать с полученными данными, например, вывести их в таблицу значений
// РезультатЗапроса.Выгрузить(ТЗ);
КонецЕсли;
Особенности синтаксиса SQL для OLEDB DBF:
* Оператор LIKE: Для OLE DB провайдера FoxPro значения в условии LIKE должны быть заключены в одинарные кавычки, как показано в примере (LIKE '%...%'). Это отличается от некоторых ODBC SQL драйверов, где кавычки не требуются.
* Псевдонимы таблиц: Рекомендуется использовать псевдонимы для таблиц (1SJOURN AS Журнал) для улучшения читаемости и предотвращения конфликтов имен.
* Специфичные поля 1С: Поля 1С, такие как реквизиты документов или справочников, часто имеют имена вида spXXXX (например, sp1033 для количества). Объект OLEDBData позволяет обращаться к ним напрямую, если они указаны в запросе.
Если по каким-то причинам метод ПрисоединитьИБ() не подходит или нам требуется более тонкий контроль над преобразованием метаданных, мы можем использовать объект MetaDataWork из той же компоненты 1С++. Этот объект позволяет вручную преобразовать текст SQL-запроса с метаименами 1С в текст запроса с физическими именами таблиц и полей DBF.
// ПутьИБ - это переменная, содержащая полный путь к каталогу информационной базы 1С
ПутьИБ = КаталогИБ();
глМД = СоздатьОбъект("MetaDataWork");
// Присоединяем файл метаданных 1Cv7.md
глМД.ПрисоединитьМД(ПутьИБ + "1Cv7.md");
ТекстЗапросаСМетаименами = "
|SELECT
| Журнал.DOCNO AS Документ_ном,
| Журнал.DATE AS Дата,
| ТМЦ.DESCR AS Товар
|FROM
| 1SJOURN AS Журнал
|INNER JOIN sc148 AS ТМЦ ON Журнал.IDDOC = ТМЦ.ID
|WHERE
| Журнал.DATE >= '20230101'
";
// Преобразуем метаимена в тексте запроса в физические имена
НовТекстЗапроса = глМД.ОбрМетаСКЛ(ТекстЗапросаСМетаименами);
Сообщить("Преобразованный SQL-запрос:");
Сообщить(НовТекстЗапроса);
// Далее выполняем преобразованный запрос через OLEDBData.ВыполнитьИнструкцию()
// Пример:
// БД = СоздатьОбъект("OLEDBData");
// СоединениеСтрока = "Provider=VFPOLEDB.1;Data Source=" + ПутьИБ + ";Exclusive=No;Mode=ReadWrite;Collating Sequence=MACHINE;Deleted=Yes";
// БД.Соединение(СоединениеСтрока);
// РезультатЗапроса = БД.ВыполнитьИнструкцию(НовТекстЗапроса);
Метод ОбрМетаСКЛ() (или ProcessMetaSQL) объекта MetaDataWork принимает текст запроса с метаименами 1С и возвращает текст запроса, где эти метаимена заменены на реальные названия таблиц и полей в DBF-файлах.
Проанализируем некоторые важные аспекты, которые следует учитывать при работе с провайдером VFPOLEDB.1:
* Кодировка: Проблемы с кодировкой могут возникать, если 29-й байт в заголовке DBF-файла, отвечающий за кодировку, не установлен в нужное значение (например, 65HEX для кириллицы). Провайдер FoxPro ориентируется на эту метку, и изменение параметра Collating Sequence или CODEPAGE в строке подключения может не помочь, если байт в заголовке файла неверен.
* Поврежденные файлы: VFPOLEDB.1 может выдавать ошибки о повреждении DBF-файлов ("has become corrupted"), если заголовок таблицы неверен (например, некорректно указано количество строк). Некоторые программы-вьюеры могут открывать такие файлы без проблем, но запросы через OLEDB могут завершаться ошибкой.
* Производительность: Несмотря на то, что SQL-запросы через OLEDB быстрее, чем прямой перебор через XBASE, производительность при работе с DBF через VFPOLEDB.1 может быть заметно ниже, чем при работе с SQL-базами данных (например, 2-3 секунды против долей секунды для аналогичных запросов). Использование индексов в DBF-файлах может значительно ускорить работу.
* Совместный доступ: Использование VFPOLEDB.1 позволяет работать с DBF-файлами в режиме совместного доступа (Exclusive=No), что является преимуществом по сравнению с объектом XBASE в 1С v7, который обычно требует монопольного доступа для записи.
* Локальные копии: При интенсивной работе с DBF-файлами, особенно расположенными по сети, рекомендуется копировать их в локальную папку для обработки. Это снижает сетевую нагрузку, повышает стабильность и производительность.
* Индексирование: Для ускорения запросов убедитесь, что DBF-файлы имеют необходимые индексы по полям, используемым в условиях WHERE и в соединениях JOIN.
* Тестирование: Всегда тщательно тестируйте соединение и запросы на тестовой базе данных, прежде чем применять их в рабочей среде.
Мы выяснили, что наиболее эффективным и универсальным способом работы с DBF-базами 1С v7 через OLE DB является использование компоненты 1С++ с объектом OLEDBData и методом ПрисоединитьИБ(). Этот подход позволяет нам использовать мощь SQL-запросов, работая при этом с привычными метаименами 1С, значительно упрощая и ускоряя доступ к данным.