Bent Tram A/S
Mechanical Testing Solutions

How to read curve data programmatically from the TramQA database

The test result data are stored in the "TramTest" table in the tram access database. The curve data series are stored in the "fldCurveData" field in binary form.

In Delphi, the binary data can be accessed with the stream reader class TReader. Each serie is stored seperately i.e. load, deformation, time etc. In the header of each serie, metadata like the serie name and the unit of the data values are stored.

Delphi example:

var
  con : TADOConnection;
  accessDatabaseFile : string;
  query : TADOQuery;
  field : TField;
  stream : TStream;
  oid : string;
  reader : TReader;
  listContainerVersion : single;
  listContainerName : string;
  listVersion : single;
  growPolicy : integer;
  itemSize : integer;
  serieName : string;
  unitName : string;
  count : integer;
  seriedata : array of single;
  n : integer;
begin
  oid := EditOID.Text;
  Memo1.Clear;
  accessDatabaseFile := Edit1.Text;
  con := TADOConnection.Create( nil );
  con.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+
                          accessDatabaseFile+';Persist Security Info=False';
  query := TADOQuery.Create ( nil );
  try
    query.DisableControls;
    query.Connection := con;
    query.SQL.Add ('Select * from TramTest where OID='+oid);
    query.Open;
    if query.RecordCount = 1 then
    begin
      field := query.FindField( 'fldCurveData' );
      stream := query.CreateBlobStream( field, bmRead );
      reader := TReader.Create ( stream, 1024 );
      try
        listContainerVersion := reader.ReadFloat; // ListContainer version number
        reader.ReadListBegin;
        while not reader.EndOfList do
        begin
          listVersion := reader.ReadFloat;  // list version number
          growPolicy := reader.ReadInteger; // 0: Log 1:1000 at a time
          itemSize := reader.ReadInteger;   // item size in bytes
          serieName := reader.ReadString;   // serie name
          unitName := reader.ReadString;    // unit on serie
          count := reader.ReadInteger;      // number of elements in serie
          SetLength ( seriedata, count );
          reader.Read( seriedata[0], itemSize*count );

          // output
          Memo1.Lines.Add( 'serie:'+serieName );
          Memo1.Lines.Add( 'unit:'+unitName );
          for n := 0 to count - 1 do
          begin
            Memo1.Lines.Add( FloatToStr ( seriedata[n] ));
          end;
        end;
        reader.ReadListEnd;
        listContainerName := reader.ReadString;
      finally
        reader.Free;
        stream.Free;
      end;
    end else
    begin
      Memo1.Lines.Add( 'No test found with OID='+oid );
    end;
  finally
    query.Free;
    con.Free;
  end;
end;

The entire Delphi example project can be downloaded here