-1

I have multi-tiered application that use OleVariant variables to send and receive data accross the line using custom communication framework. Usually the content of this OleVariant variable comes from TClientDataSet.Data (which, of course, is of OleVariant type). I have suspicion that the communication frmework changes the content of this OleVariant variable and therefore I would like to dump the contenct of the variable before sending and after receiving data. I use code:

TmpOrder: OleVariant;
Tmp: TStringList;

Tmp:=TStringList.Create;
try
  Tmp.LoadFromFile('D:\test.txt');
  Tmp.Add('---');
  Tmp.Add(TmpOrder);
  Tmp.SaveToFile('D:\test.txt');
finally
  Tmp.Free;
end;

But the content of the file is meaningless. E.g., the following content of the file can represent the content of the TClientDataSet.Data:

---
??

Of course, there is something different happening.

So - how to capture the content of the OleVariant variable.

Saving TClientDataSet as XML is not option for me, because communication uses OleVariant not XML.

I am using Unciode Delphi (Delphi 2009 and up).

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
TomR
  • 2,696
  • 6
  • 34
  • 87
  • It depends on what is inside the variant object. It's impossible to say from here. – David Heffernan Nov 08 '19 at 13:44
  • 1
    An OleVariant can hold just about anything, including a reference to an application interface. Without knowing specifically what is in that variant, it's impossible to tell how how to save it to a file (or even determine if that's possible - you can't save an instance of Excel or Word to a file, for instance). – Ken White Nov 08 '19 at 14:04
  • 2
    What's stopping you using the TCDS's SavetoFile(..., dfXML) on the sending side **and** on the receiving side and then comparing the 2 XML files? – MartynA Nov 08 '19 at 14:22

1 Answers1

4

Here is some code which converts TClientDataSet.Data to a string and a test routine which exercises it.

function VariantToString(V : OleVariant) : String;
  procedure VariantToStringInner(V : OleVariant; var AString : String);
  var
    IsArray : Boolean;
    DimCount : Integer;
    i : Integer;
  begin
    IsArray := VarIsArray(V);

    if not IsArray then begin
      //  Handle the case where V is not an array
      if (VarIsEmpty(V) or VarIsNull(V)) then begin
        AString := AString + ' ';
        exit;
      end
      else
        AString := AString + VarToStr(V);
    end
    else begin
      //  V is an array, so first we need to know how many dimensions it has
      DimCount := VarArrayDimCount(V);

      //  For TClientDataSet.Data the answer AFAIK should be 1
      //  so we'll process only dimension 1
      Assert(DimCount = 1);

      //  Recurse into this proc so that we handle the cases where V[i] is an array
      //  and where it isn't
      for i := VarArrayLowBound(V, 1) to VarArrayHighBound(V, 1) do begin
        VariantToStringInner(V[i], AString);
      end;
    end;
  end;

begin
  Result := '';
  VariantToStringInner(V, Result);
end;

procedure TForm1.TestVarToStr;
var
  V : OleVariant;
  S : String;
begin
  V := 'hello world';
  S := VariantToString(V) + #13#10;

  V := CDS1.Data;
  S := S + VariantToString(V);
  Memo1.Lines.Text := S;
end;

Obviously, if you want to save the result to a file, simply call Memo1.Lines.SaveToFile()

The result I get is

hello world 150252241891000240005020003000202027368401000107838566848980692073080651171161111051109904689711610140600000678117109981011144010000047897109101107300010587736884722020200586971081171011073000105877368847220202002010677265787169957679714013006000100000004000200000004000126585847973786786657685694010300044011000578971091014944002000578971091015026567

The same CDS data, saved as XML is as follows:

<?xml version="1.0" standalone="yes"?>  
<DATAPACKET Version="2.0">
<METADATA>
  <FIELDS>
    <FIELD attrname="ID" fieldtype="i4" SUBTYPE="Autoinc"/><FIELD   attrname="Date" fieldtype="date"/>
    <FIELD attrname="Number" fieldtype="i4"/><FIELD attrname="Name" fieldtype="string" WIDTH="20"/><FIELD attrname="Value" fieldtype="string" WIDTH="20"/>
  </FIELDS>
  <PARAMS CHANGE_LOG="1 0 4 2 0 4" AUTOINCVALUE="3"/>
</METADATA>
<ROWDATA>
  <ROW RowState="4" ID="1" Name="Name1"/><ROW RowState="4" ID="2" Name="Name2" Value="AC"/>
</ROWDATA>
</DATAPACKET>
MartynA
  • 30,454
  • 4
  • 32
  • 73