下面的程序的目的是把一个记录集的数据添加到一个TListView控件中特别说明:
geoRecordset是一个GRecordset对象,有别于Delphi的TRecordset类,故不能用传统的TDataSet和TDBGrid等类来进行绑定。
跟踪代码发现这行代码执行lstListItem.Caption := geoRecordset.GFields.Item[strArrFields[0]].Value较费时。测试说明:
现在我测试了一下,向其中添加1000条数据需要约1分钟,机器配置为:赛扬1G、512兆和10兆网卡(系统是CS结构)。我对算法以及其优化不是很有研究,特来请高人指点,谢谢!!!
type
PStateData = ^TStateData;
TStateData = record
strArrFields: array of string;
end;{-----------------------------------------------------------------------------
方法: g_pro_GetFieldEnNameOnTable
作者: 黄仁光
日期: 2004年10月27日
参数: geoRecordset: OleVariant; strTableName: string; var objStateData: PStateData
结果: None
备注: 获取给定表的字段(除去了BLOB字段和空间字段)
-----------------------------------------------------------------------------}procedure g_pro_GetFieldEnNameOnTable(
geoRecordset: OleVariant; strTableName: string; var objStateData: PStateData);
var
iLoop: Integer;
objGField: OleVariant;
iType: Integer;
iLength: Integer;
begin
for iLoop := 0 to geoRecordset.GFields.Count - 1 do
begin
objGField := geoRecordset.GFields[iLoop];
iType := objGField.Type; {11,12,8}
if (iType <> 32) and (iType <> 15) and (iType <> 33) then
begin
if Trim(objGField.Name) <> '' then
begin
iLength := Length(objStateData^.strArrFields);
SetLength(objStateData^.strArrFields, iLength + 1);
objStateData^.strArrFields[iLength] := objGField.Name;
end;
end;
end;
end;{-----------------------------------------------------------------------------
方法: g_pro_AddOneColumnCaptionToListView
作者: 黄仁光
日期: 2004年10月27日
参数: strFieldName: string; lsvListView: TListView
结果: None
备注: 向TListView中添加一列
-----------------------------------------------------------------------------}procedure g_pro_AddOneColumnCaptionToListView(
strFieldName: string; lsvListView:TListView);
var
strChFieldName: string;
lscNewColumn: TListColumn;
begin
lscNewColumn := lsvListView.Columns.Add;
lscNewColumn.Width := ColumnHeaderWidth;
lscNewColumn.Caption := strFieldName;
end;{-----------------------------------------------------------------------------
方法: g_pro_AddOneRecordValueToListView
作者: 黄仁光
日期: 2004年10月27日
参数: geoRecordset: OleVariant; strArrFields: array of string; lsvListView: TListView
结果: None
备注: 向TListView中添加添加一行
-----------------------------------------------------------------------------}procedure g_pro_AddOneRecordValueToListView(
geoRecordset: OleVariant; strArrFields: array of string; lsvListView: TListView);
var
lstListItem: TListItem;
iLoop: Integer;
begin
if Length(strArrFields) > 0 then
begin
lstListItem := lsvListView.Items.Add;
if not VarIsNull(geoRecordset.GFields.Item[strArrFields[0]].Value) then
begin
lstListItem.Caption := geoRecordset.GFields.Item[strArrFields[0]].Value;
end
else
begin
lstListItem.Caption := '';
end; for iLoop := 1 to Length(strArrFields) - 1 do
begin
if not VarIsNull(geoRecordset.GFields.Item[strArrFields[iLoop]].Value) then
begin
lstListItem.SubItems.Add(geoRecordset.GFields.Item[strArrFields[iLoop]].Value);
end
else
begin
lstListItem.SubItems.Add('');
end;
end;
end;
end;{-----------------------------------------------------------------------------
方法: g_pro_AddDataToListView
作者: 黄仁光
日期: 2004年10月27日
参数: geoRecordset: OleVariant; strTableName: string; lsvListView: TListView
结果: None
备注: 将地理实体表所对应的数据添加到TListView中,去除了BLOB字段和空间字段
-----------------------------------------------------------------------------}procedure g_pro_AddDataToListView(
geoRecordset: OleVariant; strTableName: string; lsvListView: TListView);
var
objStateData: PStateData;
iLoop: Integer;
begin
try
lsvListView.Columns.Clear;
lsvListView.Items.Clear;
New(objStateData);
SetLength(objStateData^.strArrFields, 0);
g_pro_GetFieldEnNameOnTable(geoRecordset, strTableName, objStateData);
for iLoop := 0 to Length(objStateData^.strArrFields) - 1 do
begin
g_pro_AddOneColumnCaptionToListView(objStateData^.strArrFields[0], lsvListView);
end; //有了这两条语句,就能保证得到正确的记录数量
geoRecordset.MoveLast;
geoRecordset.MoveFirst;
for iLoop := 0 to geoRecordset.RecordCount - 1 do
begin
g_pro_AddOneRecordValueToListView(geoRecordset, objStateData^.strArrFields, lsvListView);
geoRecordset.MoveNext;
end;
except end;
end;
geoRecordset是一个GRecordset对象,有别于Delphi的TRecordset类,故不能用传统的TDataSet和TDBGrid等类来进行绑定。
跟踪代码发现这行代码执行lstListItem.Caption := geoRecordset.GFields.Item[strArrFields[0]].Value较费时。测试说明:
现在我测试了一下,向其中添加1000条数据需要约1分钟,机器配置为:赛扬1G、512兆和10兆网卡(系统是CS结构)。我对算法以及其优化不是很有研究,特来请高人指点,谢谢!!!
type
PStateData = ^TStateData;
TStateData = record
strArrFields: array of string;
end;{-----------------------------------------------------------------------------
方法: g_pro_GetFieldEnNameOnTable
作者: 黄仁光
日期: 2004年10月27日
参数: geoRecordset: OleVariant; strTableName: string; var objStateData: PStateData
结果: None
备注: 获取给定表的字段(除去了BLOB字段和空间字段)
-----------------------------------------------------------------------------}procedure g_pro_GetFieldEnNameOnTable(
geoRecordset: OleVariant; strTableName: string; var objStateData: PStateData);
var
iLoop: Integer;
objGField: OleVariant;
iType: Integer;
iLength: Integer;
begin
for iLoop := 0 to geoRecordset.GFields.Count - 1 do
begin
objGField := geoRecordset.GFields[iLoop];
iType := objGField.Type; {11,12,8}
if (iType <> 32) and (iType <> 15) and (iType <> 33) then
begin
if Trim(objGField.Name) <> '' then
begin
iLength := Length(objStateData^.strArrFields);
SetLength(objStateData^.strArrFields, iLength + 1);
objStateData^.strArrFields[iLength] := objGField.Name;
end;
end;
end;
end;{-----------------------------------------------------------------------------
方法: g_pro_AddOneColumnCaptionToListView
作者: 黄仁光
日期: 2004年10月27日
参数: strFieldName: string; lsvListView: TListView
结果: None
备注: 向TListView中添加一列
-----------------------------------------------------------------------------}procedure g_pro_AddOneColumnCaptionToListView(
strFieldName: string; lsvListView:TListView);
var
strChFieldName: string;
lscNewColumn: TListColumn;
begin
lscNewColumn := lsvListView.Columns.Add;
lscNewColumn.Width := ColumnHeaderWidth;
lscNewColumn.Caption := strFieldName;
end;{-----------------------------------------------------------------------------
方法: g_pro_AddOneRecordValueToListView
作者: 黄仁光
日期: 2004年10月27日
参数: geoRecordset: OleVariant; strArrFields: array of string; lsvListView: TListView
结果: None
备注: 向TListView中添加添加一行
-----------------------------------------------------------------------------}procedure g_pro_AddOneRecordValueToListView(
geoRecordset: OleVariant; strArrFields: array of string; lsvListView: TListView);
var
lstListItem: TListItem;
iLoop: Integer;
begin
if Length(strArrFields) > 0 then
begin
lstListItem := lsvListView.Items.Add;
if not VarIsNull(geoRecordset.GFields.Item[strArrFields[0]].Value) then
begin
lstListItem.Caption := geoRecordset.GFields.Item[strArrFields[0]].Value;
end
else
begin
lstListItem.Caption := '';
end; for iLoop := 1 to Length(strArrFields) - 1 do
begin
if not VarIsNull(geoRecordset.GFields.Item[strArrFields[iLoop]].Value) then
begin
lstListItem.SubItems.Add(geoRecordset.GFields.Item[strArrFields[iLoop]].Value);
end
else
begin
lstListItem.SubItems.Add('');
end;
end;
end;
end;{-----------------------------------------------------------------------------
方法: g_pro_AddDataToListView
作者: 黄仁光
日期: 2004年10月27日
参数: geoRecordset: OleVariant; strTableName: string; lsvListView: TListView
结果: None
备注: 将地理实体表所对应的数据添加到TListView中,去除了BLOB字段和空间字段
-----------------------------------------------------------------------------}procedure g_pro_AddDataToListView(
geoRecordset: OleVariant; strTableName: string; lsvListView: TListView);
var
objStateData: PStateData;
iLoop: Integer;
begin
try
lsvListView.Columns.Clear;
lsvListView.Items.Clear;
New(objStateData);
SetLength(objStateData^.strArrFields, 0);
g_pro_GetFieldEnNameOnTable(geoRecordset, strTableName, objStateData);
for iLoop := 0 to Length(objStateData^.strArrFields) - 1 do
begin
g_pro_AddOneColumnCaptionToListView(objStateData^.strArrFields[0], lsvListView);
end; //有了这两条语句,就能保证得到正确的记录数量
geoRecordset.MoveLast;
geoRecordset.MoveFirst;
for iLoop := 0 to geoRecordset.RecordCount - 1 do
begin
g_pro_AddOneRecordValueToListView(geoRecordset, objStateData^.strArrFields, lsvListView);
geoRecordset.MoveNext;
end;
except end;
end;
比如
ADOQuery1.sql.text:='select * from myatable' ;
ADOQuery1.open;
while not ADOQuery1.eof do
begin
Item:=ListView1.items.Add;
Item.caption:=ADOQurery.fieldvalues['field1'];
Item.subitem.add(ADOQuery1.fieldvalues['field2']);
ADOQuery1.next;
end;
(1)g_pro_GetFieldEnNameOnTable:传入一个表的名称,将需要的字段放在下面的结构中
type
PStateData = ^TStateData;
TStateData = record
strArrFields: array of string;
end;(2)g_pro_AddOneColumnCaptionToListView:将上面得到的字段一个一个的添加到TListView中,就是加上一个一个的标题头(TListColumn);(3)g_pro_AddOneRecordValueToListView:这个方法是这儿最主要的方法,也就是请大家主要帮我分析的方法,该方法是把一条记录的数据添加到TListView中;(4)g_pro_AddDataToListView:传入一个记录集、对应的表名称以及要填充数据的TListView对象,它掉用上面的三个方法完成数据的填充。
数据量大的时候特别影响速度
2、你可以用自定义dataset的方法,从customdataset中引出(记不太清楚,很久没用了),在那些方法中读自己的数据,这样就可以和标准的dataset一样被dbgrid认识,也能被其他的db控件认识,我以前做股票时用过这方法,能将那些股票系统的专用数据库当标准dataset使用
......
TListItems.EndUpdate
比如:OnData,就是在显示以前调用的事件,如果你定义了自己的过程,比如DataProc并赋给OnData,那显示以前就要运行DataProc,DataProc结构为:type DataProc = procedure(Sender: TObject; Item: TListItem) of object;,这里,Sender就是TListView,Item就是要显示的项,你就可以修改将要显示的数据,不就可以实现只在要显示时读入数据了吗产只是其中一个事件,如你多了解些其中的事件和调用关系,相信可以作得更好。
第一种方法的麻烦在于,对于将要用到的每一个控件,都要自己定义,如你只用这一个,倒没什么,不然,还是定义Dataset好
(系统使用的是Oracle数据库)。
建议使用ListView的Virtual模式,可以看看delphi的例子Virtual Listview
还有前面的兄弟说的,动态数组和ole变量都是效率很低的数据类型,从我以前测试结果看,速度相差非常之大,建议还是不要用的好
关注!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!