dbgrid使用问题,或许不难(200分)

  • 主题发起人 主题发起人 skylinerover
  • 开始时间 开始时间
S

skylinerover

Unregistered / Unconfirmed
GUEST, unregistred user!
1、我想在DBGRID中某一列中输入代码1,2,10等,然后在离开此单元格时转换成具体的值
如:‘北京,云南,山东’等,但用oncolexit 事件只能对离开本列的情况下起反应,
请问如何判断在同一列的移动时如何转换我的代码?
2、如何不出dbgrid的一个单元格(cell),判断在此单元格中所所输入的数据。如先输入一个
“山”,就可以知道现在在此单元格中有一个“山”字,再输入一个“东”,就可以知道现
在在此单元格中有“山东”两字,请问如何实现?
 
1、好像是处理AfterScroll事件。
2、你可以通过新建一个lookup型的字段来实现,不过这好像不是你想要的,你要的是能输入
内容,可以根据内容自动检索相应的内容,我是配合combobox和dblookupcombobox实现的。
 
一.表结构

首先建立如下结构的数据表Code.DB,并输入一些测试数据:

字段名 类型 长度 说明
aCode 字符型 20 科目代码
aName 字符型 30 科目代码名称
...... ...... ...... ......
表(一)

其中,科目代码aCode的数据类型一定要字符型(一定),长度按具体要求而定,假如要支持六级编码,且代码结构是”3-2-2-2-2-2”,则该字段的长度不小于18,而其他字段则不作要求 。另外,要为字段aCode建一索引(切记),因为要用它来排序。

二.编写程序

1.新建一Project:CodeTree.drp,主窗体命名为frmMain,单元存为Main.Pas。在frmMain上添加一TtreeView控件,命名为tveCode,一个TImageList,命名为imgIcon,并装入三个Icon和Bmp,最后添加一Ttable控件,命名tblCode。frmMain和各控件的属性按表(二)设置:

组件 属性 设置
FrmMain Caption ’科目代码’
Font 宋体 9号
BorderStyle BsDialog
TvwCode Images ImgIcon
ReadOnly True
ImgIcon ImageList 装入三个图标
BtnClose Caption 关闭(C)

表(二)

2. 单元main.pas的完整源代码如下:

unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs,
Db, DBTables, ComCtrls, ImgList, StdCtrls;
type
TForm1 = class(TForm)
tvwCode: TTreeView;
tblCode: TTable;
ImageList1: TImageList;
btnClose: TButton;
procedure FormCreate(Sender: TObject);
procedure btnCloseClick(Sender: TObject);
private
{ Private declarations }
function LoadCode(crTbl:TDBDataSet):Integer;
function GetLevel(sFormat,sCode:String):Integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
const
SCodeFormat = ’322222’; //科目代码结构
SFirstNodeTxt = ’科目代码’; //首节点显示的文字
implementation
{$R *.DFM}
//以下函数是本文的重点部分,
其主要功能是用一循环将Code.db表中的
//科目代码和科目代码名称显示出来
function TForm1.LoadCode(crTbl:TDBDataSet):Integer;
var NowID,sName,ShowTxt:String;
i,Level:Integer;
MyNode:array[0..6]of TTreeNode;
//保存各级节点,最长支持6级(重点)
begin
Screen.Cursor:=crHourGlass;
Level:=0;
With crTbl do
begin
try
if not Active then Open;
First;
tvwCode.Items.Clear;
//以下是增加第一项
MyNode[Level]:=tvwCode.Items.Add
(tvwCode.TopItem,SFirstNodeTxt);
MyNode[Level].ImageIndex:=0;
MyNode[Level].SelectedIndex:=0;
//以上是增加第一项
While Not Eof do
begin
NowID:=Trim(FieldByName(’aCode’).AsString);
ShowTxt:=NowID+’ ’+FieldByName(’aName’).AsString;
Level:=GetLevel(SCodeFormat,NowID);
//返回代码的级数
//以下是增加子项
//以下用上一级节点为父节点添加子节点
if Level>0 then//确保代码符合标准
begin
MyNode[Level]:=tvwCode.Items.AddChild
(MyNode[Level-1],ShowTxt);
MyNode[Level].ImageIndex:=1;
MyNode[Level].SelectedIndex:=2;
end;
//以上是增加子项
Next;
end;
finally
Close;
end;
end;
MyNode[0].Expand(False);//将首节点展开
Screen.Cursor:=crDefault;
end;
//以上函数将Code.db表中的科目代码和科目代码名称显示出来
//下面函数的功能是返回一代码的级数,
参数sFormat传递科目代码结构;
//参数sCode传递某一科目代码
function TForm1.GetLevel
(sFormat,sCode:String):Integer;
var i,Level,iLen:Integer;
begin
Level:=-1;//如果代码不符合标准,则返回-1
iLen:=0;
if (sFormat< >’’)and(sCode< >’’)then
for i:=1 to Length(sFormat) do
begin
iLen:=iLen+StrToInt(sFormat);
if Length(sCode)=iLen then
begin
Level:=i;
Break;
end;
end;
Result:=Level;
end;
//上面函数的功能是返回一代码的级数
procedure TForm1.FormCreate(Sender: TObject);
begin
with tblCode do
begin
DatabaseName:=ParamStr(1);
//使tblCode的DatabaseName指向应用程序所在的路径
TableName:=’Code.DB’; //指向数据表Code.DB
Open;
IndexFieldNames:=’aCode’;
//按字段aCode排序(不要漏掉)
end;
LoadCode(tblCode);
end;
procedure TForm1.btnCloseClick(Sender: TObject);
begin
Close;
end;
end.
其中,常量ScodeFormat是科目代码的代码结构,其定义的规则一定要和数据表Code..DB中的字段aCode的值相符。所以在实际应用中,让用户新增科目代码时,必须严格检查其规范性,只有完全符合事先定义的代码结构,才能添加入库。

函数GetLevel是求某一科目代码的级数,例如,有一科目代码”10102”,在代码结构是”322222”的情况下,调用函数GetLevel(’322222’,’10102’)将返回整数2 。

当然,本文的核心是LoadCode函数,该函数用了一个循环来遍历数据表Code.DB的所有记录,将字段aCode和aName的内容按层次显示出来。而在该函数中定义的二维数组MyNode[0..6],则显得优为重要,在这里,它作用类似于递归中的栈。因为在TTreeView添加子节点的方法AddChild(Node: TTreeNode; const S: string)中,要为其指定一父节点作为参数,而父节点的代码级数一定是要添加节点的代码级数减1,所以只要用一数组来动态保存和指定父节点就成功了。

三.运行结果

好了,现在把Code.DB复制到和可执行文件相同的目录下,按下F9键编译运行,本人运行的效果如图(一)。只要在以上的基础上加以完善,如增加维护功能,就可搬到实际应用中了。当然,本算法不单能用在科目代码上,其他类似的树型结构都能奏效。本人就已将此算法应用于[科目代码]、[物料清单(BOM)]、[库房管理]和[物料主文件]等多个模块中,取得令人满意的效果。

[:)]
 
代码表,如楼上所言
要实现你所讲的替换,可以使用TField的OnGetText/OnSetText事件
比如你所讲的一列,就是Table1.Fields[3]
那么你就设置它的Table1.Fields[3].OnGetText事件处理函数
具体的,参考Delphi帮助OnGetText/OnSetText
 
可以在keydown事件中转换
if (dbgrid.selectedindex=2)and((key=13)or(key=vk_tab)) then
.......
 
bernhn的不能在dbgrid实现此功能,而twos的方法我试了一下,在onsettext中可以检查并实现替换功能,
不过只能替换掉没有数据的字段,如果原先的字段已有数据那么就无效,还是不能完善地解决第一个问题啊!

第二个问题还没有人回答!我想如果第二个问题能得到解决的话,那第一个问题也主应刃而解了。
 
枪手哈特的方法如果用上下左右鍵或鼠标点击的话就无法实现了。
 
无法解决吗?
 
同时合用colexit和keypress两个事件就可以完成你要求的动作!!
 
后退
顶部