經常在CSDN上查閱名位大俠的文章,得益不少,近期因做一個項目,需要用到交叉表,報表上倒是有,但客戶要求在Grid上能操作,沒有辦法,只好自己寫了一段代碼用於普通查詢到交叉表的實現,不敢獨享,故上傳,望能拋磚引玉,請名位大俠不吝指教。
function 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;