我在DBGrid中显示了一个表,排序顺序基于一个Sequence字段,我希望能够一次向上或向下移动一个项目。我在这里研究过,找不到任何我需要的东西。
当我禁用排序顺序进行更改时出现问题,列表将恢复为最初输入数据的顺序,因此我在下一行中丢失了该项目。
这就是我的......
Folder Sequence
----------------
Buttons 1
Thread 2 << Current Row
Cotton 3
Rags 4
点击我想要的“MoveDown”按钮......
Folder Sequence
----------------
Buttons 1
Cotton 2
Thread 3 << Current Row
Rags 4
但是 - 当我删除序列中的排序顺序时,我得到了我输入项目的顺序......
Folder Sequence
----------------
Buttons 1
Cotton 2
Rags 4
Thread 3 << Current Row
到目前为止,我的尝试证明非常繁琐,并且涉及将Rows加载到列表框中,对它们进行洗牌,然后将它们写回表中。要有一个更好的方法,但它超出了我目前掌握的SQL。
有人可以指点我去的方向。
如果在SQL中执行起来很困难,我不想太麻烦任何人,因为我总是可以使用列表框方法。如果对SQL专家来说相对简单,那么我很乐意看到SQL文本。
由于
答案 0 :(得分:4)
我的解决方案基于按Sequence
字段排序的TDataSet:
MyDataSet.Sort := 'Sequence';
然后在当前行和Sequence
(向下)/ Next
(向上)记录之间交换Prior
字段,例如:
type
TDBMoveRecord = (dbMoveUp, dbMoveDown);
function MoveRecordUpDown(DataSet: TDataSet; const OrderField: string;
const MoveKind: TDBMoveRecord): Boolean;
var
I, J: Integer;
BmStr: TBookmarkStr;
begin
Result := False;
with DataSet do
try
DisableControls;
J := -1;
I := FieldByName(OrderField).AsInteger;
BmStr := DataSet.Bookmark;
try
case MoveKind of
dbMoveUp: Prior;
dbMoveDown: Next;
end;
if ((MoveKind = dbMoveUp) and BOF) or ((MoveKind = dbMoveDown) and EOF) then
begin
Beep;
SysUtils.Abort;
end
else
begin
J := DataSet.FieldByName(OrderField).AsInteger;
Edit;
FieldByName(OrderField).AsInteger := I;
Post;
end;
finally
Bookmark := BmStr;
if (J <> -1) then
begin
Edit;
FieldByName(OrderField).AsInteger := J;
Post;
Result := True;
end;
end;
finally
EnableControls;
end;
end;
的用法:强> 的
MoveRecordUpDown(MyDataSet, 'Sequence', dbMoveDown);
// or
MoveRecordUpDown(MyDataSet, 'Sequence', dbMoveUp);
答案 1 :(得分:0)
如果我理解正确,你想找到“下一个序列项目”? 也许你可以做一些事情,比如“获得第一个最小值,然后再获得X”? 通过这种方式,您可以通过prev。行序列值。