Slash

习惯在追逐的过程中不断去完善自己;当你不再去追逐,你自我完善的脚步也就停滞下来了。

导航

Winform中使用CrystalReports

1,结合系统中数据结构的特点,打印模块详细内容主体采用有链接关系的子报表及主从表为解决方案。同时对于目前遇到的关于uniqueidentifier类型不能作为链接字段,统一采用djh替代(主从表),从而实现目录表与内容表的1对多关系。
2,数据源的处理,使用xsd架构文件,同时编程获取对应数据填充至数据集,加载报表。各种文件关系为rpt:form:xsd=1:1:1
3,用户界面设计 
        打印:直接执行打印,不显示打印设置对话框,通过加载xml文件中页面格式信息执行相关打印。
   
打印预览:需要先加载对应xml文件信息。显示报表效果,同时视情况决定是否显示相应工具栏或分组树。
   
打印设置:继续使用前期版本窗体,执行对应设置信息的XML文件加载/保存。
    
输出:选定相应的文件格式存储输出。
4,窗体复用性,对于各窗体的打印操作,可以直接传递对应的打印对象:报表文件,对应的DataSet数据源及xsd架构文件即可实现窗体的高度复用。
尚未解决:关于用户自定义设置显示字段问题,在报表中的同步显示控制尚未有解决思路。

自定义打印设计方案:
        1, 打印或打印预览时先根据主关键字读取对应的xml文件中的设置信息。
        2,  若无对应设置信息,则给出提示设置。若正确获取设置信息则执行对应的报表属性赋值过程,以设置相关打印格式,边距等属性。
各种打印设置操作均在PrintOptions类中进行操作。
打印设置中当前系统需要设置的信息列表如下:

属性名称

说明

备注

打印机名称

纸张来源

纸张类型

(纸张)宽度

(纸张)高度

打印方向

横向,纵向

打印范围

全部,或选择部分页打印

打印份数

以下为打印页面设置

上边距

下边距

左边距

右边距

左偏移量

上偏移量

上边界

下边界

左边界

右边界

页眉

页脚

打印设置属性赋值方案:
1,获取系统中打印机信息,若系统没有配置打印机,提示告警,中止运行。
2,已获取系统配置打印机,则继续读取xml格式文件,按预定义内容分别设置。
        a.若与系统预配打印机不符,则删除
   
b.找到对应打印机,对相应的打印信息进行设置。
   
c.对纸张类型初始化,设置等。
Xml配置文件说明:

///PrintSetup.xml文档说明

           
///1.缺省打印参数:由主菜单->基础信息->打印参数设置统一配配置,    ds.TableName="defaultPrint"

           
///2.窗口打印参数:由各窗体->打印参数设置 分别配置,             ds.TableName="窗口.Name"(this.msTN)

           
///3.默认打印机: 每个窗口对应一个默认打印机, 存放于"DefaultPrint";

           
///

           
///代码编写规则:

           
///1.缺省打印参数始终存在, 该参数由系统发布时预置,以表的记录形式存放,用户可以自定义

           
///2.窗口对应打印参数内的"极限边界"始终取缺省参数,即每次调用时同步刷新


待解决:
由于打印设置操作的保存与加载时所用的名字空间不同,一些枚举值也相应产生冲突,故需要重新建立打印设置信息保存窗体,使用CrystalReports中对应的名字空间以保证各属性信息的统一。
注意:CrystalReports中以百分之一英寸为单位。
英寸与厘米的换算关系

//换算单位

/* = = = = = = = = = = = = = = = = *"

| 换算一下计量单位,将其换算成厘米 |

|    厘米     PBU     英寸          |

|     1        38     0.395         |

|   0.026       1      0.01         |

|    2.54      96        1          |

"* = = = = = = = = = = = = = = = = */

厘米:cm   英寸:in (Inch)         PB UNIT

//报表导出为文件操作
private void ExportToDisk (string fileName)

{

   
// 声明变量并获取导出选项。

   ExportOptions exportOpts 
= new ExportOptions();

   DiskFileDestinationOptions diskOpts 
= 

   
new DiskFileDestinationOptions();

   exportOpts 
= Report.ExportOptions;

  
// 设置导出格式。

   exportOpts.ExportFormatType 
= ExportFormatType.RichText;

   exportOpts.ExportDestinationType 
= 

   ExportDestinationType.DiskFile;

   
// 设置磁盘文件选项。

   diskOpts.DiskFileName 
= fileName;

   exportOpts.DestinationOptions 
= diskOpts;

   
// 导出报表。

   Report.Export ();

}

同时使用SaveFileDialog类进行保存地址,文件类型选择操作
修改处:打印设置中的打印份数存在读取赋值问题,需要更正以保持设置的一致性。
对于账单登记中可能存在三个表的打印情况,且考虑到crystal Reports对uniqueidentifier类型的不支持,故可能采用间接办法实现打印模块。
    1,使用两套打印窗体,同时判断subJoin中数据记录数决定是否使用哪套打印窗体
    2,使用主从表功能,同时架构文件中包含三个表,分别建立起链接关系,三个表之间的链接.
典型错误及常见问题:
未找到项目:
    1,可能是由于尚未生成对应的数据集,即有时可能已经完成架构文件的新建,但并没有执行保存操作;
    2,没有重新登陆/注销数据库的登陆,即当前使用数据集仍然是原来的数据,没有更新,这是也需要重新刷新当前数据链接。
给子报表传递数据你可以通过单独用代码绑定子报表来解决这个问题

string sConnectionString = ConfigurationSettings.AppSettings["dbCommISMS"];
SqlConnection sqlConn 
= new SqlConnection(sConnectionString);
SqlCommand sqlComm 
= new SqlCommand();
SqlDataAdapter dataAdapter 
= new SqlDataAdapter(); 
sqlConn.Open();

sqlComm.Connection 
= sqlConn;
sqlComm.CommandType 
= CommandType.Text; 
dataAdapter.SelectCommand 
= sqlComm;
Dataset1 dataSet 
= new Dataset1();
string sSQL = "SELECT * FROM T_REQUEST WHERE APPLI_ID = '" + appli_id + "'";
sqlComm.CommandText 
= sSQL;
dataAdapter.Fill(dataSet, 
"T_REQUEST"); 
sSQL 
= "SELECT * FROM T_REQUEST_INSPECTION WHERE APPLI_ID = '" + appli_id + "'";
sqlComm.CommandText 
= sSQL;
dataAdapter.Fill(dataSet, 
"T_REQUEST_INSPECTION"); 
sSQL 
= "SELECT * FROM T_ACCEPT_INSPECTION WHERE APPLI_ID = '" + appli_id + "'";
sqlComm.CommandText 
= sSQL;
dataAdapter.Fill(dataSet, 
"T_ACCEPT_INSPECTION"); 

SubreportObject oSubreport1 
= oRpt.ReportFooterSection1.ReportObjects["Subreport1"as SubreportObject;
ReportDocument oSub1 
= oSubreport1.OpenSubreport("Inspection"); 
oSub1.SetDataSource(dataSet);
SubreportObject oSubreport2 
= oRpt.ReportFooterSection2.ReportObjects["Subreport2"as SubreportObject;
ReportDocument oSub2 
= oSubreport1.OpenSubreport("Survey"); 
oSub2.SetDataSource(dataSet);
SubreportObject oSubreport3 
= oRpt.ReportFooterSection2.ReportObjects["Subreport3"as SubreportObject;
ReportDocument oSub3 
= oSubreport1.OpenSubreport("Allonge"); 
oSub3.SetDataSource(dataSet);

oRpt.SetDataSource(dataSet);

oViewer.ReportSource 
= oRpt;

oRpt 有三个字报表,dataSet 有三个表。
上述代码通过访问每个字报表,来实现子报表数据绑定.
同时也可根据以下代码给子报表提供数据源,赋值过程:

ReportDocument rep=new rpt.zdml();

              Sections crSections
=rep.ReportDefinition.Sections;

              SubreportObject subObject;

              ReportDocument subReportDoc;

              

              
foreach(Section sec in crSections)

              
{

                  ReportObjects repObjects
=sec.ReportObjects;

                  
foreach(ReportObject repObject in repObjects)

                  
{

                     
if(repObject.Kind ==ReportObjectKind.SubreportObject)

                     
{

                         subObject
=(SubreportObject)repObject;

                         subReportDoc
=subObject.OpenSubreport(subObject.SubreportName);

                         
string sName=subReportDoc.Name;

                         
if(subReportDoc.Name =="zdnr.rpt")

                         
{

                            subReportDoc.SetDataSource(dsNR);

                         }


                     }


                  }


              }

打印页面自定义表格设置
同时设置表格各定位属性,精确定义每个框对象的位置,同时添加对应数据库字段。
注:数据库中更改记录:为实现不同表之间的关联关系,同时避免uniqueidentifier类型的不支持性,特别更改视图v_gn2_ZdSubJoin中添加字段djh作为与V_gn2_zdml的链接关系。
注: 报表尚不能正常显示问题依旧。有待解决。同时在crystal reports中的null或””的处理方法,一般情况下,Crystal Reports 在公式中遇到空值字段时,会立即停止公式求值而不产生任何值。若要处理公式中的空字段值,则必须使用专门用于处理空字段值的特殊函数进行显式处理。这些函数包括:IsNullPreviousIsNull NextIsNull(msdn) 所以需要对可能出现的null进行手动处理,示例代码如下:

//isnull({v_gn2_Zdml.je_xf},0) + isnull({v_gn2_Zdml.je_swpc},0) + isnull({v_gn2_Zdml.je_zj},0)

if isnull({v_gn2_Zdml.je_xf}) then

    
0

else

    
{v_gn2_Zdml.je_xf}

+

if isnull({v_gn2_Zdml.je_swpc}) then

    
0

else

    
{v_gn2_Zdml.je_swpc}

+

if isnull({v_gn2_Zdml.je_zj}) then

    
0

else

{v_gn2_Zdml.je_zj}

打印设置窗体中有待修正处:
uOSLandScape_ValueChanged 中的图片选择所以值存在问题,
    针对打印的具体设置,一些打印机具有自定义大小,通过获取对象的数值,可以进行自定义页面大小打印设置,同时系统中若某页面不存在对应的打印参数设置信息,则需要先调用系统默认值,然后才能进行详细参数设置。
报表页脚及页脚设计规范:
    将单据相关状态设为报表页脚,如(单据状态,审核人,制单人等信息)
同时将当前登录信息设置为页脚以使各纸张均有对应系统登录信息,如(当前登录单位,时间,当前操作员等信息).
    页脚内容不包含在报表文件的数据集中,故在此使用动态传递参数以改变报表中各文本内容。
同时对于打印预览窗体中,采用ValueList动态传递参数及对应的对象名称,以便对各特定打印窗体传递数据。
Crystal reports Bug:
   
对于被报表文件中传递动态文本参数时,若给文本对象(TextObjects)重新赋值时存在一个问题:即若该对象的当前文本值与新值存在相同形如(old:操作员,new:操作员编号……),则会产生未将对象设置到引用的实例错误。

posted on 2007-09-16 15:26  Slash  阅读(1226)  评论(0编辑  收藏  举报