• 关于excel在asp.net中使用


    .Net使用excel表有两种方式,
    一种是通过oldb来进行连接,把excel表作为数据库来处理。
    另一种则是通过引用excel对象,进行对象编程来,调用excel的函数方法。

    总的来说,第一种很方便,但缺乏变化,第二种很灵活,但是,缺乏规律性。
    具体使用中,看来还是要看情况来操作。

    第一种情况,是不需要asp.net作什么额外动作,
    第二种情况,需要使用tblim.exe来将excel的com转换成为托管主件,才能在import namespace。
    其实,也可以有vs.net进行转换,更为方便。
    一旦引用excel namespace,其后的编程就能根据excel帮助里面的编程指南,调用它的对象,方法,属性等等。

    我在想,今后把它写成一个webservice可以随意从数据库中,将数据倒出来。

    the following content updated on 2005-11-23
    ===================================
    其实,我们经常适用到的还是第二种模式。
    最近我接到一个项目用到的导入Excel数据的问题,我把我的经验和代码共享出来。

    这个项目的Excel的导入假定条件是:
    1.有几个range是固定值
    2.有一个整块的数据内容区(range)
    3.可能有多个符合上面1、2要求,但具体格式不一致的Excel模板。
    4.几个不同模板可能导入不同数据库

    当时由于正在看DOTTEXT代码,对其中Provider这种模式非常感兴趣,考虑了一番认为这个Excel导入项目可以借用Provider模式。

    对Provider模式的解释


    无论源对象是什么,通过IProvider接口,我们可以得到一个较为统一的对象,也就是说同IProvider,我们屏蔽对源数据对象的处理细节,而完成得到一个符合我们要求的目的对象。

    --这段解释完全是自己的理解和体会,请大家斧正



    综合考虑后,我觉得我应该有一个对象来描述目前Excel格式内容,比如:描述固定range,描述不固定的数据块的开始地方(range),从第几列到第几列是数据区,同时定义输入限制数据类型。

    我命名这个对象为:ExcelMapDB


    /// <summary>
        
    /// ExcelMapDB 的摘要说明。
        
    /// Author:King astar
        
    /// Date:2005-10-27
        
    /// Description:用来描述Excel列对应数据列的关系
        
    /// </summary>
        
    /// 

        [Serializable]
        
    public class ExcelMapDB
        
    {
            
    private bool _isfixed = false;
            
    /// <summary>
            
    /// 是否是固定列
            
    /// </summary>
            
    /// 

            [XmlAttribute("IsFixed")]
            
    public bool IsFixed
            
    {
                
    get{return _isfixed;}
                
    set{_isfixed = value;}
            }


            
    private String _rowshowName="";
            
    /// <summary>
            
    /// 对应的datarow的显示名称是什么
            
    /// </summary>
            
    /// 

            [XmlAttribute("RowShowName")]
            
    public String RowShowName
            
    {
                
    get{return _rowshowName;}
                
    set{_rowshowName = value;}
            }



            
    private String _rowName;
            
    /// <summary>
            
    /// 对应的datarow的列名是什么
            
    /// </summary>
            
    /// 

            [XmlAttribute("RowName")]
            
    public String RowName
            
    {
                
    get{return _rowName;}
                
    set{_rowName = value;}
            }


            
    private String _excelRangeName;
            
    /// <summary>
            
    /// 如果是固定列则直接读取rangName;
            
    /// eg. A2 B3 etc.
            
    /// </summary>
            
    /// 

            [XmlAttribute("ExcelRangeName")]
            
    public String ExcelRangeName
            
    {
                
    get{return _excelRangeName;}
                
    set{_excelRangeName = value;}
            }


            
    private int _offSetStartRange;
            
    /// <summary>
            
    /// 如果是相对列,则使用相对开始列的Y轴的距离来得到值
            
    /// </summary>
            
    /// 

            [XmlAttribute("OffYSetStartRange")]
            
    public int OffYSetStartRange
            
    {
                
    get{return _offSetStartRange;}
                
    set{_offSetStartRange = value;}
            }


            
            
    public ExcelMapDB()
            
    {
                
    //
                
    // TODO: 在此处添加构造函数逻辑
                
    //
            }

        }

     序列化对象的XML

     1<?xml version="1.0" encoding="utf-8"?>
     2<ExcelMapDbRelation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" DataTableProviderType="QAComponents.Codes.Provider.BaseDataTableProvider, QAComponents.Codes" ExcelStartRangeName="A6" ConvertorType="QAComponents.Codes.Convertor.BaseConvertor, QAComponents.Codes">
     3  <RelationItems>
     4    <ExcelMapDB IsFixed="true" RowName="Temp1" ExcelRangeName="D4" OffYSetStartRange="0" />
     5    <ExcelMapDB IsFixed="true" RowName="Temp2" ExcelRangeName="L4" OffYSetStartRange="0" />
     6    <ExcelMapDB IsFixed="true" RowName="Temp3" ExcelRangeName="T4" OffYSetStartRange="0" />
     7    <ExcelMapDB IsFixed="false" RowName="SerialNo" ExcelRangeName="" OffYSetStartRange="0" />
     8    <ExcelMapDB IsFixed="false" RowName="Ith1" ExcelRangeName="" OffYSetStartRange="1" />
     9    <ExcelMapDB IsFixed="false" RowName="Vf1" ExcelRangeName="" OffYSetStartRange="2" />
    10    <ExcelMapDB IsFixed="false" RowName="Pf1" ExcelRangeName="3" OffYSetStartRange="3" />
    11    <ExcelMapDB IsFixed="false" RowName="ImPf1" ExcelRangeName="4" OffYSetStartRange="4" />
    12    <ExcelMapDB IsFixed="false" RowName="SE1" ExcelRangeName="5" OffYSetStartRange="5" />
    13    <ExcelMapDB IsFixed="false" RowName="SMSR1" ExcelRangeName="6" OffYSetStartRange="6" />
    14    <ExcelMapDB IsFixed="false" RowName="A1" ExcelRangeName="7" OffYSetStartRange="7" />
    15    <ExcelMapDB IsFixed="false" RowName="B1" ExcelRangeName="8" OffYSetStartRange="8" />
    16    
    17    
    18    <ExcelMapDB IsFixed="false" RowName="Ith12" ExcelRangeName="9" OffYSetStartRange="9" />
    19    <ExcelMapDB IsFixed="false" RowName="Vf2" ExcelRangeName="10" OffYSetStartRange="10" />
    20    <ExcelMapDB IsFixed="false" RowName="Pf2" ExcelRangeName="11" OffYSetStartRange="11" />
    21    <ExcelMapDB IsFixed="false" RowName="ImPf2" ExcelRangeName="12" OffYSetStartRange="12" />
    22    <ExcelMapDB IsFixed="false" RowName="SE2" ExcelRangeName="13" OffYSetStartRange="13" />
    23    <ExcelMapDB IsFixed="false" RowName="SMSR2" ExcelRangeName="14" OffYSetStartRange="14" />
    24    <ExcelMapDB IsFixed="false" RowName="A2" ExcelRangeName="15" OffYSetStartRange="15" />
    25    <ExcelMapDB IsFixed="false" RowName="B2" ExcelRangeName="16" OffYSetStartRange="16" />
    26    
    27    <ExcelMapDB IsFixed="false" RowName="Sen" ExcelRangeName="17" OffYSetStartRange="17" />
    28    <ExcelMapDB IsFixed="false" RowName="Vbr" ExcelRangeName="18" OffYSetStartRange="18" />
    29    <ExcelMapDB IsFixed="false" RowName="Vop" ExcelRangeName="19" OffYSetStartRange="19" />
    30    <ExcelMapDB IsFixed="false" RowName="Iop" ExcelRangeName="20" OffYSetStartRange="20" />
    31    <ExcelMapDB IsFixed="false" RowName="Io" ExcelRangeName="21" OffYSetStartRange="21" />
    32    <ExcelMapDB IsFixed="false" RowName="Gain" ExcelRangeName="22" OffYSetStartRange="22" />
    33    <ExcelMapDB IsFixed="false" RowName="FileNo" ExcelRangeName="23" OffYSetStartRange="23" />    
    34    
    35
    36  </RelationItems>
    37</ExcelMapDbRelation>

    接着我定义Excel对应数据表的关系对象
    这个对象还要考虑,它用什么转换器来转换


      1/// <summary>
      2    /// ExcelMapDB 的摘要说明。
      3    /// Author:King astar
      4    /// Date:2005-10-27
      5    /// Description:用来描述Excel表对应数据表的关系
      6    /// </summary>

      7    public class ExcelMapDbRelation
      8    {
      9        private ExcelMapDB[] _relationItems;
     10        [XmlArray("RelationItems")]
     11        public ExcelMapDB[] RelationItems
     12        {
     13            get{return _relationItems;}
     14            set{_relationItems = value;}
     15        }

     16
     17        private String _dataTableProviderType = "BaseDataTableProvider";
     18        /// <summary>
     19        /// 数据提供者类型名称
     20        /// </summary>

     21        [XmlAttribute("DataTableProviderType")]
     22        public String DataTableProviderType
     23        {
     24            get{return _dataTableProviderType;}            
     25            set{_dataTableProviderType = value;}
     26        }

     27
     28        private String _excelStartRangeName;
     29        /// <summary>
     30        /// 开始的范围;
     31        /// eg. A2 B3 etc.
     32        /// </summary>
     33        /// 

     34        [XmlAttribute("ExcelStartRangeName")]
     35        public String ExcelStartRangeName
     36        {
     37            get{return _excelStartRangeName;}
     38            set{_excelStartRangeName = value;}
     39        }
     
     40
     41        /// <summary>
     42        /// 取得数据提供者对象
     43        /// </summary>

     44        [XmlIgnore]
     45        public IDataTableProvider TableProvider
     46        {
     47            get
     48            {
     49                IDataTableProvider dprovider =null;
     50                if(DataTableProviderType!=null)
     51                {
     52                    dprovider = (IDataTableProvider)System.Activator.CreateInstance(Type.GetType(DataTableProviderType));
     53                }

     54                return dprovider;
     55            }

     56    
     57
     58
     59        }

     60
     61        private String _convertorType ;
     62        /// <summary>
     63        /// 转换器类型名称
     64        /// </summary>

     65        [XmlAttribute("ConvertorType")]
     66        public String ConvertorType
     67        {
     68            get{return _convertorType;}
     69            set{_convertorType = value;}
     70        }

     71
     72        /// <summary>
     73        /// 取得转换器对象
     74        /// </summary>

     75        [XmlIgnore]
     76        public IConvertor DataConvertor
     77        {
     78            get
     79            {
     80                IConvertor convertor =null;
     81                if(ConvertorType!=null)
     82                {
     83                    convertor = (IConvertor)System.Activator.CreateInstance(Type.GetType(ConvertorType));
     84                }

     85                return convertor;
     86            }

     87    
     88
     89
     90        }

     91
     92        
     93
     94        constructor
    102    }

    103    


    作了这些基础工作后,我考虑可以来写转换器的工作了,这部分工作是核心工作,在这部分数据会从Excel导入到数据库去。
    看看接口

    1/// <summary>
    2    /// IConvertor 的摘要说明。
    3    /// </summary>

    4    public interface IConvertor
    5    {
    6
    7        void Execute(DataTable dt,ExcelMapDB[] excelMapdbs,String fileName,String excelStartRangeName,int IdentityID);
    8    }

    只有一个Excute的方法参数分别是Excel对应关系对象,Excel文件路径,excel开始range名称,此Excel表唯一ID

    然后,我写了一个BaseConvertor, 主要工作就是打开Excel文件,按照定义的Excel列与数据表列对应关系对象来抓数据,并导入到数据库中去。
    请参看代码(注意:打开Excel的方法是Excel11.0版本,office 2003)

      1
      2    /// <summary>
      3    /// BaseConvertor 的摘要说明。
      4    /// Author:King astar
      5    /// Date:2005-10-27
      6    /// Description:核心类,将Excel数据导入数据库,是基类,可以继承
      7    /// </summary>

      8    public class BaseConvertor : IConvertor
      9    {
     10
     11        variable
     26
     27
     28        public BaseConvertor()
     29        {
     30            //
     31            // TODO: 在此处添加构造函数逻辑
     32            //
     33        }

     34
     35        IConvertor 成员
     60
     61        public virtual void Openexcel(String fileName)
     62        {
     63            string FileName = @fileName;
     64            FileName = FileName.Replace("/",@"\");
     65            FileName = FileName.Replace(@"\\",@"\");
     66
     67
     68            if(!System.IO.File.Exists(FileName))
     69                throw new Exception("["+FileName+"]不存在!");
     70
     71            try
     72            {
     73                app = new  Excel.ApplicationClass();
     74            }

     75            catch(System.Exception ex)
     76            {
     77                new Exception("无法实例化Excel对象;<br/>details:<hr size=1/>"+ex.Message);
     78            }

     79            app.DisplayAlerts = false;
     80
     81//            //app.UserControl = true;
     82            wbs = app.Workbooks;
     83            try
     84            {
     85                
     86                wbc  = wbs.Open(FileName,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt,_objOpt);            
     87            }

     88            catch(System.Exception ex)
     89            {
     90                throw new Exception("无法正确打开文件;<br/>details:<hr size=1/>"+ex.Message);
     91            }

     92
     93
     94        }

     95        public virtual void Dispose()
     96        {
     97            fixedRange =null;
     98            firstRange = null;
     99            ws = null;
    100            wbc = null;
    101                        
    102            if(wbs!=null)
    103            {
    104                wbs.Close ();
    105                wbs = null;
    106            }

    107            if(app!=null)
    108            {
    109                app.Quit();
    110                app =null;
    111            }

    112            
    113                
    114            
    115
    116        }

    117
    118        public System.Data.DataTable  FillTable(System.Data.DataTable myTable,QAComponents.Codes.Configs.ExcelMapDB[] excelMapdbs,string excelStartRangeName)
    119        {
    120            ws= (Excel.Worksheet)wbc.Worksheets.get_Item(1);
    121            firstRange = ws.get_Range(excelStartRangeName.Trim().ToUpper(),this._objOpt);
    122            int x =0;
    123            x = Convert.ToInt32(excelStartRangeName.Trim().ToUpper().Substring(
    1241,1));
    125            //开始循环
    126            while(firstRange.Value2!=null&&firstRange.Value2.ToString()!="")
    127            {
    128                
    129                System.Data.DataRow dr = myTable.NewRow();
    130                
    131                for(int i=0;i<excelMapdbs.Length;i++)
    132                {
    133                    try
    134                    {
    135                        if(excelMapdbs[i].IsFixed)
    136                        {
    137                            fixedRange = ws.get_Range(excelMapdbs[i].ExcelRangeName.Trim().ToUpper(),this._objOpt);
    138                            dr[excelMapdbs[i].RowName] = ConverData(dr.Table.Columns[excelMapdbs[i].RowName].DataType,fixedRange.Value2);
    139                        }

    140                        else
    141                        {
    142                            dr[excelMapdbs[i].RowName]    = ConverData(dr.Table.Columns[excelMapdbs[i].RowName].DataType,
    143                                firstRange.get_Offset(_objOpt,excelMapdbs[i].OffYSetStartRange).Value2);
    144
    145#if DEBUG
    146                            object Checkvalue1 = firstRange.get_Offset(_objOpt,excelMapdbs[i].OffYSetStartRange).Value2;
    147#endif
    148                        }

    149                    }

    150                    catch(System.Exception ex)
    151                    {
    152                        throw new Exception(         
    153                            String.Format("<font color=red><b>导入数据失败</b></font><br/>附件编号:<b>{0}</b><br/>错误位置:X={1};Y(相对于开始格)={2};对应RowName:{3}<br/>details:<hr size=1/>{4}",
    154                            this._identity,
    155                            x,
    156                            excelMapdbs[i].OffYSetStartRange,
    157                            excelMapdbs[i].RowName,
    158                            ex.Message));
    159
    160
    161                    
    162                    }

    163                }

    164                
    165
    166                //myTable.Rows.Add(dr);
    167                dr["SummaryID"= this._identity;
    168                ImportDataRow(dr);
    169
    170
    171                x++;
    172                firstRange  = firstRange.get_Offset(1,_objOpt);
    173#if DEBUG
    174                object Checkvalue2 = firstRange.Value2;
    175#endif
    176                
    177
    178            }

    179            return myTable;
    180            
    181
    182        }

    183
    184        public virtual void ImportDataRow(DataRow row)
    185        {
    186            BaseDAL b = new BaseDAL();
    187            b.ConfigTable(row.Table.TableName,"ID");
    188            b.Add(row);
    189        }

    190
    191        ConverData 
    217
    218
    219
    220    }


    至此Excel导入核心的介绍就完毕了,
    抛开代码不说,解决问题的方法还是很简单。

    1. 描述Excel的数据对应关系
    2. 根据对应关系,进行数据转换。

    解决这种问题的根本是要有良好的抽象能力,将实际事务转换为一些可以用代码描述的对象。
    呵呵。。。

    另外补充的是这种方式也可以用以导出Excel, 由您自由想像了。






     

  • 相关阅读:
    Cg:访问OpenGL的状态
    C++ Exception Handling
    C语言的调用规约(Calling Convension)之参数传递和返回值
    Why is FBX readonly in animation editor when imported?
    如何在Visual Studio中编译wxWidgets
    ICU字符集编码转换一例
    VisTools
    关于数值分析和LCP问题的一些开源项目
    C++: The Case Against Global Variables
    老男孩筷子兄弟
  • 原文地址:https://www.cnblogs.com/king_astar/p/1149.html
Copyright © 2020-2023  润新知