真导出Excel功能实现(使用Gembox.Spreadsheet v2.9 组件)

  其实注册博客园很久,没有写博客的原因是因为自己手很懒。在博客园也跟踪看了很多博客,也学到一些思想和方法。一直也想把自己写的一些东西放到上面,可是都未能实现。

  下面是本人利用的Gembox.Spreadsheet v2.9 组件写的真导出Excel数据的功能。

  1. 导出DataTable数据为Excel数据

    #region TableDataSource
    /// <summary>
    /// DataTable导出Excel数据
    /// </summary>
    public class TableDataSource : baseDataSource {
        private DataTable table;
        private ReadOnlyCollection<ExportColumn> mappings;
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="Table">DataTable表格对象</param>
        /// <param name="Mappings">映射列数组</param>
        public TableDataSource(DataTable Table, params ExportColumn[] Mappings) {
            this.table = Table;

            var list = new List<ExportColumn>(Mappings.Length);
            list.AddRange(Mappings);
            this.mappings = list.AsReadOnly();
        }
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="Table">DataTable表格对象</param>
        /// <param name="Mappings">映射列数组</param>
        public TableDataSource(DataTable Table, IEnumerable<ExportColumn> Mappings) {
            this.table = Table;
            this.mappings = new List<ExportColumn>(Mappings).AsReadOnly();
        }

        internal override void Export() {
            if (this.sheet == null) throw new ArgumentNullException("请先初始化ExcelWorksheet对象。");
            if (this.table == null) throw new ArgumentNullException("导出数据时数据源不能为空。");
            if (this.mappings == null) throw new ArgumentNullException("导出样式不能为空。");

            int indexNo;
            CellStyle style;
            this.InitializeExcelWorksheetStyle(this.mappings, out indexNo, out style);
            //总列数
            int columnCount = mappings.Count;
            List<int> mapIndexs = new List<int>(columnCount);
            List<int> tableColumns = new List<int>(columnCount);
            for (int i = 0; i < mappings.Count; i++) {
                int columnIndex = this.table.Columns.IndexOf<DataColumn>(p2 => p2.ColumnName.Equals(mappings[i].Property, StringComparison.OrdinalIgnoreCase));
               if (columnIndex < 0) throw new ArgumentOutOfRangeException(string.Format("属性或字段 {0} 不存在。", mappings[i].Property));

                mapIndexs.Add(i);
                tableColumns.Add(columnIndex);
            }
            //开始转换数据
            CellRange range;
            foreach (DataRow row in this.table.Rows) {
                range = this.sheet.Cells.GetSubrangeAbsolute(indexNo, 0, indexNo, columnCount);
                for (int i = 0; i < columnCount; i++) {
                    range[i].Value = (mapIndexs.Contains(i) ? row[tableColumns[mapIndexs.IndexOf(i)]] : default(object));
                    range[i].Style = style;
                    range[i].Style.HorizontalAlignment = this.SetCellStyleAlignment(mappings[i].Alignment);

                    //格式化数据
                    if (!string.IsNullOrEmpty(mappings[i].NumberFormat)) range[i].Style.NumberFormat = mappings[i].NumberFormat;
                }
                this.sheet.Rows[indexNo].Height = Convert.ToInt32(1.6 * style.Font.Size);
                indexNo++;
            }
            range = null;
            //添加汇总行
            this.AppendSumRow(mappings, indexNo, style);
        }
    }
    #endregion

  2. 导出DataGridView数据为Excel数据

   #region DataGridViewDataSource
    /// <summary>
    /// DataGridView导出Excel数据
    /// </summary>
    public class DataGridViewDataSource : baseDataSource {
        private DataGridView viewControl;
        private ReadOnlyCollection<ExportColumn> mappings;
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="dataGridView">网格控件</param>
        public DataGridViewDataSource(DataGridView dataGridView) {
            this.viewControl = dataGridView;
            this.mappings = null;
        }
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="dataGridView">网格控件</param>
        /// <param name="Mappings">映射列数组</param>
        public DataGridViewDataSource(DataGridView dataGridView, params ExportColumn[] Mappings) {
            this.viewControl = dataGridView;
            List<ExportColumn> list = new List<ExportColumn>(Mappings.Length);
            list.AddRange(Mappings);
            this.mappings = list.AsReadOnly();
        }
        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="dataGridView">网格控件</param>
        /// <param name="Mappings">映射列数组</param>
        public DataGridViewDataSource(DataGridView dataGridView, IEnumerable<ExportColumn> Mappings) {
            this.viewControl = dataGridView;

            this.mappings = new List<ExportColumn>(Mappings).AsReadOnly();
        }

        internal override void Export() {
            if (this.sheet == null) throw new ArgumentNullException("请先初始化ExcelWorksheet对象。");
            if (this.viewControl == null) throw new ArgumentNullException("数据导出时数据源不能为空。");

            if (this.mappings == null) this.mappings = this.getDataColumnMappings(this.viewControl).AsReadOnly();
            int indexNo;
            CellStyle style;
            this.InitializeExcelWorksheetStyle(this.mappings, out indexNo, out style);
            //总列数
            int columnCount = mappings.Count;
            List<int> mapIndexs = new List<int>(columnCount);
            List<int> tableColumns = new List<int>(columnCount);
            for (int i = 0; i < mappings.Count; i++) {
                if (string.IsNullOrEmpty(mappings[i].Property)) continue;
                else {
                    int columnIndex = this.viewControl.Columns.IndexOf<DataGridViewColumn>(p2 => p2.DataPropertyName.Equals(mappings[i].Property, StringComparison.OrdinalIgnoreCase));
                    if (columnIndex < 0) throw new ArgumentOutOfRangeException(string.Format("属性或字段 {0} 不存在。", mappings[i].Property));

                    mapIndexs.Add(i);
                    tableColumns.Add(columnIndex);
                }
            }
            //开始转换数据
            CellRange range;
            foreach (DataGridViewRow row in this.viewControl.Rows) {
                range = this.sheet.Cells.GetSubrangeAbsolute(indexNo, 0, indexNo, columnCount);
                for (int i = 0; i < columnCount; i++) {
                    //如果字段为引用类型,或者空类型,则忽略此值
                    object val = (mapIndexs.Contains(i) ? row.Cells[tableColumns[mapIndexs.IndexOf(i)]].Value : default(object));
                    if (val != default(object)) {
                        TypeCode code = Type.GetTypeCode(val.GetType());
                        if ((code == TypeCode.Empty) || (code == TypeCode.Object)) range[i].Value = val.GetType().FullName;
                        else range[i].Value = val;
                    }//处理完毕

                    range[i].Style = style;
                    range[i].Style.HorizontalAlignment = this.SetCellStyleAlignment(mappings[i].Alignment);
                    //格式化数据
                    if (!string.IsNullOrEmpty(mappings[i].NumberFormat)) range[i].Style.NumberFormat = mappings[i].NumberFormat;
                }
                this.sheet.Rows[indexNo].Height = Convert.ToInt32(1.6 * style.Font.Size);
                indexNo++;
            }
            range = null;

            //添加汇总行
            this.AppendSumRow(mappings, indexNo, style);
        }

        private List<ExportColumn> getDataColumnMappings(DataGridView dataGridView) {
            List<ExportColumn> list = new List<ExportColumn>(dataGridView.Columns.Count);
            foreach (DataGridViewColumn column in dataGridView.Columns) {
                //自动生成对象时,如果为数字型,则自动计算汇总
                Type realType = TypeSystem.GetElementType(column.ValueType);
                TypeCode tc = Type.GetTypeCode(realType);
                bool appendsum = ((tc == TypeCode.Decimal) || (tc == TypeCode.Double) || (tc == TypeCode.Int16) || (tc == TypeCode.Int32) || (tc == TypeCode.Int64) || (tc == TypeCode.Single)
                    || (tc == TypeCode.UInt16) || (tc == TypeCode.UInt32) || (tc == TypeCode.UInt64));

                list.Add(new ExportColumn {
                    Property = column.DataPropertyName,
                    HeaderText = column.HeaderText,
                    Alignment = (column.HasDefaultCellStyle ? getHorizontalAlignment(column.DefaultCellStyle.Alignment) : getHorizontalAlignment(column.InheritedStyle.Alignment)),
                    Width = Convert.ToInt32(column.Width / 10),
                    AutoSum = appendsum
                });
            }
            return list;
        }
        private TextAlignment getHorizontalAlignment(DataGridViewContentAlignment style) {
            switch (style) {
                case DataGridViewContentAlignment.TopLeft:
                case DataGridViewContentAlignment.MiddleLeft:
                case DataGridViewContentAlignment.BottomLeft:
                    return TextAlignment.Left;
                case DataGridViewContentAlignment.TopCenter:
                case DataGridViewContentAlignment.MiddleCenter:
                case DataGridViewContentAlignment.BottomCenter:
                    return TextAlignment.Center;
                case DataGridViewContentAlignment.TopRight:
                case DataGridViewContentAlignment.MiddleRight:
                case DataGridViewContentAlignment.BottomRight:
                    return TextAlignment.Right;
                default:
                    return TextAlignment.Left;
            }
        }
    }
    #endregion

  先就放这两个导出功能。

  下面是用到的支持类:

    #region TextAlignment
    /// <summary>
    /// 指定控件中的对象或文本如何相对于控件元素水平对齐。
    /// </summary>
    public enum TextAlignment {
        /// <summary>
        /// 对象或文本与控件元素的左侧对齐
        /// </summary>
        Left = 0,
        /// <summary>
        /// 对象或文本与控件元素的右侧对齐
        /// </summary>
        Right = 1,
        /// <summary>
        /// 对象或文本与控件元素的中心对齐
        /// </summary>
        Center = 2,
    }
    #endregion

    #region ExportColumn
    /// <summary>
    /// 导出列设置
    /// </summary>
    public class ExportColumn {
        /// <summary>
        /// 获取或设置导出属性
        /// </summary>
        public string Property {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置列头标题
        /// </summary>
        public string HeaderText {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置列宽
        /// </summary>
        public int Width {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置对齐对象
        /// </summary>
        public TextAlignment Alignment {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置Excel单元格格式化字符串
        /// </summary>
        public string NumberFormat {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置是否自动汇总
        /// </summary>
        public bool AutoSum {
            get;
            set;
        }
    }
    #endregion

    #region ExcelExport
    /// <summary>
    /// Excel生成工厂
    /// </summary>
    public class ExcelExport {
        private ExcelFile xlsFile = null;
        /// <summary>
        /// 获取或设置文件名
        /// </summary>
        public string FileName {
            get;
            set;
        }
        /// <summary>
        /// 保存文件
        /// </summary>
        public void Save() {
            this.Save(this.FileName);
        }
        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        public void Save(string fileName) {
            if (this.xlsFile == null) throw new ArgumentNullException("Xls文件未初始化。");

            this.xlsFile.SaveXls(fileName);
        }
        /// <summary>
        /// 保存到流
        /// </summary>
        /// <param name="stream"></param>
        public void SaveToStream(System.IO.Stream stream) {
            if (this.xlsFile == null) throw new ArgumentNullException("Xls文件未初始化。");
            this.xlsFile.SaveXls(stream);
        }
        /// <summary>
        /// 输出数据
        /// </summary>
        /// <param name="excelExportor"></param>
        public void Export(baseDataSource excelExportor) {
            if (excelExportor == null) throw new ArgumentNullException("导出对象不能为空。");

            string sname = (!string.IsNullOrEmpty(excelExportor.SheetName) ? excelExportor.SheetName : string.Empty).Trim();
            if (this.xlsFile == null) this.xlsFile = new ExcelFile();
            if (this.xlsFile.Worksheets.Contains<ExcelWorksheet>(p2 => p2.Name.Equals(excelExportor.SheetName, StringComparison.OrdinalIgnoreCase))) {
                throw new ArgumentOutOfRangeException(string.Format("已经存在同名 {0} 的ExcelWorksheet。", excelExportor.SheetName));
            }

            if (string.IsNullOrEmpty(sname)) {
                const string sheetName = "Sheet{0}";
                int indexNo = 1;
                while (this.xlsFile.Worksheets.Contains<ExcelWorksheet>(p2 => p2.Name.Equals(string.Format(sheetName, indexNo), StringComparison.OrdinalIgnoreCase))) {
                    indexNo++;
                }
                sname = string.Format(sheetName, indexNo);
            } else {
                sname = sname.Replace("/", " ").Replace("?", " ").Replace("*", " ").Replace("[", " ").Replace("]", " ");
                if (string.IsNullOrEmpty(sname) || (sname.Length > 31)) throw new ArgumentOutOfRangeException("ExcelWorksheet的名称不能为空,或者超过31个字符。");
            }
            excelExportor.SetExcelWorksheet(this.xlsFile.Worksheets.Add(sname));
            excelExportor.Export();
        }
    }
    #endregion

    #region baseDataSource
    /// <summary>
    /// Excel输出器
    /// </summary>
    public abstract class baseDataSource : IDisposable {
        #region 公共属性
        /// <summary>
        /// 获取或设置Sheet名称
        /// 如果InsertCaption为真,则将作为表格标题插入标题行
        /// </summary>
        public string SheetName {
            get;
            set;
        }
        /// <summary>
        /// 是否插入标题行
        /// </summary>
        public bool InsertCaption {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置标题字体(如果标题不为空且字体未设置,则默认和数据字体一样)
        /// </summary>
        public Font CaptionFont {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置列头字体
        /// </summary>
        public Font HeaderFont {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置数据字体
        /// </summary>
        public Font DataFont {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置是否自动添加汇总行
        /// </summary>
        public bool AppendSum {
            get;
            set;
        }
        #endregion

        #region 私有保护方法
        #region 保护方法
        /// <summary>
        /// ExcelWorksheet对象
        /// </summary>
        protected ExcelWorksheet sheet;
        /// <summary>
        /// 初始化表格样式
        /// </summary>
        /// <param name="mappings"></param>
        /// <param name="indexNo"></param>
        /// <param name="style"></param>
        protected void InitializeExcelWorksheetStyle(ReadOnlyCollection<ExportColumn> mappings, out int indexNo, out CellStyle style) {
            if (this.sheet == null) throw new ArgumentNullException("请先初始化ExcelWorksheet对象。");
            if (mappings == null) throw new ArgumentNullException("导出列样式不能为空。");
            if (this.DataFont == default(Font)) this.DataFont = GetDefaultFont();

            CellRange range;
            indexNo = 0;
            //如果标题行不为空
            if (InsertCaption && (!string.IsNullOrEmpty(this.SheetName))) {
                this.sheet.Cells[0].Value = this.SheetName;
                range = this.sheet.Cells.GetSubrangeAbsolute(0, 0, 0, mappings.Count - 1);
                range.Merged = true;
                Font capfont = ((this.CaptionFont != default(Font)) ? this.CaptionFont : ((this.HeaderFont != default(Font)) ? this.HeaderFont : this.DataFont));
                this.SetCellStyleFont(range.Style, capfont);
                range.Style.Font.Weight = ExcelFont.BoldWeight;
                range.Style.HorizontalAlignment = HorizontalAlignmentStyle.Center;
                range.Style.VerticalAlignment = VerticalAlignmentStyle.Center;
                this.sheet.Rows[indexNo].Height = capfont.Height * 33;
                capfont.Dispose();

                indexNo++;
            }
            //开始处理列头
            range = this.sheet.Cells.GetSubrangeAbsolute(indexNo, 0, indexNo, mappings.Count - 1);
            Font headerFont = ((this.HeaderFont != default(Font)) ? this.HeaderFont : this.DataFont);
            for (int i = 0; i < mappings.Count; i++) {
                this.sheet.Columns[i].Width = mappings[i].Width * 264;
                range[i].Value = mappings[i].HeaderText;
                this.SetCellStyleFont(range[i].Style, headerFont);
                range[i].Style.HorizontalAlignment = HorizontalAlignmentStyle.Center;
                range[i].Style.VerticalAlignment = VerticalAlignmentStyle.Center;
                range[i].SetBorders(MultipleBorders.Top | MultipleBorders.Left | MultipleBorders.Bottom | MultipleBorders.Right, Color.Black, LineStyle.Thin);
            }
            this.sheet.Rows[indexNo].Height = Convert.ToInt32(20 * 1.6 * headerFont.Size);
            headerFont.Dispose();
            indexNo++;

            //返回数据行列样式
            style = new CellStyle();
            style.HorizontalAlignment = HorizontalAlignmentStyle.Center;
            style.VerticalAlignment = VerticalAlignmentStyle.Center;
            style.Font.Size = Convert.ToInt32(this.DataFont.Size * 20);
            style.Borders.SetBorders(MultipleBorders.Top | MultipleBorders.Left | MultipleBorders.Bottom | MultipleBorders.Right, Color.Black, LineStyle.Thin);
            style.WrapText = true;
            this.SetCellStyleFont(style, this.DataFont);
        }

        /// <summary>
        /// 设置单元格字体样式
        /// </summary>
        /// <param name="style">样式</param>
        /// <param name="font">字体</param>
        protected void SetCellStyleFont(CellStyle style, System.Drawing.Font font) {
            style.Font.Color = Color.Black;
            style.Font.Italic = font.Italic;
            style.Font.Name = font.Name;
            style.Font.Size = Convert.ToInt32(font.Size * 20);
            style.Font.Strikeout = font.Strikeout;
            style.Font.UnderlineStyle = (font.Underline ? UnderlineStyle.Single : UnderlineStyle.None);
        }
        /// <summary>
        /// 设置单元文本水平对齐方式
        /// </summary>
        /// <param name="alignment">对齐方式</param>
        /// <returns></returns>
        protected HorizontalAlignmentStyle SetCellStyleAlignment(TextAlignment alignment) {
            switch (alignment) {
                case TextAlignment.Left:
                    return HorizontalAlignmentStyle.Left;
                case TextAlignment.Center:
                    return HorizontalAlignmentStyle.Center;
                case TextAlignment.Right:
                    return HorizontalAlignmentStyle.Right;
                default:
                    return HorizontalAlignmentStyle.Left;
            }
        }
        /// <summary>
        /// 追加自动汇总行
        /// </summary>
        /// <param name="mappings">映射</param>
        /// <param name="rowIndex">汇总行索引</param>
        /// <param name="style">单元格样式</param>
        protected void AppendSumRow(ReadOnlyCollection<ExportColumn> mappings, int rowIndex, CellStyle style) {
            if (!this.AppendSum) return;

            //是否存在标题行
            bool existCaption = !string.IsNullOrEmpty(this.SheetName);
            //开始填充数据
            string SUMVALUE = (!existCaption ? "=SUM({0}2:{0}" + rowIndex + ")" : "=SUM({0}3:{0}" + rowIndex + ")");
            int columnCount = mappings.Count;
            CellRange range = this.sheet.Cells.GetSubrangeAbsolute(rowIndex, 0, rowIndex, columnCount - 1);
            if (!mappings[0].AutoSum) range[0].Value = "总计";

            for (int i = 0; i < columnCount; i++) {
                if (mappings[i].AutoSum) range[i].Formula = string.Format(SUMVALUE, ToExcelColumnName(i));
                range[i].Style = style;
                range[i].Style.HorizontalAlignment = this.SetCellStyleAlignment(mappings[i].Alignment);
                range[i].Style.Font.Weight = ExcelFont.BoldWeight;

                //格式化数据
                if (!string.IsNullOrEmpty(mappings[i].NumberFormat)) range[i].Style.NumberFormat = mappings[i].NumberFormat;
            }
            this.sheet.Rows[rowIndex].Height = Convert.ToInt32(1.6 * style.Font.Size);
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 将列索引转换为A->Z
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns></returns>
        private string ToExcelColumnName(int index) {
            if (index < 0) throw new Exception("无效参数。");
            List<string> chars = new List<string>();
            do {
                if (chars.Count > 0) index--;
                chars.Insert(0, ((char)(index % 26 + (int)'a')).ToString());
                index = (int)((index - index % 26) / 26);
            } while (index > 0);

            return string.Join(string.Empty, chars.ToArray()).ToUpper();
        }
        private Font GetDefaultFont() {
            return new Font("宋体", 10.5f, FontStyle.Regular, GraphicsUnit.Point, 0x86);
        }
        #endregion
        #endregion

        #region 公共方法
        /// <summary>
        /// 设置要填充数据ExcelWorksheet
        /// </summary>
        /// <param name="Worksheet"></param>
        internal void SetExcelWorksheet(ExcelWorksheet Worksheet) {
            this.sheet = Worksheet;
        }
        /// <summary>
        /// 输出数据
        /// </summary>
        internal abstract void Export();
        #endregion

        #region IDisposable 成员
        /// <summary>
        /// 析构方法
        /// </summary>
        public void Dispose() {
            if (this.CaptionFont != default(Font)) this.CaptionFont.Dispose();
            if (this.HeaderFont != default(Font)) this.HeaderFont.Dispose();
            if (this.DataFont != default(Font)) this.DataFont.Dispose();
        }

        #endregion
    }
    #endregion

    /// <summary>
    /// 序列扩展方法
    /// </summary>
    static class EnumerableExtensions {
        /// <summary>
        /// 确定 System.Collections.Generic.List<T> 是否包含与指定谓词所定义的条件相匹配的元素。
        /// </summary>
        /// <typeparam name="TElement">对象类型</typeparam>
        /// <param name="enumerable">源序列</param>
        /// <param name="predicate">匹配条件</param>
        /// <returns></returns>
        public static bool Contains<TElement>(this IEnumerable enumerable, Predicate<TElement> predicate) {
            foreach (TElement item in enumerable) {
                if (predicate(item)) return true;
            }
            return false;
        }
        /// <summary>
        /// 搜索指定的对象,并返回整个 System.Collections.Generic.List<T> 中第一个匹配项的从零开始的索引。
        /// </summary>
        /// <typeparam name="TElement">对象类型</typeparam>
        /// <param name="enumerable">源序列</param>
        /// <param name="predicate">匹配条件</param>
        /// <returns></returns>
        public static int IndexOf<TElement>(this IEnumerable enumerable, Predicate<TElement> predicate) {
            int index = 0;
            foreach (TElement item in enumerable) {
                if (predicate(item)) return index;
                else index++;
            }
            return -1;
        }
    }

    #region TypeSystem
    static class TypeSystem {
        internal static Type GetElementType(Type seqType) {
            Type ienum = FindIEnumerable(seqType);
            if (ienum == null) return seqType;
            return ienum.GetGenericArguments()[0];
        }

        private static Type FindIEnumerable(Type seqType) {
            if (seqType == null || seqType == typeof(string))
                return null;
            if (seqType.IsArray)
                return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
            if (seqType.IsGenericType) {
                foreach (Type arg in seqType.GetGenericArguments()) {
                    Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
                    if (ienum.IsAssignableFrom(seqType)) {
                        return ienum;
                    }
                }
            }
            Type[] ifaces = seqType.GetInterfaces();
            if (ifaces != null && ifaces.Length > 0) {
                foreach (Type iface in ifaces) {
                    Type ienum = FindIEnumerable(iface);
                    if (ienum != null) return ienum;
                }
            }
            if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
                return FindIEnumerable(seqType.BaseType);
            }
            return null;
        }
    }
    #endregion

  因为当初希望做一个相对灵活的扩展,所以代码中使用基类继承的方法。大家还可以在此基础上扩展出 ListView、Enumerable、Enumerable<T>和GridView的Excel导出功能。

     结尾再给出一个简单的调用示例,很简单的希望大家复制过去,引用完命名空间即可使用。

    string fileName = ...;

    ExcelExport export = new ExcelExport();

    var dataSource = new DataGridViewDataSource( dataGridView控件 ) { SheetName = "sheetName",  InsertCaption = true };
     export.Export(dataSource);
     export.Save( fileName );

      希望大家提出意见和建议。

你可能感兴趣的:(导出Excel)