Имя: Пароль:
1C
 
Нужен пример работы с 1С 8.0 на Delphi по COM или OLE
0 inimeg
 
27.12.07
18:11
Прочитал соответствующий топик v8: V8.COMConnector и Delphi

Все здорово но что это за интерфейс IV81COMConnector? Как мне его подключить? Откуда взять?

И еще вопрос. Попробовал реализовать через V8.Application (Automation). Автор пишет что проблема с русскими именами пропала. А у меня както она на месте. Все теже "Метод Справочники не поддерживается объектом автоматизации". Что я делаю не так? Где чего не подключил-включил?

Работаю на Delphi2005+1C v8.1 (v8.0 таже проблема)

Заранее благодарен за любую полезную информацию на эту тему. А то с 8 всего 3 дня как познакомились в отличии от 7. И отношения никак не наладятся ;)
1 shachneff
 
27.12.07
18:51
Дай ссылку на тему, где я написал, что проблема решена... Не могу сам найти
2 shachneff
 
27.12.07
18:53
3 shachneff
 
27.12.07
18:54
(2) Использовал Delphi 6, 1C v8.0.18
4 inimeg
 
28.12.07
11:37
У меня такое подозрение что в Delphi2005 что-то с OLE изменили. Работают только английские аналоги методов 1C да и то не все а через 1...ж(
5 Кураж
 
28.12.07
11:40
(0) Может быть найдешь для себя что-то полезное:
http://doc-prg.narod.ru/index_1cv8.htm
6 inimeg
 
28.12.07
11:47
Кураж -  Спасибо. Это я уже читал. Про Эмуляцию EvalExpr там хорошо написано. Но вот с остальным... Беда в том что я пока вобще не могу так настроить соединение с 1С чтобы мог использовать конструкции языка на русском. ж(

shachneff - А ты не мог бы поделится каркасом приложения? Интересует как ты до интерфейса IV81COMConnector достучался. Может быть у меня в этом проблема?
7 shachneff
 
28.12.07
12:15
(6) Я тогда решал задачу автоматического запуска обработок... Давно это было, а потом появились регламентные задания и все дельфевые приложения канули в лету... Но если не срочно, то я могу попробовать дома повторить подвиг...
8 inimeg
 
28.12.07
12:27
shachneff - буду признателен за помошь. Срок исполнения как всегда вчера, но я пока всеравно ковыряюсь безуспешно, так что буду ждать. Если озарение прийдет раньше отпишусь.
9 Hadgehogs
 
28.12.07
12:37
Ну все же написано про COMConnector в (5)
http://doc-prg.narod.ru/art_00001/art_00001.htm
Что конкретно не получается?
10 laview
 
28.12.07
13:13
А может быть кто нибудь скажет, что лучше Delphi или Visual Studio?
1C советует все делать на Visual Studio, а я в институте Delphi изучал. Он мне понятнее. В чем между ними разница с точки зрения создания Web приложений для 1С?
11 Hadgehogs
 
28.12.07
13:18
ну все, счаст начнется...
12 Salvador Limones
 
28.12.07
13:31
(10) Как можно сравнивать Delphi и Visual Studio?
13 shachneff
 
28.12.07
13:34
Вот мой код, который был в примере, но поправленный под 8.1.

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, V81_TLB, ComObj;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var

Form1: TForm1;
V81: IV8COMConnector = nil;
MainObject: OleVariant;


implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin

V81 := CreateOLEObject('V81.COMConnector') as IV8COMConnector;

MainObject := V81.Connect('Srvr="enterprise";Ref="Trade";usr="Шачнев Алексей";pwd="SHA"');

ShowMessage(MainObject.Метаданные.Справочники.Банки.Комментарий);

end;

end.

Обрати внимание на 2 последних модуля в секции uses.

Так же необходимо импортировать в проект модуль V81_TLB (Project - Import Type Library. Встать на "1CV81 COM Connector". Нажать Create Unit. Для того, чтобы это получилось, на компе должна быть установлена 1С 8.1
14 laview
 
28.12.07
13:57
А готовые шаблоны (которые вместе с web расширением) v8webApplication и v8webService в Delphi тоже можно использовать?
15 inimeg
 
28.12.07
14:33
Hadgehogs-  соединится получается. Соединение есть. А вот конструкции типа s1C8_ole.Справочники выдают ошибку. Вот что конкретно не работает.

shachneff-  Вот ведь...Project - Import Type Library нету такого пункта в Delphi2005 ж(
16 inimeg
 
28.12.07
14:45
Так... Новые сведения с полей.
Вобщем как подключить  V81_TLB в Delphi2005 разобрался. Новый Com Object Delphi 32 и там в качестве родителя выбираем IV8COMConnector.
Теперь беда другая.

На этой строке
ShowMessage(MainObject.Метаданные.Справочники.Банки.Комментарий);
Выдает окно

Method 'P   P  C oPг'PoPSPSC<P  ' not supported by automation object.
Такое впечатление что русские наименования после компиляции не подходят под кодировку с которой работает 1С. Есть соображения на этот счет?
17 shachneff
 
28.12.07
14:51
(16) Набей русские строки руками, а не копируй из форума.
18 shachneff
 
28.12.07
14:52
(16) Плюс я натравил Дельфю на типовую Управление Торговлей. У тебя таких метаданных может не быть!.
19 inimeg
 
28.12.07
15:02
shachneff метаданные точно есть. Типовая Бухгалтерия.
В отладчике пишет
Project SDIAPP.exe raised exception class EOleError with message 'Method 'Meтaдaнныe' not supported by
automation object'.

А вот в рантайме выводит
20 inimeg
 
28.12.07
15:04
shachneff метаданные точно есть. Типовая Бухгалтерия.
В отладчике пишет
Project SDIAPP.exe raised exception class EOleError with message 'Method 'Meтaдaнныe' not supported by
automation object'.

А вот в рантайме выводит
Method 'P   P  C oPг'PoPSPSC<P  ' not supported by automation object.

Если меняю Meтaдaнныe на синони Metadata то пишет тоже самое но для Справочники
Если их меняю на Catalogs то ругается на Банки и т.д.

Нашол в настройках проекта пункт code page. Может с ним поиграться?
21 shachneff
 
28.12.07
15:05
(19), логично, позднее связывание :-)

Ну поиграйся с преобразованием строки в кодировку UTF-8, а затем эту строку выполни...
22 shachneff
 
28.12.07
15:06
(20) да... 1С работает с UTF-8
23 inimeg
 
28.12.07
15:09
Вроде как 1С работает с кодировкой UTF-8 Я прав? А числовое представление этой кодировки что-то найти не могу. В code page можно только числовое значение ввести.
24 inimeg
 
28.12.07
15:10
shachneff ж) Опередил.
Погоди, а как можно строку типа
ShowMessage(MainObject.Метаданные.Справочники.Банки.Комментарий);
Задать в UTF-8 ? этож посути команда... блин.. что-то я туплю ж(
25 Балабес
 
28.12.07
15:11
стабильно работает только запуск через командную строку
26 Биньковский Виталий
 
28.12.07
15:13
поставь Delphi v7
27 inimeg
 
28.12.07
15:16
БиньковскийВиталий- ;) Если бы все было так просто ж) Это не решение.
Балабес - это к чему?
28 inimeg
 
28.12.07
16:07
Числовое представление нашол 65001. Поменял. Не помогло. Поменял кодировку у pas. Не помогло. Не представляю куда теперь двигаться дальше. Срочно нужна помошь ж)
29 shachneff
 
28.12.07
16:47
(28) Специально ради тебя дома скачаю Дельфю 2005 и покажу, как решить твою проблему. Решу виртуально, поэтому стребую виртуальное пиво.
30 inimeg
 
28.12.07
17:04
shachneff - не вопрос ж) Я даже реального согласен поставить с доставкой ж)
31 Биньковский Виталий
 
28.12.07
17:12
Ситуация у тя сложная, если верно(22), в 2005 текст юникоде. Есть сложный путь, как то делал. Нужно подменить делфевый механизм диспетчеризации типа Variant. у меня в результате было примерно так (коммент из реализации) (не пинайте, писалось хрен знает когда)

{--------------------- Mpc-интерпретация вызовов IDispatch --------------------}
{
количество параметров - не менее одного
имя функции или процедуры (любое, Ini есть Variant - переменная) -
   неуточненное (см. ниже) имя параметра

последний параметр (чаще единственный):

   при вызове как функции - значение по умолчанию,
   возвращается если параметр не сохранялся ранее.
   всегда необходим по крайней мене для опознавания типа искомого значения.
   Важное замечание:
       При передаче float - абсолютных значений
       (пример MayLastRadius := Ini.MayLastRadius(3.14))
       количество знаков должно быть более 4
       (MayLastRadius := Ini.MayLastRadius(3.14000), иначе будет
       производиться поиск Currency - значения, при сохранении
       параметр также будет записан как Currency, и при последуюжем чтении
       будет ошибка. При этом MayLastRadius := Ini.MayLastRadius(6.28 / 2)
       будет нормально распознан как поиск Double - значения.
       Это не относится к параметрам по ссылке:
       var
           D: Double;
       begin
           D := 1;
           Ini.MayDoubleValue(D); // корректно, поиск именно Double а не Currency

   при вызове как процедуры -  сохраняемое знаачение.

предпоследний параметр:
   при количестве параметров более двух -
   уточнение имени параметра, удобен при сохранении в цикле.
   тип может быть любым, логичен Integer или string.
   при уточнении ключа (параметров более двух) и отсутствии
   необходимости уточнения имени параметра передать пустую строку

   при количестве параметров равным двух -
   уточнение ключа. можно вызвать FullNameComponent:
       запись
       Ini.Height(FullNameComponent(Self), Height);
       чтение
       Height := Ini.Height(FullNameComponent(Self), Height);


при количестве параметров более двух - все до предпоследнего
рассматриваются как уточнение ключа относительно базового (Kernel.MainKey)
все приводятся к string, допустима передача к примеру счетчика цикла.
последний из них может не заканчиваться '\'.

передаваемые параметры могут иметь тип Variant, но тогда должны быть
инициализированны(иметь тип), иначе будет сгенерированно исключение.

исключение будет сгенерированно также при отсутствии параметров (см. выше)

var
   MayVarArray: Boolean;
begin
   MayVarArray := Ini.MayVarArray[Name + '\', 'Button123\', 0987654321, 555, False];
   псевдокод
   if OpenKey(MaiKey + 'Form1\Button123\0987654321\', False) and Reg.ValueExists('MayVarArray555') then
       Result := ReadBool('MayVarArray555')
   else
       Result := False;
   это галимотья,    пореальней -
procedure TForm4.FormCreate(Sender: TObject);
begin
   (шииирина и высота формы)
   Width        := Ini.Width(Name, Width);
   Height    := Ini.Height(Name, Height);

   ToolButton1.Down := Ini.ToolButton1Down(False);

   AddingMode                                    := Ini.AddingMode(Ord(emFirst));
   actCloseMainWindow.Checked    := Ini.CloseMainWindow(False);
   actShowEditor.Checked                := Ini.ShowEditor(False);
   actShowPropsHost.Checked        := Ini.ShowPropsHost(True);
   actShowTags.Checked                    := Ini.ShowTags(True);
   actShowHierarchy.Checked        := Ini.ShowHierarchy(True);
   actShowHiddden.Checked            := Ini.ShowHiddden(False);
   actMultiSelect.Checked            := Ini.MultiSelect(False);
   actShowTags.Checked                    := Ini.ShowTags(True);

   for i := 0 to MaxInt do (восстанавливаем состав и ширину столбцов)
   begin
       PropID := Ini.Column('LeafTree', i, MaxInt);
       if PropID = MaxInt then
           Break;
       AddSection(PropID, Ini.Width('LeafTree', i, 120));
   end;
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
   (шииирина и высота формы)
   Ini.Width(Name, Width);
   Ini.Height(Name, Height);

   Ini.ToolButton1Down(ToolButton1.Down);

   Ini.AddingMode(Ord(AddingMode));
   Ini.BrowserCount(pnlBrowsers.DockClientCount);
   Ini.ShowPropsHost(actShowPropsHost.Checked);
   Ini.CloseMainWindow(actCloseMainWindow.Checked);
   Ini.ShowEditor(actShowEditor.Checked);
   Ini.ShowTags(actShowTags.Checked);
   Ini.ShowHierarchy(actShowHierarchy.Checked);
   Ini.ShowHiddden(actShowHiddden.Checked);
   Ini.MultiSelect(actMultiSelect.Checked);
   Ini.UseSuiteLink(actUseSuiteLink.Checked);

   i := 0;
   if Kernel.Reg.OpenKey(Kernel.MainKey + 'LeafTree', False) then
   begin
       (удаляем старый состав и ширину колонок)
       while Kernel.Reg.DeleteValue('Column' + IntToStr(i)) do
       begin
           Kernel.Reg.DeleteValue('Width' + IntToStr(i));
           Inc(i);
       end;
       Kernel.Reg.CloseKey;
   end;

   (сохраняем новый состав и ширину колонок)
   for i := 0 to HeaderSections.Count - 1 do
   begin
       Ini.Column('LeafTree', i, HeaderSections[i].Tag);
       Ini.Width('LeafTree', i, HeaderSections[i].Width);
       псевдокод
       StoreValue(Kernel.MainKey + 'LeafTree' + '\' + 'Width' + IntToStr(i), HeaderSections[i].Width);
   end;
end;
}
32 inimeg
 
28.12.07
17:44
БиньковскийВиталий - преклдоняю колено перед вашей выкладкой, но.... К чему она? Ничего не понятн, ровным счетом ничего. Можно более доступным языком?
33 Биньковский Виталий
 
28.12.07
17:51
никто не говорил что реализация тривиална.
когда вы обращаетесь к полям вариантной переменной, делфи вызывает функцию диспетчеризации. в вашем случае - MainObject.Метаданные. при старте её адрес лежит в VarDispProc. я её подменяю при инициализации модуля:

   SaveVarDispProc := @VarDispProc;
   VarDispProc := MpcVarDispInvoke;

моя реализация MpcVarDispInvoke


var
   SaveVarDispProc: Pointer; {указатель на оригинальную функцию диспетчеризации OLE}

procedure MpcVarDispInvoke(Result: PVariant; const Instance: Variant;
   CallDesc: PCallDesc; Params: Pointer); cdecl;
var
   ArgType: Word;
   ByRef: Boolean;

   function VariantFromPtr: Variant;
   begin
       case ArgType of
           varStrArg:
               if ByRef then Result := PString(Params^)^            else Result := PString(Params)^;
           varOleStr:
               if ByRef then Result := PWideString(Params^)^    else Result := PWideString(Params)^;
           varBoolean:
               if ByRef then Result := PBool(Params^)^                else Result := PBool(Params)^;
           varByte, varSmallint, varInteger:
               if ByRef then Result := PInteger(Params^)^        else Result := PInteger(Params)^;
           varSingle:
               if ByRef then Result := PSingle(Params^)^            else Result := PSingle(Params)^;
           varDouble:
               if ByRef then Result := PDouble(Params^)^            else Result := PDouble(Params)^;
           varDate:
               if ByRef then Result := PDateTime(Params^)^        else Result := PDateTime(Params)^;
           varCurrency:
               if ByRef then Result := PCurrency(Params^)^        else Result := PCurrency(Params)^;
           varVariant:
               if ByRef then Result := PVariant(Params^)^        else Result := PVariant(Params)^;
           else
               raise Exception.CreateFmt('Invalid DataType - %d', [ArgType]);
       end;
   end;

const
   atTypeMask = $7F;
   atByRef    = $80;
var
   FLock: TRTLCriticalSection;
   ArgCount: Integer;
   NameProp: string;
   Arg: Variant;
   Reg: TRegistry;
   Key: string;
   i: Integer;
   Delta: Integer;
begin
   if (@Instance = @Ini) then
   begin
       FLock := Kernel.IniLock;
       EnterCriticalSection(FLock);
       try
           ArgCount := CallDesc^.ArgCount;
           if ArgCount < 1 then
               raise Exception.Create('Not enough actual parameters');

           NameProp    := StrPas(@CallDesc^.ArgTypes[ArgCount]);
           Key := '';
           for i := 0 to ArgCount-1 do
           begin
               ArgType    := CallDesc^.ArgTypes[i] and atTypeMask;
               ByRef        := CallDesc^.ArgTypes[i] and atByRef > 0;
               Arg            := VariantFromPtr;
               if (ArgType = varVariant) and (Arg = Unassigned) then
                   raise Exception.Create('Variant parameters must be assigned');

               if i = ArgCount - 1 then
                   Break;
               if (ArgCount > 2) and (i = ArgCount-2) then
                   NameProp := NameProp + string(Arg)
               else
                   Key := Key + string(Arg);

               Delta            := 4;
               if ByRef then
               case ArgType of
                   varDouble, varCurrency, varDate: Delta := 8;
                   varVariant: if TVarData(Arg).VType <> varString then Delta := 16;
               end;
               Inc(Integer(Params), Delta);
           end;
           Key := IncludeTrailingBackslash(Kernel.MainKey + Key);

           if ArgType = varVariant then
               ArgType := TVarData(Arg).VType;

           Reg := Kernel.Reg;
           if Result <> nil then
           begin
               Result^ := Arg;
               if Reg.OpenKey(Key, False) and Reg.ValueExists(NameProp) then
               case ArgType of
                   varString, varStrArg, varOleStr:    Result^ := Reg.ReadString(NameProp);
                   varBoolean:                                                Result^ := Reg.ReadBool(NameProp);
                   varByte, varSmallint, varInteger:    Result^ := Reg.ReadInteger(NameProp);
                   varCurrency:                                            Result^ := Reg.ReadCurrency(NameProp);
                   varSingle, varDouble:                            Result^ := Reg.ReadFloat(NameProp);
                   varDate:                                                    Result^ := Reg.ReadDateTime(NameProp);
               end;
           end else
           begin
               Reg.OpenKey(Key, True);
               case ArgType of
                   varString, varStrArg, varOleStr:    Reg.WriteString(NameProp, Arg);
                   varBoolean:                                                Reg.WriteBool(NameProp, Arg);
                   varByte, varSmallint, varInteger:    Reg.WriteInteger(NameProp, Arg);
                   varCurrency:                                            Reg.WriteCurrency(NameProp, Arg);
                   varSingle, varDouble:                            Reg.WriteFloat(NameProp, Arg);
                   varDate:                                                    Reg.WriteDateTime(NameProp, Arg);
               end;
           end;
           Reg.CloseKey;
       finally
           LeaveCriticalSection(FLock);
       end;
   end else
   asm// вызов оригинала
       mov eax, Params;
       push eax;
       mov eax, CallDesc;
       push eax;
       mov eax, Instance;
       push eax;
       mov eax, Result;
       push eax;
       call SaveVarDispProc;
   end;
end;
34 Биньковский Виталий
 
28.12.07
17:52
моя реализация пишет/читает в реестр, в вашей нужно заменить одну кодировку на другую
35 Биньковский Виталий
 
28.12.07
17:56
пройди отладчиком (в assm!) при работе с вариантной переменной, там видно как компилятор подставляет вызов "родной процедуры", изучи её сырцы, куда параметры он сует. из этого видно:
   asm// вызов оригинала
       mov eax, Params;
       push eax;
       mov eax, CallDesc;
       push eax;
       mov eax, Instance;
       push eax;
       mov eax, Result;
       push eax;
       call SaveVarDispProc;
   end;
36 inimeg
 
28.12.07
17:57
БиньковскийВиталий - спасибо. Попробую вчитаться. Буду иметь в виду этот вариант решения, хотя он мне и кажется сложным. Всеравно спасибо за помошь.
37 Биньковский Виталий
 
28.12.07
18:03
и все-же, в чем сложность паралельно с 2005 D7 поставить?
38 inimeg
 
28.12.07
18:08
БиньковскийВиталий - теоретически сложности нет. Прийдется конечно вынести весь функционал работы с 1С из приложения написаного на 2005 в службу и направлять команды синхронизации уже ей скажем по TCP протоколу. Просто хотелось без лишних усложнений, но видимо не получится. Сейчас попробую конечно еще все это проверить на 2007 может там прокатит.
39 inimeg
 
07.01.08
18:04
Решение найдено. Для того что бы компилятор Delphi корректно компилировал структуры типа ole1Cv8.Метаданные.Справочники , в понятной для 1Сv8.1 кодировке необходимо у файла проекта выставить кодировку UTF8. Тоесть не у проекта а у самого пасника. ж) Как всегда все оказалось проще чем казалось на первый взгляд. Спасибо всем за помошь в поиске решения.