xufei0110 发表于 2013-1-27 04:44:44

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

《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;            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;            //循环Hashtable填充单元格组            foreach (string filedNameInner in templateXmlInner.Keys)            {                string coordinates = templateXmlInner.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.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下测试通过
 
页: [1]
查看完整版本: C# 根据模版写Excel(Com)二