delphi中dbgrid的分页显示(分享)(0分)

  • 主题发起人 主题发起人 maldini610
  • 开始时间 开始时间
M

maldini610

Unregistered / Unconfirmed
GUEST, unregistred user!
dbgrid分页显示,最近做的小应用程序,有个需求,要求分页显示数据。
于是,在baidu中一顿搜索,关于这方面的问题还真就是不少,由于自己的愚蠢,实在是看不明白高手们的寥寥几笔,而且,程序的需求是在dbgrid中能直接修改,我看大部分都是通过sql语句实现的,但是那样的sql语句好像连dbgrid的时候不能修改,只能浏览。
在网上没找到支持分页的控件,于是决定自己想办法实现。
首先说明下,我的分页功能的实现方法,可能是违背了大多数分页显示的目的(提高效率),我做的分页功能的目的是,浏览时有好的效果。
我利用了数组和sql语句,个人认为在效率上存在问题。
窗体中的主要的控件有“上一页”,“下一页”按钮,一个dbgrid,还有一个那个叫DataModulem奥(我delphi不熟)
Var
di,ii :integer;
arr1: array of String;
arr2: array of String;
//下面的代码写在了formonshow事件中,进行调用。
//di代表当前页,ii代表总页数。
function fenye():Integer;
var
fyi1, fyi2, fyi3: integer;
fysql: String;
begin
DataModulem.ADOQuerym.Close;
DataModulem.ADOQuerym.SQL.Clear;
DataModulem.ADOQuerym.SQL.Add('select id from danjia order by id desc');
DataModulem.ADOQuerym.Open;
di:=1;
djyl1.TeLabel10.Caption:=inttostr(di);
ii:= DataModulem.ADOQuerym.RecordCount div 20;
if DataModulem.ADOQuerym.RecordCount mod 20 <> 0 then
begin
inc(ii);
end;
djyl1.TeLabel12.Caption:=inttostr(ii);
fyi1 := 0;
fyi2 := 0;
fyi3 := 0;
if DataModulem.ADOQuerym.RecordCount > 0 then
begin
setlength(arr1, DataModulem.ADOQuerym.RecordCount);
While (Not DataModulem.ADOQuerym.Eof) do
begin
arr1[fyi1] := DataModulem.ADOQuerym.FieldByName('id').AsString;
DataModulem.ADOQuerym.Next;
inc(fyi1);
end;
end;
if High(arr1) >= 0 then
begin
setlength(arr2, ii*2);
while fyi2 <= High(arr1) do
begin
arr2[fyi3] := arr1[fyi2];
fyi2 := fyi2 + 20;
inc(fyi3);
end;
arr2[fyi3] := arr1[High(arr1)];
end;
if di <ii then
begin
fysql := 'select * from danjia where id<='+arr2[di-1]+' and id>'+arr2[di]+' order by id desc';
end
else
begin
fysql := 'select * from danjia where id<='+arr2[di-1]+' and id>='+arr2[di]+' order by id desc';
end;
DataModulem.ADOQuerym.Close;
DataModulem.ADOQuerym.SQL.Clear;
DataModulem.ADOQuerym.SQL.Add(fysql);
DataModulem.ADOQuerym.Open;
Result := fyi1;
end;
////////////////////////////(每页显示20条数据)
其中 主要思想就是取出表中的第1条,21条,。。。最后一条数据的id放入数组中,然后根据当前的页数,通过sql语句查询出结果来。
//下面是“上一页”和“下一页“按钮代码
procedure Tdjyl1.TeButton11Click(Sender: TObject);//上一页
begin
if di > 1 then
begin
dec(di);
TeLabel10.Caption:=inttostr(di);
DataModulem.ADOQuerym.Close;
DataModulem.ADOQuerym.SQL.Clear;
DataModulem.ADOQuerym.SQL.Add('select * from danjia where id<='+arr2[di-1]+' and id>'+arr2[di]+' order by id desc');
DataModulem.ADOQuerym.Open;
end;
end;
procedure Tdjyl1.TeButton12Click(Sender: TObject);//下一页
var
sql :String;
begin
if di < ii then
begin
inc(di);
TeLabel10.Caption:=inttostr(di);
if di <ii then
begin
sql := 'select * from danjia where id<='+arr2[di-1]+' and id>'+arr2[di]+' order by id desc'
end
else
begin
sql := 'select * from danjia where id<='+arr2[di-1]+' and id>='+arr2[di]+' order by id desc'
end;
DataModulem.ADOQuerym.Close;
DataModulem.ADOQuerym.SQL.Clear;
DataModulem.ADOQuerym.SQL.Add(sql);
DataModulem.ADOQuerym.Open;
end;
end;
就这样我实现了分页,我知道无论从代码风格还是,编成思想上,小弟都差很多,希望各位大侠给与批评指正,我也想知道更好的方法
 
又不是 WEB 没有必要分页
 
我同意mstar,可是老板要求那样阿。我也没办法啊
 
如果数据量大的话就要必须的分页,读入数据的时候多慢啊!
可以用存储过程来分页的啊!我给你个例子你看看!
CREATE PROC ReturnRowspub(
@SQL VARCHAR(100),--表或试图的名称
@Page int,--当前的页数
@findstr varchar(255),---需要查询的值
@ID VARCHAR(255),--主键
@Sort VARCHAR(255),--需要排序的字段
@findzd varchar(255)---需要查询的字段)
AS
DECLARE @RecsPerPage int,--每页显示的记录数量(当然你可以设置成动态的)
@sqlstr varchar(1000)--需要执行的SQL语句
set @RecsPerPage=30
if @findstr='' or @findzd='' ---表示普通的浏览
SET @sqlStr='SELECT TOP '+CAST(@RecsPerPage AS VARCHAR(20))+' * FROM '+@SQL+' T WHERE T.'+@ID+' not in
(SELECT TOP '+CAST((@RecsPerPage*(@Page-1)) AS VARCHAR(20))+' '+@ID+' FROM '+@SQL+' T ORDER BY '+@Sort+') ORDER BY '+@Sort
else ---查询浏览
SET @sqlStr='SELECT TOP '+CAST(@RecsPerPage AS VARCHAR(20))+' * FROM '+@SQL+' T WHERE T.'+@ID+' not in
(SELECT TOP '+CAST((@RecsPerPage*(@Page-1)) AS VARCHAR(20))+' '+@ID+' FROM '+@SQL+' T where t.'+@findzd+' like '''+@findstr+'%'' ORDER BY '+@Sort+')
and t.'+@findzd+' like '''+@findstr+'%'' ORDER BY '+@Sort
exec (@strSQL)
go
这个存储过程我一直在用,至于效率(40万条数据量)还不错,挺快!如果还有什么问题
QQ398836954
 
在分页之前你需要得出满足条件的记录的总数/每页显示的记录条数=总的页码

还有就是当点下一页的时候只需要 让@Page的值加1就可以了
当然上一页就让@page的值减1
 
clientdataset就可以分批读的
 
分页只是界面上的效果,与读写速度没什么关系,dbgrid任何时候都只读出当前显示那一丁
点数据,其它不显示的数据,它不会理会,我想可以用更简单的方法,例如调整dataset的
指针来实现,但最后一页就不好办,因为只要数据行数超过dbgrid的显示行数,dbgrid一定
会将表格填满,假如最后一页,只有一行数据,它便会将对上一页的数据也显示出来,效果
就不好。
 
to kinneng:
您说的没错 最开始我是用dataset是实现的,可是 就是因为 最后一页 添满了 才觉得不爽,不知道 您是否 有什么方法可以实现?

您说的存储过程 的方法 因为 小弟的愚蠢,小弟有点问题, 小弟 会在 能上 qq的时候 向您 请教,谢谢
 
上面看到的方法不太通用例如ado、存储过程等,用dataset干活比较通用,用dataset不是没有方法,不过真的很烦,最后一页,先计算剩多少行,然后限制DBgrid的可显示行数为
多少行,不过做起来很困难,设计不周密,很容易导致表格失控,产生致命错误。
 
我已经做到前后翻页,并且解决最后一页只显示几行的问题,但在最后一页不能逐行滚动表格,相信可以搞掂的,这个方法肯定比什么别人的方法好很多,最重要就是通用,现在没时间,全部时间用来炒股,编程不玩了。
 
取下一页
select top 20 *
from tbl where id<...上一页取数据时最小得Id
order by id desc
取上一页
select top 20 *
from tbl where id>...下一页取数据时最大得Id
order by id asc

不就行了,弄得那么复杂
 
to 绵绵细雨:
您 自己试验了吗? 还有,我想问的是,你实现了吗?坦白的讲 我觉得你写的sql语句很有问题.
to kinneng:
不好意思 我delphi不是很熟,我想知道为什么ado不通用呢?
 
不是说ado通不通用,而是说光关照着ado,其实ado很烂,有时候会莫名其妙地弹出最后的数据已修改,如何如何的警告框,其实不是什么问题,而是系统里面的ado系统有几个文件被其它软件升级了版本,你根本不知道,交货给客户,用了几个月出现这个问题,要你去维修,根本无从入手,改用其它数据库,那么你的分页方法岂不是推倒重来。
 
to kinneng:
谢谢您的解释,我用的可能是比较少的原因,还没遇见那样的情况,不知道其他的人是否也遇到同样的问题了呢?
 
遇到也不一定知道有这回事,曾经装过别人的程序,发现自己的程序经常出错,重装系统
解决,但再装过别人的程序后,又再出错,慢慢调试分析,才知道一些ADO文件被别人的安
装程序换了,再重装系统,保存这些会被换掉的文件,再装别人的程序,然后将保存的文
件复制回去,结果别人的程序可以运行,我的程序没有出错,主要是别人的程序带的文件
是新版本,但只换了几个,而不是整个版本升级,所以出了问题。
 
其实用SQL语句也可以直接分的!
SELECT TOP '+20+' * FROM '+表名称+' T WHERE T.'+主键+' not in
(SELECT TOP '+每页的记录数量*(当前页数-1)+' '+主键+' FROM '+表名称+' T ORDER BY '+排序字段+') ORDER BY '+排序字段
这应该就是最有效最简单的分页了,只需要把我写文字的地方改成相应的值就OK了!
如果谁还觉的有问题我演示给他看!
这个SQL语句是绝对没有问题的!
 
TO 绵绵细雨
按照你的分页,如果我要跳转到用户所指定的任何一页怎么办???/????
 
to pplovejx:
我还是说一下我的想法,首先,我已经在qq中加您了。
其次,您最先前的存储过程,小弟愚昧,根本不明白,存储过程
然后,您现在写的sql语句,我觉得有点问题,我觉得您的sql语句点下一页按钮时应该是完全没有问题的,可是点“上一页”按钮时就出现问题了吧,我想问下,比如总共有5页,最开始是第一页,当我点了 4次 “下一页”按钮,到了第4页,然后 再点“下一页” 按钮,到了,第5页,我的疑问是,如果 我再点 “上一页” 到了第4页,这时第4页显示的数据和我刚才点的第4页显示的数据一样吗?
因为类似的sql语句 我看过不少,可是 上一页和下一页的sql语句 应该是不一样的,而且,下一页的比较难写。
望指正。谢
 

Similar threads

S
回复
0
查看
917
SUNSTONE的Delphi笔记
S
S
回复
0
查看
898
SUNSTONE的Delphi笔记
S
I
回复
0
查看
515
import
I
后退
顶部