大家好。
本人在使用DBGrid中遇到一个问题,手中资料有限,不知如何解决。
问题描述如下:两个表:员工表(Employee)和部门表(Department);
结构如下:
EmployeeCOLUMNNAME   DATATYPE
EmployeeID   varchar(5)  Primary Key  员工编号
employeeName varchar(10)              员工姓名
DepID varchar(2)               部门编号
BirthDate    Date                     出生日期
Sex          varchar(2)               性别Department
COLUMNNAME   DATATYPE
DepartmentID   varchar(5)  Primary Key  部门号
DepartmentName varchar(10)              部门名称员工表中的DepID 存放的是部门表中的departmentID(部门号)。我想实现的功能是: 
1、在DBGrid中显示员工的数据,但是部门一项显示的是部门名称,而不是部门编号。
2、该DBGrid具有编辑功能,当点击某员工的所在部门时,在Grid中显示一个ComboBox控件,该空间内有所有部门的名称;选择适当的部门名称后,点击更新按钮,保存该员工在员工表中的所在部门编号(DepID),DBGrid中显示更新后的部门名称。问题描述的比较繁琐,望见谅!谢谢大家了

解决方案 »

  1.   

    直接用ado查询就能办到
    select EmployeeID,employeeName,DepartmentName,
    BirthDate,Sex    
    from Employee, Department
    where Department.DepID = Department.DepartmentID
      

  2.   

    谢谢大家的up,但我的想法不是查询。这个comboBox是动态显示的,而不是用作查询用的;就是说,所有员工的信息都显示在DBGrid中,点击某个员工所在行的Department一列,这个combobox控件才显示在这一列中。另外:bbs791109(小别)所提的方法,我觉得这样做数据冗余太多,似乎不符合数据库设计的思想......
      

  3.   

    不难,给你思路把:
    显示用select EmployeeID,employeeName,DepartmentName,
    BirthDate,Sex    
    from Employee, Department
    where Department.DepID = Department.DepartmentID;
    然后做两个函数,一个将部门表中的部门名称取出放如combobox1中(mctocombobox),
    另一个将名称装换成部门代码(mctodm),当然两个函数中都用ado,
    在你点击grid的部门字段时
    mctocombobox;
    combobox1.visible:=true;combobox   onchang事件中
    mctodm
    点击更新按钮时,写回数据库。
    说的 不够明白,有问题在写出来!
      

  4.   

    我也是这个想法,动态生成一个comboBox,然后动态显示......但是我有一点顾虑:这个DBGrid数据源涉及的是两个表的操作,而且sql语句是:select EmployeeID,employeeName,DepartmentName,
    BirthDate,Sex    
    from Employee, Department
    where Department.DepID = Department.DepartmentID;没有DepID,这样DBGrid的更新操作需要在DataSet中写了?
      

  5.   

    挡心这个呀,你建一个视图好了,
    create view myview as
    select e.EmployeeID,e.employeeName,e.DepartmentName,
    e.BirthDate,e.Sex,d.DepartmentName    
    from Employee e inner join  Department d on e.depid=d.DepartmentID然后,将dateset与这一视图连上就可以了
      

  6.   

    另外:怎样实现  在DBGrid中插入ComboBox下拉选框?点击DBGrid中的一个Cell的时候,这个动态生成的comboBox显示出来?在StringGrid 中实现这个似乎并不困难,但在DBGrid中如何实现,我不知道啊......
      

  7.   

    能否将需要的事件、函数写的清楚一些......在你点击grid的部门字段时
    mctocombobox;
    combobox1.visible:=true;combobox   onchang事件中
    mctodm这段代码能否再详细一些?如何让ComboBox显示在这个Cell的位置?
      

  8.   

    要显示在某个cell的位置,只需 for j:=0 to dbfrid.columns.Count-1 do
        begin
          if columns[j].fieldname=DepartmentName then
          i:=j;
          break;
        end;dbgrid.columns[i].picklist:=combobox1.items;
    dbgrid.columns[i].buttonstyle:=cbsauto;combobox1只起传递的作用,设置dbgrid 的属性就能实现你的要求。
      

  9.   

    看来动态的生成combobox的比较好,我可是直接将combobox,不,我用的是dblookupcombobox
    放在DBGRID上,.visible:=false;在dbgrid的cell
      

  10.   

    在dbgrid的cell的事件中判断是不是你所要的字段=DepartmentName,如是将dblookupcombobox的vvisible:=true;这样就可用dblookupcombobox中的下拉框的值。
      

  11.   

    谢谢大家的关注!to gnik: 
    在dbgrid的那个cell事件中呢?能否说得详细一些?我想几种方法都试试......
      

  12.   

    看看这贴是不是这样?http://expert.csdn.net/Expert/topic/2032/2032042.xml?temp=.7392084
      

  13.   

    你还是用STRINGGRID吧,虽然代码多,但好控制。可以用数组存储你表中的数据。然后在STRINGGRID上放一个EDIT和COMBOBOX控件,动态来显示他们的位置和状态。
    procedure Tfm_xmsz.sg0DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    begin
    if gdfocused in state then
       if (acol in [0,1,3]) and (arow>0) then
          begin
           ed1.left:= Rect.Left + sg0.Left;
           ed1.top:=  rect.top + sg0.Top ;
           ed1.Width:=rect.Right-rect.Left;
           ed1.Height:=rect.Bottom-rect.Top;
           ed1.Visible:=true;
           ed1.Clear;
           ed1.Text:=sg0.cells[acol,arow];
           ed1.setfocus;
          end
       else if (acol=2) and (arow>0) then
          begin
          cob.Left:=rect.Left+sg0.Left;
          cob.Top:=rect.Top+sg0.Top;
          cob.Width:=rect.Right-rect.Left;
          cob.Height:=rect.Bottom-rect.Top;
          ed1.Visible:=false;
          cob.Visible:=true;
          cob.ItemIndex:=cob.Items.IndexOf(sg0.cells[acol,arow]);
          cob.SetFocus;
          end
       else
         begin
           ed1.Visible:=false;
           cob.Visible:=false; 
         end;
    end;
      

  14.   

    我现在有这么几种方法:
    1、在DBGrid列中的PickList中设置;
    2、在DBGrid中的DrawColumnCell事件中设置;
    3、放弃使用DBGrid,改用StringGrid。这是最彻底、完全由自己控制的方法,我再试试吧,实在不行,再用StringGrid.
      

  15.   

    那combobox里的列不是太多了,太合适吧?为什么不用treeview?
      

  16.   

    我是在dbgridcellclick()中用column.fieldname判断字段=DepartmentName。
      

  17.   

    我同意Colgatetxj的用法,不过最好编码之前首先设置:
    Combobox.Visiable := False;
    查找部门名称的SQL语句最好写成动态的。
      

  18.   

    用DBGrid的时候,我另外加了一个COLUMNS,我想让这个显示每一个记录的序号,
    这个序号不是数据库里的自增量,因为对数据库的删除操作会影响到这个序号不是按照自然增序,如何写呢?!
      

  19.   

    利用adoquery 
    select EmployeeID,employeeName,DepartmentName,BirthDate,Sex from Employee, Department where Department.DepID = Department.DepartmentID;
    部门下拉表动态生成。即采用mbzdh(一天一个进步)的做法。用cellclick事件。在adoquery 
    的beforepost事件中更新员工表的depID
      

  20.   

    1、在DBGrid中显示员工的数据,但是部门一项显示的是部门名称,而不是部门编号。
    //这个问题好解决:双击dggrid,右键-》add all fields,然后将你不需要的字段删掉,只留下部门名称
    2、该DBGrid具有编辑功能,当点击某员工的所在部门时,在Grid中显示一个ComboBox控件,该空间内有所有部门的名称;选择适当的部门名称后,点击更新按钮,保存该员工在员工表中的所在部门编号(DepID),DBGrid中显示更新后的部门名称。
    //利用lookup效果,在
    http://218.56.11.178:8000/web/File_Down.aspx
    例程-数据库/报表-》在DBGRID中下拉列表的显示,自己动手找找好吗?
      

  21.   

    我为你提供三中方法:
    一:直接查询:
        select .......
    二:使用查询字段.着也是一种很好的方法
    我主要向你介绍第三钟:
    思路是重画DBGrid,就是当DBGrid获得焦点时,在当前记录的你想要的单元中浮动一个组件:我按你的思路:QUERY1和QUERY2,DATASOURSE1和DATASOURCE2,DBGRID1,DBLOOKUPCOMBOBOX1。
    以下为属性设置:(主要的属性)
    QUERY1.sql中:SELECT * FORM Employee
    query2.sql中:select DepartmentName,DepartmentID Department
    datasource1.dataset:=Query1
    datasource2.dataset:=query2
    dbgrid1.datasource:=datasource1;
    dblookupcombobox1.datasource:=datasource2;
    dblookupcombobox1.datafeild:=DepartmentID;
    dblookupcombobox1.listsource:=datasource1;
    dblookupcombobox1.keyfield:=DepID;
    dblookupcombobox1.listField:=DepartmentName//呵呵不好意思,我有点忘了不知道着几个属性是不是这么设的,我想你应该会
    下面书写Drawdatacell事件来重新绘制单元格。当dbgrid1中的DepID网格获得焦点时就把dblookupcombobox1一道网格上去,将dblookupcombobox1显示出来:
    procedure TForm1.dbgrid1Drawdatacell(sender:Tobject;const rect:TRect;
    datacol:integer;column:Tcolumn;state:TGriddrawstate);
    begin
      if(gdFocused in state) then
      begin
        with dblookupcombobox1 do
        begin
          if(field.fieldname=datafield)then
          begin
            Left:=Rect.left+dbgrid1.left;
            top:=rect.top+dbgrid1.top;
            width:=rect.right-rect.left;
            height:=rect.bottom-rect.top;
            visible=true;
          end;
        end;
      end;
    end;
    然后写dbgrid的oncolexit事件:
    procedure TForm1.dbgrid1colexit(sender:Tobject);
    begin
      if dbgrid1.selectedfield.fieldname<>dblookupcombobox1.datafield then
      begin
        dblookupcombobox1.visible:=false;//如果不是指定的单元格有焦点就隐藏它
      end;
    end;
    当dbgid1的指定获得焦点是只是将dblookupcombobox显示出来,dblookupcombobox1是不能获得焦点的,这是应该在dbgrid1的keypress事件中使用sendmessage函数将焦点传到dblookupcombobox1上面,达到在dblookupcombobox1上进行数据输入的目的:
    procedure TForm1.DBgrid1keypress(Sender:Tobject;key:char);
    begin
      if(key<>chr(9))then
      begin
        if(dbgrid1.selectedfield.fieldname=dblookupcombobox1.datafield)then
        begin
          dblookupcombobox1.setfocus;
          sendmessage(dblookupcombobox1.handle,wm_char,word(key),0);
        end;
      end;
    end;在窗体初始化时将dblookupcombobox1隐藏
    procedure TForm1.formshow(sender:Tobject);
    begin
      dblookupcombobox1.visible:=false;
    end;谢谢 希望对你能有所帮助
    其实用第二种方法查询字段很容易就可以实现你功能的,你可以试试