序章:建多个报表实现多语言怎么样?
要实现报表的多语言支持,比如要支持中英文,往往我们会考虑建2个报表,运行时让程序去选择加载哪一个版本的报表,来实现多语言.
比如我们可以建2个dataset相同的报表:employee_en.rdlc,employee_cn.rdlc
那么运行的时候动态设定reportViewer的ReportPath就可以:如下
ok,这样实现了多语言支持,但是每当需要修改报表的时候,你会发现很恼火,每次都需要同时修改2个文件,即时调整一个column的位置,为了保持统一,你也要去修改2次,而当你忘了修改其中一个文件的时候,问题就大条了,2个版本的报表不一致.
分析
如果只需要1个rdlc文件,运行时动态翻译报表就好了.有没有可能呢,我们来建一个报表employee.rdlc,打开这个rdlc文件看下,如图:
发现了没,这完全是一个标准的xml文档,报表的所有的信息都在xml内,那么我们直接修改xml内的信息,完全可以依我们需求随意编辑这个报表,当然翻译不再话下.
怎么让reportViewer加载xml文档作为报表呢,可以采用reportViewer.LocalReport.LoadDefinition(MemoryStream ms) 的方式来加载xml文档,首先把xml文档保存为memoryStream数据流,然后传递给LocalReport就实现了动态加载xml文档,如下图.
下面的问题就是xml的翻译问题了,rdlc文字不管是body还是header,footer,文字都以textbox 节点
保存在xml文档里,如下为其中一个textbox
宽高等子节点我们不需要去处理,子节点元素value就是报表上的文字,就是我们需要处理.
在Textbox的vlaue数值可以分为4类,
1类是空的:如<Value/>,就是不会显示在报表上,可以跳过
2类是数据:如<Value>=Fields!EmployeeNo.Value</Value>,这些是报表数据,跳过,注:第一个字符为"="
3类是文本:columnName也是文本,如<Value>EmployeeNo</Value>,这些正是我们需要翻译的.注:第一个字符没有"="号
4类是文本+数据:如<Value>="Time:"+Globals!ExecutionTime</Value>,双引号引的为文本,我们需要跳出里面的文本,来翻译.
我们需要的翻译后2种,首先把rdlc作为xml文档读取,通过xml的xpath来获得所有Value非空的TextBox 节点
注意:由于rdlc使用的是特定的namespace,所有我们在使用xpath查询的时候必须先添加这个namespace,如下:
遍历这些节点,如果节点Value为文本,直接翻译,如果为文本加数据,通过正则表达式获得文本再翻译,代码如下:
xml翻译完成,剩下的就是把xml保存为Memory Stream,并传递给reportViewer,代码如下:
ok,最后的代码就是普通的插入数据,设置格式,显示报表了,
来,看下成果吧,
中文版:
英文版: