急救!dbgrid中关于dataset的删除操作!(120分)

  • 主题发起人 主题发起人 windflower
  • 开始时间 开始时间
W

windflower

Unregistered / Unconfirmed
GUEST, unregistred user!
大家好,请教一个关于dbgrid的问题!
我现在在用dbgrid来进行数据输入(通过与adoquery相连),为避免将无效数据项(譬如关键字段为空的记录)写入数据库,我在将数据
写入库之前要进行判断adoquery.fieldvalues['字段名']是否为空。我是根据adoquery.recordcount来循环的
。因为dbgrid中可以用上下键移动,我在当前行录好数据后,用向下键移动,dbgrid 中就增加了
一个空行以供继续输入数据。adoquery.recordcount加1,但如果这时(即在我未对空行进行任何编辑操作)我用向上键向上移一行,
空行自动消失,不过adoquery.recordcount的值好象没变。现在,如果我要对adoquery的dataset进行删除操作,会
出现类型转换错误,我想可能是由于空行造成的。请大家帮忙!
此外,在dbgrid中,怎样实现在一个单元格中输完数据后敲回车键就能完成TAB的功能?能不能对
一个单元格的readonly属性进行赋值?
谢谢大家!
 
据说ado控件的recordcount不是很准确,至少在asp下的确是这样的
delphi下不知如何,我一般用eof来判断。
 
那用adoquery.recordcount>0 和adoquery.isempty来判断ado的dataset是否为空谁对呢?
 
我一般用adoquery.eof(true or false)来判断是否为空的。
true为空,false则不空。
你提到的那两个属性我没有用过,不太清楚。
 
我回答那个简单的敲回车实现TAB键功能的问题.
在窗体的KeyPress事件中加入以下代码:
if (ActiveControl is TDbgrid) then
begin
with TDbgrid(ActiveControl) Do
if Selectindex<(FieldCount-1) then
Selectedindex:=Selectedindex+1
else Selectedindex:=0;
end;
end;
 
如果用RecordCount 时同时也用一下RecNo判断一下看看是否对应...
 
>>那用adoquery.recordcount>0 和adoquery.isempty来判断ado的dataset是否为空谁对呢?
用adoquery.isempty吧。
 
感觉都一样吧,你试试不就知道了吗。
 
>>能不能对一个单元格的readonly属性进行赋值?
如果是一列,可以这样(在DBGrid的OnMouseDown事件里):
procedure TForm1.DBGrid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DBGrid1.ReadOnly := False;
if (DBGrid1.SelectedField <> nil)
and (DBGrid1.SelectedField.FieldName = 'f1') then DBGrid1.ReadOnly := True;
end;
但一个确实不太好办,因为行不好确定,不知道你的记录里能不能准确地定位行,
如果能,那你试试在上面的代码中加入你的行判断行不行。
 
我是通过dbgrid来输入数据的(adoquery连接),为什么我往dbgrid中输了一条记录后,
adoquery.recordcount=0?如果我先输了一条有效记录,再按向下键,系统会自动增加一条
空记录,我在未进行任何动作的情况下,按向上键,该空记录自动消失,然而
adoquery.recordcount=1了。为什么呢?那么如果我用adoquery.recordcount>0来判断
是否为空,岂不是错了?此外,我用adoquery.next向下移动时,如果当前记录为最后一条
记录,那么adoquery.eof为假吗?还能下移吗?是不是下移后adoquery.eof就为空了?
adoquery.edit对通过dbgrid输入数据有什么影响,会不会造成空记录的添加?
 
>>为什么我往dbgrid中输了一条记录后,adoquery.recordcount=0?
因为你还没有换行,就是还没有post。
>>按向上键,该空记录自动消失,然而adoquery.recordcount=1了
实际上在你按向下键时RecordCount就已经变成1了,关键就看你是在什么时机判断的。
我估计是BeforePost吧,你要是在BeforeInsert里判断就可以看到变化。

其实要实现你的合法性检查不用遍历所有记录的,在ADOQuery的BeforePost里写就行:
if DataSet.FieldByName('keyfield').AsString = '' then begin
Application.MessageBox('keyfield不能为空', '提示', MB_ICONWARNING);
Abort;
end;
不知道我理解的对不对?
 
同意dq的说法,在提交前进行检查。
 
我试用了BeWorldMan的方法,但没有实现在一个输入格中敲回车
就自动跳到下一个单元格的功能。
 
在DBGrid的OnKeyDown里:
if Key = VK_RETURN then PostMessage(DBGrid1.Handle, WM_KEYDOWN, VK_TAB, 0);
 
谢谢大家!我用dq的方法试了一下,的确可以进行合法性检查,只要有必输项为空,就
不能提交。但是,如果我录入数据时,想删掉某行
(譬如按delete键删掉当前行,怎样连续选中几行(可以按shift,ctrl那种)),
怎么办呢?(以前,我是根据必输项是否还有为空的来进行删除的)。
 
要实现多选,把dgMutiSelect项包含进DBGrid的Options集合属性里,
也就是在属性编辑器里把Options下面的dgMutiSelect设为True。但是不能用Shift连续选择:(
至于删除,本来就可以在DBGrid上按Ctrl+Del实现,但这里有一个问题就是如果Options里
包含dgConfirmDelete,那么会在删除时出现英文提示。可以把dgConfirmDelete设为False,
然后在DBGrid的OnKeyDown里自己实现中文提示:
procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key = VK_DELETE) and (ADOQuery1.State = dsBrowse) then begin
if Application.MessageBox('确定删除选定记录?', '提示',
MB_OKCANCEL + MB_ICONQUESTION) = ID_OK then
if DBGrid1.SelectedRows.Count = 0 then ADOQuery1.Delete
else DBGrid1.SelectedRows.Delete;
Key := 0;
end;
end;
 
很奇怪,我在dbgrid中有时候按 shift是连选,有时候按 ctrl是连选,至于按ctrl+D删除,
我只成功了一次。这是怎么回事呢?
 
对于在DBgrid中按回车完成tab键的方法:
在onkeydown中
if dbgrid.SelectedIndex =dbgrid.Columns.Count - 1 then
begin
dbgrid.SelectedIndex := 0;
if dbgrid.DataSource.DataSet <> nil then
with dbgrid.DataSource.DataSet do
begin
Next;
if EOF and CanModify then Append;
end;
end
else dbgrid.SelectedIndex := Sender.SelectedIndex + 1;
 
谢谢大家,在dbgrid中用enter键完成tab键的功能已经实现,现在我想在dbgrid中选中几行(
可以连续,也可不连续),然后删除。dq说在dbgrid中用ctrl+D可以删除,按ctrl键可以连选
,我试了一下,有时成功,有时失败,是不是还有什么设置或注意事项?有没有别的办法呢?(
简单点的)?谢谢!
 
其实直接对DBGrid直接操作是不合适的,应该对和DBGird连接的Query组件进行操作
例如dg说的,在BeforePost事件中进行合法性检查
DBGrid1.SelectedRows.Delete这种用法也是不合适的,应该直接在query里进行删除
例如捕获keydown事件,找到所选记录的ID,再在query里删除
象recordNO这种属性跟sql数据库原理是冲突,除非万不得已根本不应该使用
 
后退
顶部