[爆难]TclientDataset如何实现多字段的任意排序(10分)

  • 主题发起人 主题发起人 青云
  • 开始时间 开始时间

青云

Unregistered / Unconfirmed
GUEST, unregistred user!
如果只是正排序,那么<br>可以用 clientDataset1.IndexFieldNames:='Field1;Field2;Field3';<br><br>如果都是反排序,也好办;<br>可以用 <br><br>&nbsp; &nbsp;with ClientDataSet1.IndexDefs.AddIndexDef do<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Name := 'sort';<br>&nbsp; &nbsp; &nbsp; &nbsp; Fields := 'Field1;Field2;Field3';<br>&nbsp; &nbsp; &nbsp; &nbsp; Options := [ixDescending];<br>&nbsp; &nbsp; &nbsp; end;<br><br>ClientDataSet1.IndexName:='sort';<br><br>关键最麻烦的是 ,如果这3个字段中部分正排序,部分反排序,<br>类似 AdoDataSet1.Sort:='Field1,Field2 desc,Field3';<br>TClientDataSet居然没有处理方法!<br><br>这个功能我摸索了7年多,头发都研究白了,也没有搞定!
 
http://bbs.2ccc.com/topic.asp?topicid=292173
 
用一个计算字段NewField2实现对Field2的反向取值,然后用NewField2取代Field2——也<br>许可以的(声明:俺没试过:P)。
 
爲了這個,弄了7年,你也太執著了
 
这个功能我是融合在DBGridEh控件里的。<br>所以到处都可以任意单字段或多字段排序,而不用开发者去写任何一句代码;<br>如果利用计算字段也太麻烦了。
 
唔... 看来加索引不麻烦,加字段麻烦...
 
7年的问题才10分,呵呵<br>================================================<br>procedure TCommonSortForm.SortCDS_New();<br>var<br>&nbsp; strFields,StrDescFlds : string;<br>&nbsp; i,ipos : integer;<br><br>begin<br>&nbsp; if cdsOrder.State in [dsedit,dsinsert] then<br>&nbsp; &nbsp; &nbsp;cdsOrder.Post;<br>&nbsp; cdsOrder.First;<br>&nbsp; while not cdsOrder.Eof do<br>&nbsp; begin<br>&nbsp; &nbsp; strFields := strFields + cdsOrder.fieldbyname('fieldname').AsString + ';';<br>&nbsp; &nbsp; if 'DESC' = UpperCase(trim(cdsOrder.fieldbyname('fieldOrder').AsString)) then<br>&nbsp; &nbsp; &nbsp; StrDescFlds := StrDescFlds + cdsOrder.fieldbyname('fieldname').AsString + ';';<br><br>&nbsp; &nbsp; cdsOrder.Next;<br>&nbsp; end;<br><br>&nbsp; Delete(strFields,Length(strFields),1);<br>&nbsp; Delete(StrDescFlds,Length(StrDescFlds),1);<br><br>&nbsp; (dataset as TClientDataSet).DisableControls;<br><br>&nbsp; if (dataset as TClientDataSet).IndexDefs.IndexOf('IndexKing') &gt;= 0 then<br>&nbsp; &nbsp; (dataset as TClientDataSet).DeleteIndex('IndexKing');<br><br>&nbsp; &nbsp; (dataset as TClientDataSet).AddIndex('IndexKing', strFields, [], StrDescFlds);<br>&nbsp; &nbsp; (dataset as TClientDataSet).IndexDefs.Update;<br>&nbsp; &nbsp; (dataset as TClientDataSet).IndexName := 'IndexKing';<br>&nbsp; &nbsp; (dataset as TClientDataSet).First;<br><br>&nbsp; &nbsp; (dataset as TClientDataSet).EnableControls;<br><br>end;
 
我没搞明白 多加个 ORDER BY 组装SQL不就完了麽
 
to 青云<br>这个功能我摸索了7年多,头发都研究白了,也没有搞定!<br><br>7年时间你找一个月从TCustomClientDataSet继承下来自己写码早就搞定这个问题了吧?<br>对楼主的撞墙精神汗一个!
 
是啊,7年都没搞定,太惨了,呵呵。<br><br>function DefineIndex(CDS:TClientDataSet; OldFields:String; &nbsp;var IdxFields, IdxDescFields: String): Boolean;<br>//根据传递的OldFields内容(从表格得来的)生成表的索引,格式多个字段间用逗号分隔,如果要递减顺序,字段名后加 Desc &nbsp;<br>(即OldField实际上就是一个Order by 的字句,格式为 Field1,Field2 desc,Field3,....)<br>var tpField,tpDesc:String;<br>&nbsp; i:Integer;<br>begin<br>&nbsp; Result:=False;<br>&nbsp; IdxFields:='';<br>&nbsp; IdxDescFields:='';<br>&nbsp; if StrIsEmpty(OldFields) then &nbsp;//StrIsEmpty 自写的判断是否为空的语句,自已重写吧<br>&nbsp; &nbsp; Exit;<br>&nbsp; For i:=1 to CountStrTimes(',', OldFields) do begin &nbsp;//CountStrTimes 自写的 统计有几个字段的函数,自已想办法重写吧<br>&nbsp; &nbsp; tpField:= Trim(GetAppointStr(',',OldFields, i));<br>&nbsp; &nbsp; tpDesc:='';<br>&nbsp; &nbsp; if StrIsEnd('desc',tpField) then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; tpDesc:=Trim(Copy(tpField,1,Length(tpField)-5));<br>&nbsp; &nbsp; &nbsp; &nbsp; tpField:=tpDesc;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; if Assigned(CDS.FindField(tpField)) then begin<br>&nbsp; &nbsp; &nbsp; if Not StrIsEmpty(tpField) then<br>&nbsp; &nbsp; &nbsp; &nbsp; IDXFields:=IDXFields + Trim(tpField)+ ';';<br>&nbsp; &nbsp; &nbsp; if Not StrIsEmpty(tpDesc) then<br>&nbsp; &nbsp; &nbsp; &nbsp; IDXDescFields:=IDXDescFields + Trim(tpDesc) + ';';<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>//循环的作用就是依次求出Field1,Field2 desc,Field3,然后判断这个字段是否存在,再判断后面有没关键字desc,分别加到IdxFields与IdxDescFields字段序列中。<br>&nbsp; if Not StrIsEmpty(IDXFields) then<br>&nbsp; &nbsp; Delete(IDXFields,Length(IDXFields),1);<br>&nbsp; if Not StrIsEmpty(IDXDescFields) then<br>&nbsp; &nbsp; Delete(IDXDescFields,Length(IDXDescFields),1);<br><br>&nbsp; Result:=Not StrIsEmpty(IDXFields);<br>end;<br><br>然后呢<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; with ClientDataSetl do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IndexDefs.Clear;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AddIndex('SortReport',IDXFields,[],IDXDescFields);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IndexDefs.Update;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IndexName:='SortReport';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>就可以了。<br><br>Delphi syntax:<br><br>procedure AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string = ''; const CaseInsFields: string = ''; const GroupingLevel: Integer = 0 );<br><br>C++ syntax:<br><br>void __fastcall AddIndex(const AnsiString Name, const AnsiString Fields, Db::TIndexOptions Options, const AnsiString DescFields = "", const AnsiString CaseInsFields = "", const int GroupingLevel = 0);<br><br>Description<br><br>Call AddIndex to create a new index for the client dataset.<br><br>Name is the name of the new index.<br><br>Fields is a semicolon-delimited list of the fields to include in the index.Options is a (potentially empty) set that can include up to two TIndexOptions values. The valid members for that set include ixDescending (specifying that the index sorts in descending alphanumeric order) and ixCaseInsensitive (specifying that the index should ignore case when sorting).<br><br>看一下DELPHI对Addinex帮助的说明,也不用摸索7年了。
 
楼上的兄弟,您提供的两个关键点:<br>1.<br>Delphi syntax:<br><br>procedure AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string = ''; const CaseInsFields: string = ''; const GroupingLevel: Integer = 0 ); <br>2.<br>&nbsp; &nbsp; &nbsp; &nbsp; with ClientDataSetl do begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IndexDefs.Clear;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AddIndex('SortReport',IDXFields,[],IDXDescFields);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IndexDefs.Update;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IndexName:='SortReport';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>AddIndex 这个函数我指导,但是它好像不能把多个字段的正反排序按照任意的优先次序来处理<br>比如:<br>AddIndex('SortReport','Field1,Filed3',[],'Field2');<br>那究竟是 order by &nbsp;Field1,Filed3,Field2 desc<br>还是 &nbsp;order by Field2 desc, Field1,Filed3<br>或者是 order by &nbsp; Field1,Field2 desc, &nbsp;Filed3
 
呵呵,看来此问题果然无解!
 
AddIndex可以解决,我几年前就已经实现了,<br>分这么少就只给提示了
 
我知道 哈哈,不过你自己都说难得就10分阿?<br>那就告诉你个思路 哈哈<br>1 设定一个队列,具体需要多少个元素,则根据你需要排序的字段<br>2 通过多种办法也是你说的某个字段作为排序依据,还有它的升降等,存入队列<br>3 等你排序的时候 你就循一下,组合出你的AdoDataSet1.Sort:='Field1,Field2 desc,Field3'来<br>4 至于为什么使用队列,因为假设你的队列定义了10个位置,则等你第11次点某个字段作为排序依据的时候,第一个就自动没有了<br>哎 &nbsp;一般人不告诉他
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
619
import
I
后退
顶部