实现 ActiveReports 的本地化报表(非Viewer本身)!

不是指ActiveReports Viewer 本身的本地化哦!指报表数据的本地化.

用过 ActiveReports for .Net (以下简称AR)的都知道它的优势(可代码化),这样就提供了很多报表功能开发的空间给程序员。

不多说了,下面将通过我的一个EPR软件来介绍一下实现 AR 2.0 的报表本地化功能(主要通过UI贴图+讲解方式):

开发环境:VS2005 .Net 2.0 + C# + SQL2005 + AR 2.0

=========================================================

讲解一下如何实现这几种本地化语言: 

1,报表预定义(快速!) [Default] 

   就是指实例化报表时不应用本地化设置;

2,CIMS本地化设置(推荐!)(System)

   随主系统的本地化设置一样;

3,简体中文(Chinese Simplified)

4,繁体中文(Chinese Traditional)

ReportLocal 类 定义一个属性:

public   bool  CanActive
{
  
get return  m_canActive;}
  
set { m_calActive  =  value;}
}

这个属性在ReportLocal类实例化代入,来自主系统用户权限控制,如果你的程序没有相关权限控制可忽略。

这个Active属性用来表示将要使用的本地化语言:

  ///   <summary>  
 
///  获取当前报表本地化设置('CIMS本地化设置' 除外) 
 
///   </summary>  
public  ReportLocalizableEnum Active 

   
get  
   { 
        
if  (CanActive  ==   false )   return  ReportLocalizableEnum.Default; 
        
if  (m_active  ==  ReportLocalizableEnum.System) m_active  =  GetReportLocalizableWithSystem;

        
return  m_active;   // 来自存储参数
  } 

这些属性,函数很关键,主要收集可以本地化的报表组件(未定义DataField属性的):

     ///   <summary>  
    
///  要本地化的报表控件集合,用于OnInitControlsCollection()函数。 
  
///  参数:Key = Control.Name
    
///  参数:Value = 控件(Label;TextBox,CheckBox...) 
    
///   </summary>  
public  Hashtable Collection {  get  {  return  rptControls; } } 

public  Hashtable CreateReportControls(DataDynamics.ActiveReports.ActiveReport rpt,  string  sectionNameOrType) 

    
if  (rpt  ==   null )   return   null

    Hashtable ctrls 
=   new  Hashtable(); 
    Section rs 
=   null
    
    
bool  all  =  (sectionNameOrType  ==  UnknownSection  ||   string .IsNullOrEmpty(sectionNameOrType)); 
    
// 所有报表区域 
     if  (all  ==   false ) { 
       
        try 
        { 

            SectionType type 
=  (SectionType)System.Enum.Parse( typeof (SectionType), sectionNameOrType,  true ); 

            foreach ( rs in rpt.Sections) 

            { 
                
if (rs.Name == sectionNameOrType)   break
     
            if (type == rs.Type)    break;
            }

        }
        catch { 
                all 
= true
                
break
            } 

    } 
    
    
if (all || (rs == null)) { 
        
foreach ( rs in rpt.Sections) 

        { 
            AddControlsInfo(rs, ctrls); 
        } 
    } 
    
else  {AddControlsInfo(rs, ctrls); } 
    
    
return  ctrls; 


private   void  AddControlsInfo(Section section, Hashtable collections) 

    SectionType type 
=  section.Type; 
    ARControl ctrl; 
    
foreach  ( ctrl  in  section.Controls) { 
        
if  ( string .IsNullOrEmpty(ctrl.DataField)  ==   false )    continue
          
        
// 只收集没有是定义DataField属性的组件! 
    ReportControlInfo ctrlInfo  =   null
        
if  (ctrl  is  Label) 
        { 
            Label lab 
=  (Label)ctrl; 
            ctrlInfo 
=   new  ReportControlInfo(lab.Text); 
        } 
        
        
else   if  (ctrl  is  TextBox) { 
            TextBox txt 
=  (TextBox)ctrl; 
            
if  ( string .IsNullOrEmpty(txt.Text))   continue

            ctrlInfo 
=   new  ReportControlInfo(txt.Text);  // TextBox类型必须是设置了Text的!
        } 
        
else   if  (ctrl  is  CheckBox) { 
            CheckBox chk 
=  (CheckBox)ctrl; 
            
if  ( string .IsNullOrEmpty(chk.Text))     continue
           
           
 ctrlInfo  =   new  ReportControlInfo(chk.Text); //CheckBox类型必须是设置了Text的! 
            
        } 
        
        
if  ((ctrlInfo  !=   null )) 
        { 
            ctrlInfo.DataField 
=   this .GetDataField(ctrlInfo.Text,  string .Empty); 
            ctrlInfo.Section 
=  type; 
            ctrlInfo.Parent 
=  ctrl.Parent; 
            collections.Add(ctrl.Name, ctrlInfo); 
        } 
        
    } 


///   <summary>  
///  根据组件的Name返回关联本地化设置的‘字段名’,仅判断一些常用的。 
///   </summary>  
///   <param name="controlText"> 组件.Text </param>  
///   <param name="defaultField"> 默认使用的‘字段名’,一般为空,需要后续修正 </param>  
protected   string  GetDataField( string  controlText,  string  defaultField) 

    
if  (controlText.IndexOf( " ted By " >   - 1 ) { 
        
return  DBColumns.CreatedBy; 
    } 
    
else   if  (controlText.IndexOf( " red By " >   - 1 ) { 
        
return  DBColumns.PreparedBy; 
    .......
// 根据你的报表来添加判断,主要是用于后面的BatchCreate功能,避免手功添加


这是ReportControlInfo类(用于收录组件的相关参数):

public   class  ReportControlInfo 

    
protected string m_text; 
    
protected string m_dataField; 
    
protected object m_section; 
    
protected object m_parent; 
    
public ReportControlInfo(string text) 
    

        m_text 
= text; 
    }
 
    
public ReportControlInfo(string text, object section) 
    

        m_text 
= text; 
        m_section 
= section; 
    }
 
    
public ReportControlInfo(string text, string dataField) 
    

        m_text 
= text; 
        m_dataField 
= dataField; 
    }
 
    
    
/// <summary> 
    
/// 获取或设置 组件预定义了的文本 
  
/// </summary> 

    public string Text 
        
get return m_text; } 
        
set { m_text = value; } 
    }
 
    
    
/// <summary> 
    
/// 获取或设置 用于关联本地化设置的‘字段名’ 
  
/// </summary> 

    public string DataField 
        
get return m_dataField; } 
        
set { m_dataField = value; } 
    }
 
    
    
/// <summary> 
    
/// 获取或设置 组件的父容器(PageHeader,GroupHeader...),一般可不设置 
  
/// </summary> 

    public object Parent 
        
get return m_parent; } 
        
set { m_parent = value; } 
    }
 
    
/// <summary> 
    
/// 获取或设置 组件所在的节(Report.Section),可以是SectionName OR SectionType 
    
/// </summary> 

    public object Section 
        
get return m_section; } 
        
set { m_section = value; } 
    }
 
    
}
 

=================================

下面将是实现“报表本地化关联”功能的核心:

为于实现报表同主系统使用一致的本地化定义,下面部分是必须的!

系统的本地化资源编辑器(由于此ERP的应用关系,编辑器中增加了对应用人的权限控制),源代码不提供:

这是 关联系统本地化设置 的报表本地化配置器:

解释一下各字段作用:

所属区域:指要本地化的组件所在的Section,如果为空,则为公共设置,任何报表都会搜索这些关联设置;

字段名:一般为数据表的ColumnName,要同“本地化编辑器”里的DataField定义一致;

组件名:将本地化的AR.Control,应于实际报表设计时一致,如果报表做了更改,可使用“批量修复”功能来自动修复refContrlName;

默认文本:AR.Control 预定义的Text,如果用户想始终使用这个DefaultText,只需要定义后钩选“仅使用默认标题”;

备注:不用解释了。

“报表效果预览”只是应用了最上面的参数设置。

下面,录制了一个“批量创建”报表组件的本地化关联设置的动画(文件太大!只能用GIF格式上传了,UI有失真):

索引关联设置类:

using  System;
using  System.Text;
using  System.Data;
using  System.Data.SqlClient;

namespace  CIMS.Report
{
    
public class ReportsLocalization : IDisposable
    
{
        
Const

        
Variables

        
Init

        
Properties

        
Localizable

        
IDisposable
    }

}

通过上面一些定义,就可以在实例化报表时实现本地化报表了!

先收集本地化组件到Collection,然后遍历集合并:

// GetLocalText函数很重要!

rptTest rpt 
=   new  rptTest(...);

ReportLocal reportLocal 
=   new  ReportLocal( true );

reportLocal.OnInitControlsCollection();

IDictionaryEnumerator ie 
=  collection.GetEnumerator();
while  (ie.MoveNext())
{
    
string  controlName  =  ie.Key.ToString();
    
string  localText  =   reportLocal.GetLocalText(controlName); // 得到本地化资源
   if ( string .IsNullOrEmpty(localText))  continue ;

    ARControl ctrl
=  (ARControl)((ReportControl)ie.Value).Control;
    
if ( ctrl  is  Label)
     
    ((Label)ctrl).Text
=  localText ; // 设置Text属性完成本地化
   else   if  ......

}

最终报表本地化预览:

 繁体报表结果预览:

英文报表本地化结果(BUG: SubReport 还不能本地化):

猜你喜欢

转载自blog.csdn.net/3tzjq/article/details/2068022