delphi CXGRID用法 (取行、列值;定位选中某行等等)
CXGRID用法 (取行、列值;定位选中某行等等)
Delphi Cxgrid获取选中行列,排序规则,当前正在编辑的单元格内的值
cxGrid1DBTableView1.Controller.FocusedRowIndex 当前行号
cxGrid1DBTableView1.Controller.FocusedRow 当前行
cxGrid1DBTableView1.Controller.FocusedColumn 当前列
cxGrid1DBTableView1.Controller.FocusedColumnIndex 当前列号
cxGrid1DBTableView1.Controller.EditingItem 当前编辑中的单元框
cxGrid1DBTableView1.Controller.EditingController.Edit 当前的编辑框
在编辑状态下可以这样取当前单元格的值:
if cxGrid1DBTableView1.Controller.FocusedColumn.Editing then
ShowMessage(cxGrid1DBTableView1.Controller.EditingController.Edit.EditingValue)
else
cxGrid1DBTableView1.DataController.GetValue(cxGrid1DBTableView1.DataController.FocusedRecordIndex, cxGrid1DBTableView1.Controller.FocusedItemIndex);
非编辑状态下可以这样取得单元格内的值:
OnCellClick事件代码:
procedure TForm1.cxGrid1DBTableView1CellClick( Sender: TcxCustomGridTableView;
ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton; AShift: TShiftState; var AHandled: Boolean); var
v : Variant; begin
v := ACellViewInfo.Value; end;
取列值
i := cxGrid1DBBandedTableView1.Controller.FocusedColumn.Index;
cxGrid1DBBandedTableView1.DataController.GetValue(cxGrid1DBBandedTableView1.Controller.SelectedRows[0].RecordIndex,i);
cxGrid1DBTableView1.DataController.Values[行,列]
取得焦点
cxGrid1DBTableView1.Columns[5].FocusWithSelection; cxGrid1DBTableView1.Columns[4].Focused:=True;
得到当前点击的单元格的值
uses Clipbrd;
OnCellClick事件代码: procedure TForm1.cxGrid1DBTableView1CellClick( Sender: TcxCustomGridTableView; ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton; AShift: TShiftState; var AHandled: Boolean); var v : Variant; begin v := ACellViewInfo.Value;//值 Clipboard.AsText := vartostr(v);
//保存到clipboard end; cxGrid的DBTableView的名称为dgtv1
1. 返回选中的行数 gdtv1.DataController.GetSelectedCount;
2. 返回选中行的索引: gdtv1.DataController.GetSelectedRowIndex(0) , 表示第一个选中行的索引
3. 返回选中行的数据;
var I, J:Integer;
begin
for I:=0 to gdtv1.DataController.GetSelectedCount - 1 do
begin J := gdtv1.DataController.GetSelectedRowIndex(I); ShowMessage(VarToStr(gdtv1.DataController.GetValue(J, 0))); //选择中行的第列的值
end;
end;
4. 获取cxGrid排序规则
const
OrderArray: array[soNone..soDescending] of string = ('None', 'ASC', 'DESC');
var
I: integer;
S, OrderStr: string;
begin
for I := 0 to gdtv1.SortedItemCount - 1 do
begin
if S <> '' then S := S + ', ';
OrderStr := OrderStr + gdtv1.SortedItems[I].DataBinding.DefaultCaption + ' ';
OrderStr := OrderStr + OrderArray[TcxDataSortOrder(gdtv1.SortedItems[I].SortOrder)];
S := S + OrderStr;
end;
ShowMessage('ORDER BY ' + S);
5.获取多选的值
for i := 0 to cxgrid1.SelectedRows.Count-1 do begin
cxgrid1.DataSource.DataSet.GotoBookmark(Pointer(cxgrid1.SelectedRows.Items[i])); //定位选中的字段 end;
6.//选择行的第1列的值
for I:=0 to cxGrid1DBTableView1.DataController.GetSelectedCount - 1 do begin
J := cxGrid1DBTableView1.DataController.GetSelectedRowIndex(I);
ShowMessage(VarToStr(cxGrid1DBTableView1.DataController.GetValue(J, 0))); end;
7.获取所选行的值
with cxGrid1DBTableView1.Controller do
begin
for i:=0 to SelectedRowCount-1 do
begin
SelectedRows[i].Focused:=True;
ShowMessage(ADOQuery1.fieldbyname('mc').AsString);
end;
end
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;
技巧二:在内置右键菜单的后面增加菜单项
首先应在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;
技巧三 按条件计算合计值
在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;
技巧四:根据某列的值设定其它列的可编辑性
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;
技巧五:保存/恢复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); //保存为布局文件