Ich habe oft Artikel berühmter Helden auf CSDN gelesen und davon sehr profitiert. Kürzlich habe ich an einem Projekt gearbeitet und musste eine Kreuztabelle im Bericht verwenden, aber der Kunde wollte, dass sie im Grid lauffähig ist. Ich hatte keine andere Wahl, als es selbst zu schreiben, um die Kreuztabelle zu realisieren. Ich traue mich nicht, es ausschließlich zu verwenden, also lade ich es hoch, in der Hoffnung, dass es andere inspirieren kann einige Ratschläge berühmter Helden.
function CreateTmptab(const AFieldDefs:TFieldDefs):TDataSet;
var
TempTable:TatClientDataSet;
beginnen
TempTable:=nil;
Ergebnis:=nil;
wenn AFieldDefs<>nil dann
beginnen
versuchen
TempTable:=TatClientDataSet.Create(application);
TempTable.FieldDefs.Assign(AFieldDefs);
TempTable.CreateDataSet;
Ergebnis:=(TempTable als TDataSet);
Außer
wenn TempTable<>nil dann
TempTable.Free;
Ergebnis:=nil;
erheben;
Ende
Ende;
Ende;
{
SouDataset-Quelldatensatz
Dynamisches Spaltenfeld der ColField-Kreuztabelle
RowField Kreuztabellen-Zeilenfeld
DataFieldDatenfeld
}
function GenCrossTable(SouDataset:tdataset;ColField,RowField,DataField:string):tdataset;
var
Vdataset:tdataset;
tmpdataset:tatclientdataset;
Datenquelle:tdatasource;
tmpstrs:tstrings;
rowval,colval,dataval:string;
i,j:Ganzzahl;
Datentyp:TFieldType;
Datengröße:integer;
beginnen
Ergebnis:=nil;
if (ColField='') or(RowField='')or(DataField='') then
showmessage('Alle Felder dürfen nicht NULL sein!')
anders
beginnen
if (ColField=RowField)
oder(ColField=DataField)
oder(RowField=DataField) dann
showmessage('Alle Felder sind nicht gleich!')
anders
if (self.SouDataSet.FieldByName(ColField).DataType=ftString)
oder (self.SouDataSet.FieldByName(ColField).DataType<>ftWideString)
oder (self.SouDataSet.FieldByName(ColField).DataType<>ftFixedChar)
oder (self.SouDataSet.FieldByName(ColField).DataType<>ftMemo)
oder (self.SouDataSet.FieldByName(ColField).DataType<>ftFmtMemo) dann
beginnen
versuchen
tmpstrs:=tstringlist.Create;
Vdataset:=SouDataSet;
Vdataset.First;
for i:=0 to Vdataset.RecordCount-1 do
beginnen
if (varisnull(SouDataSet.FieldValues[colfield])=false) and (SouDataSet.FieldValues[colfield]<>'') then
wenn tmpstrs.IndexOf(SouDataSet.FieldValues[colfield])=-1 dann
beginnen
tmpstrs.Add(SouDataSet.FieldValues[colfield]);
Ende;
Vdataset.Next;
Ende;
//Dynamische Spaltentitel generieren
tmpdataset:=TClientDataSet.Create(Self);
tmpdataset.FieldDefs.Add(rowfield,ftstring,50,False);
for i:=0 to tmpstrs.Count-1 do
beginnen
mit tmpdataset.FieldDefs tun
beginnen
Add(tmpstrs.Strings[i],ftInteger,0,False);
Ende;
Ende;
tmpdataset.FieldDefs.Add('Sum',ftInteger,0,False);
DataSource:=tdatasource.Create(self);
DataSource.DataSet:=tmpdataset;
mit DataSource tun
beginnen
dataset:=Createtmptab(tmpdataset.FieldDefs);
dataset.Open;
Ende;
//Temporäre Tabelle erstellen
Vdataset.First;
for i:=0 to Vdataset.RecordCount-1 do
beginnen
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]) dann
beginnen
DataSource.DataSet.Edit;
DataSource.DataSet.FieldByName(colval).AsString:=dataval;
DataSource.DataSet.FieldByName('Sum').AsInteger:=
DataSource.DataSet.FieldByName('Sum').AsInteger+strtoint(dataval);
DataSource.DataSet.Post;
Ende
anders
beginnen
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;
Ende;
Vdataset.Next;
Ende;
result:=DataSource.DataSet;
//Kreuztabellendatensatz generieren
tmpstrs.Free;
außer
Ende;
Ende
anders
showmessage('ColField muss vom Typ String sein!');
Ende;
Ende;
Der obige Code hat den Test auf D7 und SQL Server 7.0/2000 bestanden