1

I have a TADODataSet connected with a stored procedure which produce 40 Columns * 800 Row the TADODataSet has an AfterOpen event which assign an OnGetText for it is Fields like :

procedure TForm1.ADODataSet1AfterOpen(DataSet: TDataSet);
begin
  with DataSet do 
  begin
    Fields[4].DisplayLabel:=TR(AS2); //RefId
    Fields[4].DisplayWidth:=8;
    Fields[4].Tag:=1;
    Fields[4].OnGetText:=RefGetText;

    Fields[5].DisplayLabel:=TR(AS3); //ClientId
    Fields[5].DisplayWidth:=8;
    Fields[5].Tag:=1;
    Fields[5].OnGetText:=ClientGetText;
  end;
end;


procedure TForm1.RefGetText(Sender: TField; var Text: String; DisplayText:   Boolean);
begin
  if Sender.DataSet.FieldByName('RelStoreId').AsString='' then
    Text:='NO REF ID'
  else
    KHDM.RefGetText(Sender,Text,DisplayText);
end;

procedure TForm1.ClientGetText(Sender: TField; var Text: String; DisplayText:   Boolean);
begin
  if Sender.DataSet.FieldByName('ClientId').AsString='' then
    Text:='Client ID is not Assigned'
  else
    KHDM.ClientGetText(Sender,Text,DisplayText);
end;

I want to export the data to an XML with the texts I don't want to make a loop on fields and records because it is very slow I want something like bulk copy to stream or something like that

I cannot change the way I'm working because there are around 800 module which using the same way...

please help.

user1512094
  • 611
  • 2
  • 10
  • 23
  • Have you seen [`this example`](http://www.swissdelphicenter.ch/torry/showcode.php?id=1498) ? – TLama Nov 28 '12 at 15:55
  • 1
    Yes @TLama but this doesn't export the text of the fields...since i'm overriding the OnGetText event of the fields I want to have the provided text not the values...your example only exports the values that came from the Server engine and it doesn't take the text values that are provided in the onGetText events. – user1512094 Nov 29 '12 at 09:46
  • No way to do this without looping the TDataSet AFAIK. [This example](http://www.swissdelphicenter.ch/en/showcode.php?id=772) might help. – kobik Nov 29 '12 at 10:41

2 Answers2

0

There is not much you can do to optimize this, since you don't want to make too many changes.

I hope you can optimize this: If your dataset has fixed fields (added in design time), you can reference the field using the component field, which is usually named as DataSetNameFieldName, (for instance cdsEmployeeEMPNO).

If that is the case, you can reference cdsEmployeeEMPNO.AsString (or whatever property you need). The reason this is faster, is because the field component you use in this case, already knows which field it refers to.

In your case, you use a lookup by name: if Sender.DataSet.FieldByName('RelStoreId').AsString=.. This means that each and every time, the code performs DataSet.Fields.IndexOf(FieldName). This is a slow lookup, because those fields aren't sorted or anything. Given the size of your dataset, this can be thousands of such lookups, which can easily be twice as fast if you do it smarter.

If, for some reason, you cannot use these field component wrappers, you can also perform the lookup once, store the indexes of the fields you need in variables in your datamodule and request the value like this: if Sender.DataSet.Fields[RelStoreIdIndex].AsString= You now use the index of the field directly, which saves the lookup. This will make it a little faster.

Note however that XML outputting is slow as well. You don't show any code of the export, but maybe there could be some serious possibilities for optimization there. It's always good to do some profiling on various parts of your code to find the actual bottleneck, before you start refactoring everything.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
0

I have used this kind of technique before - Any Help to you ? I can see the length of the output is a problem but you might be able to fettle it somehow. Perhaps look at the ClientDataset.SavetoFile() Method

function DataSetToXml(const ADataSet : TOraQuery) : String;
var
  Provider : TDataSetProvider;
  ClientDataSet : TClientDataset;
begin
  Provider := TDataSetProvider.Create(nil);
  try
    Provider.Name := 'tmpProvider';
    Provider.DataSet := ADataSet;
    ClientDataSet := TClientDataSet.Create(nil);
    try
      ClientDataSet.Data := Provider.Data;
      Result := ClientDataSet.XMLData;
    finally
      FreeAndNil(ClientDataSet);
    end;
  finally
    FreeAndNil(Provider);
  end;
end;
Hugh Jones
  • 2,706
  • 19
  • 30
  • This doesn't get Fields Text but it gets only the Field value which doesn't fit any of my needs since i'm using OnGetText event to handle the value of the text and show another data for the user using the Text property of the field. – user1512094 Nov 28 '12 at 15:41
  • @user1512094 - I dont understand. In your original question you said 'I want to export the data to an XML'. When you say 'Fields Text' do you mean FieldNames Only without data ? – Hugh Jones Nov 28 '12 at 16:04
  • I think I understand better what you are asking now - are you saying that you want the XML to contain the values as provided by the OnGetText() method? – Hugh Jones Nov 28 '12 at 16:22
  • Exactly I want the XML to contain the text provided by the OnGetText Method!! without doing a loop because it is very slow – user1512094 Nov 29 '12 at 09:18
  • Are you able to modify the Sql for your datasets so it provides the correct values? You could probably do it in such a manner as to leave the exising code undisturbed e.g NVL(RelStoreId, 'NO REF ID' ) – Hugh Jones Nov 29 '12 at 12:59
  • yes i can do it in the sql code but it would take ages to finish that because i have like 800 report and over which need to be modified – user1512094 Dec 03 '12 at 09:03