在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
TClientDataSet的基本属性和方法TClientDataSet控件继承自TDataSet,其数据存储文件格式扩展名为 .cds/.xml,是基于文件型数据存储和操作的控件。 该控件封装了对数据进行操作处理的接口和功能,而本身并不依赖其它数据库驱动程序,基本上能满足单机"瘦"数据库应用程序的需要。 FieldDefs: 字段定义列表属性可通过单击属性编辑器中的属性编辑按钮,或在该控件上单击右键选择弹出菜单中的"Fields Editor"菜单进行字段编辑。设置完此属性后,实际上就相当于定义了表的结构; 如果想装入已有的数据表的结构和数据,可通过单击右键选择弹出菜单中的"Assign Local Data"菜单,从弹出对话框中选取当前窗体中已与数据库连接好的数据集控件名称即可(当前窗体中必须已放置好要套用的数据集控件并打开激活) 使用注意:对于自定义的字段名表,该属性编辑完后,该控件仍然无法打开。必须右键单击该控件,选择弹出菜单中的"Create DataSet"菜单,让该控件以上述编辑的字段列表为依据,创建数据集后,才能够被激活打开和使用。否则,会出现类似"ClientDataSet1: Missing data provider or data packet."的错误(包括在运行期,运行期可调用该控件的CreateDataSet方法,从而动态定义字段和表) FileName:数据存储文件的名称因该控件是基于文件型的数据操作控件,因此,必须指定所操作的数据文件名称(默认扩展名称.cds),从而打开和激活该控件,进而进行数据编辑。 例如:利用此属性打开指定的.cds文件 var Path: string; begin Path := ExtractFilePath(Application.ExeName); //取得可执行文件路径 CDataSet1.FileName := Path + 'test.cds'; CDataSet1.Open; end; CreateDataSet:以FieldDefs中的字段名表为结构建立数据集,常用来进行动态定义表。例如:动态创建一具有姓名和年龄两个字段的数据集 //创建字段名表 CDataSet.FieldDefs.Clear; with CDataSet.FieldDefs.AddFieldDef do begin Name := 'Name'; Size := 10; DataType := ftString; end; with CDataSet.FieldDefs.AddFieldDef do begin Name := 'Age'; DataType := ftInteger; end; //动态创建数据集 CDataSet.CreateDataSet; //激活和打开该数据集 CDataSet.Open; Open:打开和激活数据集控件,从而进行数据编辑
LoadFromFile/SaveToFile:从文件中装入表结构和数据以及存储数据到文件例如::将数据集的数据存储到指定文件中 CDataSet.SaveToFile('c:\windows\desktop\test.cds'); Filter, Filtered: 过滤筛选属性说明:用于筛选指定条件的记录,用法同一般数据集控件,略。 例如:在已经激活打开的数据集中筛选性别为男性的记录 CDataSet.Close; CDataSet.Filter := '性别=''' + '男' + ''''; CDataSet.Filtered := True; CDataSet.Open; 其它方法First(到首),Prior(向前),Next(向后),Last(到尾),Edit(编辑),CanCel(取消编辑),Post(保存),Insert(插入记录),Append(添加记录),Delete(删除),Refresh(数据刷新)等
使用TClientDataSet控件的应用程序发布的注意事项使用TClientDataSet控件的程序发布时不需要任何数据库驱动程序,大大节省了安装文件的大小。 但是,在发布程序时别忘了将Windows系统目录下midas.dll与应用程序一起发布,否则,程序可能无法正常运行。
手动建立数据集示例代码: //放置控件: ClientDataSet1、DataSource1、DBGrid1、Button1, 然后 procedure TForm1.Button1Click(Sender: TObject); begin { 添加字段 } with ClientDataSet1.FieldDefs.AddFieldDef do begin Name := 'ID'; DataType := ftInteger; end; with ClientDataSet1.FieldDefs.AddFieldDef do begin Name := 'Name'; DataType := ftString; Size := 12; { ftString 类型的 Size 默认 20 } end; with ClientDataSet1.FieldDefs.AddFieldDef do begin Name := 'Age'; DataType := ftWord; end; with ClientDataSet1.FieldDefs.AddFieldDef do begin Name := 'Sex'; DataType := ftBoolean; end; { 构建数据集, 不可缺少的一步 } ClientDataSet1.CreateDataSet; { 显示; 如果在设计时已挂接或不需要显示, 可省略下两行 } DataSource1.DataSet := ClientDataSet1; DBGrid1.DataSource := DataSource1; { 添加数据 } ClientDataSet1.AppendRecord([1, '张三', 33, True]); ClientDataSet1.AppendRecord([2, '李四', 44, False]); ClientDataSet1.AppendRecord([3, '王五', 55, True]); { 保存为 cds 或 XML } ClientDataSet1.SaveToFile('C:\Temp\TestBinary.cds'); ClientDataSet1.SaveToFile('C:\Temp\TestXMLUTF8.xml', dfXMLUTF8); end; 代码可另写为(下面这种方法简单, 但上一种方法可设置更多选项): procedure TForm1.Button1Click(Sender: TObject); begin { 添加字段 } with ClientDataSet1.FieldDefs do begin Add('ID', ftInteger); Add('Name', ftString, 12); Add('Age', ftWord); Add('Sex', ftBoolean); end; { 构建数据集, 不可缺少的一步 } ClientDataSet1.CreateDataSet; { 显示; 如果在设计时已挂接或不需要显示, 可省略下两行 } DataSource1.DataSet := ClientDataSet1; DBGrid1.DataSource := DataSource1; { 插入数据 } ClientDataSet1.InsertRecord([1, '张三', 33, True]); ClientDataSet1.InsertRecord([2, '李四', 44, False]); ClientDataSet1.InsertRecord([3, '王五', 55, True]); { 保存为 cds 或 XML } ClientDataSet1.SaveToFile('C:\Temp\TestBinary.cds'); ClientDataSet1.SaveToFile('C:\Temp\TestXMLUTF8.xml', dfXMLUTF8); end;
数据读取方法介绍 TClientDataSet.Fields[]; { 字段集合; 它比 FieldList 有更多功能, 如可获取嵌套字段 } TClientDataSet.FieldList[]; { 字段列表; 它比 Fields 轻便, 如果只是取值用它快一些 } TClientDataSet.FieldByName(); { 根据字段名称获取字段对象; 获取一个字段对象时它比上两个快 } TClientDataSet.FindField(); { 根据字段名称查找字段对象 } TClientDataSet.FieldValues[]; { 根据字段名称获取字段值; 如果仅是获取字段值, 这个最快 } TClientDataSet.First; { 到第一个记录 } TClientDataSet.Next; { 到下一个记录 } TClientDataSet.Last; { 到最后一个记录 } TClientDataSet.Prior; { 到上一个记录 } TClientDataSet.RecNo; { 设置或读取当前记录的位置 } TClientDataSet.Bof; { 当前位置是否是第一个记录 } TClientDataSet.Eof; { 当前位置是否是最后一个记录 } TClientDataSet.RecordSize; { 一个记录的大小; 所谓一个记录就是当前行的所有字段 } TClientDataSet.RecordCount; { 记录总数; 也就是总行数 } TClientDataSet.GetFieldList(); { 根据指定的几个字段名获取字段对象的列表 } TClientDataSet.GetFieldData(); { 把指定字段的值写入一个缓冲区 } TClientDataSet.GetCurrentRecord(); { 把当前记录(不包括 Bolb 字段)写入到一个缓冲区 }
数据读取示例: 例子使用了 Common Files\CodeGear Shared\Data\holdings.xml, 若更换文件需调整代码 这是 holdings.xml 的字段信息 ACCT_NBR { 类型是 r8, 对应 ftFloat, 相当于 Double } SYMBOL { 类型是 string, 对应 ftString, 相当于 AnsiString; 指定 Size=7, 加上空结束, 大小是 8 } SHARES { 类型是 r8, 对应 ftFloat, 相当于 Double } PUR_PRICE { 类型是 r8, 对应 ftFloat, 相当于 Double } PUR_DATE { 类型是 date, 对应 ftInteger, 相当于 Integer } 先窗体上放置 ClientDataSet1、DataSource1、DBGrid1、Memo1 和七个 Button { 准备数据, 也可在设计时完成 } procedure TForm1.FormCreate(Sender: TObject); begin ChDir(GetEnvironmentVariable('CommonProgramFiles') + '\CodeGear Shared\Data\'); ClientDataSet1.LoadFromFile('holdings.xml'); DBGrid1.DataSource := DataSource1; DataSource1.DataSet := ClientDataSet1; end; { 读取字段值的几种方法 } procedure TForm1.Button1Click(Sender: TObject); var v1,v2,v3,v4,v5,v6,v7,v8,v9: Variant; num: Double; fName: string; begin { 获取首字段的名称 } fName := ClientDataSet1.Fields[0].FieldName; { 获取第一个字段值的几种方法: } v1 := ClientDataSet1.Fields[0].Value; v2 := ClientDataSet1.FieldByName(fName).Value; v3 := ClientDataSet1.FindField(fName).Value; v4 := ClientDataSet1.FieldValues[fName]; v5 := ClientDataSet1[fName]; { FieldValues 是默认的数组属性 } v6 := ClientDataSet1.FieldList[0].Value; v7 := ClientDataSet1.FieldList.FieldByName(fName).Value; v8 := ClientDataSet1.FieldList.Find(fName).Value; v9 := ClientDataSet1.FieldList.Fields[0].Value; { 已知这个字段是 Double 类型的, 可同时转换 } num := ClientDataSet1.Fields[0].AsFloat; { 查看结果 } with Memo1.Lines do begin Clear; Add(v1); Add(v2); Add(v3); Add(v4); Add(v5); Add(v6); Add(v7); Add(v8); Add(FloatToStr(num)); end; end; { 遍历当前行字段的几种方法 } procedure TForm1.Button2Click(Sender: TObject); var Field: TField; i: Integer; begin Memo1.Clear; for Field in ClientDataSet1.Fields do begin Memo1.Lines.Add(Field.Value); end; Memo1.Lines.Add(''); for i := 0 to ClientDataSet1.FieldCount - 1 do begin Memo1.Lines.Add(ClientDataSet1.Fields[i].Value); end; Memo1.Lines.Add(''); for i := 0 to ClientDataSet1.FieldList.Count - 1 do begin Memo1.Lines.Add(ClientDataSet1.FieldList[i].Value); end; Memo1.Lines.Add(''); end; { First、Next、Last、Prior、RecNo } procedure TForm1.Button3Click(Sender: TObject); var s1,s2,s3: string; begin { 读取第二行第二个字段 } ClientDataSet1.First; ClientDataSet1.Next; s1 := ClientDataSet1.Fields[1].AsString; { 读取倒数第二行第二个字段 } ClientDataSet1.Last; ClientDataSet1.Prior; s2 := ClientDataSet1.Fields[1].AsString; { 读取第四行第二个字段 } ClientDataSet1.RecNo := 4; s3 := ClientDataSet1.Fields[1].AsString; { 查看结果 } with Memo1.Lines do begin Clear; Add('第二行第二个字段: ' + s1); Add('倒数第二行第二个字段: ' + s2); Add('第四行第二个字段: ' + s3); end; end; { 遍历指定字段的所有记录 } procedure TForm1.Button4Click(Sender: TObject); var i: Integer; begin if not ClientDataSet1.Bof then ClientDataSet1.First; Memo1.Clear; while not ClientDataSet1.Eof do begin Memo1.Lines.Add(ClientDataSet1.FieldList[0].Value); ClientDataSet1.Next; end; Memo1.Lines.Add('-------'); for i := 1 to ClientDataSet1.RecordCount do begin ClientDataSet1.RecNo := i; Memo1.Lines.Add(ClientDataSet1.FieldList[1].Value); end; end; { 通过 GetFieldList 可以读取几个指定字段的 TField 对象的列表 } procedure TForm1.Button5Click(Sender: TObject); var List: TList; Field: TField; i: Integer; begin List := TList.Create; ClientDataSet1.GetFieldList(List, 'ACCT_NBR; SYMBOL; SHARES'); Memo1.Clear; for i := 0 to List.Count - 1 do begin Field := List[i]; Memo1.Lines.Add(Field.Value); end; List.Free; end; { GetFieldData 读取字段值到指针 } procedure TForm1.Button6Click(Sender: TObject); var F1: Double; F2: array[0..7] of AnsiChar; begin ClientDataSet1.GetFieldData(ClientDataSet1.Fields[0], @F1); ClientDataSet1.GetFieldData(ClientDataSet1.Fields[1], @F2); with Memo1.Lines do begin Clear; Add(FloatToStr(F1)); Add(F2); end; end; //这是后面的例子用到的函数, 转换 TClientDataSet 时间格式到 TDateTime function TDateTimeRecToDateTime(DataType: TFieldType; Data: TDateTimeRec): TDateTime; var TimeStamp: TTimeStamp; begin case DataType of ftDate: begin TimeStamp.Time := 0; TimeStamp.Date := Data.Date; end; ftTime: begin TimeStamp.Time := Data.Time; TimeStamp.Date := DateDelta; end; else try TimeStamp := MSecsToTimeStamp(Data.DateTime); except TimeStamp.Time := 0; TimeStamp.Date := 0; end; end; Result := TimeStampToDateTime(TimeStamp); end; { GetCurrentRecord 是把当前行的所有字段(不包括 Blob 字段)读入到缓冲区 } procedure TForm1.Button7Click(Sender: TObject); type THoldingsStruct = packed record { 这是根据 holdings.xml 建立的数据结构 } ACCT_NBR: Double; SYMBOL: array[0..7] of AnsiChar; { 其 Size=7, 但后面还有个 #0 } SHARES: Double; PUR_PRICE: Double; PUR_DATE: Integer; // Other: array[0..4] of Byte; { 它后面还若干字节偏移, 测试时其字节数等于前面的字段数 } end; var buf: THoldingsStruct; DateTimeRec: TDateTimeRec; begin //ShowMessage(IntToStr(ClientDataSet1.RecordSize)); { 可通过这个值对照上面的结构 } if ClientDataSet1.GetCurrentRecord(@buf) then with Memo1.Lines do begin Clear; Add(FloatToStr(buf.ACCT_NBR)); Add(buf.SYMBOL); Add(FloatToStr(buf.SHARES)); Add(FloatToStr(buf.PUR_PRICE)); DateTimeRec.Date := buf.PUR_DATE; Add(DateToStr(TDateTimeRecToDateTime(ftDate, DateTimeRec))); end; end;
数据查找方法介绍
其中的 GotoNearest、FindNearest 在找不到的情况下会定位到近似值 测试代码: //准备: 窗体上放一个 ClientDataSet1 和六个 Button { 准备测试数据 } procedure TForm1.FormCreate(Sender: TObject); begin with ClientDataSet1 do begin FieldDefs.Add('ID', ftInteger); FieldDefs.Add('Name', ftString, 6); FieldDefs.Add('Age', ftWord); CreateDataSet; AppendRecord([1, '赵AB', 11]); AppendRecord([2, '钱AB', 22]); AppendRecord([3, '孙AB', 33]); AppendRecord([4, '李AB', 44]); AppendRecord([5, '赵ab', 55]); AppendRecord([6, '钱ab', 66]); AppendRecord([7, '孙ab', 77]); AppendRecord([8, '李ab', 88]); end; end; { Locate 测试 } procedure TForm1.Button1Click(Sender: TObject); begin if ClientDataSet1.Locate('Name', '赵ab', []) then ShowMessage(ClientDataSet1.FieldValues['Age']); { 55 } if ClientDataSet1.Locate('Name', '赵ab', [loCaseInsensitive]) then ShowMessage(ClientDataSet1.FieldValues['Age']); { 11 } if ClientDataSet1.Locate('Name', '钱a', [loPartialKey]) then ShowMessage(ClientDataSet1.FieldValues['Age']); { 66 } if ClientDataSet1.Locate('Name', '钱a', [loCaseInsensitive,loPartialKey]) then ShowMessage(ClientDataSet1.FieldValues['Age']); { 22 } if ClientDataSet1.Locate('Name;Age', VarArrayOf(['钱ab',66]), []) then ShowMessage(ClientDataSet1.FieldValues['Age']); { 66 } end; { Lookup 测试 } procedure TForm1.Button2Click(Sender: TObject); var R: Variant; i: Integer; begin R := ClientDataSet1.Lookup('Name', '钱AB', 'Age'); if not VarIsNull(R) then ShowMessage(R); { 22 } R := ClientDataSet1.Lookup('Name;Age', VarArrayOf(['钱ab',66]), 'Age'); if not VarIsNull(R) then ShowMessage(R); { 66 } R := ClientDataSet1.Lookup('ID', 6, 'Name;Age'); if VarIsArray(R) then for i := VarArrayLowBound(R, 1) to VarArrayHighBound(R, 1) do ShowMessage(R[i]); { 钱ab / 66} end; { SetKey、GotoKey 测试 } procedure TForm1.Button3Click(Sender: TObject); begin ClientDataSet1.IndexFieldNames := 'Name'; ClientDataSet1.SetKey; ClientDataSet1.FieldValues['Name'] := '钱ab'; if ClientDataSet1.GotoKey then ShowMessage(ClientDataSet1.FieldValues['Age']); { 66 } end; { SetKey、GotoNearest 测试 } procedure TForm1.Button4Click(Sender: TObject); begin ClientDataSet1.IndexFieldNames := 'Name'; ClientDataSet1.SetKey; ClientDataSet1.FieldValues['Name'] := '孙'; ClientDataSet1.GotoNearest; ShowMessage(ClientDataSet1.FieldValues['Age']); { 77 } end; { FindKey 测试 } procedure |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论