Имя: Пароль:
1C
1С v8
Передача Таблицы Значений в Delphi
, ,
0 steep1
 
09.01.12
21:42
Здравствуйте, есть com_object на дельфи.
подскажите как заполнить таблицу значений переданную из 1с в Delphi и вернуть обратно заполненную.
1 Dethmont
 
09.01.12
21:44
Разве в делфях есть такой тип Таблица значений?
2 Torquader
 
09.01.12
21:44
Интересно, а каким методом эта таблица значений попадает в Delphi, так как от метода попадания будет зависеть и способ заполнения.
3 steep1
 
09.01.12
21:46
(2) передача через параметр
ТаблицаЗначенийЗаполненная = comobject.GetTable(ТаблицаЗначенийПустая)
4 Torquader
 
09.01.12
21:49
То есть ты передаёшь стороннему OLE-объекту таблицу значений, а он получит "плохой тип переменной", так как таблицу ни во что преобразовать нельзя.
Если же будет внешняя компонента, то она получить IDispatch от таблицы значений и стандартными методами сможет её заполнить.
5 steep1
 
09.01.12
22:02
ком объект не сторонний, а мой. Мне бы исходники или пример как работать с ТЗ в дельфи
6 Dethmont
 
09.01.12
22:06
А что array не покатит?
7 steep1
 
09.01.12
22:17
(6) пробовал, но двухмерный массив нужен, а его передать нельзя насколько я понял.
8 Mashinist
 
09.01.12
22:31
Tab:=GetNParam(paParams,1); - из 1С передается таблица значений и она попадает в дельфи - второй параметр метода если считать от нуля...

Error:=Error+IsValueTable(Tab); - IsValueTable - функция проверяющая действительно ли передали таблицу значений

дальше выполним запрос и получим датасет
         if Error=0 then
         begin
           q:=Sql.OpenQuery(String(GetNParam(paParams,0)));

если все нормально - сконвертируем его в ТЗ
          if (Assigned(q)) and (sql.ErrorFlag = 0) then
           begin
             Error:=ConvertDataSetToValueTable(q,Tab);
           end

ConvertDataSetToValueTable(q,Tab); - конфертирует DataSet - тут уже нужно смотреть что есть у кого - в таблицу значений




{ Переводим DataSet в таблицу значений }
function TAddSQLObject.ConvertDataSetToValueTable(q: TDataSet; Tab: OleVariant): integer;
var
 Err: integer;
 i,j: integer;
 s: string;
 f: TField;
 Str: OleVariant;
begin
 Err:=IsValueTable(Tab);
 if Err = 0 then
 begin
   Tab.Очистить;
   if Assigned(q) then
   begin
     for i:=0 to q.FieldCount-1 do
     begin
       f:=q.Fields[i];
       if Ver1C = ver1cv8 then
         Tab.Колонки.Добавить(f.FieldName)
       else
         Tab.НоваяКолонка(f.FieldName,VT_EMPTY,VT_EMPTY,VT_EMPTY,f.FieldName,12);
     end;
     if Ver1C = ver1cv8 then
     begin
       while not q.EOF do
       begin
         Str:=Tab.Добавить;
         for j:=0 to q.FieldCount-1 do
         begin
           f:=q.Fields[j];
           if not(q.Fields[j].Value=null) then
           begin
             s:=f.AsString;
             if f.DataType=ftFloat then
               Str.Установить(j,StringReplace(s,',','.',[rfReplaceAll]))
             else
               Str.Установить(j,s);
           end;
         end;
         q.Next;
       end;
     end
     else
     begin
       i:=0;      
       while not q.EOF do
       begin
         Tab.НоваяСтрока;
         for j:=0 to q.FieldCount-1 do
         begin
           f:=q.Fields[j];
           if not(q.Fields[j].Value=null) then
           begin
             s:=f.AsString;
             if f.DataType=ftFloat then
               Tab.УстановитьЗначение(i+1,j+1,StringReplace(s,',','.',[rfReplaceAll]))
             else
               Tab.УстановитьЗначение(i+1,j+1,s);
           end;
         end;
         inc(i);
         q.Next;
       end;
     end;
   end
   else
   begin
     Err:=1;
     Tab.Очистить;
   end;
 end;
 Result:=Err;
end;


function TAddSQLObject.CallAsFunc(lMethodNum: Integer; var pVarRetValue: OleVariant; var paParams: PSafeArray{(OleVariant)}): HResult; stdcall;
var
 q: TDataSet;
 Tab: OleVariant;
begin
 case TMethods(lMethodNum) of
.....................
   methOpenQuery:
     begin
       { SQL -> OpenQuery }
       if sql.IsConnected then
       begin
         pStatusLine.SetStatusLine('Query is executing ...');
         Tab:=GetNParam(paParams,1);
         Error:=IsString(GetNParam(paParams,0));
         Error:=Error+IsValueTable(Tab);
         if Error=0 then
         begin
           q:=Sql.OpenQuery(String(GetNParam(paParams,0)));
           if (Assigned(q)) and (sql.ErrorFlag = 0) then
           begin
             Error:=ConvertDataSetToValueTable(q,Tab);
           end
           else if sql.ErrorFlag = 0 then
           begin
             sql.ErrorFlag:=1;
             Error:=1;
           end;
           q.Free;
         end
         else
         begin
           sql.ErrorFlag:=1;
           Error:=1;
         end;
         pStatusLine.ResetStatusLine;
       end
       else
       begin
         sql.ErrorFlag:=1;
         Error:=1;
       end;
       pVarRetValue:=Error;
     end;

unction TAddSQLObject.IsValueTable(Tab: OleVariant): integer;
var
 Err: integer;
begin
 Err:=0;
 try
   {если ошибка, считаем переменную не таблицей значений}
   if Ver1C = ver1cv8 then
     Tab.Колонки.Количество
   else      
     Tab.КоличествоКолонок;
 except
   Err:=1;
 end;
 Result:=Err;
end;
9 steep1
 
09.01.12
22:54
(8) можешь кинуть исходник?
10 Mashinist
 
09.01.12
22:58
(9) так а я что выложил? это не мое.
Автор Ганьшин Михаил ([email protected])
у него есть AddSQL - библиотека прямого доступа к ORACLE для 1С:Предприятия 7.7/8.0
там как раз оно и возвращает ТЗ назад
я у него этот код выпросил
отдал своему программеру-дельфисту
ему хватило ВК сделать, которая мне ТЗ возвращает и на 7.7. и на 8.1
11 steep1
 
09.01.12
23:02
(10) Спасибо за наводку, я сам делаю, вот и задаю вопросы нубские
12 H A D G E H O G s
 
09.01.12
23:09
XDTO сериализацию используйте.
Потом, в native api пригодится.
13 Torquader
 
10.01.12
00:32
Кстати, а в 1С можно передать двумерный массив из VbScript причём даже динамический (если описать свой Class), так что, есть мнение, что таблица - это лишнее.
14 steep1
 
10.01.12
06:48
(12) не подходит, так как работает тока в 8.2
(13) заморочек с Delphi уже много, вплетать VbScript уже лишнее с моей точки зрения.