CSDN에서 유명 히어로들의 글을 자주 읽고 많은 도움을 받았습니다. 최근 프로젝트를 진행하면서 크로스탭을 사용해야 하는데, 고객께서 그리드에서 작동 가능하게 해달라고 요청하셨습니다. 크로스탭을 구현하기 위해 일반 쿼리에 사용하는 코드는 어쩔 수가 없어서 다른 분들에게 영감을 줄 수 있기를 바라면서 올립니다. 유명한 영웅들의 조언.
함수 CreateTmptab(const AFieldDefs:TFieldDefs):TDataSet;
var
TempTable:TatClientDataSet;
시작하다
임시테이블:=nil;
결과:=nil;
AFieldDefs<>nil이면
시작하다
노력하다
TempTable:=TatClientDataSet.Create(응용 프로그램);
TempTable.FieldDefs.Assign(AFieldDefs);
TempTable.CreateDataSet;
결과:=(TempTable as TDataSet);
제외하고
TempTable<>nil인 경우
TempTable.Free;
결과:=nil;
들어올리다;
끝
끝;
끝;
{
SouDataset 소스 데이터 세트
ColField 크로스탭 동적 열 필드
RowField 크로스탭 행 필드
DataField데이터 필드
}
함수 GenCrossTable(SouDataset:tdataset;ColField,RowField,DataField:string):tdataset;
var
Vdataset:t데이터세트;
tmpdataset:tatclientdataset;
데이터소스:t데이터소스;
tmpstrs:tstrings;
rowval,colval,dataval:문자열;
i,j:정수;
데이터 유형:TFieldType;
데이터 크기:정수;
시작하다
결과:=nil;
if (ColField='') 또는(RowField='')또는(DataField='') then
showmessage('모든 필드는 NULL이 아닙니다!')
또 다른
시작하다
if(ColField=RowField)
또는(ColField=DataField)
또는(RowField=DataField) 다음
showmessage('모든 필드가 동일하지 않습니다!')
또 다른
if (self.SouDataSet.FieldByName(ColField).DataType=ftString)
또는 (self.SouDataSet.FieldByName(ColField).DataType<>ftWideString)
또는 (self.SouDataSet.FieldByName(ColField).DataType<>ftFixedChar)
또는 (self.SouDataSet.FieldByName(ColField).DataType<>ftMemo)
또는 (self.SouDataSet.FieldByName(ColField).DataType<>ftFmtMemo)
시작하다
노력하다
tmpstrs:=tstringlist.Create;
Vdataset:=SouDataSet;
Vdataset.First;
i:=0에서 Vdataset.RecordCount-1로 수행
시작하다
if (varisnull(SouDataSet.FieldValues[colfield])=false) 및 (SouDataSet.FieldValues[colfield]<>'') then
tmpstrs.IndexOf(SouDataSet.FieldValues[colfield])=-1이면 다음
시작하다
tmpstrs.Add(SouDataSet.FieldValues[colfield]);
끝;
Vdataset.Next;
끝;
//동적 열 제목 생성
tmpdataset:=TClientDataSet.Create(Self);
tmpdataset.FieldDefs.Add(rowfield,ftstring,50,False);
i:=0에서 tmpstrs.Count-1로 수행
시작하다
tmpdataset.FieldDefs를 사용하면
시작하다
Add(tmpstrs.Strings[i],ftInteger,0,False);
끝;
끝;
tmpdataset.FieldDefs.Add('Sum',ftInteger,0,False);
데이터소스:=tdatasource.Create(self);
DataSource.DataSet:=tmpdataset;
DataSource를 사용하면
시작하다
데이터 세트:=Createtmptab(tmpdataset.FieldDefs);
데이터세트.열기;
끝;
//임시 테이블 생성
Vdataset.First;
i:=0에서 Vdataset.RecordCount-1로 수행
시작하다
rowval:=SouDataSet.fieldbyname(rowfield).AsString;
colval:=SouDataSet.fieldbyname(colfield).AsString;
dataval:=SouDataSet.fieldbyname(datafield).AsString;
dataval=''이면 dataval:='0';
if DataSource.DataSet.Locate(rowfield,rowval,[loPartialKey]) then
시작하다
데이터소스.DataSet.Edit;
DataSource.DataSet.FieldByName(colval).AsString:=dataval;
DataSource.DataSet.FieldByName('Sum').AsInteger:=
DataSource.DataSet.FieldByName('Sum').AsInteger+strtoint(dataval);
데이터소스.DataSet.Post;
끝
또 다른
시작하다
데이터소스.DataSet.Append;
DataSource.DataSet.FieldByName(rowfield).AsString:=rowval;
j:=1에서 DataSource.DataSet.Fields.Count-1로 수행
DataSource.DataSet.Fields[j].AsCurrency:=0;
DataSource.DataSet.FieldByName(colval).AsString:=dataval;
DataSource.DataSet.FieldByName('Sum').AsString:=dataval;
데이터소스.DataSet.Post;
끝;
Vdataset.Next;
끝;
결과:=DataSource.DataSet;
//크로스탭 데이터 세트 생성
tmpstrs.Free;
제외하고
끝;
끝
또 다른
showmessage('ColField는 문자열 유형이어야 합니다!') ;
끝;
끝;
위 코드는 D7 및 SQL Server 7.0/2000에서 테스트를 통과했습니다.