六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 35|回复: 0

C# 根据模版写Excel(Com)二

[复制链接]

升级  22%

23

主题

23

主题

23

主题

秀才

Rank: 2

积分
83
 楼主| 发表于 2013-1-27 04:44:44 | 显示全部楼层 |阅读模式
《C# 根据模版写Excel(Com)一 》   里给出写Excel的主要类
 
这里给出2个辅助类。
这2个类用来 读Excel模版的xml描述文件
和 写入Excel的sheet 用的
 
/// <summary>/// 根据数据结果集,修改临时文件内容/// </summary>/// <param name="ds">要传入到Excel的数据集</param>/// <returns></returns>private void writeExcelContent(Object o){        try        {                        ExcelObj.Visible = false;            ExcelDescriptions a = new ExcelDescriptions();            Hashtable templateXml = a.parseXml(templateDiscriptionFilePath);                        WookSheetWrite wStW = new WookSheetWrite(xSt);            wStW.setWorksheet(o, templateXml);        ...........} 就是这个 方法里 用到的 2个类
 
首先是读Excel模版的xml描述文件的类
using System;using System.Data;using System.Configuration;using System.Linq;using System.Xml.Linq;using System.Xml;using System.Collections.Generic;using System.Collections;using System.Reflection;/// <summary>/// 解析Excel模版对应的xml描述文件/// </summary>public class ExcelDescriptions{                             /// <summary>    /// 解析模版描述文件到 Hashtable    /// </summary>    /// <param name="descriptionFilePath">解析模版描述文件 全名</param>    /// <returns>包含模版描述文件信息的    ///     Hashtable: key:字段名 或 类名,    ///               value:对应模版文件坐标(例如:A1), 或 一个Hashtable    ///          当key为类名时, value:为一个Hashtable;    ///     这个关系 最多为二层    /// </returns>    public Hashtable parseXml(string descriptionFileName)    {        Hashtable templateXml = new Hashtable();        XmlDocument xmlDoc = new XmlDocument();                try{            //xmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "xml/Template1.xml");            xmlDoc.Load(descriptionFileName);        } catch(Exception ex){                           throw new Exception("没有找到模版描述文件");        }        //每个 Excel模版对应一个 描述文件 table节点 是唯一的        XmlNode xn = xmlDoc.SelectSingleNode("table");        XmlNodeList xnl = xn.ChildNodes;                //因为只有2层 所以就直接写在这里了        foreach (XmlNode xnf in xnl)        {            XmlElement xeOuter = (XmlElement)xnf;                        //map 的key为 字段名, 或类名;            //      value为 对应的模版的单元格的 坐标. 例如:A1            if (xeOuter.HasChildNodes)            {                //内层 Hashtable                //Hashtable: key:字段名                //          value:对应模版文件坐标(例如:A1),                //内层Hashtable 不可以再 包含Hashtable                Hashtable templateXmlInner = new Hashtable();                XmlNodeList xnlInner = xeOuter.ChildNodes;                foreach (XmlNode xnfInner in xnlInner)                {                    XmlElement xeInner = (XmlElement)xnfInner;                    templateXmlInner.Add(xeInner.GetAttribute("filed").ToString().Trim(),                        xeInner.GetAttribute("coordinates").ToString().Trim());                }                templateXml.Add(xeOuter.GetAttribute("filed").ToString().Trim(),                    templateXmlInner);            }            else            {                templateXml.Add(xeOuter.GetAttribute("filed").ToString().Trim(),                    xeOuter.GetAttribute("coordinates").ToString().Trim());            }                    }        return templateXml;    }    } 
 
对应的xml文件, 这个文件是自己定义的
<?xml version="1.0" encoding="utf-8" ?><table name="User">    <Cell coordinates="A1" filed="name"></Cell>    <Cell coordinates="A2" filed="sex"></Cell>    <Cell coordinates="B1" filed="age"></Cell>    <Cell coordinates="B2" filed="id"></Cell>    <Cells filed="car">        <Cell coordinates="B20" filed="id"></Cell>        <Cell coordinates="E20" filed="name"></Cell>    </Cells>    <Cells filed="address">        <Cell coordinates="D37" filed="id"></Cell>        <Cell coordinates="D38" filed="name"></Cell>    </Cells></table> 
 
然后是写入Excel文件的类
 
using System;using System.Data;using System.Configuration;using System.Linq;using System.Web;using System.Web.Security;using Excel = Microsoft.Office.Interop.Excel;using System.Collections;using System.Collections.Generic;using System.Text.RegularExpressions;using System.Reflection;/// <summary>/// 根据模版文件, 描述信息 和 数据集/// 写Excel 的 sheet/// </summary>public class WookSheetWrite{    private object missing = System.Reflection.Missing.Value;    //工作Sheet    private Excel._Worksheet xSt;    public WookSheetWrite(Excel._Worksheet _xSt)     {        if (_xSt == null)        {            throw new Exception("目标 Excel 的 sheet对象 为空");        }        else        {            this.xSt = _xSt;        }    }    /// <summary>    /// 根据模版, 模版描述文件的 Hashtable, 以及数据对象来填充Excel    /// </summary>    /// <param name="dataObject">数据集对象,     ///         这里的数据集对象 为 linq查出来的实体对象,    ///         该实体对象可能包含另外一个或多个实体对象,     ///         或 另外一个或多个实体对象的List。    /// </param>    /// <param name="templateXml">装载模版描述文件的信息的 Hashtable    ///         该Hashtable    ///     Hashtable: key:字段名 或 类名,    ///               value:对应模版文件坐标(例如:A1), 或 一个Hashtable    ///          当key为类名时, value:为一个Hashtable;    ///     这个关系 最多为二层    /// </param>    public void setWorksheet(Object dataObject, Hashtable templateXml)    {        if(dataObject == null)        {            throw new Exception("数据集对象为空");        }                        foreach (string filedName in templateXml.Keys)        {            Object value = templateXml[filedName];            if (value == null)            {                throw new Exception("指定的数据集的属性:" + filedName + " 为空");            }            if (value is Hashtable)            {                //如果sheet对象里包含 循环结构                //dataObject数据集里 对应的一个List                Object innerDataObject = getFiled(dataObject, filedName);                if (innerDataObject is IList)                {                    setCells(value, (IList)innerDataObject);  //数据集属性类型 为一个List                }                else                 {                    setCells(value, innerDataObject);  //数据集属性类型 为一个实体对象                }            }            else            {                string coordinates = value.ToString();                string data = getFiled(dataObject, filedName).ToString();                xSt.get_Range(coordinates, missing).Value2 = data;            }        }    }        /// <summary>    /// 填充一组单元格。这组单元格有如下特征:    /// 1,这些单元个的字段组合起来是一个类的属性    /// 2,这些单元个顺序排列在一行里    /// 3, 这些单元个所在行的接下来几行的值,可以通过循环填充    /// </summary>    /// <param name="value">    ///             Hashtable里指定key对应的 值, 这里仍然是一个Hashtable    ///             存放的是,key:特定对象的属性名, value:对应的坐标</param>    /// <param name="innerList">    ///             指定数据集对象里包含的IList对象,    ///             IList里包含的对象就是 value 里的属性对应的对象    /// </param>    private void setCells(Object value, IList innerList)    {        Hashtable templateXmlInner = (Hashtable)value;        //循环IList 填充行        for (int i = 0; i < innerList.Count; i++)        {                            Object innerObject = innerList[i];            //循环Hashtable填充单元格组            foreach (string filedNameInner in templateXmlInner.Keys)            {                string coordinates = templateXmlInner[filedNameInner].ToString();                //对应单元个的行坐标                string innerNum = getRowNo(coordinates);                //将行坐标+i返回,第一次为第一行, 第二次为第二行,循环填充                coordinates = coordinates.Replace(innerNum, (int.Parse(innerNum) + i).ToString());                //这里还没有判断 模版预留行数量小于 数据数量的情况                //取得对应单元格的数据                string dataInnert = getFiled(innerObject, filedNameInner).ToString();                xSt.get_Range(coordinates, missing).Value2 = dataInnert;            }        }    }    /// <summary>    /// 填充一组单元格。这组单元格有如下特征:    /// 1,这些单元个的字段组合起来是一个类的属性    /// </summary>    /// <param name="value">    ///             Hashtable里指定key对应的 值, 这里仍然是一个Hashtable    ///             存放的是,key:特定对象的属性名, value:对应的坐标</param>    /// <param name="innerDataObject">    ///             指定数据集对象里的 一个数据对象    ///             该对象的属性与Hashtable的key 一一对应    /// </param>    private void setCells(Object value, Object innerDataObject)     {        Hashtable templateXmlInner = (Hashtable)value;        //循环Hashtable填充单元格组        foreach (string filedNameInner in templateXmlInner.Keys)        {            string coordinates = templateXmlInner[filedNameInner].ToString();            string data = getFiled(innerDataObject, filedNameInner).ToString();            xSt.get_Range(coordinates, missing).Value2 = data;        }    }    /// <summary>    /// 通过类 和 属性名 得到该类的该属性的值    /// </summary>    /// <param name="dataObject">类对象</param>    /// <param name="filedName">字符串类型的属性名</param>    /// <returns></returns>    private Object getFiled(Object dataObject, string filedName)    {        if (string.IsNullOrEmpty(filedName))        {            throw new Exception("属性名为空");        }        PropertyInfo field = dataObject.GetType().GetProperty(filedName);        if (field == null)        {            throw new Exception("在类: " + dataObject.GetType().Name.ToString()                               + " 中不存在名为: " + filedName + " 的属性");        }        return field.GetValue(dataObject, null);    }    /// <summary>    /// 取出Excel对应单元格坐标的行号    /// </summary>    /// <param name="coordinates">坐标(列:A1)</param>    /// <returns>单元个的行坐标</returns>    private static string getRowNo(string coordinates)    {        //取出坐标中的数字 “A1” 中的 “1”        if (string.IsNullOrEmpty(coordinates))        {            throw new Exception("模版坐标为空");        }        Regex rg = new Regex("\\D");        return rg.Replace(coordinates, "");    }} 这样只要有 Excel模版 和 模版描述文件 我们就可以  写Excel文件了
 
vs2008下测试通过
 
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表