A menudo leo los artículos de héroes famosos en CSDN y me beneficié mucho. Recientemente, estaba trabajando en un proyecto y necesitaba usar una tabla cruzada. Hay una tabla cruzada en el informe, pero el cliente solicitó que fuera operable en Grid. No tuve más remedio que escribirlo yo mismo. Se utiliza un fragmento de código para consultas generales para realizar la tabla cruzada. No me atrevo a usarlo exclusivamente, así que lo subo con la esperanza de que pueda inspirar a otros. Dame algunos consejos de héroes famosos.
función CreateTmptab(const AFieldDefs:TFieldDefs):TDataSet;
var
Tabla Temporal:TatClientDataSet;
comenzar
Tabla temporal:=nil;
Resultado:=nulo;
si AFieldDefs<>nil entonces
comenzar
intentar
TempTable:=TatClientDataSet.Create(aplicación);
TempTable.FieldDefs.Assign(AFieldDefs);
TempTable.CreateDataSet;
Resultado:=(TempTable como TDataSet);
Excepto
si TempTable<>nil entonces
TempTable.Gratis;
Resultado:=nulo;
aumentar;
fin
fin;
fin;
{
Conjunto de datos de origen de SouDataset
Campo de columna dinámica de tabla cruzada ColField
Campo de fila de tabla cruzada RowField
Campo de datosCampo de datos
}
función GenCrossTable(SouDataset:tdataset;ColField,RowField,DataField:string):tdataset;
var
Vdataset:tdataset;
tmpdataset: tatclientdataset;
Fuente de datos:tdatasource;
tmpstrs:tstrings;
valor de fila, colval, valor de datos: cadena;
i,j:entero;
tipo de datos: TFieldType;
Tamaño de datos: entero;
comenzar
resultado:=nulo;
si (ColField='') o (RowField='')o(DataField='') entonces
showmessage('¡Todos los campos no son NULL!')
demás
comenzar
si (CampoCol=CampoFila)
o (ColField=Campo de datos)
o (RowField = DataField) entonces
showmessage('¡Todos los campos no son iguales!')
demás
si (self.SouDataSet.FieldByName(ColField).DataType=ftString)
o (self.SouDataSet.FieldByName(ColField).DataType<>ftWideString)
o (self.SouDataSet.FieldByName(ColField).DataType<>ftFixedChar)
o (self.SouDataSet.FieldByName(ColField).DataType<>ftMemo)
o (self.SouDataSet.FieldByName(ColField).DataType<>ftFmtMemo) entonces
comenzar
intentar
tmpstrs:=tstringlist.Create;
Vdataset:=SouDataSet;
Vdataset.Primero;
para i:=0 a Vdataset.RecordCount-1 hacer
comenzar
si (varisnull(SouDataSet.FieldValues[colfield])=false) y (SouDataSet.FieldValues[colfield]<>'') entonces
si tmpstrs.IndexOf(SouDataSet.FieldValues[colfield])=-1 entonces
comenzar
tmpstrs.Add(SouDataSet.FieldValues[colfield]);
fin;
Vdataset.Siguiente;
fin;
//Generar títulos de columnas dinámicas
tmpdataset:=TClientDataSet.Create(Self);
tmpdataset.FieldDefs.Add(campo de fila,ftstring,50,False);
para i:=0 a tmpstrs.Count-1 hacer
comenzar
con tmpdataset.FieldDefs hacer
comenzar
Agregar(tmpstrs.Strings[i],ftInteger,0,False);
fin;
fin;
tmpdataset.FieldDefs.Add('Suma',ftInteger,0,False);
Fuente de datos:=tdatasource.Create(self);
DataSource.DataSet:=tmpdataset;
con DataSource hacer
comenzar
conjunto de datos:=Createtmptab(tmpdataset.FieldDefs);
conjunto de datos. Abierto;
fin;
//Crear tabla temporal
Vdataset.Primero;
para i:=0 a Vdataset.RecordCount-1 hacer
comenzar
rowval:=SouDataSet.fieldbyname(rowfield).AsString;
colval:=SouDataSet.fieldbyname(colfield).AsString;
dataval:=SouDataSet.fieldbyname(campo de datos).AsString;
si valordedatos='' entonces valordedatos:='0';
si DataSource.DataSet.Locate(rowfield,rowval,[loPartialKey]) entonces
comenzar
Fuente de datos.Set de datos.Editar;
DataSource.DataSet.FieldByName(colval).AsString:=dataval;
DataSource.DataSet.FieldByName('Suma').AsInteger:=
DataSource.DataSet.FieldByName('Suma').AsInteger+strtoint(dataval);
Fuente de datos.DataSet.Post;
fin
demás
comenzar
Fuente de datos.DataSet.Append;
DataSource.DataSet.FieldByName(campo de fila).AsString:=rowval;
para j:=1 a DataSource.DataSet.Fields.Count-1 hacer
DataSource.DataSet.Fields[j].AsCurrency:=0;
DataSource.DataSet.FieldByName(colval).AsString:=dataval;
DataSource.DataSet.FieldByName('Suma').AsString:=dataval;
Fuente de datos.DataSet.Post;
fin;
Vdataset.Siguiente;
fin;
resultado:=DataSource.DataSet;
//Generar conjunto de datos de tabla cruzada
tmpstrs.Gratis;
excepto
fin;
fin
demás
showmessage('¡ColField debe ser de tipo cadena!');
fin;
fin;
El código anterior pasó la prueba en D7 y SQL Server 7.0/2000.