Delphi подключение к базе 1с

Обновлено: 04.07.2024

Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.

Прямой доступ к базе данных 1С

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

В завершение всего, данные, получаемые посредством OLE не очень полезны - часто показываются только те данные, которые действительны на данное время. Так, например, курс валют будет показываться на дату системы, а не выводиться таблица изменений курсов валют.

Поэтому, изрядно повозившись с OLE-механизмом я всё таки решил реализовать прямой доступ к 1С.

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

Прямой доступ к таблицам в формате dbf-файлов

Прежде всего, необходимо было выбрать компоненты для доступа к таблицам 1С. К dbf-файлам можно получить доступ с помощью BDE, ODBC или компонент прямого доступа. Первые два способа я сразу же отмёл, остался - третий.

Хранение информации в 1С

Теперь рассмотрим где же взять информацию о таблицах 1С.

1С для каждого справочника создаёт отдельную таблицу. Таких таблиц получается достаточно большое количество и догадаться о назначении каждой из них довольно тяжело.

Прежде всего следует отметить, что 1С создаёт пары файлов: .DBF-файл (данные) и одноимённый .CDX-файл (индексный файл).

Мы можем CDX файлы удалить - потери информации не будет, так как это индексные файлы. При запуске 1С в монопольном режиме автоматически создадутся необходимые индексные файлы.

Информацию о любом файле базы данных и любом поле Вы можете почерпнуть из текстового файла 1Сv7.DD.

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

Пароли пользователей хранятся в папке usrdef. Если удалить этот каталог, то можно входить в систему 1С без пароля с наибольшими правами.

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

Заключение

Если Вы собираетесь делать шлюз, то предусматривайте в программе возможность программирования, т.к. многие поля придётся декодировать и адаптировать под данные Вашей системы. Но это уже тема отдельной статьи.

Насколько мне известно, многие 1С-ники хотели бы изучить написание внешних компонент, чтобы поднять свое магическое искусство 1С на качественно иную ступень.

Что этому может помешать? Во-первых, известный синдром компонентофобии (который исторически берет свое начало от криво написанных внешних компонент). Во-вторых –синдром клинически запутанного кода. OLE-программирование – это не самая простая штука, и, как говорится, «не всякая птица долетит до середины Днепра» (особенно, если эта «птица» – программист 1С).

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

Сборка проекта

Для компиляции примера потребуется среда разработки Delphi 6 или 7.

Файл проекта - TestVK.dpr.
Откройте этот файл (например, двойным щелчком мыши из Проводника).
Нажмите сочетание клавиш Ctrl-F9 (или пункт меню Project-Compile). Если все прошло нормально, в этой же папке образуется готовая внешняя компонента TestVK.dll (для проверки, а все ли хорошо, ее можно удалить, и получить готовую TestVK.dll еще раз).

Проверка работоспособности DLL

В комплект примера входит тестовая конфигурация 1С:Предприятие 7.7.

Переименование DLL

Первое, что я делаю при создании новой внешней компоненты – переименовываю уже существующий образец.

Переименуйте TestVK.dpr так, как вы хотите (например, MyVK.dpr).

Произведите замену всех вхождений подстроки TestVK в файлах проекта на нужное вам имя внешней компоненты.

Подсказка: чтобы открыть другие модули проекта, используйте пункт меню View-Units…

Программный код 1С, разумеется, также нужно не забыть изменить так, чтобы заменить все подстроки «TestVK».

Важно: замените значение CLSID внешней компоненты, чтобы новая DLL, с точки зрения Windows, стала действительно новой.

Чтобы сгенерировать новый CLSID, нажмите сочетание клавиш Ctrl-Shift-G.

Попробуйте скомпилировать новый проект – 1С должна «увидеть» вашу новую внешнюю компоненту, которая создана на основе другой ВК, но содержит полный набор ее свойств и методов.

Что такое свойства и методы?

Новички могут задаться вопросом, а что такое свойства и что такое методы?
В коде 1С свойства выглядят как, своего рода, «переменные», объекта, доступные через точку, например

Здесь объект – имеет имя vk (посмотрите, как он объявляется и инициализируется в глобальном модуле 1С).. Этот объект поддерживает свойства и методы.

В этом коде я установил свойству "Заголовок" текстовое значение (посмотрите, как будет работать пример, если установить этому свойству другое значение заголовка, например, «Здесь был romix», или не устанавливать его вовсе).

Метод объекта – это, своего рода, «функция» объекта, доступная «через точку».

Изменение списка свойств и методов ВК

В модуле AddinObj.pas за количество свойств отвечают участки кода, которые я пометил (*2*), (*5*), (*6*), (*8*), (*11*) а за количество методов - (*3*), (*7*), (*9*), (*10*), (*12*).

Я завел в шаблон по 5 свойств и методов, но что нужно сделать, чтобы их стало 6, например, в приведенном ниже фрагменте кода, - я надеюсь, понятно без объяснений.

Вы можете завести свойства и методы «с запасом» - лишние заготовки не повредят (их можно будет оставить пустыми).

Программирование функциональности свойств

Откройте (через меню View – Units…) модуль vk_object.pas

Для свойств вы увидите примерно такой код, продублированный, с небольшими отличиями, несколько раз: Это самая важная часть наших действий, которую важно постараться понять.

Что я здесь делаю?

Программирование функциональности методов

Для методов код похожий:

Этот абзац можно воспроизвести несколько раз (что и сделано в примере), заменив meth1 на meth2, meth3 и т.д.

Приведенные ниже строчки устанавливают русское и английское имя метода.

Попробуйте изменить то или другое, перекомпилировать проект и посмотреть, что получится.

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

Подробнее код я опишу ниже – но сначала полезно потренироваться со вставкой в него отладочной печати (именно так я исследую код).

Возвращаемое значение функции

Чтобы вернуть значение из функции, надо установить переменную g_Value, например:

Отладочная печать

Вы можете в качестве теста вписать в функциональность метода что-то свое, например,

Этот вызов покажет стандартное окно предупреждения с кнопкой ОК. Или вот так:

Во втором случае, если Delphi будет ругаться при компиляции, добавьте Dialogs в раздел uses модуля.

Получение параметров функции

В своей функции я завел две переменные для хранения параметров:

Сейчас мы их заполним значениями, полученными из 1С.

Параметры нумеруются, начиная с 0 (давняя традиция программистов на языке С).

Чем отличаются AsString и AsInteger, надеюсь, понятно.

Этот код можно было бы написать и так:

Отладочная печать параметров

При отладке полученные из 1С значения полезно выводить на экран. Но как это сделать?
Я обычно использую следующий прием:

Чтобы показать строковые переменные, я пишу так:

А числовые значения и значение типа "дата-время" я отображаю примерно так:

Функциональность методов

Получив все значения из 1С, можно приступать к собственно написанию полезного кода.

Узнавать, как работают те или иные функции API, можно в поисковых машинах или в сборниках Delphi FAQ, которые в изобилии выложены в сети Интернет.

Есть какая-то стандартная функция, возвращающая соединение к SQL собственной базы? Надо UPDATE запустить. Типовая вещь должна быть вроде.

Но для этого нужны 5 секунд поиска и 1 примитивнейший запрос в поисковик

(0) С чего это типовая вещь и почему она должна быть? 1С в клиент-сервере - это трехзвенка, доступ до СУБД никто не обещал.

В общем за все эти годы одинэсники даже самое простое не написали.

(7) Ага. Извини, пожалуйста - придется тебе самому. Справишся?

(7) Они написали самое простое. То, что обычно не читают. Называется "лицензионное соглашение".

(11) И что тебе в этой статье не понятно? Там же всё черным по белому расписано.

(11) Готовой функции ПолучитьЗначениеИзБазы нет в статье. Написано что есть ADODB или SQLOLEDB или. А готового нет.
Зачем понятия подменять? при чем тут "понятно" и "есть готовое"?
Там написано "Учимся получать доступ к СУБД из 1С." Чем оно готовое? Как раз наоборот.

В статье тоже не готовое. Хотя на готовое ПолучитьЗначениеИзБазы в примерах ссылает.

Как это связано с тем, что ПолучитьЗначениеИзБазы нет?

Штаны тоже можно научиться шить самому, все разжевано. Бурда моден а не среда.

"Есть какая-то стандартная функция, возвращающая соединение к SQL собственной базы?" - и каждый как обычно разговаривает что-то свое. А по теме нечего сказать?

864666 попытка завести тематическую ветку.
"Видимо, место здесь такое" (с) Жмурки

(21) Значит автор и ему подобные врут про ПолучитьЗначениеИзБазы(ТекстЗапросаSQL)?

+(23) есть в открытой публикации хоть одна такая функция?
(24) Не Жужжите.

(0) Доступ к БД иначе как средствами 1С запрещен лицензионным соглашением. А 1С не предоставляет прямого доступа к базе, потому что 90% 1Сников положат базу, будь у них такая возможность. Запускать UPDATE при работающем серверном процессе - вообще за гранью добра и зла. У сервера есть свой кеш, и он не рассчитан на то, что кто-то будет запускать UPDATE в базе.

(26) В соседней ветке один друг пытается 470 000 пачек сигарет отгрузить одной фурой и у каждой пачки своя марка. А после этого ему надо базу 1С свернуть по прошлым периодам. Что же будет делать 1С в связи с этим?

(27) Доработает интерфейс программы, чтобы коробки лучше продавались.

(28) Какой интерфейс? Будут блокнотики и карандашик в коробку вкладывать? Скажут "работайте на мягких регистрах".

(31) ну иди в фузину. Зачем в 1с пришел? Изначально же понятно, что это тормоза?

(27) 1С тут не лимитирующий фактор. Ведь эти коды надо еще сосканировать каждый ;)

(0) Чего сложного через ADODB.Connection порубиться, и делай что хочешь.

(35) Да, давно пора перевести на rfid. А потом заказать в Китае сканеры, которые полмиллиона кодов за раз берут. Кетайцы оху@ют и пришлют две деревни крестьян в контейнере.
(36) Чего сложного написать свою ОС на ассемблере.
были люди в наше время, Не то, что нынешнее племя: Богатыри — не вы! Плохая им досталась доля:

(37) Да, Вася. Тебе до твоего тёзки - как Маску до Альфы Кассиопеи в позе гордого моллюска.

(37)обычно говорят я делал то-то и то-то.Что не получилось. А ты ничего не сделал, не попробовал, а просто требуешь готовое. "А кушать вы за меня тоже будете?" Ага!

(38) Одинэсу до консоли скуля видимо ближе.
(39) Кто кому говорят? В смысле чтобы функция появилась нужно позаклинать?

Человеку нужно соединение с БД на прямую, для которого и через ADODB.Connection нужены Логин/Пароль на SQL, не говоря уже о адресе сервера и имени БД, которые можно получить средствами 1С.
Логин/Пароль нельзя получить из снеговика.

(39) Точно.
(40) Нет, заклинанание не надо. Надо миллион долларов и личная встреча с братьями Нуралиевмыи, чтобы они за эти деньги дали команду своим наемным работникам добавить в платформу "1С:Предприятие 8" ту функциональность, что тебе нужно.
ПыСы: сумма взята с потолка, реальная сумма выяснится после того, как сторгуешься с братьями Нуралиевмыи

+(42) Читать: братья Нуралиевы. Это была опечатка, а не коверкание.

(41) У снеговика оно все уже есть. Иначе как он в скуль ходит?
(44) Сестры сделали матрицу, а у этих сплошное дежавю. Все чего-то меняют.
(45) Ни разу пока.
(47) Нет, их в муках рожают.
(48) Не подсказывай.

(48) восхищённый зритель видит чудо, и радуется
а где-то в сторонке кто-то читает заклинание. потому и магия.

(50) А где функция-то? Расскажите подробнее чего Нуралиевы читают.

У майкрософта консоль, у оракла SQL*Plus, а у 1С - лицензионное соглашение.

(52) У 1са тоже есть консоль. И не одна. Для своего языка.

Который за 100 часов делает то, что напрямую выполняется за 25 секунд..

(54) А напрямую ты все обработчики Перед и При записи вызвал? А подписки?

(60) Пруф на что? На то, что 1с работает через объектную модель и у каждой записи могут быть обработчики событий? Так это тебе в книжки для начинающих.

(61) В книжках есть про внешний источник данных (ВИД). Там никаких событий вроде нет, но ограничения на изменение данных. Никакой объектной модели. Как раз чтобы её не обошли и не построили на ВИД свои быстрые регистры и прочее введено ограничение, а так же Лицензионным соглашением. Не может одинэска конкурировать с другими решениями по скорости.

(62) Совсем запутал. Ты же вроде хотел получить программный доступ до таблиц самой базы, а теперь говоришь о внешних источниках данных. Чего в итоге-то ты хочешь? Или ты просто стебешься тут на форуме?

(62) Вот интересно. А почему ты не хочешь записать в базу SQL напрямую, редактируя секторы на диске? Это ж какая скорость получается!

Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.

1C + Delphi 5: Простой пример подключения к Базе Данных 1C

(через OLE; в данном случае рассматривается подключение к "1C-предприятие версии 7.7")

Создадим простое приложение, которое считывает список из справочника "ФизическиеЛица".

Пример (в формате MS Word) можно скачать здесь (792 Кб)

Шаг N 1. (скачать, 177 Кб)

Создадим проект с именем Project1
Положим на форму 2-а компонента типа TPanel (у Panel1 свойство Align установим равным AlTop, а у Panel2 - AlClient)
На Panel1 положим кнопку Button1 (TButton) и установим свойство Caption = "Соединить"
Положим на Panel1 еще 4 компонента :
Label1, Edit1, Label2, Edit2
Установим :
- свойство Caption :
Label1.Caption - "Имя 1C-сервера Строка инициализации V77.Application"
Edit2.Text - "/DF:\1CV77\ATCDEMO"


Должно получиться что-то вроде этого:

Некоторые пояснения.
Edit1.Text содержит имя 1C, как OLE - сервера автоматизации.
В нашем случае мы указали : V77.Application
Возможные значения (согласно документации по 1C) :
- V1СEnterprise.Application - версия независимый ключ;
- V77.Application - версия зависимый ключ;
- V77S.Application - версия зависимый ключ, SQL версия;
- V77L.Application - версия зависимый ключ, локальная версия;
- V77M.Application - версия зависимый ключ, сетевая версия.
Edit2.Text содержит строку инициализации 1C
В нашем случае мы указали : /D F:\1CV77\ATCDEMO
Т.е., указали только местонахождение Базы Данных, к которой желаем подключиться
(в этом примере : указан каталог F:\1CV77\ATCDEMO)
Возможные значения ключей (согласно документации по 1C) :
/D - Имя каталога (папки), где располагается База Данных
/N - Имя Пользователя
/P - Пароль доступа
Пример : /DC:\1CV77\ATCDEMO /NАдмин /P123

В исходном тексте программы добавим следующее (выделено жирным красным цветом) :
uses
ComObj,
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
< Private declarations >
Ole1C : OleVariant;
public
< Public declarations >
end;

Переменная Ole1C (типа OleVariant) будет использована в дальнейшем, как указатель на объект 1C (OLE - сервер автоматизации).


Сделаем двойной щелчок по компоненту Button1 и изменим стандартный обработчик события - нажатие на кнопку - следующим образом :
procedure TForm1.Button1Click(Sender: TObject);
Var
ResOpen : integer;
begin
Ole1C := CreateOleObject(Edit1.Text);
ResOpen:=Ole1C.Initialize(Ole1C.RMTrade, Edit2.Text, '');
end;

Строка :
Ole1C := CreateOleObject(Edit1.Text);
собственно, "запускает" программу 1C, как OLE - сервер автоматизации (имя указано в Edit1.Text)

Строка :
ResOpen:=Ole1C.Initialize(Ole1C.RMTrade, Edit2.Text, '');
инициализирует 1C, согласно нашим "указаниям" (Edit2.Text)

Более подробно можно почитать соотв. документацию по 1C

Откомпилируем и запустим приложение Project1.exe
Нажмите на кнопку " Соединить ".
Если все указано корректно (содержание Edit1.Text и Edit2.Text ),
программа 1C должна запуститься (как OLE сервер автоматизации).


Если в строке инициализации НЕ указаны имя пользователя и(или) пароль доступа, то следует запрос :


Если не корректно указан каталог Базы Данных, то следует запрос :


После загрузки и инициализации программы 1C, ссылка на 1C хранится в переменной Ole1C.
Следует помнить, что программа 1С:Предприятие (как и все создаваемые объекты OLE Automation), выступающая в качестве объекта OLE Automation в другой программе, будет находиться в памяти компьютера до удаления или изменения значения переменной, содержащей ее в качестве объекта.
Именно поэтому, мы вынесли объявление переменной Ole1C "за пределы" обработчика : TForm1.Button1Click


Явных (видимых) признаков того, что мы запустили 1C - нет.
Для того, что убедиться в этом, нужно запустить диспетчер задач (по комбинации Ctrl+Alt+Del).
В списке задач можно увидеть :

Следует отметить, что после того, как Project1.exe будет закрыт - автоматически выгрузится из памяти и 1C.

Шаг N 2. (скачать, 180Кб)
Продолжим наш проект.


На Panel2 положим компонент ListBox1 (TListBox). Свойство Align установим равным AlClient.
Рядом с кнопкой Button1 ("Соединить") положим на Panel1 кнопку Button2 (установим свойство Caption = ФизЛица)
Получится что-то вроде этого :


В исходном тексте программы добавим описание переменной OleFizLica

private
< Private declarations >
Ole1C : OleVariant;
OleFizLica : OleVariant;
public
< Public declarations >
end;

Сделаем двойной щелчок по компоненту Button2 и изменим стандартный обработчик события - нажатие на кнопку - следующим образом :

procedure TForm1.Button2Click(Sender: TObject);
begin
OleFizLica := Unassigned;
if not VarIsEmpty(Ole1C) then begin
OleFizLica:=Ole1C.CreateObject('Справочник.ФизическиеЛица');
end;
end;

Строка :
OleFizLica := Unassigned;
Здесь "обнуляется" значение переменной OleFizLica.
Тем самым, если ранее был создан какой-либо OLE-объект, на который ссылалась эта переменная, он будет уничтожен.

Строка :
if not VarIsEmpty(Ole1C) then begin
Здесь проверяется, чтобы значение переменной Ole1C не было "пустым".
Т.е., если Ole1C имеет "не пустое" значение, то это значит (в контексте нашего проекта), что программа 1C запущена и связь с ней установлена.

Строка :
OleFizLica:=Ole1C.CreateObject('Справочник.ФизическиеЛица');
Здесь создается объект, который ссылается на справочник "ФизическиеЛица".
Если такой справочник существует, то в дальнейшем, переменная OleFizLica будет содержать ссылку на него.

Шаг N 3. (скачать, 184 Кб)

Сделаем двойной щелчок по компоненту Button2 и еще раз изменим обработчик события нажатия на кнопку следующим образом :

Строки N 3,4,5,6 теперь понятны.

Строка N 7 :
if not VarIsEmpty(OleFizLica) then begin
Здесь проверяется, что объект, ссылающийся на справочник "ФизическиеЛица" действительно создан.

Строки N 8..13
Здесь реализован стандартный алгоритм на языке 1C по перебору элементов справочника.

Строка N 11
ListBox1.Items.Add(OleFizLica.Код+' '+OleFizLica.Наименование);
Здесь продемонстрирован один из вариантов обращения к реквизитам справочника по именам.

Строка N 16
OleFizLica := Unassigned;
Здесь "обнуляется" значение переменной OleFizLica.
Тем самым, мы уничтожаем созданный нами объект, чтобы зря не занимать ресурсы.
Следует отметить, что поскольку (в нашем случае) мы используем переменную OleFizLica только в "пределах" обработчика
procedure TForm1.Button2Click(Sender: TObject), то мы могли бы и объявить эту переменную в этом обработчике.


Откомпилируем и запустим приложение Project1.exe
Нажмите на кнопку " Соединить ". После того, как загрузится программа 1C, нажмите на кнопку " ФизЛица ".
Если все указано корректно , то в ListBox1 будет содержание справочника "ФизическиеЛица".
Т.е., будет что-то вроде этого :

Читайте также: