如何获得DBGrid中某一个格的内容(200分)

  • 主题发起人 主题发起人 caowei
  • 开始时间 开始时间
C

caowei

Unregistered / Unconfirmed
GUEST, unregistred user!
使用ACCESS数据库,用DBGrid显示
现在我想知道某个指定行和列处的字符串,
有没有办法呢?
有个GetEditText,但是没法用,
另外,能知道当前位于哪一行和哪一列吗?
 
在DBGRID1的 onCellClick事件中, 传入的参数就是当前列, 你取该列的
字符串就是当前行当前列的内容.
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
showmessage(column.Field.AsString);
end;
 
问题是我并不是在CELL被CLICK时才响应
而是:比如有个按钮被按下时,我想知道第2行第3列处格子中的字符串
那怎么办呢?
谢谢!
 
Dbgid有Cell属性.
 
没有!
DBGrid并没有CELL属性,不信你写一个给我看看 :-)
 
TDBGrid确实并没有CELL属性,这可能是为了保持数据的完整性.
 
恕小弟愚见,实在无法做好.
出个馊主意,在你需要的时候,发送一个鼠标消息到指定位置,让DBGrid自己选上你要的数据.然后就ok了!
 
本人也在进行数据库的编写工作,这个问题实现起来并不太难。
为了浏览数据库,我自编写了与DBNavigator1相似的按钮,这样就能任意操纵数据库
了。你的问题也可用此方法,以确定DBGrid的行(记录编号),以待显示的数据库字段
作为列,当你点击nbNext等按钮后,DBGrid指针也跟着联动,你的'行、列'值即得出,
若感兴趣,日后贴上程序。
 
行值换个角度就是记录值,可用 Table1.Recordno得到,
Field字段名可用 DBGrid.Columns.Items[列值].FieldName得到,
有了这两样,值是什么就不用我说了!
 
把上一条修正一下,记录值是Table1.RecNo,
另外,结果我也写出来吗,就是:
定义一整形变量 num
Table1.First
Table1.MoveBy(行值)
您想要的字患=
Table1.FieldByName(DBGrid1.Coloumns.Items[列值].FieldName).AsString
 
to gefei:
TTable.RecNo 属性作用于 ACCESS97 时,总是返回 -1,
RECNO 属性只适用于 Paradox and xDbase,不适用于其它.
access数据库是无法用Recno的.
 
to gefei:
TTable.RecNo 属性作用于 ACCESS97 时,总是返回 -1,
RECNO 属性只适用于 Paradox and xDbase,不适用于其它.
access数据库是无法用Recno的.
 
总结:
1.DBGrid从数据库中的读取方式是这样的:
对于Client/Server数据库,server端数据查询时只会将当前已查询出来的数据
传送出来, 你此时并不知道到底有多少条记录符合条件, 只有到全部记录传送
到客户端后, 你才可能知道数据集究竟有多少条记录,(这样做要花费大量时间).
所以不可能通过Grid得知第几行,第几列的数据.
(比如我要知道第3000行,第2列的数据,但是现在这一行还未传到DBGrid内,该如
何是好?)
而对于文件型数据库查询时是一次性地将所有记录都查询出来,这样在下一步操作
前就可取得记录条目数, 也就可以定DBGrid的各种属性值. 自然也就可以获得某
个指定行, 列处的字符串了.
但是Delphi并不是对所有的文件型数据库都是这样做的,因此,可靠的方法还是对
该DBGrid所对应的TDataSet(包括TTable, TQuery, TClientDataSet)的指定行,
列进行检索.gefei的方法是正确的(除去对RecNo的说法).
2.GetEditText是对于当前正在编辑的某个Cell进行的操作.它有几个局限.首先,
DBGrid必须处于编辑状态,其次,它还只能返回编辑时选定的字符.而一般性的选定
则不会返回字符串.返回当前选择的Cell值,可以继承TCustomDBGrid类,将其中的
Cols和Rows(应该是这两个,名字可能有点出入)设为publish或public就可获得当
前选择的行,列,而不必使DBGrid处于编辑状态.
3.也可人为地发出某种消息,或者通过定位而使DBGrid的当前记录指向您所要的记录,
但是这样做,窃以为不如直接从DBGrid所对应的数据集中选取,那样直接,方便,可读
性强.我的原则是这样的:程序可读性一定要比技巧重要,因为您不能保证什么时候会
重读自己的源码,而过于强调技巧会使阅读程序困难.
 
看一下下面这段从Borland拷来的东西也许有用。
Howdo
I know what is being typed into the grid?
Answer:
You can see what is being typed into a TDBGrid by looking at
the TInPlaceEdit control of the TDBGrid. Care should be taken
to make sure that the TInPlaceEdit control is created before
trying to use it. The following function will show the data in
the column of the grid that is being edited:
procedure TForm1.DBGrid1KeyUp(Sender: TObject;
var Key: Word;
Shift: TShiftState);
var
B: byte;
begin
for B := 0 to DBGrid1.ControlCount - 1do
if DBGrid1.Controls is TInPlaceEdit then
begin
with DBGrid1.Controls as TInPlaceEditdo
begin
Label1.Caption := 'Text = ' + Text;
end;
end;
end;

Please reference TInPlaceEdit in the Delphi 3 help file for
more information on it's functionality.
 
如果是用移动记录号的方法,当然是很容易实现的,我只要
用Table1.First,然后不断用Table1.Next就可以了,但是
这样的话,DBGrid的指针位置就要来回变. 试想,如果我希望
在某个格中的数据输入以后,与以前的所有值作比较,看看是否
有重复,那么每此输入完了以后一回车,指针就从上到下走一遍,
用户怎么接受呢?
gefei的方法是移动记录号来实现的,所以不太合适我的要求.
Jams的好象也是通过移动DBGRID的指针来实现的,茶叶蛋说的
"可靠的方法还是对该DBGrid所对应的TDataSet(包括TTable,
TQuery, TClientDataSet)的指定行,列进行检索"是什么意思?
怎么检索?
zhaoyipeng贴出来的方法是显示当前编辑的格中的文字,不用
这种方法也能实现吧?
StringGrid也是从TCustomGrid继承来的,为什么就可以这样呢?
有没有可能改一改东西,让DBGrid也有这个属性呢?我想,既然它
已经显示了数据库的内容,就应该可以得到诸如count之类的值的
...
但是,怎么实现呢?
 
让我来为你解决这个问题吧,其实也不难,对任何类型的数据库
都可用,请看(用于获取第4行第3列的数据):
你应在表单中加入一个DBGrid及一个Button,点按Button时将
获取该单元的值。
.
tb0: TBookMark;
//定义一个TBookMark变量
.
.
tb0:=nil;
//在Form的Create事件中初始化
.
.
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject;
const Rect: TRect;
Field: TField;
State: TGridDrawState);
begin
if tb0=nil then
if field.fieldname='Species No' then
tb0:=table1.GetBookmark;
// 因为只需获得GRID1中的第一行的BOOKMARK,这里要清楚的是
// 每次重绘,均要从第一行开始,这是知道该BOOKMARK的最好时机
// 以后的事情就好办了。
end;
.
.
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
// 这里的目的是要得到当前DBGRID中的第四行第3列的值
tb0:=nil;
// 首先,清空BOOKMARK,以便重绘时得到一个新的BOOKMARK
DBGRid1.refresh;
//强迫DBGRID1重绘,从而得到当前第一行的BOOKMARK
table1.gotobookmark(tb0);
for i:=1 to 3do
table1.Next;
//到第4行,下移3次
label1.caption:=dbgrid1.Columns.Items[2].field.asstring;
//第3列
end;

至此,万事大吉,满意了吗?只是上面的方法会引起DBGRID的滚动,当然你
可以把它滚动回来,另外,你也可不用BOOKMARK而使用关键字,这样,你便可
使用LOOKUP直接获得而不必滚动DBGRID了。
希望本方法不算复杂。
快给我加分吧。
 
yanghaijun大侠的作法与:
Table1.First;
for i:=1 to 4do
Table1.Next;
label1.caption := table1.fields[2].asstring;
好象没有什么区别吧?
问题的关键就在于我想在DBGrid不滚动的情况下,得到
某个指定行和列的值,就象StringGrid的cell一样....
难道就没有什么解决办法吗?
唉!
 
To CaoWei:
根据你的建议,我将前面的程序稍作更改,既可符合你的要求,
希望你能接受,原理一样,方法略作更改而已:(此范例需要
一个Grid1、一个Label1、一个Button1)
.
.
i:integer;
//控制当前行
j:integer;
//控制当前列
ts:string;
//用于获取第一列的字段名,因第一字段名在用户使用过程中
//可能会改变,不能固定其值
RowNum,ColNum:integer;
//你要获取CELL的行、列值,如4行3列
.
.
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject;
const Rect: TRect;
Field: TField;
State: TGridDrawState);
begin
{
检查是否正在绘制第1列中的内容,若是,则将行号i加1,
同时列号j清零,否则表示未改变行,故将列号加1
}
if field.fieldname=ts then
begin
inc(i);
j:=0;
end else
inc(j);
//若行、列号与指定的行、列号相符,注意,实际列号应该减1
//则获取该单元的数据
if (i = RowNum) and (j=ColNum-1) then
label1.caption:=field.asstring;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
i:=0;
j:=0;
RowNum:=4;
ColNum:=3;
ts:=dbgrid1.columns[0].fieldname;
//获得第一列的列字段名,
//有时你也可使用其标题名
dbgrid1.refresh;
//强迫其重新绘制以得到指定单元数据
end;

此次再不会滚动数据了,希望你满意,赶快加分吧。
 
To CaiWei:
根据你的建议,我将前面的程序稍作更改,既可符合你的要求,
希望你能接受,原理一样,方法略作更改而已:(嗳,服务器老是不
响应,为发这封信我用掉的时间实在太多了)
.
.
i:integer;
//控制当前行
j:integer;
//控制当前列
ts:string;
//用于获取第一列的字段名,因第一字段名在用户使用过程中
//可能会改变,不能固定其值
RowNum,ColNum:integer;
//你要获取CELL的行、列值,如4行3列
.
.
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject;
const Rect: TRect;
Field: TField;
State: TGridDrawState);
begin
{
检查是否正在绘制第1列中的内容(看是不是ts指定的字段名
即可,若是,则将行号i加1,同时列号j清零,否则表示未改
变行号,故将列号加1
}
if field.fieldname=ts then
begin
inc(i);
j:=0;
end else
inc(j);
//若行、列号与指定的行、列号相符,注意,实际列号应该减1
//则获取该单元的数据,并显示在Label1中
if (i = RowNum) and (j=ColNum-1) then
label1.caption:=field.asstring;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
i:=0;
//初始化行变量
j:=0;
//初始化列变量
RowNum:=4;
//你指定的行,若愿意,可变为某编辑框的值,以进行动态查询
ColNum:=3;
//你指定的列,若愿意,可变为某编辑框的值,以进行动态查询
ts:=dbgrid1.columns[0].fieldname;
//获得第一列的列字段名,
//有时你也可使用其标题名
dbgrid1.refresh;
//强迫其重新绘制以得到指定单元数据
end;

此次再不会滚动数据了,希望你满意,赶快加我200分吧。
希望这是最终答案。Good Luck!
 
后退
顶部