cxGrid使用汇总4

1.     CxGrid汇总功能

① OptionsView-Footer设置为True,显示页脚   ② CxGrid的Summary选项卡定义要汇总的列和字段名及汇总方式,Footer选项卡定义单个汇总,Default For Groups定义按组汇总。OptionsView-GroupFooters设置为gfAlwaysVisible则显示按组汇总。设置后界面如图。

   

2.       CxGrid的样式设置

 当设置了Kind时,NativeStyle必须设置为False,如果指定了SkinName则Kind属性失效。

  

下图是设置skinname为MoneyTwins后效果

  

4.       取某个单元格的值

 Cxgrid.DataController.Values[i,j]

5.       列操作,选择CxGrid控件后,点击“Customize”新建一列,在Columns集合中选中新建的列,选择propertites属性可以设置该列的显示形式。下面介绍常用的几个

①     Properties选择CheckBox,则该列显示一个复选框,如下:

 
判断是否选中 if  Cxgrid.DataController.Values[i,j]=’1’   选中

②     Properties选择ButtonEdit,并对该列的属性编辑器设置如下属性Buttons属性添加按钮项,对按钮项设置可以设置kind属性定义按钮样式;ViewStyle属性设置为vsButtonsOnly,Options-ShowEditButton设置为isebAlways。可以编写点击事件如下:

procedure TForm1.cxgrdbtblvwGrid1DBTableView1Column1PropertiesButtonClick(

  Sender: TObject; AButtonIndex: Integer);

begin

  ShowMessage('aaa');

end;

③ImageComboBox,可以关联一个imagelist,显示图片。如下关联imagelist后效果。

 

6.动态添加列和记录行

var

Column:   TcxGridColumn;

i:integer;

acount:integer;

begin

    Column:= cxgrd1TableView1.CreateColumn;

    Column.Caption   :=   'Test ';

    cxgrd1TableView1.DataController.AppendRecord;

    cxgrd1TableView1.DataController.Values[0,   0]   :=   'ABC ';

cxgrd1TableView1.DataController.Post;

//添加多条记录

for i:=1 to 4 do

  begin

    acount:=cxgrd1TableView1.DataController.RecordCount;

    cxgrd1TableView1.DataController.AppendRecord;

    cxgrd1TableView1.DataController.Values[acount,   0]   :=IntToStr(i*1);

    cxgrd1TableView1.DataController.Post();

  end;

end;

  //删除记录

   cxgrd1TableView1.DataController.DeleteRecord(0);

end;


50 保存/恢复带汇总行的布局

<TableView>.StoreToIniFile('c:Grid.ini', True, [gsoUseSummary]);
<GridView>.RestoreFromIniFile(<inifilename>,True,False {or True, optional},[gsoUseSummary]);

****************************************************************************

49 指定Filter   Builder打开/保存过滤文件的默认路径

解决:
uses   
      ...,   cxFilterControlDialog;   
    
procedure   TForm.GridView1FilterControlDialogShow(   
      Sender:   TObject);   
begin   
      TfmFilterControlDialog(Sender).OpenDialog.InitialDir   :=   'D:/'   
end;
****************************************************************************
50在主从TableView中根据主TableView得到对应的从TableView
解决:

var   
      ADetailDC:   TcxGridDataController;   
      AView:   TcxCustomGridTableView;   
begin   
      with   cxGrid1DBTableView1.DataController   do   
          ADetailDC   :=   TcxGridDataController(GetDetailDataController(FocusedRecordIndex,   0));   
      AView   :=   ADetailDC.GridView;   
end;

****************************************************************************
51取消过滤时移到第一行
解决:
uses   
      cxCustomData;   
    
procedure   TYour_Form.AViewDataControllerFilterChanged(Sender:   TObject);   
var   
      Filter:   TcxDataFilterCriteria;   
begin   
      with   Sender   as   TcxDataFilterCriteria   do   
          if   IsEmpty   then   
              DataController.FocusedRowIndex   :=   0;   
end;
****************************************************************************
52排序后移到第一行
解决:
可以设置DataController.Options.FocusTopRowAfterSorting   :=   True,也可以使用如下的代码:   
    
uses   
      cxCustomData;   
    
procedure   TYour_Form.Your_ViewDataControllerSortingChanged(Sender:   TObject);   
begin   
      TcxCustomDataController(Sender).FocusedRowIndex   :=   0;   
end;
****************************************************************************
53判断当前行是否第一行或最后一行
解决:
可以使用DataController的IsBOF,   IsEOF方法,或者:   
<AView>.Controller.Controller.FocusedRow.IsFirst   
<AView>.Controller.Controller.FocusedRow.IsLast
****************************************************************************
54根据指定值查找记录
解决:
DataController提供了好几个方法来得到指定值对应的RecordIndex   
对于Bound   View可以使用FindRecordIndexByKeyValue方法
****************************************************************************
55 编辑和显示Blob字段
解决:
该字段的Properties设置为BlobEdit,并将BlobPaintStyle   属性设为   bpsText 
****************************************************************************
56得到可见行数 
解决:
<View>.ViewInfo.VisibleRecordCount 
****************************************************************************
57保存后的行设置为当前行
解决:
const   
      CM_SETFOCUSEDRECORD   =   WM_USER   +   1002;   
    
type   
      TForm1   =   class(TForm)   
          cxGrid1DBTableView1:   TcxGridDBTableView;   
          cxGrid1Level1:   TcxGridLevel;   
          cxGrid1:   TcxGrid;   
          dxMemData1:   TdxMemData;   
          dxMemData1Field1:   TStringField;   
          dxMemData1Field2:   TIntegerField;   
          DataSource1:   TDataSource;   
          cxGrid1DBTableView1RecId:   TcxGridDBColumn;   
          cxGrid1DBTableView1Field1:   TcxGridDBColumn;   
          cxGrid1DBTableView1Field2:   TcxGridDBColumn;   
          Timer1:   TTimer;   
          CheckBox1:   TCheckBox;   
          procedure   Timer1Timer(Sender:   TObject);   
          procedure   dxMemData1AfterPost(DataSet:   TDataSet);   
          procedure   CheckBox1Click(Sender:   TObject);   
      private   
          procedure   CMSetFocusedRecord(var   Msg:   TMessage);   message   CM_SETFOCUSEDRECORD;   
      public   
          {   Public   declarations   }   
      end;   
    
var   
      Form1:   TForm1;   
      FocusedIdx:   Integer;   
    
    
implementation   
    
{$R   *.dfm}   
    
procedure   TForm1.Timer1Timer(Sender:   TObject);   
begin   
      dxMemData1.AppendRecord(['',   IntToStr(Random(1000)),   Random(1000)]);   
end;   
    
procedure   TForm1.dxMemData1AfterPost(DataSet:   TDataSet);   
begin   
      PostMessage(Handle, CM_SETFOCUSEDRECORD,   Integer(cxGrid1DBTableView1),   MakeLParam(cxGrid1DBTableView1.Controller.FocusedRowIndex,   cxGrid1DBTableView1.Controller.TopRowIndex));   
end;   
    
procedure   TForm1.CMSetFocusedRecord(var   Msg:   TMessage);   
begin   
      TcxGridDBTableView(msg.WParam).Controller.FocusedRowIndex   :=   Msg.LParamLo;   
      TcxGridDBTableView(msg.WParam).Controller.TopRowIndex   :=   Msg.LParamHi;   
end;   
    
procedure   TForm1.CheckBox1Click(Sender:   TObject);   
begin   
      Timer1.Enabled   :=   TCheckBox(Sender).Checked;   
end;   
    
end.
****************************************************************************
58删除记录并获得焦点
解决:
procedure   TForm1.BtnDeleteClick(Sender:   TObject);   
var   
      FocusedRow,   TopRow:   Integer;   
      View:   TcxGridTableView;   
      DataController:   TcxGridDataController;   
begin   
      View   :=   cxGrid1.FocusedView   as   TcxGridTableView;   
      DataController   :=   View.DataController;   
    
      //   Remember   the   top   row   (the   vertical   scrollbar   position)   
      TopRow   :=   View.Controller.TopRowIndex;   
      //   Remember   the   focused   row(!)   index   
      FocusedRow   :=   DataController.FocusedRowIndex;   
    
      DataController.DeleteFocused;   
    
      //   After   deletion   the   same   row   must   be   focused,   
      //   although   it   will   correspond   to   a   different   data   record   
      DataController.FocusedRowIndex   :=   FocusedRow;   
      //   Restore   the   top   row   
      View.Controller.TopRowIndex   :=   TopRow;   
end;
****************************************************************************
59cxGrid的 TableView 数据排序与对应的数据集同步
解决:
         //描述: cxGrid的 TableView 数据排序与对应的数据集同步, 该方法主要用于打印时 

       //         的排序与所见到的排序保持一致; 
       //参数: @tv: 排序的cxGridTableView 
       //说明: @tv: 对应的数据集只支持 ADOQuery与 ClientDataSet; 
       procedure cxGridSortSyncToDataSet(tv: TcxGridDBTableView); overload;

       //描述: 功能同上, 实现代码一样, 如果有更改就同步更改 
       procedure cxGridSortSyncToDataSet(tv: TcxGridDBBandedTableView); overload;

procedure cxGridSortSyncToDataSet(tv: TcxGridDBTableView); 
const 
     SortArray: array[soAscending..soDescending] of string = (’ASC’, ’DESC’); 
var 
     AscFields, DescFields, S, SortOrder: string; 
     IndexPrint: string; 
     I: integer; 
     Index: integer; 
     cds: TClientDataSet; 
begin 
     S := ’’; 
     AscFields := ’’; 
     DescFields := ’’; 
     if tv.SortedItemCount = 0 then 
       Exit; 
     if tv.DataController.DataSource.DataSet is TADOQuery then begin 
       for I := 0 to tv.SortedItemCount - 1 do begin 
         SortOrder := SortArray[tv.SortedItems[I].SortOrder]; 
         if S <> ’’ then 
           S := S + ’, ’; 
         Index := tv.SortedItems[I].Index; 
         S := S + tv.Columns[Index].DataBinding.Field.FieldName + ’ ’ + SortOrder; 
       end; 
       (tv.DataController.DataSource.DataSet as TADOQuery).Sort := S; 
     end else if (tv.DataController.DataSource.DataSet is TClientDataSet)     then begin 
       Cds := tv.DataController.DataSource.DataSet as TClientDataSet; 
       for I := 0 to tv.SortedItemCount - 1 do begin 
         Index := tv.SortedItems[I].Index; 
         S := tv.Columns[Index].DataBinding.Field.FieldName +’;’; 
         AscFields := AscFields + S; 
         if tv.SortedItems[I].SortOrder = soDescending then 
           DescFields := DescFields + S; 
       end; 
       if AscFields <> ’’ then 
         Delete(AscFields, Length(AscFields), 1); //删除 ;

       if DescFields <> ’’ then 
         Delete(DescFields, Length(DescFields), 1); 
       IndexPrint := TimeToStr(Now()); 
       Cds.IndexDefs.Clear; 
       IndexPrint := TimeToStr(Now()); 
       cds.AddIndex(IndexPrint, AscFields, [], DescFields); 
       cds.IndexName := IndexPrint; 
     end; 
end;
****************************************************************************
60cxGRID怎么遍历已经选择的单元格
解决:
n := cxGrid1DBTableView1.DataController.GetSelectedCount;   
       
      for   i:=0   to   n   -   1   do   
      begin   
          Index   :=   cxGrid1DBTableView1.DataController.GetSelectedRowIndex(i);   
          if   Index   <   0   then   continue;   
          AccID   :=   
                          cxGrid1DBTableView1.DataController.GetRowvalue(   
                          cxGrid1DBTableView1.DataController.GetRowInfo(Index)   
                          ,0);   
          AccID   :=   dsData.DataSet.FieldByName(’AccountID’).AsString;   
     
      end; 
n := cxGrid1DBTableView1.DataController.GetSelectedCount;   
      for   i:=0   to   n   -   1   do   
      begin   
          Index   :=   cxGrid1DBTableView1.DataController.GetSelectedRowIndex(i);   
          if   Index   <   0   then   continue;   
          AccID   := cxGrid1DBTableView1.DataController.GetRowvalue(   
                  cxGrid1DBTableView1.DataController.GetRowInfo(Index)   
                  ,0);//这里的0是列的索引,能指定,也可用通过GridView获取   
     
      end;
****************************************************************************
61动态设置显示格式
解决:
procedure SetDisplayFormat(ACtrlData: TClientDataSet;
TbView: TcxGridDBTableView);
var
i: integer;
begin
if ACtrlData.RecordCount <= 0 then Exit;
try
    TbView.ClearItems;
    ACtrlData.First;
    for i := 0 to ACtrlData.RecordCount - 1 do
    begin
      if ACtrlData.FieldByName('SQBF_DisplayInGrid').AsString = '1' then //在表格中显示
      with TbView.CreateColumn do
      begin
        DataBinding.FieldName := ACtrlData.FieldByName('SQBF_FieldName').AsString;
        Caption := ACtrlData.FieldByName('SQBF_Caption').AsString; //字段中文标题
        Hint := ACtrlData.FieldByName('SQBF_Hint').AsString;
        Width := ACtrlData.FieldByName('SQBF_Width').AsInteger;
        HeaderAlignmentHorz := taCenter;
      end;
      ACtrlData.Next;
    end;
except
    on E: Exception do
      SaveLog('设置显示格式时出错:' + E.Message);
end;
end;
****************************************************************************
62给cxGRID加序号列
解决:
procedure SetRowNumber(var ASender: TcxGridTableView; 
AViewInfo: TcxCustomGridIndicatorItemViewInfo; 
   var ACanvas: TcxCanvas; var ADone: boolean);

uses cxLookAndFeelPainters;

procedure SetRowNumber(var ASender: TcxGridTableView; AViewInfo: TcxCustomGridIndicatorItemViewInfo; 
   var ACanvas: TcxCanvas; var ADone: boolean); 
var 
   AIndicatorViewInfo: TcxGridIndicatorRowItemViewInfo; 
   ATextRect: TRect; 
   AFont: TFont; 
   AFontTextColor, AColor: TColor; 
begin 
   AFont := ACanvas.Font; 
   AColor := clBtnFace; 
   AFontTextColor := clWindowText ; 
if (AViewInfo is TcxGridIndicatorHeaderItemViewInfo) then begin 
   ATextRect := AViewInfo.Bounds; 
   InflateRect(ATextRect, -1, -1); 
     
   ASender.LookAndFeelPainter.DrawHeader(ACanvas, AViewInfo.Bounds, 
     ATextRect, [], cxBordersAll, cxbsNormal, taCenter, vaCenter, 
     False, False, '序号', AFont, AFontTextColor, AColor); 
     ADone := True; 
   end ;
if not (AViewInfo is TcxGridIndicatorRowItemViewInfo) then 
     Exit; 
   ATextRect := AViewInfo.ContentBounds; 
   AIndicatorViewInfo := AViewInfo as TcxGridIndicatorRowItemViewInfo; 
   InflateRect(ATextRect, -1, -1); 
   ASender.LookAndFeelPainter.DrawHeader(ACanvas, AViewInfo.ContentBounds, 
     ATextRect, [], [bBottom, bLeft, bRight], cxbsNormal, taCenter, vaCenter, 
     False, False, IntToStr(AIndicatorViewInfo.GridRecord.Index + 1), 
     AFont, AFontTextColor, AColor); 
   ADone := True; 
ASender.LookAndFeelPainter.DrawIndicatorImage(ACanvas,ATextRect, AIndicatorViewInfo.IndicatorKind); 
end;

如果你不要行标志的话,你可以不改控件 
直接注释掉这一行: ASender.LookAndFeelPainter.DrawIndicatorImage(ACanvas, ATextRect, AIndicatorViewInfo.IndicatorKind); 
要标志的话,在DrawIndicatorImage 从这里跟进去(Ctrl+左键单击) 
在 cxLookAndFeelPainters 单元中作如下修改:

class procedure TcxCustomLookAndFeelPainter.DrawIndicatorImage(ACanvas: TcxCanvas; 
   const R: TRect; AKind: TcxIndicatorKind); 
var 
   X, Y: Integer; 
begin 
   if AKind = ikNone then Exit; 
   with cxIndicatorImages, R do 
   begin 
     X := (Left + Right - Width);               //靠右 
     Y := (Top + Bottom - Height) div 2;       //居中 
   end; 
   cxIndicatorImages.Draw(ACanvas.Canvas, X, Y, Ord(AKind) - 1); 
end;

注意,我已注明靠右的那一行, 就是去掉 DIV 2 了, 
还要改一个地方: 
SKIN控件目录下的dxSkinLookAndFeelPainter单元,找到 
TdxSkinLookAndFeelPainter.DrawIndicatorImage 函数 
的 
OffsetRect(ARect, (Left + Right - cx div 2) , (Top + Bottom - cy) div 2); 
这一行,将 (Left + Right - cx div 2) 改为(Left + Right - cx) 也是去掉 div 2 就是靠右; 
修改后: OffsetRect(ARect, (Left + Right - cx) , (Top + Bottom - cy) div 2);

使用 
procedure TForm1.cxGrid1DBTableView1CustomDrawIndicatorCell( 
   Sender: TcxGridTableView; ACanvas: TcxCanvas; 
   AViewInfo: TcxCustomGridIndicatorItemViewInfo; var ADone: Boolean); 
begin 
     SetRowNumber(Sender,AviewInfo,ACanvas,ADone); 
end;

另外序号列的列宽最好改为25以上!
效果图:




****************************************************************************
63 cxGrid自带过滤后数据也数据集同步
解决:
在cxGrid的View Filter事件的OnBeforeChange中写代码就可以了. 
procedure TForm1.tvcxgd1DBTableView1DataControllerFilterBeforeChange( Sender: TcxDBDataFilterCriteria; ADataSet: TDataSet; const AFilterText: String); begin //这里可以增加数据集控件的filter:=false; //如:adoquery.filter:=false; //如果使用的是cxgrid的汉化版本,可以将AFilterText中的 中文等于,小于 替换成 = <等 //adoquery.filter:=替换了中文的AFilterText; ShowMessage(AFilterText); end; 写了上述步骤后可以在tvcxgd1DBTableView1DataControllerFilterChanged写adoquery.filter:=true; 这样就起到了cxgrid过滤后的数据同步到adoquery的数据集,打印的时候就可以打印出符合要求的记录了。

原文地址:https://www.cnblogs.com/karkash/p/9531684.html