用DELPHI一年,在这里提个简单的问题,还肯请各位高手指点。

gegangqiao 2004-08-05 09:53:18
我用BDE连接数据库,现在要求在点击DBGRID列首时,能自动按照列首对应的字段进行排序。(注意:不能用QUERY查询来进行新的排序,只可以读取内存中的数据或都用其它的办法去读数据来排序。此功能可以参照ADO的SORT方法来做,但我不会,请高手帮忙。)
此功能做完后即可扩充至DATASET,也就是不论按照哪一个方法来连接数据库都可以轻松排序。
以上不可以用索引来做,谢谢。
...全文
425 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
todouwang 2005-01-05
  • 打赏
  • 举报
回复
up
tengxiang05 2005-01-04
  • 打赏
  • 举报
回复
以后再看
herman~~ 2005-01-04
  • 打赏
  • 举报
回复
学习
kuki84 2005-01-04
  • 打赏
  • 举报
回复
mark
fayeflash 2005-01-04
  • 打赏
  • 举报
回复
帮你顶上去!
very2773029 2004-08-06
  • 打赏
  • 举报
回复
就是用索引,就可以实现了,曾经有个哥们做到了。只是还在找不到代码!!!你自己研究一下吧,就是使用索引实现的。很容易的,Delphi本身就支持的。不需要什么第三方的东西。我现在找不到代码在哪里了,我这里的源码太多了,不好找。等找到了我想你也已经做出来了吧。
GoldShield 2004-08-05
  • 打赏
  • 举报
回复
楼主也可以直接找个三方控件啊DBGRIDVIEW不就可以么
boatzm 2004-08-05
  • 打赏
  • 举报
回复
mark ,藏了
zhj009 2004-08-05
  • 打赏
  • 举报
回复
(转贴)点击DBGrid的Title对查询结果排序 关键词:DBGrid 排序

欲实现点击DBGrid的Title对查询结果排序,想作一个通用程序,不是一事一议,例如不能在SQL语句中增加Order by ...,因为SQL可能原来已经包含Order by ...,而且点击另一个Title时又要另外排序,目的是想作到象资源管理器那样随心所欲。

procedure TFHkdata.SortQuery(Column:TColumn);
var
SqlStr,myFieldName,TempStr: string;
OrderPos: integer;
SavedParams: TParams;
begin
if not (Column.Field.FieldKind in [fkData,fkLookup]) then exit;
if Column.Field.FieldKind =fkData then
myFieldName := UpperCase(Column.Field.FieldName)
else
myFieldName := UpperCase(Column.Field.KeyFields);
while Pos(myFieldName,';')<>0 do
myFieldName := copy(myFieldName,1,Pos(myFieldName,';')-1)+ ',' + copy(myFieldName,Pos(myFieldName,';')+1,100);
with TQuery(TDBGrid(Column.Grid).DataSource.DataSet) do
begin
SqlStr := UpperCase(Sql.Text);
// if pos(myFieldName,SqlStr)=0 then exit;
if ParamCount>0 then
begin
SavedParams := TParams.Create;
SavedParams.Assign(Params);
end;
OrderPos := pos('ORDER',SqlStr);
if (OrderPos=0) or (pos(myFieldName,copy(SqlStr,OrderPos,100))=0) then
TempStr := ' Order By ' + myFieldName + ' Asc'
else if pos('ASC',SqlStr)=0 then
TempStr := ' Order By ' + myFieldName + ' Asc'
else
TempStr := ' Order By ' + myFieldName + ' Desc';
if OrderPos<>0 then SqlStr := Copy(SqlStr,1,OrderPos-1);
SqlStr := SqlStr + TempStr;
Active := False;
Sql.Clear;
Sql.Text := SqlStr;
if ParamCount>0 then
begin
Params.AssignValues(SavedParams);
SavedParams.Free;
end;
Prepare;
Open;
end;
end;


去掉DbGrid的自动添加功能

移动到最后一条记录时再按一下“下”就会追加一条记录,如果去掉这项功能
procedure TForm1.DataSource1Change(Sender: TObject; Field: TField);
begin
if TDataSource(Sender).DataSet.Eof then TDataSource(Sender).DataSet.Cancel;
end;


DBGrid不支持鼠标的上下移动的解决代码自己捕捉WM_MOUSEWHEEL消息处理
private
OldGridWnd : TWndMethod;
procedure NewGridWnd (var Message : TMessage);
public

procedure TForm1.NewGridWnd(var Message: TMessage);
var
IsNeg : Boolean;
begin
if Message.Msg = WM_MOUSEWHEEL then
begin
IsNeg := Short(Message.WParamHi) < 0;
if IsNeg then
DBGrid1.DataSource.DataSet.MoveBy(1)
else
DBGrid1.DataSource.DataSet.MoveBy(-1)
end
else
OldGridWnd(Message);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
OldGridWnd := DBGrid1.WindowProc ;
DBGrid1.WindowProc := NewGridWnd;
end;

dbgrid中移动焦点到指定的行和列 dbgrid是从TCustomGrid继承下来的,它有col与row属性,只不过是protected的,不能直接访问,要处理一下,可以这样:

TDrawGrid(dbgrid1).row:=row;
TDrawGrid(dbgrid1).col:=col;
dbgrid1.setfocus;
就可以看到效果了。

1 这个方法是绝对有问题的,它会引起DBGrid内部的混乱,因为DBGrid无法定位当前纪录,如果DBGrid只读也就罢了(只读还是会出向一些问题,比如原本只能单选的纪录现在可以出现多选等等,你可以自己去试试),如果DBGrid可编辑那问题就可大了,因为当前纪录的关系,你更改的数据字段很可能不是你想象中的
2 我常用的解决办法是将上程序改为(随便设置col是安全的,没有一点问题)

Query1.first;
TDrawGrid(dbgrid1).col:=1;
dbgrid1.setfocus;

这就让焦点移到第一行第一列当中

如何使DBGRID网格的颜色随此格中的数据值的变化而变化? 在做界面的时候,有时候为了突出显示数据的各个特性(如过大或者过小等),需要通过改变字体或者颜色,本文就是针对这个情况进行的说明。

如何使DBGRID网格的颜色随此格中的数据值的变化而变化。如<60的网格为红色?
Delphi中数据控制构件DBGrid是用来反映数据表的最重要、也是最常用的构件。在应用程序中,如果以彩色的方式来显示DBGrid,将会增加其可视性,尤其在显示一些重要的或者是需要警示的数据时,可以改变这些数据所在的行或列的前景和背景的颜色。
  DBGrid属性DefaultDrawing是用来控制Cell(网格)的绘制。若DefaultDrawing的缺省设置为True,意思是Delphi使用DBGrid的缺省绘制方法来制作网格和其中所包含的数据,数据是按与特定列相连接的Tfield构件的DisplayFormat或EditFormat特性来绘制的;若将DBGrid的DefaultDrawing特性设置成False,Delphi就不绘制网格或其内容,必须自行在TDBGrid的OnDrawDataCell事件中提供自己的绘制例程(自画功能)。
  在这里将用到DBGrid的一个重要属性:画布Canvas,很多构件都有这一属性。Canvas代表了当前被显示DBGrid的表面,你如果把另行定义的显示内容和风格指定给DBGrid对象的Canvas,DBGrid对象会把Canvas属性值在屏幕上显示出来。具体应用时,涉及到Canvas的Brush属性和FillRect方法及TextOut方法。Brush属性规定了DBGrid.Canvas显示的图像、颜色、风格以及访问Windows GDI 对象句柄,FillRect方法使用当前Brush属性填充矩形区域,方法TextOut输出Canvas的文本内容。

  以下用一个例子来详细地说明如何显示彩色的DBGrid。在例子中首先要有一个DBGrid构件,其次有一个用来产生彩色筛选条件的SpinEdit构件,另外还有ColorGrid构件供自由选择数据单元的前景和背景的颜色。

  1.建立名为ColorDBGrid的Project,在其窗体Form1中依次放入所需构件,并设置属性为相应值,具体如下所列:

   Table1 DatabaseName: DBDEMOS
TableName: EMPLOYEE.DB
Active: True;
  DataSource1 DataSet: Table1
  DBGrid1 DataSource1: DataSource1
DefaultDrawing: False
  SpinEdit1 Increment:200
Value: 20000
  ColorGrid1 GridOrdering: go16*1

  2.为DBGrid1构件OnDrawDataCell事件编写响应程序:

//这里编写的程序是<60的网格为红色的情况,其他的可以照此类推
  procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;Field: TField; State: TGridDrawState);
  begin
   if Table1.Fieldbyname(′Salary′).value<=SpinEdit1.value then
   DBGrid1.Canvas.Brush.Color:=ColorGrid1.ForeGroundColor
   else
    DBGrid1.Canvas.Brush.Color:=ColorGrid1.BackGroundColor;
   DBGrid1.Canvas.FillRect(Rect);
   DBGrid1.Canvas.TextOut(Rect.left+2,Rect.top+2,Field.AsString);
  end;

  这个过程的作用是当SpinEdit1给定的条件得以满足时,如′salary′变量低于或等于SpinEdit1.Value时,DBGrid1记录以ColorGrid1的前景颜色来显示,否则以ColorGrid1的背景颜色来显示。然后调用DBGrid的Canvas的填充过程FillRect和文本输出过程重新绘制DBGrid的画面。

  3.为SpinEdit1构件的OnChange事件编写响应代码:

  procedure TForm1.SpinEdit1Change(Sender: TObject);
  begin
   DBGrid1.refresh; //刷新是必须的,一定要刷新哦
  end;

  当SpinEdit1构件的值有所改变时,重新刷新DBGrid1。

  4.为ColorGrid1的OnChange事件编写响应代码:

  procedure TForm1.ColorGrid1Change(Sender: TObject);
  begin
   DBGrid1.refresh; //刷新是必须的,一定要刷新哦
  end;

  当ColorGrid1的值有所改变时,即鼠标的右键或左键单击ColorGrid1重新刷新DBGrid1。

  5.为Form1窗体(主窗体)的OnCreate事件编写响应代码:

  procedure TForm1.FormCreate(Sender: TObject);
  begin
   ColorGrid1.ForeGroundIndex:=9;
    ColorGrid1.BackGroundIndex:=15;
 end;

  在主窗创建时,将ColorGrid1的初值设定前景为灰色,背景为白色,也即DBGrid的字体颜色为灰色,背景颜色为白色。

  6.现在,可以对ColorDBGrid程序进行编译和运行了。当用鼠标的左键或右键单击ColorGrid1时,DBGrid的字体和背景颜色将随之变化。

  在本文中,只是简单展示了以彩色方式显示DBGrid的原理,当然,还可以增加程序的复杂性,使其实用化。同样道理,也可以将这个方法扩展到其他拥有Canvas属性的构件中,让应用程序的用户界面更加友好。


判断Grid是否有滚动条?这是一个小技巧,如果为了风格的统一的话,还是不要用了。:)

。。。

if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_VSCROLL) <> 0 then
ShowMessage('Vertical scrollbar is visible!');
if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_HSCROLL) <> 0 then
ShowMessage('Horizontal scrollbar is visible!');

。。。
Lwg0901 2004-08-05
  • 打赏
  • 举报
回复
高难。。。

学习。。。

收藏。。。
zhlwyy 2004-08-05
  • 打赏
  • 举报
回复
这里有一篇自动编号的产生的文章
http://www.delphiun.com/article_view.asp?id=681
数字蛋糕 2004-08-05
  • 打赏
  • 举报
回复
>> 但不能总用别人的,即然别人做到了,为什么我做不到呢?

其实并非是你做不到,排序谁都会做。

不要钻到DBGrid的牛角尖里去,硬要它勉为其难进行排序。就算你做出来了,也学不到什么有价值的东西(当然只是相对你的目标而言,不排除可能有意外的收获)。

从另一个角度去尝试一下吧。
miky 2004-08-05
  • 打赏
  • 举报
回复
有点搞笑!
你不用别人的,那你自己造电脑,自己写操作系统,自己写编译器。
哦,你还要自己设计编程语言,等你弄好这些了,我们的孙子的孙子已经在用256位电脑了!

面向对向的最终目的就是代码重用,不要做太多的无用功。如果你觉得他们推荐的不好,你完全可以使用VCL本身带的StringGrid,DBGrid的功能太差了,他必须和数据绑定,不能自由发挥,要自由,就用他的兄弟StringGrid吧,他本身有保存内容的功能,只要取到了内容,就可以脱离数据库,你爱怎么样就怎么样,和数据库再无任何关系。
jame024 2004-08-05
  • 打赏
  • 举报
回复
有点想笑,,,,,,,
gegangqiao 2004-08-05
  • 打赏
  • 举报
回复
我有DBGRIDEH 很好用,但不能总用别人的,即然别人做到了,为什么我做不到呢?为什么ADO就会有SORT方法来排序,肯定能做出来,但要仔细看系统提供的代码才可以.
其实可以把读出来的数据保存到本地,然后要求排序时再按要求的顺序读出来,但我没有试成功.
请高手指点.
LoveIvy 2004-08-05
  • 打赏
  • 举报
回复
支持楼上的做说,这样做比较简单,也不用写代码
princesd 2004-08-05
  • 打赏
  • 举报
回复
用dbgride实现真的太麻烦了,用一个别的控件来做,根本不用代码就能实现。ExpressQuantumGrid Suite v5.0 (表格控件)
capoatguitar 2004-08-05
  • 打赏
  • 举报
回复
有些难了,主要是不知道数据在内存里是怎么放的。
hevin 2004-08-05
  • 打赏
  • 举报
回复
我们公司也有一套,但不能给,嘎嘎!!
iknowwn 2004-08-05
  • 打赏
  • 举报
回复
这么长

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧