Я часто читал статьи известных героев на CSDN и получил большую пользу. Недавно я работал над проектом, и мне нужно было использовать кросс-таблицу. В отчете есть кросс-таблица, но заказчик попросил, чтобы ее можно было использовать в Grid. У меня не было другого выбора, кроме как написать его самому. Часть кода используется для общего запроса, чтобы реализовать кросс-таблицу. Я не осмеливаюсь использовать его исключительно, поэтому загружаю его в надежде, что он может вдохновить других. мне несколько советов от известных героев.
функция CreateTmptab(const AFieldDefs:TFieldDefs):TDataSet;
вар
Темптабле: татклиентдатасет;
начинать
TempTable: = ноль;
Результат: = ноль;
если AFieldDefs<>nil, то
начинать
пытаться
TempTable:=TatClientDataSet.Create(приложение);
TempTable.FieldDefs.Assign(AFieldDefs);
TempTable.CreateDataSet;
Результат:=(TempTable как TDataSet);
Кроме
если TempTable<>nil, тогда
TempTable.Free;
Результат: = ноль;
поднимать;
конец
конец;
конец;
{
Исходный набор данных SouDataset
Поле динамического столбца кросс-таблицы ColField
Поле строки кросс-таблицы RowField
Поле данных DataField
}
функция GenCrossTable(SouDataset:tdataset;ColField,RowField,DataField:string):tdataset;
вар
Vdataset:tdataset;
tmpdataset:tatclientdataset;
Источник данных: tdatasource;
tmpstrs: tstrings;
rowval, colval, dataval: строка;
я, j: целое число;
тип данных: TFieldType;
Размер данных: целое число;
начинать
результат: = ноль;
если (ColField='') или (RowField='') или (DataField=''), то
showmessage('Все поля не равны NULL!')
еще
начинать
если (ColField=RowField)
или(ColField=ПолеДанных)
или(RowField=DataField), тогда
showmessage('Все поля не равны!')
еще
если (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;
Вдатасет.Первый;
для i:=0 до Vdataset.RecordCount-1 сделать
начинать
если (varisnull(SouDataSet.FieldValues[colfield])=false) и (SouDataSet.FieldValues[colfield]<>''), то
если tmpstrs.IndexOf(SouDataSet.FieldValues[colfield])=-1, то
начинать
tmpstrs.Add(SouDataSet.FieldValues[colfield]);
конец;
Вдатасет.Следующий;
конец;
//Генерируем динамические заголовки столбцов
tmpdataset:=TClientDataSet.Create(Self);
tmpdataset.FieldDefs.Add(rowfield,ftstring,50,False);
для i:=0 до tmpstrs.Count-1 сделать
начинать
с tmpdataset.FieldDefs сделайте
начинать
Добавить(tmpstrs.Strings[i],ftInteger,0,False);
конец;
конец;
tmpdataset.FieldDefs.Add('Sum',ftInteger,0,False);
DataSource:=tdatasource.Create(self);
DataSource.DataSet:=tmpdataset;
с источником данных сделать
начинать
набор данных: = Createtmptab (tmpdataset.FieldDefs);
набор данных.Открыть;
конец;
//Создаем временную таблицу
Вдатасет.Первый;
для i:=0 до Vdataset.RecordCount-1 сделать
начинать
rowval:=SouDataSet.fieldbyname(rowfield).AsString;
colval:=SouDataSet.fieldbyname(colfield).AsString;
dataval:=SouDataSet.fieldbyname(поле данных).AsString;
если dataval='', то dataval:='0';
если DataSource.DataSet.Locate(rowfield,rowval,[loPartialKey]), то
начинать
Источник Данных.НаборДанных.Редактировать;
DataSource.DataSet.FieldByName(colval).AsString:=dataval;
DataSource.DataSet.FieldByName('Sum').AsInteger:=
DataSource.DataSet.FieldByName('Sum').AsInteger+strtoint(dataval);
Источник Данных.НаборДанных.Пост;
конец
еще
начинать
Источник Данных.НаборДанных.Добавить;
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;
Источник Данных.НаборДанных.Пост;
конец;
Вдатасет.Следующий;
конец;
результат: = DataSource.DataSet;
//Создаем набор данных перекрестной таблицы
tmpstrs.Бесплатно;
кроме
конец;
конец
еще
showmessage('Поле ColField должно иметь тип String!') ;
конец;
конец;
Приведенный выше код прошел проверку на D7 и SQL Server 7.0/2000.