#2
sssooosss2022-06-13 19:34
|
注:程序内注释均按个人理解添加,可能有误!
附代码:
程序代码:
procedure TForm1.DBGrid1TitleClick(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 TFDQuery(TDBGrid(Column.Grid).DataSource.DataSet) do //根据column获取FDQuery对象
begin
SqlStr := UpperCase(Sql.Text); //SQL语句字符串大写
// if pos(myFieldName,SqlStr)=0 then exit; //如果SQL语句中不存在所选字段名,则退出
if ParamCount>0 then //如果运行过程时包含参数
begin
SavedParams := TParams.Create; //创建保存参数变量
SavedParams.Assign(Params); //连接参数
end;
OrderPos := pos('ORDER',SqlStr); //获取'ORDER'串在SQL语句中的起始位置
if (OrderPos=0) or
(pos(myFieldName,copy(SqlStr,OrderPos,100))=0) then //如不存在ORDER或ORDER子句中不包含所选字段
TempStr := ' Order By ' + myFieldName + ' Asc' //生成按照所选字段升序排列的ORDER子句
else if pos('ASC',SqlStr)=0 then //如果ORDER子句中有所选字段但不包含升序标志
TempStr := ' Order By ' + myFieldName + ' Asc' //生成按所选字段升序排列的ORDER子句
else //如果ORDER子句中有所选字段且包含升序标志
TempStr := ' Order By ' + myFieldName + ' Desc'; //生成按所选字段降序排列的ORDER子句
if OrderPos<>0 then SqlStr := Copy(SqlStr,1,OrderPos-1); //如果存在ORDER子句,提取ORDER子句之前的SQL语句内容
SqlStr := SqlStr + TempStr; //将其与新生成的ORDER子句连接
Active := False; //锁定QUERY状态
Sql.Clear; //清除SQL内容
Sql.Text := SqlStr; //更新SQL内容
if ParamCount>0 then //如果运行过程时包含参数
begin
Params.Assign(SavedParams); //提取保存的参数变量
SavedParams.Free; //释放参数变量
end;
Prepare; //将带参数的SQL语句传给数据库引擎
Open; //打开查询
end;
end;
procedure TForm1.DBGrid1TitleClick(Column: TColumn); //方法二
var
temp, title: string;
lastcolumn,icount:integer; //应设为单元内全局变量,记录已点击状态和添加SQL排序子句的位置?
begin
temp := Column.FieldName;
lastcolumn:=DBGrid1.DataSource.DataSet.FieldCount-1;
icount:=1;
FDQuery1.Close; //关闭查询
if Column.Index <> lastcolumn then // 如果不是已点击列
begin
if (Pos('↑', DBGrid1.Columns[LastColumn].Title.Caption) > 0)
or (Pos('↓', DBGrid1.Columns[LastColumn].Title.Caption) > 0) then
DBGrid1.Columns[LastColumn].Title.Caption :=
Copy(DBGrid1.Columns[LastColumn].Title.Caption, 3,
Length(DBGrid1.Columns[LastColumn].Title.Caption) - 2); //如果字段名中包含上下箭头,去掉字段名前两个字符
FDQuery1.Sql[icount] := 'order by ' + temp + ' asc'; //查询SQL中添加按当前字段排序
DBGrid1.Columns[Column.Index].Title.Caption :=
'↑' + DBGrid1.Columns[Column.Index].Title.Caption; //字段名前添加上箭头
lastcolumn := column.Index; //当前列加入已点击
end
else
begin
LastColumn := Column.Index; //当前列加入已点击
title := DBGrid1.Columns[LastColumn].Title.Caption; //标题等于字段名
if Pos('↑', title) > 0 then //如果标题中包含上箭头
begin
FDQuery1.Sql[icount] := 'order by ' + temp + ' desc';
Delete(title, 1, 2); //删除标题中前两个字符
DBGrid1.Columns[LastColumn].Title.Caption := '↓' + title; //字段名前添加下箭头
end
else if Pos('↓', title) > 0 then //如果标题中包含下箭头
begin
FDQuery1.Sql[icount] := 'order by ' + temp + ' asc';
Delete(title, 1, 2); //删除标题中前两个字符
DBGrid1.Columns[LastColumn].Title.Caption := '↑' + title; //字段名前添加上箭头
end
else //如果标题中不包含箭头
begin
FDQuery1.Sql[icount] := 'order by ' + temp + ' asc'; //查询SQL中添加按当前字段排序?
DBGrid1.Columns[LastColumn].Title.Caption := '↑' + title; //字段名前添加上箭头
end;
end;
FDQuery1.Open; //打开查询
end;
综合以上两种方法的优点,经过思考修改后,最终采用的方案(方法三):
程序代码:
procedure TDM1.DBGridSort(DBGrid:TDBGrid; Column: TColumn); //DBgrid点击标题栏排序(方法三)
var
SqlStr,myFieldName,TempStr,TitleStr: string;
i,OrderPos,colnum: 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 TFDQuery(DBGrid.DataSource.DataSet) do
begin
colnum:=column.index;
if (Pos('↑', column.Title.Caption) > 0)
or (Pos('↓', column.Title.Caption) > 0) then
column.Title.Caption :=
Copy(column.Title.Caption, 3,
Length(column.Title.Caption) - 2); //如果字段名中包含上下箭头,去掉字段名前两个字符
TitleStr := Column.Title.Caption; //取字段标题
SqlStr := UpperCase(Sql.Text); //SQL语句字符串大写
if ParamCount>0 then //如果运行过程时包含参数
begin
SavedParams := TParams.Create; //创建保存参数变量
SavedParams.Assign(Params); //连接参数
end
else
savedparams := nil;
OrderPos := pos('ORDER',SqlStr); //获取'ORDER'串在SQL语句中的起始位置
if (OrderPos=0) or
(pos(myFieldName,copy(SqlStr,OrderPos,100))=0) then //如不存在ORDER或ORDER子句中不包含所选字段
begin
TempStr := ' Order By ' + myFieldName + ' Asc'; //生成按照所选字段升序排列的ORDER子句
TitleStr := '↑ ' + TitleStr;
end
else if pos('ASC',SqlStr)=0 then //如果ORDER子句中有所选字段但不包含升序标志
begin
TempStr := ' Order By ' + myFieldName + ' Asc'; //生成按照所选字段升序排列的ORDER子句
TitleStr := '↑ ' + TitleStr;
end
else //如果ORDER子句中有所选字段且包含升序标志
begin
TempStr := ' Order By ' + myFieldName + ' Desc'; //生成按所选字段降序排列的ORDER子句
TitleStr := '↓ ' + TitleStr;
end;
if OrderPos<>0 then SqlStr := Copy(SqlStr,1,OrderPos-1); //如果存在ORDER子句,提取ORDER子句之前的SQL语句内容
SqlStr := SqlStr + TempStr; //将其与新生成的ORDER子句连接
Active := False; //锁定QUERY状态
Sql.Clear; //清除SQL内容
Sql.Text := SqlStr; //更新SQL内容
if ParamCount>0 then //如果运行过程时包含参数
begin
Params.Assign(SavedParams); //提取保存的参数变量
SavedParams.Free; //释放参数变量
end;
Prepare; //将带参数的SQL语句传给数据库引擎
if Not Active then Open ; //打开查询,按点击字段排序
DBGrid.Columns[colnum].Title.Caption := TitleStr; //显示排序修改后的字段标题
end;
end;
//以上过程放入数据模块DM1中作为公用过程,其它单元引用后即可使用,调用方法如下:
procedure TForm1.DBGrid1TitleClick(Column: TColumn);
begin
DM1.DBGridSort(DBGrid1,Column);
end;
[此贴子已经被作者于2022-6-4 13:28编辑过]