样例测试代码下载:ReportVeiwer实现多语言样例
由于使用了MS的ReportViewer来做报表,项目上线又会跨地区,故多语言的问题在所难免。
对于ReportViewer的多语言在网上已有不少文章,这里所描述的也是参考网上的一些思路而成。
现在,我所知道的对于ReportViewer的多语言的解决方案只有三种:
1.通过编写多语言的RDLC(ReportViewer所承载的报表定义文件),然后根据不同的语言编程实现加载不同语言的报表定义文件,如Report.ZH-CN.rdlc等。
【缺点:后续需要修改报表的情况下,需要同步修改多份报表定义,增加维护的难度】
2.通过把所有在Report中显示的所有标识类文本,都提出来作为参数的方式传递给报表,这样传进来的参数的值实现多语言就行了。
【缺点:增加编写报表定义和编程的一些难度,参数列表会比较冗繁,维护难度也有所增加】
3.通过修改报表定义文档内容后,再通过ReportViewer动态加载报表定义来实现多语言。
【缺点:修改报表定义是通过把RDLC当作XML文档来读取并修改相应的XMLNode节点内容,所以在性能方面有所损耗】
对于1,2和3,这三种解决方案,对于熟悉ReportViewer报表的朋友来说,前1和2的方案基本上是毫无问题,测试例子也相当容易,对于3的方案,则有些陌生。这里,我也是为了记录3方案所做的测试和例子进行标记。
通过利用ReportViewer.LocalReport.LoadReportDefinition()函数,动态加载报表定义,该函数支持从MemoryStream中加载报表定义,同时RDLC文件是标准的XML文档.
至于我们如何定义在报表中需要进行多语言转换的标识文本呢,我们知道RDLC中的TEXTBOX文本会有一个Name的属性,我们会根据Name属性和Resource中的Key的值对应起来,这样我们就很清晰明确地知道哪些文本是需要转换成多语言的。
【建议:对于存储在Resource中的信息,最好跟Report的ID关联起来,如Key的ID取名为ReportName_lbl0001,这样我们就知道ReportName中的lbl0001对应于Resource文档中的哪一个值。】
Dim xmldoc As New XmlDocument
'对XML文档的方式读取RDLC文档
xmldoc.Load(Server.MapPath("~") + "/Report.rdlc")
Dim hashTran As New Hashtable
'RDLC控件的Name和Resource的Key值对
hashTran("textbox3") = "V0001"
hashTran("textbox4") = "V0002"
hashTran("textbox5") = "V0003"
hashTran("textbox1") = "V0004"
hashTran("textbox2") = "V0005"
'遍历XML文档中的节点和转换成多语言的值
TraversalXMLNodes2Translate(xmldoc, hashTran, "ReportResource")
xmldoc.Save(ms)
ms.Position = 0
Me.ReportViewer1.LocalReport.ReportPath = String.Empty
'动态加载报表定义
Me.ReportViewer1.LocalReport.LoadReportDefinition(ms)
2 For Each node As XmlNode In pXmlDoc.DocumentElement.ChildNodes
3 If node.HasChildNodes Then
4 TraversalXMLChildrenNodes2Translate(node, pHash, pResourceFile)
5 End If
6 Next
7 End Sub
Try
Dim strValue As String = String.Empty
If TypeOf (pNode) Is XmlElement And pNode.Name.ToUpper.Equals("TEXTBOX") Then
strValue = pNode.Attributes("Name").Value
For Each node As XmlNode In pNode.ChildNodes
If node.Name.ToUpper.Equals("VALUE") Then
If node.InnerText.Trim.Length > 0 _
AndAlso node.InnerText(0) <> "=" _
AndAlso pHash IsNot Nothing _
AndAlso pHash.Contains(strValue) Then
strValue = GetValueFromResourceFile(pResourceFile, pHash(strValue))
If Not String.IsNullOrEmpty(strValue) Then
node.InnerText = strValue
End If
End If
Exit For
End If
Next
ElseIf pNode.HasChildNodes Then
For Each cNode As XmlNode In pNode.ChildNodes
TraversalXMLChildrenNodes2Translate(cNode, pHash, pResourceFile)
Next
End If
Catch ex As Exception
End Try
End Sub
Try
Return CStr(GetGlobalResourceObject(pResourceFile, key))
Catch ex As Exception
Return String.Empty
End Try
End Function