500分求中国式交叉表(0分)

  • 主题发起人 主题发起人 wazhqi
  • 开始时间 开始时间
W

wazhqi

Unregistered / Unconfirmed
GUEST, unregistred user!
A表
损耗类型 损耗名称
01 aaa
02 bbb
03 ccc
...
nn nnn

B表
项目名 子项目名 损耗类型 损耗数量 损耗金额
A aa 01 10 100
A aa 02 10 100
A aa 03 20 250
A aa 01 10 100
A bb 01 10 30
B cc 01 10 40
....
....
现按项目,子项目,统计分类汇总如下
损耗类型
项目名 子项目 aaa个数 aaa损耗数 aaa金额 bbb的个数 bbb损耗数 bbb金额 ...金额和
A aa 1 10 100 1 10 100 550
bb 1 10 100 100
A总计 2 20 200 1 10 100 650
B....
...
合计 ...
 
用fastreport可以实现比你的更为复杂的Cross报表,我做过,当然不是用fastreport的cross,而是用userDatabase...
 
To jc_wwp
你是怎样解决的?
 
先用华表编辑,然后在Delphi中添加cell组件联接即可。
 
偶也是用华表解决问题……
 
后面的 bbb的个数 bbb损耗数 bbb金额
是什么意思?难道重复的值就要无限往后面加字段?
 
用RM+脚本可以处理任何报表。
 
可以任意个,根据A表来定,A表的记录数不会多于6个
 
To kkyy
你能给一点提示吗
 
因为RM可以在脚本里面提出所需要的数据分析运算,然后填到需要的地方去,当然FR也可以,
 
能否详细说说,有没有示例呀
 
是不是用友的华表呀?
你们可不可以把做好的报表发给我们看看?
oasisllz@21cn.com
 
用友的那个好用吗?..
各位谁用过"速达"软件自带的那个报表编辑器?
 
转过来一个BCB的,希望对你有帮助
交叉表控件组说明

交叉表控件组说明
一> 简介
本控件是一个用于交叉表数据的显示/录入/打印的小控件.
特别适合于:
1>如服装行业的订单中常用的规格/颜色/数量这样的交叉格式数据录入
2>按二个字段分组统计的结果显示与打印,如按年度,销售员分组统计个人业绩,那么用本控件来显示和打印将是方便之极.
其他尚待各位发掘,呵呵!
本控件的发布版本包括部分源码.如果你同意后面的声明,你可以对这些源码进行修改或重新继承写新的控件.
二> 快速入门
安装后会在Additional2页上出现数个控件TCrossDataSet, TACrossDataSet, TIACrossDataSet, TCrosswwDBGrid, TCrossGridReport.其中后面三个才是最常用的,他们相互搭配,即可完成交叉表数据的读取/写入,显示/编辑,打印.此三控件提供了源代码,可自行修改扩充功能后安装.
(首先必须放上连接后台数据库的控件,本处以ADO为例,先放ADOConnection和ADOQuery,并设置好连接和SQL)
在窗体上分别放上上述三个控件各一个,再放上FrReport页上的frDBDataSet一个.这样总计放四个控件,设置他们之间的关联:
IACrossDataSet1.CrosswwDBGrid := CrosswwDBGrid1
frDBDataSet1.DataSet := IACrossDataSet1
CrossGridReport1.CrossfrDBDataSet := frDBDataSet1
CrossGridReport1.CrosswwDBGrid := CrosswwDBGrid1
读取: IACrossDataSet1.ReadFromDataSet(ADOQuery1,'颜色','规格','数量');
写入: IACrossDataSet1.WritetoDataset(ADOQuery1,'颜色','规格','数量');
打印:
CrossGridReport1.LoadFromFile(ExtractFilePath(Application.ExeName)
+'1.frf');
CrossGridReport1.ShowReport;
{
上面一行是预览,如果直接打印用
CrossGridReport1.PrepareReport;
CrossGridReport1.PrintPreparedReport('',1,true,frall);
}
够简单吧,当然这只是最简单的使用,事实上本组控件提供了相当多的事件,属性,方法用于精确控制,不过这样费时就要多一点了.
三>类继承关系
交叉表(数据集)
TCustomClientDataSet
|
|--TCustomCrossDataSet
|
|---TCrossDataSet
|
|---TCustomACrossDataSet
|
|-- TACrossDataSet
|
|----TIACrossDataSet
打印
TfrReport
|
|- TCrossGridReport
网格
TwwDBGrid
|
|- TCrosswwDBGrid
数据源
TDataSource
|
|---TIDataSource
其他
TComponent
|
|-- TInterDataSetTotal
|- TFieldFormat
三>类型说明
TCrossFieldType = (CftSmallint, CftInteger, CftWord, CftLargeint, CftAutoInc, CftCurrency, CftBCD, CftFloat, CftBoolean, CftDate, CftTime, CftDateTime,
CftTimeStamp, CftBlob, CftMemo, CftGraphic, CftWideString, CftString);
//交叉表控件所支持的字段类型
TFieldTotalMethod = (FTM_MIN, FTM_MAX, FTM_SUM, FTM_AVG, FTM_COUNT, FTM_COUNTNOTNULL, FTM_AVGNOTNULL, FTM_MAXNOTNULL, FTM_MINNOTNULL, FTM_UNKNOWN);
//内置合计器支持的合计方法,带有NOTNULL表示忽略空值(NULL值)
TCCDFdKind = (ccdRow, ccdData, ccdCalculated, ccdOther);
//字段类型,在很多事件中有这样类型的参数.分别表示字段是行,数据,计算(合计),或其他类型.
TNumFieldType = CftSmallint..CftFloat;
TIntNumFieldType = CftSmallint..CftAutoInc;
TRealNumFieldType = CftCurrency..CftFloat;
TSecWrite = (swOverWrite, swSkip, swAddValue);
//当交叉表从数据集读取数据时如果读到一条重复记录时如何进行处理.分别为覆写,跳过,相加(对NumFieldTypes数值型)或连接(CftWideString, CftString),字串连接的话则支持分隔字串
TSpecRowCol = (srAll, srOnlySpecRowCol, srOnlyDataSetRowCol);
//当交叉表从数据集读取数据时如何构造行列.分别是自身结构合并读取到的行列,仅仅自身指定的行列,仅仅读取的行列.请注意当读取完毕后,自身行列结构将自动更新当前的行列结构
四>常量,变量与函数
calcmethodlist: array[0..8] of string = ('min', 'max', 'sum', 'avg', 'count',
'countnotnull', 'avgnotnull', 'maxnotnull', 'minnotnull');
//内置合计器目前支持的合计方法
NumFieldTypes = [CftSmallint, CftInteger, CftWord, CftLargeint, CftAutoInc,
CftCurrency, CftBCD, CftFloat];
IntNumFieldTypes = [CftSmallint, CftInteger, CftWord, CftLargeint, CftAutoInc];
RealNumFieldTypes = [CftCurrency, CftBCD, CftFloat];
FTClass: array[CftSmallint..CftString] of TFieldClass =
(TSmallIntField, TIntegerField, TWordField, TLargeintField, TAutoIncField,
TCurrencyField, TBCDField, TFloatField, TBooleanField, TDateField,
TTimeField, TDateTimeField,
TSQLTimeStampField, TBlobField, TMemoField, TGraphicField, TWideStringField,
TStringField);
function TCFT2TFT(value: TCrossFieldType): TFieldType;
function TFT2TCFT(value: TFieldType): TCrossFieldType;
// TcrossFieldType与TfieldType相互转换
function GetFieldType(FieldClass: TfieldClass): TFieldType;
//根据FieldClass得到TFieldType
procedure ClearRepeatLine(var str: string);
overload;
procedure ClearRepeatLine(v: TStrings);
overload;
//清除重复行和空行
function InterTotalMethod2String(ftm: TFieldTotalMethod): string;
function String2InterTotalMethod(mdn: string): TFieldTotalMethod;
//内置统计方法与字符串转换
{下面四函数用于根据交叉表数据来控制wwDBGrid的外观}
function CalcwwDBGridHeight(Self: TwwDBGrid;
MaxRow: Integer = 0;
MaxCol: Integer = 0): Integer;
//计算TwwDBGrid的高度
function CalcwwDBGridWidth(Self: TwwDBGrid;
MaxCol: Integer = 0): Integer;
//计算TwwDBGrid的宽度
procedure ApplyTitleSet(Self: TwwDBGrid;
ACrossDataSet1: TCustomCrossDataSet;
DataHeadStr: string;
CalcHeadStr: string = '');
//自动设置TwwDBGrid的列头
procedure UpdatewwGridFooter(Self: TwwDBGrid;
TotalValue: Variant);
//根据内置统计器的统计值更新TwwDBGrid的页脚
function GetTextWidth(Font: TFont): Integer;
//根据字体测算单字宽度
function PixelTotMM(V: Integer): Integer;
function tMMToPixel(V: Integer): Integer;
//象素与十分之一MM相互转换(fastreport)
function GetColumnWd(Grid: TCrosswwDBGrid;
Index: Integer;
Locate: Integer;
Font: TFont;
ColorPrint: boolean): Integer;
//根据列号计算宽度
function CalcfrFormat(Field: TField;
var Format: Integer): string;
//根据字段类别和DisplayFormat来取得对应的frReport的Format/FormatStr
五>类简单说明
TACrossDataSet = class(TCustomAcrossDataSet)
public
{ Public declarations }
procedure RefreshTotal;
//刷新内部合计器的值
procedure InsertCol(Col: string;
Index: Integer;
defaultvalue: Variant);
//插入新列,Index<=0自动放到数据列的最后,缺省值可为空(NULL)
procedure DeleteCol(Col: string);
//删除列
procedure InsertRow(Row: Variant;
defaultvalue: Variant);
//插入行
procedure DeleteRow(Row: string);
//删除行
function RowExist(Row: string): boolean;
function ColExist(Col: string): boolean;
//判断行列是否存在
function SumTotalValue(FieldList: string;
TotalMode: string): Variant;
//进行记录合计(合计所有行的值), FieldList, TotalMode是以#13或’;’分隔的字段列表和合计方法列表,返回的Variant是一个Extended数组
function CreateEmpty: boolean;
//创建交叉表,数据均为空,创建前Rowlists允许为空串
procedure ApplyFieldFormat;
//引发设置交叉表字段格式事件
function IsDataField(Field: TField): boolean;
//判断一个字段是否是一个数据列字段
function SumDataField(Mode: string): Extended;
//合计计算字段,仅对数值型字段有效,mode合计方法,如’sum’,一般在计算事件中调用
function IsInterCalc(CalcMethod: string): boolean;
//判断合计方法是否一个内部支持的合计方法
function ReadFromDataSet(const ADataSet: TDataSet;
const RowField, ColField, DataField: string): boolean;
function WritetoDataset(const ADataSet: TDataSet;
const RowField,
ColField, DataField: string): boolean;
//从数据集读取和写入数据
published
{ Published declarations }
property SpecRowColMode;
//指定读取数据时如何合并现有行列与读取到的行列
property ActionSecWrite;
//指定在读取到重复数据的时候如何动作
property SpaceString;
//如果读取到重复记录,并且数据是字符串, ActionSecWrite为连接(swAddValue)时,字串连接的分隔符
property AutoDelDataSetOriRec;
//写入数据集时自动删除数据集原来数据,缺省为true,一般来说如果数据重要,要注意在写入前进行数据库事务控制.讲究效率的话,关联的数据集应设置为缓冲更新.
property AutoClearSelfData;
//写完后是否自动清除自身数据
property BeforeReadFromDataSet;
//读取数据前的事件,可以在此控制初始行列等等
property AfterReadFromDataSet;
//读取完毕后的事件
property BeforeWriteToDataset;
//写回数据集前的事件,一般就在此开始数据库事务
property AfterWriteToDataset;
//写回数据集完毕后的事件
property OnWriteOneRecToDataSet;
//写回数据集的事件,当写交叉表的一条数据到数据集时,可以根据双方的条件来控制是否写入(Skip)
property OnReadOneRecFromDataSet;
//从数据集读取数据的事件,意义与上面相似,可以根据条件控制是否读取此条记录
property WriteOtherField;
//一般来说,原数据集不一定只有交叉表的三个字段,这里提供写数据集的其他字段的机会
property OnReadRowFromDataSet;
property OnReadDataFromDataSet;
property OnReadColFromDataSet;
//从数据集读取数据时的事件,可以改变读取后的值,如原来是TdataTime,可以将其转为交叉表的字符串格式.
property OnWriteRowToDataSet;
property OnWriteDataToDataSet;
property OnWriteColToDataSet;
//写入数据集的事件,意义与上面相似,只是反过来而已
property OnReadDataSetError;
//读取数据发生错误时的事件,请注意,读取时如果发生错误不会产生异常,请在此重新Raise异常,参数中包括一个异常对象
property OnWriteDataSetError
//写回数据集发生错误时的事件,说明同上;
//------------------------------------
property DefaultDataFieldFormat;
property DefaultRowFieldFormat;
property DefaultCalcFieldFormat;
//分别为缺省的数据字段类,行字段类,计算字段类的格式,如设置DisplayWidth,DisplayFormat,小数位数等
property RowFieldName;
//行字段名
property ColFieldClass;
//列字段类,缺省为BCD
property CalcFieldClass;
//计算字段类,缺省为BCD
property RowFieldClass;
//行字段类,缺省为String
property CalcLists;
property ColLists;
property RowLists;
{计算字段,列,行列表.注意计算字段略有不同,为字段名=计算方法形式,如
小计=sum
平均=avgnotnull
字段名不可省,但计算方法可以省,如果计算方法为空或非内置计算方法,将引发自定义计算事件
}
property InterDataSetTotaler;
//内置的合计器,可设置计算字段,数据字段,行字段缺省的合计方法
//事件
property OnGetFieldClass;
//生成交叉表字段时提供改变缺省字段类的机会.一般不需使用
property OnSetFieldFormat;
//设置字段格式的事件,提供机会改变字段的缺省格式
property OnCustomCalcFields;
//自定义计算字段的计算事件,若计算字段的计算方法为空或非内置方法,就会引发此事件
property OnGetFieldTotalMethod;
//提供根据具体字段来改变合计方法的事件
property OnUpdateTotalValue;
//更新合计值的事件,一般用于更新相关的Grid的页脚合计数据,其参数若非空(NULL),则为一个Extended数组,是各字段的所有行的合计值
{
其它事件,属性,方法等是从TCustomClientDataSet继承来,请参考TcustomClientDataSet的类说明
}
end;

TIACrossDataSet = class(TACrossDataSet)
published
{ Published declarations }
property AllowInsert;
//允许插入,一般来说,交叉表还是通过InsertRow来插入行为好,所以缺省为False
property CrosswwDBGrid;
//关联的TCrosswwDBGrid,本控件可以在数据发生变化时自动控制关联的TCrosswwDBGrid的外观
property OnFormatTotalV;
//格式化统计值时的事件,可以根据统计字段和统计值控制格式化后的字串
{
其它事件,属性,方法等是从TACrossDataSet继承来,请参考TACrossDataSet的类说明
}
end;

TCrossGridReport = class(TfrReport)
Public
procedure BuildTo(frReport: TfrReport;
NStarty: Integer;
NPageIndex: Integer);
//将交叉表的报表Build到另一个报表或自身上,指定Y向起始位置和报表页号.一般用于将多个交叉表用同一个CrossGridReport来打印的时候使用,在CrossGridReport的 AfterBuild中调用其他要打印的交叉表打印控件的BuildTo方法
Published
property CrosswwDBGrid: TCrosswwDBGrid;
//要打印的TCrosswwDBGrid
property CrossfrDBDataSet: TfrDBDataSet;
//打印TCrosswwDBGrid要用到TfrDBDataSet,它的DataSet指向必须与CrosswwDBGrid指向的交叉表数据集相同
property Starty: Integer;
{
打印Y向位置,交叉表将打印在指定页,此属性控制起始位置
在设计报表时查看一下报表页中拟打印交叉表位置的Y坐标即可.注意在此位置后面保留一定的空间供交叉表报印使用,否则可能会出现报表重叠
}
property PageIndex: Integer;
//指定交叉表打印到哪一个报表页
property PageCenter: Boolean ;
//交叉表在报表页中水平位置自动居中
property AfterBuild: TNotifyEvent ;
//报表Build后的事件,可以在此再调用其他CrossGridReport的BuildTo方法,将另外的交叉表打印到自身
property ViewVertiMargin: Integer;
//打印效果控制,每个打印的frMemoView 的Y向预留空白
property ColorPrint: Boolean;
//是否支持彩色打印
property BooleanFormat: string
//bool字段的格式,以:分隔True/False,参考fr的boolean值打印方式
{
其他属性事件方法请参考TfrReport
}
end;

TCrosswwDBGrid = class(TwwDBGrid);
public
{ Public declarations }
procedure RefreshHeight;
procedure RefreshWidth;
procedure ApplyTitle;
//刷新行高,列高,应用列头,一般不需调用,因为它会自动控制
published
property IACrossDataSet: TIACrossDataSet;
//关联的交叉表数据集
property MaxRow: Integer;
//最多显示的行数,如果为0,则无限制,高度将无限制
property MaxCol: Integer;
//最多显示的列数,如果为0,则无限制,宽度将无限制
property IncHeight: Integer;
//用于精确调整高度,缺省为0
property IncWidth: Integer;
//用于精确调整宽度,缺省为,以上二属性一般不需设置
property DataHeadStr: string;
//数据字段的分组头字串
property CalcHeadStr: string;
//计算字段的分组头字串
property RowFont: Tfont;
property DataFont: Tfont;
property CalcFont: TFont;
property RowHeadFont: TFont;
property DataHeadFont: TFont;
property DataGroupFont: TFont;
property CalcHeadFont: TFont;
property CalcGroupFont: TFont;
property RowFooterFont: TFont;
property DataFooterFont: Tfont;
property CalcFooterFont: TFont
property CalcColor: TColor ;
property RowColor: Tcolor;
property DataColor: TColor;
//无须多说,一看就知
property AutoColExitPost: Boolean;
//每个单元格的值改变(移出)后自动更新合计值与统计值,如果为false,只有移动到另外一行时才会更新,缺省为true
{
其他属性,事件,方法请参考TwwDBGrid
}
end;

五>版权声明
本控件组是由Lynu (罗应飞)个人开发的,网友可以免费使用于商业和非商业场合,但未经作者允许,不得对基类(TCustomCrossDataSet, TCustomACrossDataSet)作任何修改.对其他控件作过修改或从其他控件类进行继承都必须同时发送修改后的版本和新的控件给原作者.
Lynu联系方式: Email:Lynu@yeah.net 主页:http://www.51bcb.com QQ:970861
2002-09-20

 
拷,这么长给谁看呀。
解决方法:
1。sql法
2。临时表法
3。报表法 (fr)
 
文明点好吗?
 
说500分,这里连个屁也没有,不是骗人吗?
 
打PP!
还没有结贴
 
接受答案了.
 

Similar threads

回复
0
查看
1K
不得闲
D
回复
0
查看
890
DelphiTeacher的专栏
D
D
回复
0
查看
858
DelphiTeacher的专栏
D
D
回复
0
查看
808
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部