1. 程式人生 > >Delphi CxGrid 匯總(4)

Delphi CxGrid 匯總(4)

grid param 刪除記錄 說明 idle proc 同步 def reserve

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]);

****************************************************************************
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 保存後的行設置為當前行
解決:

[delphi] view plaincopy
  1. const
  2. CM_SETFOCUSEDRECORD = WM_USER + 1002;
  3. type
  4. TForm1 = class(TForm)
  5. cxGrid1DBTableView1: TcxGridDBTableView;
  6. cxGrid1Level1: TcxGridLevel;
  7. cxGrid1: TcxGrid;
  8. dxMemData1: TdxMemData;
  9. dxMemData1Field1: TStringField;
  10. dxMemData1Field2: TIntegerField;
  11. DataSource1: TDataSource;
  12. cxGrid1DBTableView1RecId: TcxGridDBColumn;
  13. cxGrid1DBTableView1Field1: TcxGridDBColumn;
  14. cxGrid1DBTableView1Field2: TcxGridDBColumn;
  15. Timer1: TTimer;
  16. CheckBox1: TCheckBox;
  17. procedure Timer1Timer(Sender: TObject);
  18. procedure dxMemData1AfterPost(DataSet: TDataSet);
  19. procedure CheckBox1Click(Sender: TObject);
  20. private
  21. procedure CMSetFocusedRecord(var Msg: TMessage); message CM_SETFOCUSEDRECORD;
  22. public
  23. { Public declarations }
  24. end;
  25. var
  26. Form1: TForm1;
  27. FocusedIdx: Integer;
  28. implementation
  29. {$R *.dfm}
  30. procedure TForm1.Timer1Timer(Sender: TObject);
  31. begin
  32. dxMemData1.AppendRecord([‘‘, IntToStr(Random(1000)), Random(1000)]);
  33. end;
  34. procedure TForm1.dxMemData1AfterPost(DataSet: TDataSet);
  35. begin
  36. PostMessage(Handle, CM_SETFOCUSEDRECORD, Integer(cxGrid1DBTableView1), MakeLParam(cxGrid1DBTableView1.Controller.FocusedRowIndex, cxGrid1DBTableView1.Controller.TopRowIndex));
  37. end;
  38. procedure TForm1.CMSetFocusedRecord(var Msg: TMessage);
  39. begin
  40. TcxGridDBTableView(msg.WParam).Controller.FocusedRowIndex := Msg.LParamLo;
  41. TcxGridDBTableView(msg.WParam).Controller.TopRowIndex := Msg.LParamHi;
  42. end;
  43. procedure TForm1.CheckBox1Click(Sender: TObject);
  44. begin
  45. Timer1.Enabled := TCheckBox(Sender).Checked;
  46. end;
  47. end.
  48. ****************************************************************************
  49. 58 刪除記錄並獲得焦點
  50. 解決:
  51. procedure TForm1.BtnDeleteClick(Sender: TObject);
  52. var
  53. FocusedRow, TopRow: Integer;
  54. View: TcxGridTableView;
  55. DataController: TcxGridDataController;
  56. begin
  57. View := cxGrid1.FocusedView as TcxGridTableView;
  58. DataController := View.DataController;
  59. // Remember the top row (the vertical scrollbar position)
  60. TopRow := View.Controller.TopRowIndex;
  61. // Remember the focused row(!) index
  62. FocusedRow := DataController.FocusedRowIndex;
  63. DataController.DeleteFocused;
  64. // After deletion the same row must be focused,
  65. // although it will correspond to a different data record
  66. DataController.FocusedRowIndex := FocusedRow;
  67. // Restore the top row
  68. View.Controller.TopRowIndex := TopRow;
  69. end;
  70. ****************************************************************************
  71. 59 cxGrid的 TableView 數據排序與對應的數據集同步
  72. 解決:
  73. COPYRIGHT BY cnCharles, ALL RIGHTS RESERVED.
  74. delphi群: 16497064, blog: http://hi.baidu.com/cnCharles
  75. //描述: cxGrid的 TableView 數據排序與對應的數據集同步, 該方法主要用於打印時
  76. // 的排序與所見到的排序保持一致;
  77. //參數: @tv: 排序的cxGridTableView
  78. //說明: @tv: 對應的數據集只支持 ADOQuery與 ClientDataSet;
  79. procedure cxGridSortSyncToDataSet(tv: TcxGridDBTableView); overload;
  80. //描述: 功能同上, 實現代碼一樣, 如果有更改就同步更改
  81. procedure cxGridSortSyncToDataSet(tv: TcxGridDBBandedTableView); overload;
  82. procedure cxGridSortSyncToDataSet(tv: TcxGridDBTableView);
  83. const
  84. SortArray: array[soAscending..soDescending] of string = (’ASC’, ’DESC’);
  85. var
  86. AscFields, DescFields, S, SortOrder: string;
  87. IndexPrint: string;
  88. I: integer;
  89. Index: integer;
  90. cds: TClientDataSet;
  91. begin
  92. S := ’’;
  93. AscFields := ’’;
  94. DescFields := ’’;
  95. if tv.SortedItemCount = 0 then
  96. Exit;
  97. if tv.DataController.DataSource.DataSet is TADOQuery then begin
  98. for I := 0 to tv.SortedItemCount - 1 do begin
  99. SortOrder := SortArray[tv.SortedItems[I].SortOrder];
  100. if S <> ’’ then
  101. S := S + ’, ’;
  102. Index := tv.SortedItems[I].Index;
  103. S := S + tv.Columns[Index].DataBinding.Field.FieldName + ’ ’ + SortOrder;
  104. end;
  105. (tv.DataController.DataSource.DataSet as TADOQuery).Sort := S;
  106. end else if (tv.DataController.DataSource.DataSet is TClientDataSet) then begin
  107. Cds := tv.DataController.DataSource.DataSet as TClientDataSet;
  108. for I := 0 to tv.SortedItemCount - 1 do begin
  109. Index := tv.SortedItems[I].Index;
  110. S := tv.Columns[Index].DataBinding.Field.FieldName +’;’;
  111. AscFields := AscFields + S;
  112. if tv.SortedItems[I].SortOrder = soDescending then
  113. DescFields := DescFields + S;
  114. end;
  115. if AscFields <> ’’ then
  116. Delete(AscFields, Length(AscFields), 1); //刪除 ;
  117. if DescFields <> ’’ then
  118. Delete(DescFields, Length(DescFields), 1);
  119. IndexPrint := TimeToStr(Now());
  120. Cds.IndexDefs.Clear;
  121. IndexPrint := TimeToStr(Now());
  122. cds.AddIndex(IndexPrint, AscFields, [], DescFields);
  123. cds.IndexName := IndexPrint;
  124. end;
  125. end;
  126. ****************************************************************************
  127. 60 cxGRID怎麽遍歷已經選擇的單元格
  128. 解決:
  129. n := cxGrid1DBTableView1.DataController.GetSelectedCount;
  130. for i:=0 to n - 1 do
  131. begin
  132. Index := cxGrid1DBTableView1.DataController.GetSelectedRowIndex(i);
  133. if Index < 0 then continue;
  134. AccID :=
  135. cxGrid1DBTableView1.DataController.GetRowvalue(
  136. cxGrid1DBTableView1.DataController.GetRowInfo(Index)
  137. ,0);
  138. AccID := dsData.DataSet.FieldByName(’AccountID’).AsString;
  139. end;
  140. n := cxGrid1DBTableView1.DataController.GetSelectedCount;
  141. for i:=0 to n - 1 do
  142. begin
  143. Index := cxGrid1DBTableView1.DataController.GetSelectedRowIndex(i);
  144. if Index < 0 then continue;
  145. AccID := cxGrid1DBTableView1.DataController.GetRowvalue(
  146. cxGrid1DBTableView1.DataController.GetRowInfo(Index)
  147. ,0);//這裏的0是列的索引,能指定,也可用通過GridView獲取
  148. end;
  149. ****************************************************************************
  150. 61 動態設置顯示格式
  151. 解決:
  152. procedure SetDisplayFormat(ACtrlData: TClientDataSet;
  153. TbView: TcxGridDBTableView);
  154. var
  155. i: integer;
  156. begin
  157. if ACtrlData.RecordCount <= 0 then Exit;
  158. try
  159. TbView.ClearItems;
  160. ACtrlData.First;
  161. for i := 0 to ACtrlData.RecordCount - 1 do
  162. begin
  163. if ACtrlData.FieldByName(‘SQBF_DisplayInGrid‘).AsString = ‘1‘ then //在表格中顯示
  164. with TbView.CreateColumn do
  165. begin
  166. DataBinding.FieldName := ACtrlData.FieldByName(‘SQBF_FieldName‘).AsString;
  167. Caption := ACtrlData.FieldByName(‘SQBF_Caption‘).AsString; //字段中文標題
  168. Hint := ACtrlData.FieldByName(‘SQBF_Hint‘).AsString;
  169. Width := ACtrlData.FieldByName(‘SQBF_Width‘).AsInteger;
  170. HeaderAlignmentHorz := taCenter;
  171. end;
  172. ACtrlData.Next;
  173. end;
  174. except
  175. on E: Exception do
  176. SaveLog(‘設置顯示格式時出錯:‘ + E.Message);
  177. end;
  178. end;

****************************************************************************
62 給cxGRID加序號列
解決:

[delphi] view plaincopy
  1. procedure SetRowNumber(var ASender: TcxGridTableView;
  2. AViewInfo: TcxCustomGridIndicatorItemViewInfo;
  3. var ACanvas: TcxCanvas; var ADone: boolean);
  4. uses cxLookAndFeelPainters;
  5. procedure SetRowNumber(var ASender: TcxGridTableView; AViewInfo: TcxCustomGridIndicatorItemViewInfo;
  6. var ACanvas: TcxCanvas; var ADone: boolean);
  7. var
  8. AIndicatorViewInfo: TcxGridIndicatorRowItemViewInfo;
  9. ATextRect: TRect;
  10. AFont: TFont;
  11. AFontTextColor, AColor: TColor;
  12. begin
  13. AFont := ACanvas.Font;
  14. AColor := clBtnFace;
  15. AFontTextColor := clWindowText ;
  16. if (AViewInfo is TcxGridIndicatorHeaderItemViewInfo) then begin
  17. ATextRect := AViewInfo.Bounds;
  18. InflateRect(ATextRect, -1, -1);
  19. ASender.LookAndFeelPainter.DrawHeader(ACanvas, AViewInfo.Bounds,
  20. ATextRect, [], cxBordersAll, cxbsNormal, taCenter, vaCenter,
  21. False, False, ‘序號‘, AFont, AFontTextColor, AColor);
  22. ADone := True;
  23. end ;
  24. if not (AViewInfo is TcxGridIndicatorRowItemViewInfo) then
  25. Exit;
  26. ATextRect := AViewInfo.ContentBounds;
  27. AIndicatorViewInfo := AViewInfo as TcxGridIndicatorRowItemViewInfo;
  28. InflateRect(ATextRect, -1, -1);
  29. ASender.LookAndFeelPainter.DrawHeader(ACanvas, AViewInfo.ContentBounds,
  30. ATextRect, [], [bBottom, bLeft, bRight], cxbsNormal, taCenter, vaCenter,
  31. False, False, IntToStr(AIndicatorViewInfo.GridRecord.Index + 1),
  32. AFont, AFontTextColor, AColor);
  33. ADone := True;
  34. ASender.LookAndFeelPainter.DrawIndicatorImage(ACanvas,ATextRect, AIndicatorViewInfo.IndicatorKind);
  35. end;
  36. 如果你不要行標誌的話,你可以不改控件
  37. 直接註釋掉這一行: ASender.LookAndFeelPainter.DrawIndicatorImage(ACanvas, ATextRect, AIndicatorViewInfo.IndicatorKind);
  38. 要標誌的話,在DrawIndicatorImage 從這裏跟進去(Ctrl+左鍵單擊)
  39. 在 cxLookAndFeelPainters 單元中作如下修改:
  40. class procedure TcxCustomLookAndFeelPainter.DrawIndicatorImage(ACanvas: TcxCanvas;
  41. const R: TRect; AKind: TcxIndicatorKind);
  42. var
  43. X, Y: Integer;
  44. begin
  45. if AKind = ikNone then Exit;
  46. with cxIndicatorImages, R do
  47. begin
  48. X := (Left + Right - Width); //靠右
  49. Y := (Top + Bottom - Height) div 2; //居中
  50. end;
  51. cxIndicatorImages.Draw(ACanvas.Canvas, X, Y, Ord(AKind) - 1);
  52. end;
  53. 註意,我已註明靠右的那一行, 就是去掉 DIV 2 了,
  54. 還要改一個地方:
  55. SKIN控件目錄下的dxSkinLookAndFeelPainter單元,找到
  56. TdxSkinLookAndFeelPainter.DrawIndicatorImage 函數
  57. OffsetRect(ARect, (Left + Right - cx div 2) , (Top + Bottom - cy) div 2);
  58. 這一行,將 (Left + Right - cx div 2) 改為(Left + Right - cx) 也是去掉 div 2 就是靠右;
  59. 修改後: OffsetRect(ARect, (Left + Right - cx) , (Top + Bottom - cy) div 2);
  60. 使用
  61. procedure TForm1.cxGrid1DBTableView1CustomDrawIndicatorCell(
  62. Sender: TcxGridTableView; ACanvas: TcxCanvas;
  63. AViewInfo: TcxCustomGridIndicatorItemViewInfo; var ADone: Boolean);
  64. begin
  65. SetRowNumber(Sender,AviewInfo,ACanvas,ADone);
  66. end;
  67. 另外序號列的列寬最好改為25以上!
  68. 效果圖:

****************************************************************************
63 cxGrid自帶過濾後數據也數據集同步
解決:
在cxGrid的View Filter事件的OnBeforeChange中寫代碼就可以了.

[delphi] view plaincopy
  1. procedure TForm1.tvcxgd1DBTableView1DataControllerFilterBeforeChange( Sender: TcxDBDataFilterCriteria; ADataSet: TDataSet; const AFilterText: String);
  2. begin
  3. //這裏可以增加數據集控件的
  4. filter:=false; //如:adoquery.filter:=false; //如果使用的是cxgrid的漢化版本,可以將AFilterText中的中文等於,小於 替換成 = <等 //adoquery.filter:=替換了中文的AFilterText; ShowMessage(AFilterText); end; 寫了上述步驟後可以在tvcxgd1DBTableView1DataControllerFilterChanged寫 adoquery.filter:=true; 這樣就起到了cxgrid過濾後的數據同步到adoquery

Delphi CxGrid 匯總(4)