Delphi中建立交叉表2010-10-24function CreateTmptab(const AFieldDefs:TFieldDefs):TDataSet; var TempTable:TatClientDataSet; begin TempTable:=nil; Result:=nil; if AFieldDefs<>nil then begin try TempTable:=TatClientDataSet.Create(Application); TempTable.FieldDefs.Assign(AFieldDefs); TempTable.CreateDataSet; Result:=(TempTable as TDataSet); Except if TempTable<>nil then TempTable.Free; Result:=nil; raise; end end; end; { SouDataset源数据集 ColField交叉表动态列字段 RowField交叉表行字段 DataField数据字段 } function GenCrossTable(SouDataset:tdataset;ColField,RowField,DataField:string):tdataset; var Vdataset:tdataset; tmpdataset:tatclientdataset; DataSource:tdatasource; tmpstrs:tstrings; rowval,colval,dataval:string; i,j:integer; datatype:TFieldType; DataSize:integer; begin result:=nil; if (ColField="") or(RowField="")or(DataField="") then showmessage("All Field not be NULL!") else begin if (ColField=RowField) or(ColField=DataField) or(RowField=DataField) then showmessage("All Field not be Equ!") else if (self.SouDataSet.FieldByName(ColField).DataType=ftString) or (self.SouDataSet.FieldByName(ColField).DataType<>ftWideString) or (self.SouDataSet.FieldByName(ColField).DataType<>ftFixedChar) or (self.SouDataSet.FieldByName(ColField).DataType<>ftMemo) or (self.SouDataSet.FieldByName(ColField).DataType<>ftFmtMemo) then begin try tmpstrs:=tstringlist.Create; Vdataset:=SouDataSet; Vdataset.First; for i:=0 to Vdataset.RecordCount-1 do begin if (varisnull(SouDataSet.FieldValues[colfield])=false) and (SouDataSet.FieldValues[colfield]<>"") then if tmpstrs.IndexOf(SouDataSet.FieldValues[colfield])=-1 then begin tmpstrs.Add(SouDataSet.FieldValues[colfield]); end; Vdataset.Next; end; //生成动态列标题 tmpdataset:=TClientDataSet.Create(Self); tmpdataset.FieldDefs.Add(rowfield,ftstring,50,False); for i:=0 to tmpstrs.Count-1 do begin with tmpdataset.FieldDefs do begin Add(tmpstrs.Strings[i],ftInteger,0,False); end; end; tmpdataset.FieldDefs.Add("Sum",ftInteger,0,False); DataSource:=tdatasource.Create(self); DataSource.DataSet:=tmpdataset; with DataSource do begin dataset:=Createtmptab(tmpdataset.FieldDefs); dataset.Open; end; //建立临时表 Vdataset.First; for i:=0 to Vdataset.RecordCount-1 do begin rowval:=SouDataSet.fieldbyname(rowfield).AsString; colval:=SouDataSet.fieldbyname(colfield).AsString; dataval:=SouDataSet.fieldbyname(datafield).AsString; if dataval="" then dataval:="0"; if DataSource.DataSet.Locate(rowfield,rowval,[loPartialKey]) then begin DataSource.DataSet.Edit; DataSource.DataSet.FieldByName(colval).AsString:=dataval; DataSource.DataSet.FieldByName("Sum").AsInteger:= DataSource.DataSet.FieldByName("Sum").AsInteger+strtoint(dataval); DataSource.DataSet.Post; end else begin DataSource.DataSet.Append; DataSource.DataSet.FieldByName(rowfield).AsString:=rowval; for j:=1 to DataSource.DataSet.Fields.Count-1 do DataSource.DataSet.Fields[j].AsCurrency:=0; DataSource.DataSet.FieldByName(colval).AsString:=dataval; DataSource.DataSet.FieldByName("Sum").AsString:=dataval; DataSource.DataSet.Post; end; Vdataset.Next; end; result:=DataSource.DataSet; //生成交叉表数据集 tmpstrs.Free; except end; end else showmessage("ColField Must be of Type String!") ; end; end;