尝试在Delphi中构建Excel RTD服务器

时间:2018-09-13 22:08:10

标签: excel delphi com rtd

我正在尝试在Delphi中为Excel构建RTD服务器,但我无法使这部分代码正常工作:

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(尽管对该函数的第一次调用未能产生结果(N / A)。仅在RTD()调用中更改主题后,它将显示结果(仅一次))

我基于https://blog.learningtree.com/excel-creating-rtd-server-c/

中的C#示例创建代码

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:3)

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;