Попытка построить сервер Excel RTD в Delphi

Я пытаюсь создать RTD-сервер для Excel в Delphi и не могу заставить работать эту часть кода:

function TRtdServer.RefreshData(var TopicCount: Integer): PSafeArray;
//Called when Excel is requesting a refresh on topics. RefreshData will be called
//after an UpdateNotify has been issued by the server. This event should:
//- supply a value for TopicCount (number of topics to update)
//- The data returned to Excel is an Object containing a two-dimensional array.
//  The first dimension represents the list of topic IDs.
//  The second dimension represents the values associated with the topic IDs.
var
  Data : OleVariant;
begin
   //Create an array to return the topics and their values
   //note:The Bounds parameter must contain an even number of values, where each pair of values specifies the upper and lower bounds of one dimension of the array.
   Data:=VarArrayCreate([0, 1, 0, 0], VT_VARIANT);
   Data[0,0]:=MyTopicId;
   Data[1,0]:=GetTime();
   if Main.Form1.CheckBoxExtraInfo.Checked then Main.Form1.ListBoxInfo.Items.Add('Excel called RefreshData. Returning TopicId: '+IntToStr(Data[0,0])+' and Value: '+Data[1,0]);
   TopicCount:=1;
//   RefreshTimer.Enabled:=true;
   //Result:=PSafeArray(VarArrayAsPSafeArray(Data));
   Result:=PSafeArray(TVarData(Data).VArray);
end;

Я не уверен в этой части:

Result:=PSafeArray(TVarData(Data).VArray);

Но это может быть любая часть кода. Excel просто не показывает никакого результата в ячейке, содержащей вызов функции rtd(). Мне удалось получить результат в ячейке, когда Excel впервые вызывает мою функцию «ConnectData», которая просто возвращает строку вместо PSafeArray (хотя самый первый вызов этой функции не дает результата (Н/Д). Только после изменения темы в вызове RTD() он отображает результат (только один раз))

Я основывал код на примере на C# из https://blog.learningtree.com/excel-creating-rtd-server-c/

Может кто-то указать мне верное направление?


person Bigman74066    schedule 13.09.2018    source источник
comment
Почему голосование вниз?   -  person Bigman74066    schedule 14.09.2018


Ответы (1)


OleVariant владеет данными, которые он хранит, и выпустит эти данные, когда выйдет за рамки. Таким образом, вы возвращаете недопустимый указатель PSafeArray в Excel. Вам нужно либо:

  1. освободите право собственности на указатель массива перед его возвратом:

    function TRtdServer.RefreshData(var TopicCount: Integer): PSafeArray;
    var
      Data : OleVariant;
    begin
      ...
      Result := PSafeArray(TVarData(Data).VArray);
      TVarData(Data).VArray = nil; // <-- add this
    end;
    
  2. используйте SafeArrayCopy() чтобы сделать копию массива, а затем вернуть копию:

    uses
       ..., ActiveX;
    
    function TRtdServer.RefreshData(var TopicCount: Integer): PSafeArray;
    var
      Data : OleVariant;
    begin
      ...
      OleCheck(
        SafeArrayCopy(
          PSafeArray(TVarData(Data).VArray),
          Result
        )
      );
    end;
    
person Remy Lebeau    schedule 13.09.2018
comment
Вау, ты лучший Реми! Теперь это работает. Не идеально (по-прежнему дает мне n/a при запуске), но я добираюсь туда! Спасибо! - person Bigman74066; 14.09.2018