好久沒有寫筆記了,現在有點時間,來篇。
happycyp 2007-7-19
cxGrid功能強大,適合做企業級的復雜查詢。非常方便。
但是對其用法介紹的並不多,在此總結他人的使用經驗和自己的一點小經驗,供大家參考。
(1)動態設置顯示格式
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;
(2)顯示行號
procedure TFmQueryBase.cxDBViewMasterCustomDrawIndicatorCell(
Sender: TcxGridTableView; ACanvas: TcxCanvas;
AViewInfo: TcxCustomGridIndicatorItemViewInfo; var ADone: Boolean);
var
FValue: string;
FBounds: TRect;
begin
FBounds := AViewInfo.Bounds;
if (AViewInfo is TcxGridIndicatorRowItemViewInfo) then
begin
ACanvas.FillRect(FBounds);
ACanvas.DrawComplexFrame(FBounds, clBlack, clBlack, [bBottom, bLeft, bRight], 1);
FValue := IntToStr(TcxGridIndicatorRowItemViewInfo(AViewInfo).GridRecord.Index+1);
InflateRect(FBounds, -3, -2); //Platform specific. May not work on Linux.
ACanvas.Font.Color := clBlack;
ACanvas.Brush.Style := bsClear;
ACanvas.DrawText(FValue, FBounds, cxAlignCenter or cxAlignTop);
ADone := True;
end;
end;
(3)設置顯示格式,我的項目要求先動態添加字段,這時不知道字段類型,所以設置DisplayFormat不方便,我還沒有找到好方法。
所以采用打開數據集后再設置:
procedure TFmQueryBase.cdsMasterAfterOpen(DataSet: TDataSet);
var
i: Integer;
begin
for i := 0 to cxDBViewMaster.DataController.DataSet.FieldCount -1 do
begin
if cxDBViewMaster.DataController.DataSet.Fields[i] is TNumericField then
begin
if Pos('AMOUNT', UpperCase(cxDBViewMaster.DataController.DataSet.Fields[i].FieldName)) > 0 then
begin
TNumericField(cxDBViewMaster.DataController.DataSet.Fields[i]).DisplayFormat := '#,##0.000';
Continue;
end;
if Pos('QUANTITY', UpperCase(cxDBViewMaster.DataController.DataSet.Fields[i].FieldName)) > 0 then
begin
TNumericField(cxDBViewMaster.DataController.DataSet.Fields[i]).DisplayFormat := '#,##0.000';
Continue;
end;
if Pos('MONEY', UpperCase(cxDBViewMaster.DataController.DataSet.Fields[i].FieldName)) > 0 then
begin
TNumericField(cxDBViewMaster.DataController.DataSet.Fields[i]).DisplayFormat := '#,##0.00';
Continue;
end;
end;
end;
end;
2007-7-19 12:48:54
查看評語»»»
2007-7-19 12:53:09 別人的,轉載http://www.showding.cn/item/cxGrid__182526.aspx
最近在學習使用cxGrid,安裝的版本是ExpressQuantumGrid Suite v5.10
我發現這個控件功能雖然強大,但是非常難用。
現在我手頭就有幾個問題還沒解決:
1)主從模式下導出Excel中文會產生亂碼,而且從表內容沒有導出。
我不知道是不是因為我的字段名包括單引號的原因。
導出代碼:ExportGrid4ToExcel(FileName, cxGrid);
2)主從模式下通過按鈕對從表添加/刪除行,代碼怎么寫。
附:單表添加/刪除行的代碼
procedure TFormAccount.cxButtonNewClick(Sender: TObject);
begin
Self.tvAccount.DataController.Append;
Self.tvAccount.Columns[0].Focused := True;
cxGrid.SetFocus;
end;
procedure TFormAccount.cxButtonDeleteClick(Sender: TObject);
begin
if Self.tvAccount.DataController.RowCount = 0 then
Exit;
if Application.MessageBox('確認刪除當前記錄?', '確認刪除',
MB_YesNo + MB_IconQuestion) = IDNO then
Exit;
Self.tvAccount.DataController.DeleteFocused;
end;
3)動態創建主從結構出錯(Compiler沒錯,運行時出現系統錯誤0000000018),
我使用了二個ADOStoreProcedure作主從表
代碼如下:
var
Level: TcxGridLevel;
GridView: TcxGridDBTableView;
begin
Level := cxGrid1.Levels[0].Add;
GridView := TcxGridDBTableView(cxGrid1.CreateView(TcxGridDBTableView));
GridView.DataController.DataSource := Self.dsDetail;
GridView.DataController.KeyFieldNames := 'PurchOrderID;POLineNbr;PromiseDate;ReceiverDate';
GridView.DataController.MasterKeyFieldNames := 'VendorID';
GridView.DataController.DetailKeyFieldNames := 'VendorID';
GridView.DataController.DataModeController.SmartRefresh := True;
GridView.OptionsCustomize.ColumnHiding := True;
GridView.OptionsCustomize.ColumnsQuickCustomization := True;
GridView.OptionsData.Deleting := False;
GridView.OptionsData.Inserting := False;
GridView.OptionsView.Indicator := True;
Level.GridView := GridView;
GridView := TcxGridDBTableView(cxGrid1.Levels[0].GridView);
GridView.DataController.KeyFieldNames := 'VendorID';
GridView.OptionsView.GroupByBox := False;
//顯示主表內容
tvResult.BeginUpdate;
tvResult.ClearItems;
tvResult.DataController.CreateAllItems;
tvResult.EndUpdate;
//顯示明細表內容
GridView := TcxGridDBTableView(cxGrid1.Levels[0].Items[0].GridView);
GridView.BeginUpdate;
GridView.ClearItems;
GridView.DataController.CreateAllItems;
GridView.DataController.Refresh;
GridView.EndUpdate;
end;
此樓回復Re:
--------------------------------------------------------------------------------
小技巧:用代碼展開/收縮主從結構
Self.tvDepartment.ViewData.Expand(True);
Self.tvDepartment.ViewData.Collaspe(True);
注:tvDepartment為主表對應的TableView
此樓回復Re:
--------------------------------------------------------------------------------
你說的這幾個問題我也遇到過。
第一個問題是編碼的問題,修改了其中關於編碼的函數,OK.
第二個問題在cxGrid的社區可以找到解答,但從表必須滿足某種條件,例如關鍵字排序。
第三個問題的解決辦法,你可以嘗試在動態創建的代碼前后加上:
grid.beginupdate;
...
grid.endupdate
來解決。
此樓回復Re:
--------------------------------------------------------------------------------
沒用過
不要經常使用三方控件
此樓回復Re:
--------------------------------------------------------------------------------
to tttk(網絡芝麻):
第一個問題:如何修改啊,貼出代碼
第二個問題:沒搜到啊
第三個問題:試一下再說
此樓回復Re:
--------------------------------------------------------------------------------
不要經常使用三方控件
======================
我感覺不用cxGrid的話,沒必要用Delphi了,呵呵
此樓回復Re:
--------------------------------------------------------------------------------
樓上這話是不是有點問題?DELPHI能做得事情很多很多,難道非要用CXGRID?CXGRID不是用DELPHI做出來得?
此樓回復Re:
--------------------------------------------------------------------------------
沒用過.....
此樓回復Re:
--------------------------------------------------------------------------------
回復人: zxkid(沒有人會像我這樣...) ( ) 信譽:101 2006-01-06 16:58:00 得分: 0
不要經常使用三方控件
======================
我感覺不用cxGrid的話,沒必要用Delphi了,呵呵
**********
樓主乃天人也!!
此樓回復Re:
--------------------------------------------------------------------------------
呵呵
此樓回復Re:
--------------------------------------------------------------------------------
cxGrid比較不錯,我也使用過導出到Excel,沒有遇到你說的亂碼
主從表也沒有問題的,其實跟單表操作還不是一回事
此樓回復Re:
--------------------------------------------------------------------------------
up
此樓回復Re:
--------------------------------------------------------------------------------
沒用過cxGrid,以后考慮
此樓回復Re:
--------------------------------------------------------------------------------
樓主乃天人也!!
=============================
Delphi下有cxGrid, .NET下有XtraGrid, 它們都是同一公司出的。
遲早都會轉到.NET,所以。。。
此樓回復Re:
--------------------------------------------------------------------------------
路過
此樓回復Re:
--------------------------------------------------------------------------------
用過,挺好,只會使用最簡單的。
此樓回復Re:
--------------------------------------------------------------------------------
發一個郵件給我,我把解決亂碼后的源代碼發一分給你,放到你的項目文件夾下即可。
tttk2000@hotmail.com
此樓回復Re:
--------------------------------------------------------------------------------
第二個問題:https://www.devexpress.com/Support/Center/default.aspx?view=ViewIssue&issueid=B2691
此樓回復Re:
--------------------------------------------------------------------------------
謝謝tttk(網絡芝麻)
第二個問題:我現在直接讓用戶用導航條的刪除/添加按鈕了。根據你給的網址上的內容我知道大概該怎么寫了,有空再試試。
第一個問題:不光是亂碼問題,還有從表內容沒導出的問題。
只有一個表的話是不會出現亂碼的。
第三個問題:還沒來得及試。
此樓回復Re:
--------------------------------------------------------------------------------
第一個問題:看了一下幫助,原來cxGrid不支持主從表的導出,只能導出主表(頂層表)的內容。暈
此樓回復Re:
--------------------------------------------------------------------------------
貼一些小技巧,希望與各位使用cxGrid的朋友共同交流
各位有什么好個技巧也可以貼出來:
技巧二:在內置右鍵菜單的后面增加菜單項
首先應在Form上加一個cxGridPopupMenu控件 以啟用右鍵菜單
UseBuildInPopupMenus設為True
procedure TFormItemList.FormCreate(Sender: TObject);
var
AMenu: TComponent;
FMenuItem, FSubMenuItem: TMenuItem;
begin
AMenu := nil;
if cxGridPopupMenu.BuiltInPopupMenus.Count = 0 then
Exit;
AMenu := cxGridPopupMenu.BuiltInPopupMenus[0].PopupMenu; //第一個內置右鍵菜單(表頭菜單)
if Assigned(AMenu) and AMenu.InheritsFrom(TPopupMenu) then
begin
TPopupMenu(AMenu).AutoHotkeys := maManual; //手動熱鍵
//-------------------------
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Caption := '-';
FMenuItem.Name := 'miLineForGroup';
TPopupMenu(AMenu).Items.Add(FMenuItem);
//展開所有組
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miExpandAllGroup';
FMenuItem.Caption := '展開所有組(&X)';
FMenuItem.OnClick := miExpandAllGroupClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//收縮所有組
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miCollapseAllGroup';
FMenuItem.Caption := '收縮所有組(&O)';
FMenuItem.OnClick := miCollapseAllGroupClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//-------------------------
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Caption := '-';
TPopupMenu(AMenu).Items.Add(FMenuItem);
//過濾面板
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miFilterPanel';
FMenuItem.Caption := '過濾面板(&P)';
//自動顯示
FSubMenuItem := TMenuItem.Create(Self);
FSubMenuItem.Name := 'miFilterPanelAuto';
FSubMenuItem.Caption := '自動(&A)';
FSubMenuItem.RadioItem := True;
FSubMenuItem.GroupIndex := 5; //指定同一組
FSubMenuItem.Checked := True;
FSubMenuItem.OnClick := miFilterPanelClick;
FMenuItem.Add(FSubMenuItem); //加入二級子菜單
//總是顯示
FSubMenuItem := TMenuItem.Create(Self);
FSubMenuItem.Name := 'miFilterPanelAlways';
FSubMenuItem.Caption := '總是顯示(&W)';
FSubMenuItem.RadioItem := True;
FSubMenuItem.GroupIndex := 5;
FSubMenuItem.OnClick := miFilterPanelClick;
FMenuItem.Add(FSubMenuItem);
//從不顯示
FSubMenuItem := TMenuItem.Create(Self);
FSubMenuItem.Name := 'miFilterPanelNerver';
FSubMenuItem.Caption := '從不顯示(&N)';
FSubMenuItem.RadioItem := True;
FSubMenuItem.GroupIndex := 5;
FSubMenuItem.OnClick := miFilterPanelClick;
FMenuItem.Add(FSubMenuItem);
TPopupMenu(AMenu).Items.Add(FMenuItem);
//自定義過濾
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miCustomFilter';
FMenuItem.Caption := '自定義過濾(&M)';
FMenuItem.OnClick := miCustomFilterClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//過濾管理器
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miFilterBuilder';
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 44); //添加圖標圖像
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1; //指定圖標序號
FMenuItem.Caption := '過濾管理器';
FMenuItem.OnClick := Self.miFilterBuilderClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//---------------------
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Caption := '-';
TPopupMenu(AMenu).Items.Add(FMenuItem);
//導出
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miExport';
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 37);
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1;
FMenuItem.Caption := '導出(&E)';
FMenuItem.OnClick := Self.miExportClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//打印
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miPrint';
FMenuItem.Caption := '打印(&P)';
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 14);
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1;
FMenuItem.OnClick := Self.miPrintClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
end;
end;
procedure TFormItemList.miExportClick(Sender: TObject);
var
FileName, FileExt, msg: String;
begin
if Self.aqyQuery.IsEmpty then
begin
msg := '沒有導出數據...';
Application.MessageBox(PChar(msg), PChar(Application.Title),
MB_OK or MB_IconWarning);
Exit;
end;
Self.SaveDialogExport.Filter := 'Excel文件 (*.xls)|*.xls|XML文件 (*.xml)|*.xml'
+ '|文本文件 (*.txt)|*.txt|網頁文件 (*.html)|*.html';
Self.SaveDialogExport.Title := '導出為';
if not Self.SaveDialogExport.Execute then
Exit;
FileName := Self.SaveDialogExport.FileName;
FileExt := LowerCase(ExtractFileExt(FileName));
if FileExt = '.xls' then
ExportGrid4ToExcel(FileName, Self.cxGrid1)
else if FileExt = '.xml' then
ExportGrid4ToXML(FileName, Self.cxGrid1)
else if FileExt = '.txt' then
ExportGrid4ToText(FileName, Self.cxGrid1)
else if FileExt = '.html' then
ExportGrid4ToHTML(FileName, Self.cxGrid1)
else
begin
msg := '不支持的導出文件類型...';
Application.MessageBox(PChar(msg), PChar(Application.Title),
MB_OK or MB_IconError);
Exit;
end;
msg := '導出完成...';
Application.MessageBox(PChar(msg), PChar(Application.Title),
MB_OK or MB_IconInformation);
end;
procedure TFormItemList.miPrintClick(Sender: TObject);
begin
//打印
Self.dxComponentPrinter.Preview(True, Self.dxComponentPrinterLink1);
end;
procedure TFormItemList.cxGridPopupMenuPopup(ASenderMenu: TComponent;
AHitTest: TcxCustomGridHitTest; X, Y: Integer; var AllowPopup: Boolean);
begin
if GetHitTypeByHitCode(AHitTest.HitTestCode) = gvhtColumnHeader then //右擊列標題時
begin
//if tvResult.DataController.Groups.GroupingItemCount > 0 then
if tvResult.GroupedColumnCount > 0 then //有分組時顯示
begin
TMenuItem(Self.FindComponent('miLineForGroup')).Visible := True;
TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible := True;
TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible := True;
end
else
begin
TMenuItem(Self.FindComponent('miLineForGroup')).Visible := False;
TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible := False;
TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible := False;
end;
end;
end;
procedure TFormItemList.miFilterBuilderClick(Sender: TObject);
begin
//過濾管理器
//彈出Filter Builder Dialog對話框
tvResult.Filtering.RunCustomizeDialog;
end;
procedure TFormItemList.miCustomFilterClick(Sender: TObject);
var
AHitTest: TcxCustomGridHitTest;
begin
//自定義過濾
//彈出Custom Filter Dialog對話框
AHitTest := cxGridPopupMenu.HitTest;
if GetHitTypeByHitCode(AHitTest.HitTestCode) = gvhtColumnHeader then //獲得右擊的列
tvResult.Filtering.RunCustomizeDialog(TcxGridColumnHeaderHitTest(AHitTest).Column);
end;
procedure TFormItemList.miFilterPanelClick(Sender: TObject);
var
mi: TMenuItem;
begin
//隱藏/顯示過濾面板
mi := TMenuItem(Sender);
mi.Checked := True;
if mi.Name = 'miFilterPanelAlways' then
tvResult.Filtering.Visible := fvAlways
else if mi.Name = 'miFilterPanelNerver' then
tvResult.Filtering.Visible := fvNever
else
tvResult.Filtering.Visible := fvNonEmpty;
end;
procedure TFormItemList.miExpandAllGroupClick(Sender: TObject);
begin
//展開所有組
tvResult.DataController.Groups.FullExpand;
end;
procedure TFormItemList.miCollapseAllGroupClick(Sender: TObject);
begin
//收縮所有組
tvResult.DataController.Groups.FullCollapse;
end;
此樓回復Re:
--------------------------------------------------------------------------------
在用,留名
此樓回復Re:
--------------------------------------------------------------------------------
技巧三 按條件計算合計值
在Footer的第一列顯示[合計:]
加一個Summary項,Column設為Grid的第一列,Kind設為skNone
在該Summary項的OnGetText事件中,輸入:
procedure TFormExpense.tvExpenseTcxGridDBDataControllerTcxDataSummaryFooterSummaryItems2GetText(
Sender: TcxDataSummaryItem; const AValue: Variant; AIsFooter: Boolean;
var AText: String);
begin
AText := '合計:';
end;
按條件匯總:
在TableView的DataController->Summary->FooterSummary->OnSummary事件中,輸入:
procedure TFormExpense.tvExpenseDataControllerSummaryFooterSummaryItemsSummary(
ASender: TcxDataSummaryItems; Arguments: TcxSummaryEventArguments;
var OutArguments: TcxSummaryEventOutArguments);
begin
//得到字段名 TcxDBDataSummaryItem(Arguments.SummaryItem).FieldName;
if (ASender.DataController.Values[Arguments.RecordIndex, tvExpenseLevel.Index] > 1) //只統計Level列=1的值
and (TcxDBDataSummaryItem(Arguments.SummaryItem).Kind = skSum) then
OutArguments.Value := 0; //Level > 1的統計值設為0
end;
此樓回復Re:
--------------------------------------------------------------------------------
借貴地一用,問個CXGrid問題,在cxgrid中如何使一些行不能編輯,如:字段isenable = false的行
此樓回復Re:
--------------------------------------------------------------------------------
樓上的問題
請參考下面的技巧
技巧四:根據某列的值設定其它列的可編輯性
procedure TFormUser.tvUserEditing(Sender: TcxCustomGridTableView;
AItem: TcxCustomGridTableItem; var AAllow: Boolean);
begin
//如果第三列值為True,則第4列不能修改
if (tvUser.Controller.FocusedRecord.Values[2] = True) and (AItem.Index = 4) then
AAllow := False
else
AAllow := True;
end;
此樓回復Re:
--------------------------------------------------------------------------------
技巧五:保存/恢復Grid布局
//恢復布局
IniFileName := ExtractFilePath(Application.ExeName) + 'Layout\' + Self.Name + '.ini';
if FileExists(IniFileName) then
Self.tvResult.RestoreFromIniFile(IniFileName) //從布局文件中恢復
else
begin
Self.tvResult.BeginUpdate;
for i := 0 to Self.tvResult.ItemCount - 1 do
Self.tvResult.Items[i].ApplyBestFit; //調整為最佳寬度
Self.tvResult.EndUpdate;
end;
//保存布局
IniFileName := ExtractFilePath(Application.ExeName) + 'Layout\' + Self.Name + '.ini';
if not DirectoryExists(ExtractFileDir(IniFileName)) then
CreateDir(ExtractFileDir(IniFileName));
Self.tvResult.StoreToIniFile(IniFileName); //保存為布局文件
此樓回復Re:
--------------------------------------------------------------------------------
借用地問一下:在 cxgrid中,如果我同時選中主表與子表中的記錄,怎么樣能同時進行對其所選記錄進行處理呢。
我現在只能判斷 焦點是在主表還是從表中,然后只能對主表或子表中的數據進行處理。
此樓回復Re:
--------------------------------------------------------------------------------
看來用cxGrid人不多啊
再多貼一些技巧,需要的朋友頂一下
==========================================================================
在主從TableView中根據主TableView得到對應的從TableView
var
ADetailDC: TcxGridDataController;
AView: TcxCustomGridTableView;
begin
with cxGrid1DBTableView1.DataController do
ADetailDC := TcxGridDataController(GetDetailDataController(FocusedRecordIndex, 0));
AView := ADetailDC.GridView;
end;
==============================================================================
定位在第一行並顯示內置編輯器
cxDBVerticalGrid1.FocusedRow := cxDBVerticalGrid1.Rows[0];
cxDBVerticalGrid1.ShowEdit;
==============================================================================
隱藏 "<No data to display>" 字符串
該文本存儲在scxGridNoDataInfoText資源字符串,可以將該資源字符串的內容設為空
來隱藏該文本。
uses cxClasses, cxGridStrs;
...
cxSetResourceString(@scxGridNoDataInfoText, '');
//如果"<No data to display>" 字符串已經顯示,需要調用:
<View>.LayoutChanged;
============================================================
刪除應用過濾后的行
var
I: Integer;
begin
with <GridView> do
for I := 0 to ViewData.RecordCount - 1 do
begin
ViewData.Records[0].Focused := True;
DataController.DataSet.Delete;
end;
=============================================================
根據單元的值設置樣式
procedure <aForm>.<aColumn>StylesGetContentStyle(
Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord;
AItem: TcxCustomGridTableItem; out AStyle: TcxStyle);
begin
if ARecord.Values[AItem.Index] = aSomeValue then
AStyle := <aSomeStyle>;
end;
procedure <aForm>.<aView>StylesGetContentStyle(
Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord;
AItem: TcxCustomGridTableItem; out AStyle: TcxStyle);
var
AColumn: TcxCustomGridTableItem;
begin
AColumn := (Sender as TcxGridDBTableView).GetColumnByFieldName('Email');
if VarToStr(ARecord.Values[AColumn.Index]) = '' then
AStyle := cxStyleNullEmail;
end;
==============================================================================
TcxCustomGridTableView.FindItemByName, TcxGridDBTableView.GetColumnByFieldName or
TcxGridDBDataController.GetItemByFieldName
with cxGrid1DBBandedTableView1.DataController do
AValue := Values[FocusedRecordIndex, GetItemByFieldName('SomeFieldName').Index];
===================================================================
動態生成BandedView
var
AView: TcxCustomGridView;
begin
AView := <cxGrid>.CreateView(TcxGridDBBandedTableView);
TcxGridDBBandedTableView(AView).DataController.DataSource := <DataSource>;
TcxGridDBBandedTableView(AView).Bands.Add;
with TcxGridDBBandedTableView(AView).Bands.Add do
begin
Visible := False;
FixedKind := fkLeft;
end;
TcxGridDBBandedTableView(AView).DataController.CreateAllItems;
<cxGridLevel>.GridView := AView;
此樓回復Re:
--------------------------------------------------------------------------------
======================================================================
當底層數據集為空時顯示一條空記錄
procedure <Form>.<cxGrid>Enter(Sender: TObject);
var
View: TcxGridDBTableView;
begin
View := TcxGridDBTableView((Sender as TcxGrid).FocusedView);
if View.DataController.DataSet.IsEmpty then
begin
View.DataController.DataSet.Append;
View.Controller.EditingController.ShowEdit;
end;
end;
=======================================================================
在當前View插入記錄
使用FocusedView屬性得到當前焦點View,用View.DataController得到對應的Data Controller,
之后使用Data Controller的方法來操作數據:
- Append
- Insert
- Post
- Cancel
- DeleteFocused
- DeleteSelection
示例:
var
ARecIndex: Integer;
…
View.DataController.Append;
ARecIndex := View.DataController.FocusedRecordIndex;
View.DataController.Values[ARecIndex, SomeItemIndex] := SomeValue;
View.DataController.Post;
另外一種方法是使用View.DataController.DataSource.DataSet得到底層數據集后,再用數據集的
方法來操作數據。
========================================================================
激活內置編輯控件
1) <aView>.Controller.EditingController.ShowEdit(<aColumn>);
2) <aView>.Controller.EditingController.StartEditShowingTimer(<aColumn>);
3) <aView>.Controller.EditingItem := <aColumn>;
4) <aColumn>.Editing := True;
隱藏內置編輯控件
<aView>.Controller.EditingController.HideEdit(True);
===========================================================================
移除一個分組列
<aColumn>.GroupIndex := -1;
<aColumn>.Visible := True;
===========================================================================
保存修改到數據庫
procedure <aForm>.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if (<aGrid>.FocusedView <> nil) and (<aGrid>.FocusedView.DataController.EditState <> []) then
<aGrid>.FocusedView.DataController.Post;
end;
============================================================================
設置內置右鍵菜單
內置右鍵菜單包括二個菜單:cxGridStdHeaderMenu, TcxGridStdFooterMenu
uses cxGridStdPopupMenu;
procedure TForm1.cxGridPopupMenu1Popup(ASenderMenu: TComponent;
AHitTest: TcxCustomGridHitTest; X, Y: Integer; var AllowPopup: Boolean);
begin
if ASenderMenu is TcxGridStdHeaderMenu then
TcxGridStdHeaderMenu(ASenderMenu).OnPopup := StdHeaderMenuPopup;
end;
procedure TForm1.StdHeaderMenuPopup(Sender: TObject);
var
I: Integer;
begin
with TcxGridStdHeaderMenu(Sender).Items do
for I := 0 to Count - 1 do
if Items[I].Caption = 'Group By Box' then
begin
Items[I].Enabled := False;
System.Break;
end
end;
===========================================================================
得到選中記錄的值
1) View.DataController.DataModeController.GridMode = False時
RecIdx := View.Controller.SelectedRecords[i].RecordIndex;
ColIdx := View.DataController.GetItemByFieldName(AFieldName).Index;
OutputVal := View.DataController.Values[RecIdx, ColIdx];
//RecID := View.DataController.GetRecordId(RecIdx);
//OutputVal := ADataSet.Lookup(View.DataController.KeyFieldNames, RecID, AFieldName);
2) View.DataController.DataModeController.GridMode = True時
Bkm := View.DataController.GetSelectedBookmark(ASelectedRecordIndex);
if ADataSet.BookmarkValid(TBookmark(Bkm)) then
begin
ADataSet.Bookmark := TBookmark(Bkm);
OutputVal := ADataSet.FieldByName(AFieldName).Value;
end;
View.BeginUpdate;
View.DataController.BeginLocate;
try
// make changes here…
finally
View.DataController.EndLocate;
View.EndUpdate;
end;
=============================================================
在GridMode禁用內置的右鍵Footer菜單
uses cxGridStdPopupMenu;
procedure cxGridPopupMenuOnPopup(...)
begin
if (ASenderMenu is TcxGridStdFooterMenu) and
<GridView>.DataController.DataModeController.GridMode then
AllowPopup := False;
end;
==============================================================
主從表任何時候只能展開一個組
procedure TForm1.ADetailDataControllerCollapsing(
ADataController: TcxCustomDataController; ARecordIndex: Integer;
var AAllow: Boolean);
var
I: Integer;
C: Integer;
begin
AAllow := False;
C := 0;
for I := 0 to ADataController.RecordCount - 1 do
begin
if ADataController.GetDetailExpanding(I) then
Inc(C);
if C > 1 then
AAllow := True;
end;
end;
procedure TForm1.ADetailDataControllerExpanding(
ADataController: TcxCustomDataController; ARecordIndex: Integer;
var AAllow: Boolean);
begin
ADataController.CollapseDetails;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
cxGrid1DBTableView1.DataController.OnDetailExpanding := ADetailDataControllerExpanding;
cxGrid1DBTableView1.DataController.OnDetailCollapsing := ADetailDataControllerCollapsing;
end;
=================================================================
動態創建層次(Level)和視圖(View)
var
Grid: TcxGrid;
Level: TcxGridLevel;
View: TcxGridDBTableView;
begin
// Creates a Grid instance
Grid := TcxGrid.Create(SomeOwner);
Grid.Parent := SomeParent;
// Creates a Level
Level := Grid.Levels.Add;
Level.Name := 'SomeLevelName';
// Creates a View
View := Grid.CreateView(TcxGridDBTableView) as TcxGridDBTableView;
View.Name := 'SomeViewName';
// … and binds it to the Level
Level.GridView := View;
// Hooks up the View to the data
View.DataController.DataSource := SomeDataSource;
// … and creates all columns
View.DataController.CreateAllItems;
end;
此樓回復Re:
--------------------------------------------------------------------------------
======================================================================
獲得Group Footer合計行對應的記錄
procedure TForm1.cxGrid1DBTableView1CustomDrawFooterCell(
Sender: TcxGridTableView; ACanvas: TcxCanvas;
AViewInfo: TcxGridColumnHeaderViewInfo; var ADone: Boolean);
var
ALevel, ADataGroupIndex: Integer;
AGridRecord, AGroupRecord: TcxCustomGridRecord;
begin
if AViewInfo is TcxGridRowFooterCellViewInfo and // Row footer
(TcxGridDBColumn(AViewInfo.Column).DataBinding.FieldName = 'Area') then // Area column
begin
AGridRecord := TcxGridRowFooterCellViewInfo(AViewInfo).GridRecord;
ALevel := TcxGridRowFooterCellViewInfo(AViewInfo).Container.GroupLevel;
ADataGroupIndex := Sender.DataController.Groups.DataGroupIndexByRowIndex[AGridRecord.Index];
if ADataGroupIndex <> -1 then
begin
AGroupRecord := AGridRecord;
while AGroupRecord.Level <> ALevel do
AGroupRecord := AGroupRecord.ParentRecord;
AViewInfo.Text := AGroupRecord.DisplayTexts[0];
end;
end;
end;
===========================================================================
訪問過濾之后的記錄
var
I: Integer;
begin
Memo1.Lines.Clear;
with cxGrid1DBTableView1.DataController do
for I := 0 to FilteredRecordCount - 1 do
Memo1.Lines.Add(DisplayTexts[FilteredRecordIndex[I], 0]);
end;
============================================================================
獲得單元的Font
cxGrid1DBTableView1.ViewInfo.RecordsViewInfo.Items[1].GetCellViewInfoByItem(
cxGrid1DBTableView1Company).EditViewInfo.Font;
============================================================================
根據Level名稱找到Level對象
function GetLevelByName(AGrid: TcxGrid; ALevelName: string): TcxGridLevel;
function LoopThroughLevels(ALevel: TcxGridLevel; ALevelName: string): TcxGridLevel;
var
I: Integer;
begin
Result := nil;
for I := 0 to ALevel.Count - 1 do
begin
if ALevel[I].Name = ALevelName then
begin
Result := ALevel[I];
Exit;
end;
if ALevel[I].Count > 0 then
begin
Result := LoopThroughLevels(ALevel[I], ALevelName);
if Result <> nil then
Exit;
end;
end;
end;
var
I: Integer;
begin
Result := nil;
for I := 0 to AGrid.Levels.Count - 1 do
begin
if AGrid.Levels[I].Name = ALevelName then
begin
Result := AGrid.Levels[I];
Exit;
end;
if AGrid.Levels[I].Count > 0 then
begin
Result := LoopThroughLevels(AGrid.Levels[I], ALevelName);
if Result <> nil then
Exit;
end;
end;
end;
============================================================================
指定Filter Builder打開/保存過濾文件的默認路徑
uses
..., cxFilterControlDialog;
procedure TForm.GridView1FilterControlDialogShow(
Sender: TObject);
begin
TfmFilterControlDialog(Sender).OpenDialog.InitialDir := 'D:\'
end;
============================================================================
保存/恢復帶匯總行的布局
<TableView>.StoreToIniFile('c:\Grid.ini', True, [gsoUseSummary]);
<GridView>.RestoreFromIniFile(<inifilename>,True,False {or True, optional},[gsoUseSummary]);
============================================================================
取消過濾時移到第一行
uses
cxCustomData;
procedure TYour_Form.AViewDataControllerFilterChanged(Sender: TObject);
var
Filter: TcxDataFilterCriteria;
begin
with Sender as TcxDataFilterCriteria do
if IsEmpty then
DataController.FocusedRowIndex := 0;
end;
=============================================================================
排序后移到第一行
可以設置DataController.Options.FocusTopRowAfterSorting := True,也可以使用如下的代碼:
uses
cxCustomData;
procedure TYour_Form.Your_ViewDataControllerSortingChanged(Sender: TObject);
begin
TcxCustomDataController(Sender).FocusedRowIndex := 0;
end;
==============================================================================
判斷當前行是否第一行或最后一行
可以使用DataController的IsBOF, IsEOF方法,或者:
<AView>.Controller.Controller.FocusedRow.IsFirst
<AView>.Controller.Controller.FocusedRow.IsLast
==============================================================================
根據指定值查找記錄
DataController提供了好幾個方法來得到指定值對應的RecordIndex
對於Bound View可以使用FindRecordIndexByKeyValue方法
===============================================================================
編輯和顯示Blob字段
該字段的Properties設置為BlobEdit,並將BlobPaintStyle 屬性設為 bpsText
===============================================================================
得到可見行數
<View>.ViewInfo.VisibleRecordCount
===============================================================================
保存后的行設置為當前行
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.
=================================================================================
刪除記錄並獲得焦點
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;
//=======================================================================================
數據庫中的財務表為:
ID 收支類型 金額 其它屬性
其中收支類型只有兩種值:0 表示收入,1 表示支出 ;金額都是正數。
設置cxGrid的Footer 可以使得在顯示時,列表的下方出現匯總行:“金額”的和
同樣設置Default For Groups可以使得在用戶拖動表頭屬性實現分組時,顯示組內的匯總行:“金額”的和。
上面說的,用過cxGrid應該都會,下面就有這么一個問題
如果我想使匯總行的值變為如下的值應該怎樣實現:
收支類型為0的金額的和 - 收支類型為1的金額的和
實現Footer的功能好辦,因為它的值不會變,自己用循環寫一個就完了,但是Default For Groups的功能就不好說了,因為它的值是根據用戶拖動的屬性計算的,而且還有可能是多層分組,想不出來了,所有到這來問
是不是要設置什么屬性?或者cxGrid根本就沒這個功能,那該用什么方法解決?希望哪位幫我解決,謝謝了先!
給你一個例子,可能對你有幫助,
with tvOrders.DataController.Summary do
begin
BeginUpdate;
try
SummaryGroups.Clear;
//The first summary group
with SummaryGroups.Add do
begin
//Add proposed grouping column(s)
TcxGridTableSummaryGroupItemLink(Links.Add).Column := tvOrdersCustomerID;
//Add summary items
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersPaymentAmount;
Kind := skSum;
Format := 'Amount Paid: $,0';
end;
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersPaymentAmount;
Kind := skCount;
Format := 'Records: 0';
end;
end;
//The second summary group
with SummaryGroups.Add do
begin
//Add proposed grouping column(s)
TcxGridTableSummaryGroupItemLink(Links.Add).Column := tvOrdersProductID;
//Add summary items
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersQuantity;
Kind := skSum;
Position := spFooter;
Format := 'TOTAL = 0';
end;
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersPurchaseDate;
Kind := skMin;
Position := spFooter;
end;
end;
finally
EndUpdate;
end;
end;
2007-7-19 12:56:41 go on 訂單號 商品名 單價 數量 金額
001 aa 11.00 2 22.00
001 bb 2.00 2 4.00
001 cc 3.00 3 9.00
----------------------合計 7 35.00
002 ee 11.00 2 22.00
002 bb 3.00 2 6.00
002 cc 3.00 3 9.00
----------------------合計 7 37.00
總計14 72.00
每個單號分一個小結,能實現嗎?
最后在底下實現總的合計
回復人:dctony() ( ) 信譽:100 2007-1-12 21:48:23 得分:100
?
可以的,cxGrid的功能比你想象的還要強大。
1.你先放一個cxGrid,設置好View,設置View.DataController連接的DataSource
2.激活DataSource連接的DataSet,雙擊cxGrid,點擊Retrieve Fields,取得所有的Column
3.設置View的OptionsView.Footer=True,OptionsView.GroupFooters=True,這是為了把分組小計和總計面板顯示出來
4.將“訂單號”字段拖到cxGrid上方的分組面板(GroupbyBox),將數據按“訂單號”分組。這時你會發現單身所有的數據都縮起來了,如果想使所有的數據都展開,可以設置View.DataController.Options.dcoGroupsAlwaysExpanded=True
5.設置分組小計:把View.DataController.Summary.DefaultGroupSummaryItems點開,新增一個Item,Column屬性在下拉里選擇“數量”字段,FieldName屬性為空,Format屬性可以設置數值的顯示格式,Kind屬性下拉skSum加總,Position屬性一定要選擇spFooter。
6.設置總計:把View.DataController.Summary.FooterSummaryItems點開,新增一個Item,Column屬性在下拉里選擇“數量”字段,FieldName屬性為空,Format屬性可以設置數值的顯示格式,Kind屬性下拉skSum加總,Position屬性一定要選擇spFooter。
大功告成,按F9看一下勝利果實吧。
再奉送一個技巧,在Form1再放一個TcxGridPopupMenu控件,就在cxGrid控件旁邊的那個,把TcxGridPopupMenu的Grid屬性設置成你的cxGrid。
然后運行程序,在運行狀態,點擊Grid上的所有地方,左鍵或右鍵,你都會有意外收獲。
ExpressQuantumGrid控件實在是太復雜,太龐大,最好的了解它的方法就是查幫助。
好久沒有寫筆記了,現在有點時間,來篇。
happycyp 2007-7-19
cxGrid功能強大,適合做企業級的復雜查詢。非常方便。
但是對其用法介紹的並不多,在此總結他人的使用經驗和自己的一點小經驗,供大家參考。
(1)動態設置顯示格式
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;
(2)顯示行號
procedure TFmQueryBase.cxDBViewMasterCustomDrawIndicatorCell(
Sender: TcxGridTableView; ACanvas: TcxCanvas;
AViewInfo: TcxCustomGridIndicatorItemViewInfo; var ADone: Boolean);
var
FValue: string;
FBounds: TRect;
begin
FBounds := AViewInfo.Bounds;
if (AViewInfo is TcxGridIndicatorRowItemViewInfo) then
begin
ACanvas.FillRect(FBounds);
ACanvas.DrawComplexFrame(FBounds, clBlack, clBlack, [bBottom, bLeft, bRight], 1);
FValue := IntToStr(TcxGridIndicatorRowItemViewInfo(AViewInfo).GridRecord.Index+1);
InflateRect(FBounds, -3, -2); //Platform specific. May not work on Linux.
ACanvas.Font.Color := clBlack;
ACanvas.Brush.Style := bsClear;
ACanvas.DrawText(FValue, FBounds, cxAlignCenter or cxAlignTop);
ADone := True;
end;
end;
(3)設置顯示格式,我的項目要求先動態添加字段,這時不知道字段類型,所以設置DisplayFormat不方便,我還沒有找到好方法。
所以采用打開數據集后再設置:
procedure TFmQueryBase.cdsMasterAfterOpen(DataSet: TDataSet);
var
i: Integer;
begin
for i := 0 to cxDBViewMaster.DataController.DataSet.FieldCount -1 do
begin
if cxDBViewMaster.DataController.DataSet.Fields[i] is TNumericField then
begin
if Pos('AMOUNT', UpperCase(cxDBViewMaster.DataController.DataSet.Fields[i].FieldName)) > 0 then
begin
TNumericField(cxDBViewMaster.DataController.DataSet.Fields[i]).DisplayFormat := '#,##0.000';
Continue;
end;
if Pos('QUANTITY', UpperCase(cxDBViewMaster.DataController.DataSet.Fields[i].FieldName)) > 0 then
begin
TNumericField(cxDBViewMaster.DataController.DataSet.Fields[i]).DisplayFormat := '#,##0.000';
Continue;
end;
if Pos('MONEY', UpperCase(cxDBViewMaster.DataController.DataSet.Fields[i].FieldName)) > 0 then
begin
TNumericField(cxDBViewMaster.DataController.DataSet.Fields[i]).DisplayFormat := '#,##0.00';
Continue;
end;
end;
end;
end;
2007-7-19 12:48:54
查看評語»»»
2007-7-19 12:53:09 別人的,轉載http://www.showding.cn/item/cxGrid__182526.aspx
最近在學習使用cxGrid,安裝的版本是ExpressQuantumGrid Suite v5.10
我發現這個控件功能雖然強大,但是非常難用。
現在我手頭就有幾個問題還沒解決:
1)主從模式下導出Excel中文會產生亂碼,而且從表內容沒有導出。
我不知道是不是因為我的字段名包括單引號的原因。
導出代碼:ExportGrid4ToExcel(FileName, cxGrid);
2)主從模式下通過按鈕對從表添加/刪除行,代碼怎么寫。
附:單表添加/刪除行的代碼
procedure TFormAccount.cxButtonNewClick(Sender: TObject);
begin
Self.tvAccount.DataController.Append;
Self.tvAccount.Columns[0].Focused := True;
cxGrid.SetFocus;
end;
procedure TFormAccount.cxButtonDeleteClick(Sender: TObject);
begin
if Self.tvAccount.DataController.RowCount = 0 then
Exit;
if Application.MessageBox('確認刪除當前記錄?', '確認刪除',
MB_YesNo + MB_IconQuestion) = IDNO then
Exit;
Self.tvAccount.DataController.DeleteFocused;
end;
3)動態創建主從結構出錯(Compiler沒錯,運行時出現系統錯誤0000000018),
我使用了二個ADOStoreProcedure作主從表
代碼如下:
var
Level: TcxGridLevel;
GridView: TcxGridDBTableView;
begin
Level := cxGrid1.Levels[0].Add;
GridView := TcxGridDBTableView(cxGrid1.CreateView(TcxGridDBTableView));
GridView.DataController.DataSource := Self.dsDetail;
GridView.DataController.KeyFieldNames := 'PurchOrderID;POLineNbr;PromiseDate;ReceiverDate';
GridView.DataController.MasterKeyFieldNames := 'VendorID';
GridView.DataController.DetailKeyFieldNames := 'VendorID';
GridView.DataController.DataModeController.SmartRefresh := True;
GridView.OptionsCustomize.ColumnHiding := True;
GridView.OptionsCustomize.ColumnsQuickCustomization := True;
GridView.OptionsData.Deleting := False;
GridView.OptionsData.Inserting := False;
GridView.OptionsView.Indicator := True;
Level.GridView := GridView;
GridView := TcxGridDBTableView(cxGrid1.Levels[0].GridView);
GridView.DataController.KeyFieldNames := 'VendorID';
GridView.OptionsView.GroupByBox := False;
//顯示主表內容
tvResult.BeginUpdate;
tvResult.ClearItems;
tvResult.DataController.CreateAllItems;
tvResult.EndUpdate;
//顯示明細表內容
GridView := TcxGridDBTableView(cxGrid1.Levels[0].Items[0].GridView);
GridView.BeginUpdate;
GridView.ClearItems;
GridView.DataController.CreateAllItems;
GridView.DataController.Refresh;
GridView.EndUpdate;
end;
此樓回復Re:
--------------------------------------------------------------------------------
小技巧:用代碼展開/收縮主從結構
Self.tvDepartment.ViewData.Expand(True);
Self.tvDepartment.ViewData.Collaspe(True);
注:tvDepartment為主表對應的TableView
此樓回復Re:
--------------------------------------------------------------------------------
你說的這幾個問題我也遇到過。
第一個問題是編碼的問題,修改了其中關於編碼的函數,OK.
第二個問題在cxGrid的社區可以找到解答,但從表必須滿足某種條件,例如關鍵字排序。
第三個問題的解決辦法,你可以嘗試在動態創建的代碼前后加上:
grid.beginupdate;
...
grid.endupdate
來解決。
此樓回復Re:
--------------------------------------------------------------------------------
沒用過
不要經常使用三方控件
此樓回復Re:
--------------------------------------------------------------------------------
to tttk(網絡芝麻):
第一個問題:如何修改啊,貼出代碼
第二個問題:沒搜到啊
第三個問題:試一下再說
此樓回復Re:
--------------------------------------------------------------------------------
不要經常使用三方控件
======================
我感覺不用cxGrid的話,沒必要用Delphi了,呵呵
此樓回復Re:
--------------------------------------------------------------------------------
樓上這話是不是有點問題?DELPHI能做得事情很多很多,難道非要用CXGRID?CXGRID不是用DELPHI做出來得?
此樓回復Re:
--------------------------------------------------------------------------------
沒用過.....
此樓回復Re:
--------------------------------------------------------------------------------
回復人: zxkid(沒有人會像我這樣...) ( ) 信譽:101 2006-01-06 16:58:00 得分: 0
不要經常使用三方控件
======================
我感覺不用cxGrid的話,沒必要用Delphi了,呵呵
**********
樓主乃天人也!!
此樓回復Re:
--------------------------------------------------------------------------------
呵呵
此樓回復Re:
--------------------------------------------------------------------------------
cxGrid比較不錯,我也使用過導出到Excel,沒有遇到你說的亂碼
主從表也沒有問題的,其實跟單表操作還不是一回事
此樓回復Re:
--------------------------------------------------------------------------------
up
此樓回復Re:
--------------------------------------------------------------------------------
沒用過cxGrid,以后考慮
此樓回復Re:
--------------------------------------------------------------------------------
樓主乃天人也!!
=============================
Delphi下有cxGrid, .NET下有XtraGrid, 它們都是同一公司出的。
遲早都會轉到.NET,所以。。。
此樓回復Re:
--------------------------------------------------------------------------------
路過
此樓回復Re:
--------------------------------------------------------------------------------
用過,挺好,只會使用最簡單的。
此樓回復Re:
--------------------------------------------------------------------------------
發一個郵件給我,我把解決亂碼后的源代碼發一分給你,放到你的項目文件夾下即可。
tttk2000@hotmail.com
此樓回復Re:
--------------------------------------------------------------------------------
第二個問題:https://www.devexpress.com/Support/Center/default.aspx?view=ViewIssue&issueid=B2691
此樓回復Re:
--------------------------------------------------------------------------------
謝謝tttk(網絡芝麻)
第二個問題:我現在直接讓用戶用導航條的刪除/添加按鈕了。根據你給的網址上的內容我知道大概該怎么寫了,有空再試試。
第一個問題:不光是亂碼問題,還有從表內容沒導出的問題。
只有一個表的話是不會出現亂碼的。
第三個問題:還沒來得及試。
此樓回復Re:
--------------------------------------------------------------------------------
第一個問題:看了一下幫助,原來cxGrid不支持主從表的導出,只能導出主表(頂層表)的內容。暈
此樓回復Re:
--------------------------------------------------------------------------------
貼一些小技巧,希望與各位使用cxGrid的朋友共同交流
各位有什么好個技巧也可以貼出來:
技巧二:在內置右鍵菜單的后面增加菜單項
首先應在Form上加一個cxGridPopupMenu控件 以啟用右鍵菜單
UseBuildInPopupMenus設為True
procedure TFormItemList.FormCreate(Sender: TObject);
var
AMenu: TComponent;
FMenuItem, FSubMenuItem: TMenuItem;
begin
AMenu := nil;
if cxGridPopupMenu.BuiltInPopupMenus.Count = 0 then
Exit;
AMenu := cxGridPopupMenu.BuiltInPopupMenus[0].PopupMenu; //第一個內置右鍵菜單(表頭菜單)
if Assigned(AMenu) and AMenu.InheritsFrom(TPopupMenu) then
begin
TPopupMenu(AMenu).AutoHotkeys := maManual; //手動熱鍵
//-------------------------
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Caption := '-';
FMenuItem.Name := 'miLineForGroup';
TPopupMenu(AMenu).Items.Add(FMenuItem);
//展開所有組
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miExpandAllGroup';
FMenuItem.Caption := '展開所有組(&X)';
FMenuItem.OnClick := miExpandAllGroupClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//收縮所有組
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miCollapseAllGroup';
FMenuItem.Caption := '收縮所有組(&O)';
FMenuItem.OnClick := miCollapseAllGroupClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//-------------------------
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Caption := '-';
TPopupMenu(AMenu).Items.Add(FMenuItem);
//過濾面板
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miFilterPanel';
FMenuItem.Caption := '過濾面板(&P)';
//自動顯示
FSubMenuItem := TMenuItem.Create(Self);
FSubMenuItem.Name := 'miFilterPanelAuto';
FSubMenuItem.Caption := '自動(&A)';
FSubMenuItem.RadioItem := True;
FSubMenuItem.GroupIndex := 5; //指定同一組
FSubMenuItem.Checked := True;
FSubMenuItem.OnClick := miFilterPanelClick;
FMenuItem.Add(FSubMenuItem); //加入二級子菜單
//總是顯示
FSubMenuItem := TMenuItem.Create(Self);
FSubMenuItem.Name := 'miFilterPanelAlways';
FSubMenuItem.Caption := '總是顯示(&W)';
FSubMenuItem.RadioItem := True;
FSubMenuItem.GroupIndex := 5;
FSubMenuItem.OnClick := miFilterPanelClick;
FMenuItem.Add(FSubMenuItem);
//從不顯示
FSubMenuItem := TMenuItem.Create(Self);
FSubMenuItem.Name := 'miFilterPanelNerver';
FSubMenuItem.Caption := '從不顯示(&N)';
FSubMenuItem.RadioItem := True;
FSubMenuItem.GroupIndex := 5;
FSubMenuItem.OnClick := miFilterPanelClick;
FMenuItem.Add(FSubMenuItem);
TPopupMenu(AMenu).Items.Add(FMenuItem);
//自定義過濾
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miCustomFilter';
FMenuItem.Caption := '自定義過濾(&M)';
FMenuItem.OnClick := miCustomFilterClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//過濾管理器
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miFilterBuilder';
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 44); //添加圖標圖像
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1; //指定圖標序號
FMenuItem.Caption := '過濾管理器';
FMenuItem.OnClick := Self.miFilterBuilderClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//---------------------
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Caption := '-';
TPopupMenu(AMenu).Items.Add(FMenuItem);
//導出
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miExport';
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 37);
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1;
FMenuItem.Caption := '導出(&E)';
FMenuItem.OnClick := Self.miExportClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
//打印
FMenuItem := TMenuItem.Create(Self);
FMenuItem.Name := 'miPrint';
FMenuItem.Caption := '打印(&P)';
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 14);
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1;
FMenuItem.OnClick := Self.miPrintClick;
TPopupMenu(AMenu).Items.Add(FMenuItem);
end;
end;
procedure TFormItemList.miExportClick(Sender: TObject);
var
FileName, FileExt, msg: String;
begin
if Self.aqyQuery.IsEmpty then
begin
msg := '沒有導出數據...';
Application.MessageBox(PChar(msg), PChar(Application.Title),
MB_OK or MB_IconWarning);
Exit;
end;
Self.SaveDialogExport.Filter := 'Excel文件 (*.xls)|*.xls|XML文件 (*.xml)|*.xml'
+ '|文本文件 (*.txt)|*.txt|網頁文件 (*.html)|*.html';
Self.SaveDialogExport.Title := '導出為';
if not Self.SaveDialogExport.Execute then
Exit;
FileName := Self.SaveDialogExport.FileName;
FileExt := LowerCase(ExtractFileExt(FileName));
if FileExt = '.xls' then
ExportGrid4ToExcel(FileName, Self.cxGrid1)
else if FileExt = '.xml' then
ExportGrid4ToXML(FileName, Self.cxGrid1)
else if FileExt = '.txt' then
ExportGrid4ToText(FileName, Self.cxGrid1)
else if FileExt = '.html' then
ExportGrid4ToHTML(FileName, Self.cxGrid1)
else
begin
msg := '不支持的導出文件類型...';
Application.MessageBox(PChar(msg), PChar(Application.Title),
MB_OK or MB_IconError);
Exit;
end;
msg := '導出完成...';
Application.MessageBox(PChar(msg), PChar(Application.Title),
MB_OK or MB_IconInformation);
end;
procedure TFormItemList.miPrintClick(Sender: TObject);
begin
//打印
Self.dxComponentPrinter.Preview(True, Self.dxComponentPrinterLink1);
end;
procedure TFormItemList.cxGridPopupMenuPopup(ASenderMenu: TComponent;
AHitTest: TcxCustomGridHitTest; X, Y: Integer; var AllowPopup: Boolean);
begin
if GetHitTypeByHitCode(AHitTest.HitTestCode) = gvhtColumnHeader then //右擊列標題時
begin
//if tvResult.DataController.Groups.GroupingItemCount > 0 then
if tvResult.GroupedColumnCount > 0 then //有分組時顯示
begin
TMenuItem(Self.FindComponent('miLineForGroup')).Visible := True;
TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible := True;
TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible := True;
end
else
begin
TMenuItem(Self.FindComponent('miLineForGroup')).Visible := False;
TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible := False;
TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible := False;
end;
end;
end;
procedure TFormItemList.miFilterBuilderClick(Sender: TObject);
begin
//過濾管理器
//彈出Filter Builder Dialog對話框
tvResult.Filtering.RunCustomizeDialog;
end;
procedure TFormItemList.miCustomFilterClick(Sender: TObject);
var
AHitTest: TcxCustomGridHitTest;
begin
//自定義過濾
//彈出Custom Filter Dialog對話框
AHitTest := cxGridPopupMenu.HitTest;
if GetHitTypeByHitCode(AHitTest.HitTestCode) = gvhtColumnHeader then //獲得右擊的列
tvResult.Filtering.RunCustomizeDialog(TcxGridColumnHeaderHitTest(AHitTest).Column);
end;
procedure TFormItemList.miFilterPanelClick(Sender: TObject);
var
mi: TMenuItem;
begin
//隱藏/顯示過濾面板
mi := TMenuItem(Sender);
mi.Checked := True;
if mi.Name = 'miFilterPanelAlways' then
tvResult.Filtering.Visible := fvAlways
else if mi.Name = 'miFilterPanelNerver' then
tvResult.Filtering.Visible := fvNever
else
tvResult.Filtering.Visible := fvNonEmpty;
end;
procedure TFormItemList.miExpandAllGroupClick(Sender: TObject);
begin
//展開所有組
tvResult.DataController.Groups.FullExpand;
end;
procedure TFormItemList.miCollapseAllGroupClick(Sender: TObject);
begin
//收縮所有組
tvResult.DataController.Groups.FullCollapse;
end;
此樓回復Re:
--------------------------------------------------------------------------------
在用,留名
此樓回復Re:
--------------------------------------------------------------------------------
技巧三 按條件計算合計值
在Footer的第一列顯示[合計:]
加一個Summary項,Column設為Grid的第一列,Kind設為skNone
在該Summary項的OnGetText事件中,輸入:
procedure TFormExpense.tvExpenseTcxGridDBDataControllerTcxDataSummaryFooterSummaryItems2GetText(
Sender: TcxDataSummaryItem; const AValue: Variant; AIsFooter: Boolean;
var AText: String);
begin
AText := '合計:';
end;
按條件匯總:
在TableView的DataController->Summary->FooterSummary->OnSummary事件中,輸入:
procedure TFormExpense.tvExpenseDataControllerSummaryFooterSummaryItemsSummary(
ASender: TcxDataSummaryItems; Arguments: TcxSummaryEventArguments;
var OutArguments: TcxSummaryEventOutArguments);
begin
//得到字段名 TcxDBDataSummaryItem(Arguments.SummaryItem).FieldName;
if (ASender.DataController.Values[Arguments.RecordIndex, tvExpenseLevel.Index] > 1) //只統計Level列=1的值
and (TcxDBDataSummaryItem(Arguments.SummaryItem).Kind = skSum) then
OutArguments.Value := 0; //Level > 1的統計值設為0
end;
此樓回復Re:
--------------------------------------------------------------------------------
借貴地一用,問個CXGrid問題,在cxgrid中如何使一些行不能編輯,如:字段isenable = false的行
此樓回復Re:
--------------------------------------------------------------------------------
樓上的問題
請參考下面的技巧
技巧四:根據某列的值設定其它列的可編輯性
procedure TFormUser.tvUserEditing(Sender: TcxCustomGridTableView;
AItem: TcxCustomGridTableItem; var AAllow: Boolean);
begin
//如果第三列值為True,則第4列不能修改
if (tvUser.Controller.FocusedRecord.Values[2] = True) and (AItem.Index = 4) then
AAllow := False
else
AAllow := True;
end;
此樓回復Re:
--------------------------------------------------------------------------------
技巧五:保存/恢復Grid布局
//恢復布局
IniFileName := ExtractFilePath(Application.ExeName) + 'Layout\' + Self.Name + '.ini';
if FileExists(IniFileName) then
Self.tvResult.RestoreFromIniFile(IniFileName) //從布局文件中恢復
else
begin
Self.tvResult.BeginUpdate;
for i := 0 to Self.tvResult.ItemCount - 1 do
Self.tvResult.Items[i].ApplyBestFit; //調整為最佳寬度
Self.tvResult.EndUpdate;
end;
//保存布局
IniFileName := ExtractFilePath(Application.ExeName) + 'Layout\' + Self.Name + '.ini';
if not DirectoryExists(ExtractFileDir(IniFileName)) then
CreateDir(ExtractFileDir(IniFileName));
Self.tvResult.StoreToIniFile(IniFileName); //保存為布局文件
此樓回復Re:
--------------------------------------------------------------------------------
借用地問一下:在 cxgrid中,如果我同時選中主表與子表中的記錄,怎么樣能同時進行對其所選記錄進行處理呢。
我現在只能判斷 焦點是在主表還是從表中,然后只能對主表或子表中的數據進行處理。
此樓回復Re:
--------------------------------------------------------------------------------
看來用cxGrid人不多啊
再多貼一些技巧,需要的朋友頂一下
==========================================================================
在主從TableView中根據主TableView得到對應的從TableView
var
ADetailDC: TcxGridDataController;
AView: TcxCustomGridTableView;
begin
with cxGrid1DBTableView1.DataController do
ADetailDC := TcxGridDataController(GetDetailDataController(FocusedRecordIndex, 0));
AView := ADetailDC.GridView;
end;
==============================================================================
定位在第一行並顯示內置編輯器
cxDBVerticalGrid1.FocusedRow := cxDBVerticalGrid1.Rows[0];
cxDBVerticalGrid1.ShowEdit;
==============================================================================
隱藏 "<No data to display>" 字符串
該文本存儲在scxGridNoDataInfoText資源字符串,可以將該資源字符串的內容設為空
來隱藏該文本。
uses cxClasses, cxGridStrs;
...
cxSetResourceString(@scxGridNoDataInfoText, '');
//如果"<No data to display>" 字符串已經顯示,需要調用:
<View>.LayoutChanged;
============================================================
刪除應用過濾后的行
var
I: Integer;
begin
with <GridView> do
for I := 0 to ViewData.RecordCount - 1 do
begin
ViewData.Records[0].Focused := True;
DataController.DataSet.Delete;
end;
=============================================================
根據單元的值設置樣式
procedure <aForm>.<aColumn>StylesGetContentStyle(
Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord;
AItem: TcxCustomGridTableItem; out AStyle: TcxStyle);
begin
if ARecord.Values[AItem.Index] = aSomeValue then
AStyle := <aSomeStyle>;
end;
procedure <aForm>.<aView>StylesGetContentStyle(
Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord;
AItem: TcxCustomGridTableItem; out AStyle: TcxStyle);
var
AColumn: TcxCustomGridTableItem;
begin
AColumn := (Sender as TcxGridDBTableView).GetColumnByFieldName('Email');
if VarToStr(ARecord.Values[AColumn.Index]) = '' then
AStyle := cxStyleNullEmail;
end;
==============================================================================
TcxCustomGridTableView.FindItemByName, TcxGridDBTableView.GetColumnByFieldName or
TcxGridDBDataController.GetItemByFieldName
with cxGrid1DBBandedTableView1.DataController do
AValue := Values[FocusedRecordIndex, GetItemByFieldName('SomeFieldName').Index];
===================================================================
動態生成BandedView
var
AView: TcxCustomGridView;
begin
AView := <cxGrid>.CreateView(TcxGridDBBandedTableView);
TcxGridDBBandedTableView(AView).DataController.DataSource := <DataSource>;
TcxGridDBBandedTableView(AView).Bands.Add;
with TcxGridDBBandedTableView(AView).Bands.Add do
begin
Visible := False;
FixedKind := fkLeft;
end;
TcxGridDBBandedTableView(AView).DataController.CreateAllItems;
<cxGridLevel>.GridView := AView;
此樓回復Re:
--------------------------------------------------------------------------------
======================================================================
當底層數據集為空時顯示一條空記錄
procedure <Form>.<cxGrid>Enter(Sender: TObject);
var
View: TcxGridDBTableView;
begin
View := TcxGridDBTableView((Sender as TcxGrid).FocusedView);
if View.DataController.DataSet.IsEmpty then
begin
View.DataController.DataSet.Append;
View.Controller.EditingController.ShowEdit;
end;
end;
=======================================================================
在當前View插入記錄
使用FocusedView屬性得到當前焦點View,用View.DataController得到對應的Data Controller,
之后使用Data Controller的方法來操作數據:
- Append
- Insert
- Post
- Cancel
- DeleteFocused
- DeleteSelection
示例:
var
ARecIndex: Integer;
…
View.DataController.Append;
ARecIndex := View.DataController.FocusedRecordIndex;
View.DataController.Values[ARecIndex, SomeItemIndex] := SomeValue;
View.DataController.Post;
另外一種方法是使用View.DataController.DataSource.DataSet得到底層數據集后,再用數據集的
方法來操作數據。
========================================================================
激活內置編輯控件
1) <aView>.Controller.EditingController.ShowEdit(<aColumn>);
2) <aView>.Controller.EditingController.StartEditShowingTimer(<aColumn>);
3) <aView>.Controller.EditingItem := <aColumn>;
4) <aColumn>.Editing := True;
隱藏內置編輯控件
<aView>.Controller.EditingController.HideEdit(True);
===========================================================================
移除一個分組列
<aColumn>.GroupIndex := -1;
<aColumn>.Visible := True;
===========================================================================
保存修改到數據庫
procedure <aForm>.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if (<aGrid>.FocusedView <> nil) and (<aGrid>.FocusedView.DataController.EditState <> []) then
<aGrid>.FocusedView.DataController.Post;
end;
============================================================================
設置內置右鍵菜單
內置右鍵菜單包括二個菜單:cxGridStdHeaderMenu, TcxGridStdFooterMenu
uses cxGridStdPopupMenu;
procedure TForm1.cxGridPopupMenu1Popup(ASenderMenu: TComponent;
AHitTest: TcxCustomGridHitTest; X, Y: Integer; var AllowPopup: Boolean);
begin
if ASenderMenu is TcxGridStdHeaderMenu then
TcxGridStdHeaderMenu(ASenderMenu).OnPopup := StdHeaderMenuPopup;
end;
procedure TForm1.StdHeaderMenuPopup(Sender: TObject);
var
I: Integer;
begin
with TcxGridStdHeaderMenu(Sender).Items do
for I := 0 to Count - 1 do
if Items[I].Caption = 'Group By Box' then
begin
Items[I].Enabled := False;
System.Break;
end
end;
===========================================================================
得到選中記錄的值
1) View.DataController.DataModeController.GridMode = False時
RecIdx := View.Controller.SelectedRecords[i].RecordIndex;
ColIdx := View.DataController.GetItemByFieldName(AFieldName).Index;
OutputVal := View.DataController.Values[RecIdx, ColIdx];
//RecID := View.DataController.GetRecordId(RecIdx);
//OutputVal := ADataSet.Lookup(View.DataController.KeyFieldNames, RecID, AFieldName);
2) View.DataController.DataModeController.GridMode = True時
Bkm := View.DataController.GetSelectedBookmark(ASelectedRecordIndex);
if ADataSet.BookmarkValid(TBookmark(Bkm)) then
begin
ADataSet.Bookmark := TBookmark(Bkm);
OutputVal := ADataSet.FieldByName(AFieldName).Value;
end;
View.BeginUpdate;
View.DataController.BeginLocate;
try
// make changes here…
finally
View.DataController.EndLocate;
View.EndUpdate;
end;
=============================================================
在GridMode禁用內置的右鍵Footer菜單
uses cxGridStdPopupMenu;
procedure cxGridPopupMenuOnPopup(...)
begin
if (ASenderMenu is TcxGridStdFooterMenu) and
<GridView>.DataController.DataModeController.GridMode then
AllowPopup := False;
end;
==============================================================
主從表任何時候只能展開一個組
procedure TForm1.ADetailDataControllerCollapsing(
ADataController: TcxCustomDataController; ARecordIndex: Integer;
var AAllow: Boolean);
var
I: Integer;
C: Integer;
begin
AAllow := False;
C := 0;
for I := 0 to ADataController.RecordCount - 1 do
begin
if ADataController.GetDetailExpanding(I) then
Inc(C);
if C > 1 then
AAllow := True;
end;
end;
procedure TForm1.ADetailDataControllerExpanding(
ADataController: TcxCustomDataController; ARecordIndex: Integer;
var AAllow: Boolean);
begin
ADataController.CollapseDetails;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
cxGrid1DBTableView1.DataController.OnDetailExpanding := ADetailDataControllerExpanding;
cxGrid1DBTableView1.DataController.OnDetailCollapsing := ADetailDataControllerCollapsing;
end;
=================================================================
動態創建層次(Level)和視圖(View)
var
Grid: TcxGrid;
Level: TcxGridLevel;
View: TcxGridDBTableView;
begin
// Creates a Grid instance
Grid := TcxGrid.Create(SomeOwner);
Grid.Parent := SomeParent;
// Creates a Level
Level := Grid.Levels.Add;
Level.Name := 'SomeLevelName';
// Creates a View
View := Grid.CreateView(TcxGridDBTableView) as TcxGridDBTableView;
View.Name := 'SomeViewName';
// … and binds it to the Level
Level.GridView := View;
// Hooks up the View to the data
View.DataController.DataSource := SomeDataSource;
// … and creates all columns
View.DataController.CreateAllItems;
end;
此樓回復Re:
--------------------------------------------------------------------------------
======================================================================
獲得Group Footer合計行對應的記錄
procedure TForm1.cxGrid1DBTableView1CustomDrawFooterCell(
Sender: TcxGridTableView; ACanvas: TcxCanvas;
AViewInfo: TcxGridColumnHeaderViewInfo; var ADone: Boolean);
var
ALevel, ADataGroupIndex: Integer;
AGridRecord, AGroupRecord: TcxCustomGridRecord;
begin
if AViewInfo is TcxGridRowFooterCellViewInfo and // Row footer
(TcxGridDBColumn(AViewInfo.Column).DataBinding.FieldName = 'Area') then // Area column
begin
AGridRecord := TcxGridRowFooterCellViewInfo(AViewInfo).GridRecord;
ALevel := TcxGridRowFooterCellViewInfo(AViewInfo).Container.GroupLevel;
ADataGroupIndex := Sender.DataController.Groups.DataGroupIndexByRowIndex[AGridRecord.Index];
if ADataGroupIndex <> -1 then
begin
AGroupRecord := AGridRecord;
while AGroupRecord.Level <> ALevel do
AGroupRecord := AGroupRecord.ParentRecord;
AViewInfo.Text := AGroupRecord.DisplayTexts[0];
end;
end;
end;
===========================================================================
訪問過濾之后的記錄
var
I: Integer;
begin
Memo1.Lines.Clear;
with cxGrid1DBTableView1.DataController do
for I := 0 to FilteredRecordCount - 1 do
Memo1.Lines.Add(DisplayTexts[FilteredRecordIndex[I], 0]);
end;
============================================================================
獲得單元的Font
cxGrid1DBTableView1.ViewInfo.RecordsViewInfo.Items[1].GetCellViewInfoByItem(
cxGrid1DBTableView1Company).EditViewInfo.Font;
============================================================================
根據Level名稱找到Level對象
function GetLevelByName(AGrid: TcxGrid; ALevelName: string): TcxGridLevel;
function LoopThroughLevels(ALevel: TcxGridLevel; ALevelName: string): TcxGridLevel;
var
I: Integer;
begin
Result := nil;
for I := 0 to ALevel.Count - 1 do
begin
if ALevel[I].Name = ALevelName then
begin
Result := ALevel[I];
Exit;
end;
if ALevel[I].Count > 0 then
begin
Result := LoopThroughLevels(ALevel[I], ALevelName);
if Result <> nil then
Exit;
end;
end;
end;
var
I: Integer;
begin
Result := nil;
for I := 0 to AGrid.Levels.Count - 1 do
begin
if AGrid.Levels[I].Name = ALevelName then
begin
Result := AGrid.Levels[I];
Exit;
end;
if AGrid.Levels[I].Count > 0 then
begin
Result := LoopThroughLevels(AGrid.Levels[I], ALevelName);
if Result <> nil then
Exit;
end;
end;
end;
============================================================================
指定Filter Builder打開/保存過濾文件的默認路徑
uses
..., cxFilterControlDialog;
procedure TForm.GridView1FilterControlDialogShow(
Sender: TObject);
begin
TfmFilterControlDialog(Sender).OpenDialog.InitialDir := 'D:\'
end;
============================================================================
保存/恢復帶匯總行的布局
<TableView>.StoreToIniFile('c:\Grid.ini', True, [gsoUseSummary]);
<GridView>.RestoreFromIniFile(<inifilename>,True,False {or True, optional},[gsoUseSummary]);
============================================================================
取消過濾時移到第一行
uses
cxCustomData;
procedure TYour_Form.AViewDataControllerFilterChanged(Sender: TObject);
var
Filter: TcxDataFilterCriteria;
begin
with Sender as TcxDataFilterCriteria do
if IsEmpty then
DataController.FocusedRowIndex := 0;
end;
=============================================================================
排序后移到第一行
可以設置DataController.Options.FocusTopRowAfterSorting := True,也可以使用如下的代碼:
uses
cxCustomData;
procedure TYour_Form.Your_ViewDataControllerSortingChanged(Sender: TObject);
begin
TcxCustomDataController(Sender).FocusedRowIndex := 0;
end;
==============================================================================
判斷當前行是否第一行或最后一行
可以使用DataController的IsBOF, IsEOF方法,或者:
<AView>.Controller.Controller.FocusedRow.IsFirst
<AView>.Controller.Controller.FocusedRow.IsLast
==============================================================================
根據指定值查找記錄
DataController提供了好幾個方法來得到指定值對應的RecordIndex
對於Bound View可以使用FindRecordIndexByKeyValue方法
===============================================================================
編輯和顯示Blob字段
該字段的Properties設置為BlobEdit,並將BlobPaintStyle 屬性設為 bpsText
===============================================================================
得到可見行數
<View>.ViewInfo.VisibleRecordCount
===============================================================================
保存后的行設置為當前行
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.
=================================================================================
刪除記錄並獲得焦點
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;
//=======================================================================================
數據庫中的財務表為:
ID 收支類型 金額 其它屬性
其中收支類型只有兩種值:0 表示收入,1 表示支出 ;金額都是正數。
設置cxGrid的Footer 可以使得在顯示時,列表的下方出現匯總行:“金額”的和
同樣設置Default For Groups可以使得在用戶拖動表頭屬性實現分組時,顯示組內的匯總行:“金額”的和。
上面說的,用過cxGrid應該都會,下面就有這么一個問題
如果我想使匯總行的值變為如下的值應該怎樣實現:
收支類型為0的金額的和 - 收支類型為1的金額的和
實現Footer的功能好辦,因為它的值不會變,自己用循環寫一個就完了,但是Default For Groups的功能就不好說了,因為它的值是根據用戶拖動的屬性計算的,而且還有可能是多層分組,想不出來了,所有到這來問
是不是要設置什么屬性?或者cxGrid根本就沒這個功能,那該用什么方法解決?希望哪位幫我解決,謝謝了先!
給你一個例子,可能對你有幫助,
with tvOrders.DataController.Summary do
begin
BeginUpdate;
try
SummaryGroups.Clear;
//The first summary group
with SummaryGroups.Add do
begin
//Add proposed grouping column(s)
TcxGridTableSummaryGroupItemLink(Links.Add).Column := tvOrdersCustomerID;
//Add summary items
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersPaymentAmount;
Kind := skSum;
Format := 'Amount Paid: $,0';
end;
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersPaymentAmount;
Kind := skCount;
Format := 'Records: 0';
end;
end;
//The second summary group
with SummaryGroups.Add do
begin
//Add proposed grouping column(s)
TcxGridTableSummaryGroupItemLink(Links.Add).Column := tvOrdersProductID;
//Add summary items
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersQuantity;
Kind := skSum;
Position := spFooter;
Format := 'TOTAL = 0';
end;
with SummaryItems.Add as TcxGridDBTableSummaryItem do
begin
Column := tvOrdersPurchaseDate;
Kind := skMin;
Position := spFooter;
end;
end;
finally
EndUpdate;
end;
end;
2007-7-19 12:56:41 go on 訂單號 商品名 單價 數量 金額
001 aa 11.00 2 22.00
001 bb 2.00 2 4.00
001 cc 3.00 3 9.00
----------------------合計 7 35.00
002 ee 11.00 2 22.00
002 bb 3.00 2 6.00
002 cc 3.00 3 9.00
----------------------合計 7 37.00
總計14 72.00
每個單號分一個小結,能實現嗎?
最后在底下實現總的合計
回復人:dctony() ( ) 信譽:100 2007-1-12 21:48:23 得分:100
?
可以的,cxGrid的功能比你想象的還要強大。
1.你先放一個cxGrid,設置好View,設置View.DataController連接的DataSource
2.激活DataSource連接的DataSet,雙擊cxGrid,點擊Retrieve Fields,取得所有的Column
3.設置View的OptionsView.Footer=True,OptionsView.GroupFooters=True,這是為了把分組小計和總計面板顯示出來
4.將“訂單號”字段拖到cxGrid上方的分組面板(GroupbyBox),將數據按“訂單號”分組。這時你會發現單身所有的數據都縮起來了,如果想使所有的數據都展開,可以設置View.DataController.Options.dcoGroupsAlwaysExpanded=True
5.設置分組小計:把View.DataController.Summary.DefaultGroupSummaryItems點開,新增一個Item,Column屬性在下拉里選擇“數量”字段,FieldName屬性為空,Format屬性可以設置數值的顯示格式,Kind屬性下拉skSum加總,Position屬性一定要選擇spFooter。
6.設置總計:把View.DataController.Summary.FooterSummaryItems點開,新增一個Item,Column屬性在下拉里選擇“數量”字段,FieldName屬性為空,Format屬性可以設置數值的顯示格式,Kind屬性下拉skSum加總,Position屬性一定要選擇spFooter。
大功告成,按F9看一下勝利果實吧。
再奉送一個技巧,在Form1再放一個TcxGridPopupMenu控件,就在cxGrid控件旁邊的那個,把TcxGridPopupMenu的Grid屬性設置成你的cxGrid。
然后運行程序,在運行狀態,點擊Grid上的所有地方,左鍵或右鍵,你都會有意外收獲。
ExpressQuantumGrid控件實在是太復雜,太龐大,最好的了解它的方法就是查幫助。
