热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

通用的web系统数据导出功能设计实现(导出excel2003/2007wordpdfzip等)

转自:http:www.cnblogs.comxqinp3165258.html前言我们在做web系统中,导出也是很常用的一个功能,如果每一个数据列表都要对应写一个导出的方法不太现

转自:http://www.cnblogs.com/xqin/p/3165258.html

前言

我们在做web系统中,导出也是很常用的一个功能,如果每一个数据列表都要对应写一个导出的方法不太现实。现在就想设计一个共通的功能来实现这个导出。

需求分析

在开始之前我们先要明白我们要实现怎样一个功能 
1、支持导出excel2003/excel2007 word pdf等文件格式 
2、支持数据分页,可以导出全部页或指定页 
3、支持导出的文档再压缩zip rar 7z 
4、支持导出多行的题头 
5、支持格式化,如将 0、1 转换为 男、女 
5、可拓展、可自定义等 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

 

技术分析设计

1、生成文件基本可以使用开源的组件实现 
excel2003 使用 NPOI (有网友提醒我npoi已经支持2007了,我这里暂时还是只处理2003) 
excel2007 使用 EPPlus 
word        使用 DocX 还可以使用直接使用html table导出假的word 
pdf          使用 Gios Pdf 
其它格式预留接口…


2、B/S系统要分前后台,先看前台设计 
可以定义一个共通的js方法如com.exporter那么我们前台使用时应该要可以这样用:

com.exporter(grid)         把grid对象传递给前台导出对象,取得题头的相关信息及grid的url和queryParams传给后台重新取数据
     .paging(2,20)         分页处理表示每页20条,导出第2页,如果第两个参数为0则表示不分页
     .compress('zip’)      文件生成之后压缩成zip文件
     .download(‘xlsx’);    导出excel2007格式的文件

设计成这样基本足够,但是有可能我的grid中没有exporter需要的信息,不能直接com.exporter(grid)这种写法,或者大家不喜欢linq的这种写法,我们再设计另一种参数的写法:

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
com.exporter({
    fileType:’xls’,
    compressType:’none’,
    dataGetter:’api’,                   因为我们数据基本要到后台重新取数据,所以怎么取数据可能有很多种方法,dataGetter就是定义用哪一种方式取数据
    dataUrl:’/mms/api/recive’           接下来的dataUrl及dataParams都是dataGetter=‘api’中用到的参数
    dataParams:{BillNo:’20130701’,Supplier:’huawei’,page:1,rows:0},
    titles: [[]]                        多行的表头数据,跟easyui的多行表头格式设计一致
}).download();
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

那么前台基本就可以这样,有了这两种写法,使用起来就很方便了。


3、后台部分设计 
同样我们从调用的地方入手,在我的下载请求的方法中入手:

    new Exporter()
        .Data(new ApiData())                      定义数据取得方式
        .AddFormatter("sex",new SexFormatter())   添加sex列的formatter
        .Export(new PdfExport())                  设置导出pdf
        .Compress(new ZipCompress())              压缩为zip
        .Download();                              下载文件向浏览器输出

我们要设计一个Exporter的类,它下面有Data Export Compress 等方法 
因为这些东西变动性很大,我取数据不能写死是怎么取的,所以我们定义一个取数据的接口来实现 
比如Exporter的Data方法

public Exporter Data(IDataGetter data)
{
 
}

我在具体取数据的方法中继承IDataGetter接口并实现

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
public class ApiData : IDataGetter
{
    public object GetData(HttpContext context)
    {
        ....
        return data;
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

这样的话,假如我的取数据方式不太一样,我只要 new Exporter().Data(new XXDataGetter())就行了 
同样导出Export方法也一样,我定义了一个接口

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
    public interface IExport
    {
        string suffix { get;}
 
        void MergeCell(int x1,int y1,int x2,int y2);
        void FillData(int x, int y,string field, object data);

        void Init(object data);
        Stream SaveAsStream();

        void SetHeadStyle(int x1, int y1, int x2, int y2);
        void SetRowsStyle(int x1, int y1, int x2, int y2);
    }
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

然后在 XlsExport XlsxExporter DocExporter PdfExporter中实现这个接口就可,然后就可以实现导出不同格式的文档的 
压缩方法Comress及字段格式化方法AddFormatter都同样定义接口,同样有人也不喜欢Exporter的写法,那我们再定义一种和前台差不的写法

    new Exporter()
        .Data("api")
        .Export("xlsx")
        .Compress("zip")
        .Download();

这样的话后台这个exporter类也挺好用的了,那么接下来我们再来谈谈如何具体实现吧

 

技术实现

设计时我们先实现后台 
一、后台其实我已经实现出来了,截个图给大家看看先 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等) 
1、首先我们定义一些基本的元素 
定义题头结构

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
    public class Column
    {
        public Column()
        {
            rowspan = 1;
            colspan = 1;
        }
        public string field { get; set; }
        public string title { get; set; }
        public int rowspan { get; set; }
        public int colspan { get; set; }
        public bool hidden { get; set; }
    }
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

定义压缩接口

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Zephyr.Core
{
    public interface ICompress
    {
        string Suffix(string orgSuffix);
        Stream Compress(Stream fileStream,string fullName);
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

定义数据获取的接口

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System.Web;

namespace Zephyr.Core
{
    public interface IDataGetter
    {
        object GetData(HttpContext context);
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

定义文件导出的接口

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System.IO;

namespace Zephyr.Core
{
    public interface IExport
    {
        string suffix { get;}
 
        void MergeCell(int x1,int y1,int x2,int y2);
        void FillData(int x, int y,string field, object data);

        void Init(object data);
        Stream SaveAsStream();

        void SetHeadStyle(int x1, int y1, int x2, int y2);
        void SetRowsStyle(int x1, int y1, int x2, int y2);
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

定义格式化接口

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
namespace Zephyr.Core
{
    public interface IFormatter
    {
        object Format(object value);
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

 

2、基本的元素都定义好了,我们再来实现Exporter导出类,关键性的代码就在这里了

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using Newtonsoft.Json;
using Zephyr.Utils;

namespace Zephyr.Core
{
    public class Exporter
    {
        const string DEFAULT_EXPORT = "xls";
        const string DEFAULT_DATAGETTER = "api";
        const string DEFAULT_COMPRESS = "none";

        private Dictionary _compress = new Dictionary() { 
            { "zip", typeof(ZipCompress)},
            {"none",typeof(NoneCompress)}
        };
        private Dictionary _dataGetter = new Dictionary() { 
            { "api", typeof(ApiData) } 
        };
        private Dictionary _export = new Dictionary() { 
            { "xls", typeof(XlsExport) }, 
            { "xlsx", typeof(XlsxExport) } ,
            { "doc", typeof(HtmlDocExport) },
            { "pdf", typeof(PdfExport) }
        };

        private Dictionary _fieldFormatter = new Dictionary();

        private object _data;
        private List> _title;
        private Stream _fileStream = null;
        private string _fileName = string.Empty;
        private string _suffix = string.Empty;

        public static Exporter Instance()
        {
            var export = new Exporter();
            var cOntext= HttpContext.Current;

            if (context.Request.Form["titles"]!=null)
                export.Title(JsonConvert.DeserializeObject>>(context.Request.Form["titles"]));

            if (context.Request.Form["dataGetter"] != null)
                export.Data(context.Request.Form["dataGetter"]);

            if (context.Request.Form["fileType"] != null)
                export.Export(context.Request.Form["fileType"]);

            if (context.Request.Form["compressType"] != null)
                export.Compress(context.Request.Form["compressType"]);
 
            return export;
        }
 
        public Exporter Data(IDataGetter data)
        {
            _data = data.GetData(HttpContext.Current);
            return this;
        }
 
        public Exporter Data(string type)
        {
            var dataGetter = GetActor(_dataGetter, DEFAULT_DATAGETTER,type);
            return Data(dataGetter);
        }

        public Exporter Data(object data)
        {
            _data = data;
            return this;
        }

        public Exporter AddFormatter(string field,IFormatter formatter)
        {
            _fieldFormatter[field] = formatter;
            return this;
        }

        public Exporter Title(List> title)
        {
            _title = title;
            return this;
        }

        public Exporter FileName(string fileName)
        {
            _fileName = fileName;
            return this;
        }

        public Exporter Export(string type)
        {
            var export = GetActor(_export, DEFAULT_EXPORT, type);
            return Export(export);
        }

        public Exporter Export(IExport export)
        {
            if (_title == null)
            {
                _title = new List>();
                _title.Add(new List());
                EachHelper.EachListHeader(_data, (i, field, type) => _title[0].Add(new Column() { title = field, field = field, rowspan = 1, colspan = 1 }));
            }
 
            Dictionary currentHeadRow = new Dictionary();
            Dictionary> fieldIndex = new Dictionary>();
            Func GetCurrentHeadRow = cell => currentHeadRow.ContainsKey(cell) ? currentHeadRow[cell] : 0;
            var currentRow = 0;
            var currentCell = 0;

            export.Init(_data);

            //生成多行题头
            for (var i = 0; i <_title.Count; i++)
            {
                currentCell = 0;

                for (var j = 0; j <_title[i].Count; j++)
                {
                    var item = _title[i][j];
                    if (item.hidden) continue;

                    while (currentRow  2)
                        export.MergeCell(currentCell, currentRow, currentCell + item.colspan - 1, currentRow + item.rowspan - 1);

                    if (!string.IsNullOrEmpty(item.field))
                    {
                        if (!fieldIndex.ContainsKey(item.field))
                            fieldIndex[item.field] = new List();
                        fieldIndex[item.field].Add(currentCell);
                    }

                    for (var k = 0; k  dataCount++);
            export.SetRowsStyle(0, currentRow, currentCell - 1, currentRow + dataCount - 1);

            //填充数据
            EachHelper.EachListRow(_data, (rowIndex, rowData) =>
            {
                EachHelper.EachObjectProperty(rowData, (i, name, value) =>
                {
                    if (fieldIndex.ContainsKey(name))
                        foreach (int cellIndex in fieldIndex[name])
                        {
                            if (_fieldFormatter.ContainsKey(name)) 
                                value = _fieldFormatter[name](value);
                            export.FillData(cellIndex, currentRow, name, value);
                        }
                });
                currentRow++;
            });
           
            _fileStream = export.SaveAsStream();

            _suffix = export.suffix;
            if (string.IsNullOrEmpty(_fileName))
                _fileName = DateTime.Now.ToString("yyyyMMddHHmmss");
            
            return this;
        }

        public Exporter Compress(string type)
        {
            var compress = GetActor(_compress, DEFAULT_COMPRESS, type);
            return Compress(compress);
        }

        public Exporter Compress(ICompress compress)
        {
            _fileStream = compress.Compress(_fileStream,string.Format("{0}.{1}",_fileName,_suffix));
            _suffix = compress.Suffix(_suffix);
            return this;
        }

        public void Download()
        {
            if (_fileStream != null && _fileStream.Length > 0)
                ZFiles.DownloadFile(HttpContext.Current, _fileStream, string.Format("{0}.{1}",_fileName,_suffix), 1024 * 1024 * 10);
        }
 
        private T GetActor(Dictionary dict, string defaultKey, string key)
        {
            if (!dict.ContainsKey(key))
                key = defaultKey;

            return (T)Activator.CreateInstance(dict[key]);
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

 

3、Exporter类实现之后我们还要实现一些接口才能使用 
我们这里就先实现 
IDataGetter   ApiData 
IExport         XlsxExport XlsExport HtmlDocExport PdfExport 
IComresss     ZipCompress 
其它的以后再实现就可以了,很方便 

ApiData

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Dynamic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;

namespace Zephyr.Core
{
    public class ApiData : IDataGetter
    {
        public object GetData(HttpContext context)
        {
            dynamic data = null;
            var url = context.Request.Form["dataAction"];
            var param = JsonConvert.DeserializeObject(context.Request.Form["dataParams"]);

            var route = url.Replace("/api/", "").Split('/'); // route[0]=mms,route[1]=send,route[2]=get
            var type = Type.GetType(String.Format("Zephyr.Areas.{0}.Controllers.{1}ApiController,Zephyr.Web", route), false, true);
            if (type != null)
            {
                var instance = Activator.CreateInstance(type);

                var action = route.Length > 2 ? route[2] : "Get";
                var methodInfo = type.GetMethod(action);
                var parameters = new object[] { new RequestWrapper().SetRequestData(param) };
                data = methodInfo.Invoke(instance, parameters);

                if (data.GetType() == typeof(ExpandoObject))
                {
                    if ((data as ExpandoObject).Where(x => x.Key == "rows").Count() > 0)
                        data = data.rows;
                }
            }

            return data;
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)


XlsxExport 导出excel2007 利用 Epplus实现

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Drawing;
using Zephyr.Utils;
using Zephyr.Utils.EPPlus;
using Zephyr.Utils.EPPlus.Style;

namespace Zephyr.Core
{
    public class XlsxExport:IExport
    {
        public string suffix { get {return "xlsx"; } }
 
        private ExcelPackage package;
        private ExcelWorksheet sheet;

        public void Init(object data)
        {
            package = new ExcelPackage();
            sheet = package.Workbook.Worksheets.Add("sheet1");
        }

        public void MergeCell(int x1,int y1,int x2,int y2)
        {
            sheet.Cells[y1+1, x1+1, y2+1, x2+1].Merge = true;
        }

        public virtual void FillData(int x, int y,string field, object value)
        {
            if (ZGeneric.IsTypeIgoreNullable(value))
                sheet.Cells[y + 1, x + 1].Style.Numberformat.Format = "yyyy-MM-dd hh:mm:ss";
            sheet.Cells[y + 1, x + 1].Value = value;
        }

        public virtual void SetHeadStyle(int x1, int y1, int x2, int y2)
        {
            using (var head = sheet.Cells[y1 + 1, x1 + 1, y2 + 1, x2 + 1]) // set head style
            {
                head.Style.Font.Bold = true;
                head.Style.Font.Size = 12;
                head.Style.Font.Name = "Arial";

                head.Style.Border.Top.Style = ExcelBorderStyle.Thin;
                head.Style.Border.Top.Color.SetColor(Color.Gray);
                head.Style.Border.Right.Style = ExcelBorderStyle.Thin;
                head.Style.Border.Right.Color.SetColor(Color.Gray);
                head.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                head.Style.Border.Bottom.Color.SetColor(Color.Gray);
                head.Style.Border.Left.Style = ExcelBorderStyle.Thin;
                head.Style.Border.Left.Color.SetColor(Color.Gray);

                head.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                head.Style.HorizOntalAlignment= ExcelHorizontalAlignment.Center;
                head.Style.Fill.PatternType = ExcelFillStyle.Solid;
                head.Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
            }
        }

        public virtual void SetRowsStyle(int x1, int y1, int x2, int y2)
        {
            using (var data = sheet.Cells[y1 + 1, x1 + 1, y2 + 1, x2 + 1])// set data style
            {
                data.Style.Font.Name = "Arial";
                data.Style.Font.Size = 11;

                data.Style.Border.Top.Style = ExcelBorderStyle.Thin;
                data.Style.Border.Top.Color.SetColor(Color.Gray);
                data.Style.Border.Right.Style = ExcelBorderStyle.Thin;
                data.Style.Border.Right.Color.SetColor(Color.Gray);
                data.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                data.Style.Border.Bottom.Color.SetColor(Color.Gray);
                data.Style.Border.Left.Style = ExcelBorderStyle.Thin;
                data.Style.Border.Left.Color.SetColor(Color.Gray);
            }
        }

        public Stream SaveAsStream()
        {
            var ms = new MemoryStream();
            package.SaveAs(ms);

            package = null;
            sheet = null;
            return ms;
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)


XlsExport 导出excel2003 利用NPOI实现

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System.IO;
using Zephyr.Utils;
using Zephyr.Utils.NPOI.HSSF.UserModel;
using Zephyr.Utils.NPOI.SS.UserModel;
using Zephyr.Utils.NPOI.HSSF.Util;
using Zephyr.Utils.NPOI.SS.Util;

namespace Zephyr.Core
{
    public class XlsExport:IExport
    {
        public string suffix { get {return "xls"; } }

        private HSSFWorkbook workbook;
        private ISheet sheet;

        public void Init(object data)
        {
            workbook = new HSSFWorkbook();
            sheet = workbook.CreateSheet("sheet1");
            sheet.DefaultRowHeight = 200 * 20;
        }

        public void MergeCell(int x1,int y1,int x2,int y2)
        {
            CellRangeAddress range = new CellRangeAddress(y1, y2, x1, x2);
            sheet.AddMergedRegion(range);  
        }

        public virtual void FillData(int x, int y,string field, object value)
        {
            var row = sheet.GetRow(y) ?? sheet.CreateRow(y);
            var cell = row.GetCell(x) ?? row.CreateCell(x);
            switch ((value ?? string.Empty).GetType().Name.ToLower())
            {
                case "int32":
                case "int64":
                case "decimal":
                    cell.CellStyle.Alignment = HorizontalAlignment.RIGHT;
                    cell.SetCellValue(ZConvert.To(value, 0));
                    break;
                default:
                    cell.SetCellValue(ZConvert.ToString(value));
                    break;
            }
        }

        public virtual void SetHeadStyle(int x1, int y1, int x2, int y2)
        {
            var style = GetHeadStyle();
            for (var y = y1; y <= y2; y++)
            {
                var row = sheet.GetRow(y) ?? sheet.CreateRow(y);
                for (var x = x1; x <= x2; x++)
                {
                    var cell = row.GetCell(x) ?? row.CreateCell(x);
                    cell.CellStyle = style;
                }
            }
        }

        public virtual void SetRowsStyle(int x1, int y1, int x2, int y2)
        {
            var style = GetDataStyle();
            for (var y = y1; y <= y2; y++)
            {
                var row = sheet.GetRow(y) ?? sheet.CreateRow(y);
                for (var x = x1; x <= x2; x++)
                {
                    var cell = row.GetCell(x) ?? row.CreateCell(x);
                    cell.CellStyle = style;
                }
            }
        }

        public Stream SaveAsStream()
        {
            var ms = new MemoryStream();
            workbook.Write(ms);
            ms.Flush();
            ms.Position = 0;

            workbook = null;
            sheet = null;
            return ms;
        }

        private ICellStyle GetHeadStyle()
        {
            //表头样式
            var headStyle = workbook.CreateCellStyle();
            headStyle.Alignment = HorizontalAlignment.CENTER;//居中对齐
            headStyle.VerticalAlignment = VerticalAlignment.CENTER;

            //表头单元格背景色
            headStyle.FillForegroundColor = HSSFColor.LIGHT_GREEN.index;
            headStyle.FillPattern = FillPatternType.SOLID_FOREGROUND;
            //表头单元格边框
            headStyle.BorderTop = BorderStyle.THIN;
            headStyle.TopBorderColor = HSSFColor.BLACK.index;
            headStyle.BorderRight = BorderStyle.THIN;
            headStyle.RightBorderColor = HSSFColor.BLACK.index;
            headStyle.BorderBottom = BorderStyle.THIN;
            headStyle.BottomBorderColor = HSSFColor.BLACK.index;
            headStyle.BorderLeft = BorderStyle.THIN;
            headStyle.LeftBorderColor = HSSFColor.BLACK.index;
            //表头字体设置
            var fOnt= workbook.CreateFont();
            font.FOntHeightInPoints= 12;//字号
            font.Boldweight = 600;//加粗
            //font.Color = HSSFColor.WHITE.index;//颜色
            headStyle.SetFont(font);

            return headStyle;
        }

        private ICellStyle GetDataStyle()
        {
            //数据样式
            var dataStyle = workbook.CreateCellStyle();
            dataStyle.Alignment = HorizontalAlignment.LEFT;//左对齐
            //数据单元格的边框
            dataStyle.BorderTop = BorderStyle.THIN;
            dataStyle.TopBorderColor = HSSFColor.BLACK.index;
            dataStyle.BorderRight = BorderStyle.THIN;
            dataStyle.RightBorderColor = HSSFColor.BLACK.index;
            dataStyle.BorderBottom = BorderStyle.THIN;
            dataStyle.BottomBorderColor = HSSFColor.BLACK.index;
            dataStyle.BorderLeft = BorderStyle.THIN;
            dataStyle.LeftBorderColor = HSSFColor.BLACK.index;
            //数据的字体
            var datafOnt= workbook.CreateFont();
            datafont.FOntHeightInPoints= 11;//字号
            dataStyle.SetFont(datafont);

            return dataStyle;
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)


PdfExport 利用Gios pdf实现

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using Zephyr.Utils;
using Zephyr.Utils.Gios.Pdf;
using System.Data;

namespace Zephyr.Core
{
    public class PdfExport:IExport
    {
        public string suffix { get {return "pdf"; } }

        private DataTable table;
        private List title;

        public void Init(object data)
        {
            
            var type = ZGeneric.GetGenericType(data);
            var tableName = ZGeneric.IsDynamicType(type) ? string.Empty : type.Name;
            
            table = new DataTable(tableName);
            EachHelper.EachListHeader(data, (rowIndex, name, cellType) =>
            {
                string typeName = cellType.ToString();
                if (cellType.IsGenericType)
                    typeName = cellType.GetGenericArguments()[0].ToString();

                Type newType = Type.GetType(typeName, false);
                if (newType != null)
                    table.Columns.Add(name, newType);
            });
            table.BeginLoadData();
            title = new List();
        }

        public void MergeCell(int x1,int y1,int x2,int y2)
        {
            throw new Exception("pdf未实现多选title");
        }

        public virtual void FillData(int x, int y,string field, object value)
        {
            if (field.StartsWith("title_"))
            {
                title.Add(field.Split('_')[1]);
                return;
            }

            if (table.Rows.Count();
            foreach (DataColumn dc in table.Columns)
                if (title.IndexOf(dc.ColumnName) == -1)                    
removes.Add(dc.ColumnName);
foreach(var name in removes)
table.Columns.Remove(name);
            var pdfTitle = table.TableName;

            // Starting instantiate the document.
            // Remember to set the Docuement Format. In this case, we specify width and height.
            PdfDocument myPdfDocument = new PdfDocument(PdfDocumentFormat.InCentimeters(21, 29.7));

            // Now we create a Table of 100 lines, 6 columns and 4 points of Padding.
            PdfTable myPdfTable = myPdfDocument.NewTable(new Font("Arial", 12), table.Rows.Count, table.Columns.Count, 4);

            // Importing datas from the datatables... (also column names for the headers!)
            //myPdfTable.ImportDataTable(Table);
            myPdfTable.ImportDataTable(table);

            // Sets the format for correct date-time representation
            //myPdfTable.Columns[2].SetContentFormat("{0:dd/MM/yyyy}");

            // Now we set our Graphic Design: Colors and Borders...
            myPdfTable.HeadersRow.SetColors(Color.White, Color.Navy);
            myPdfTable.SetColors(Color.Black, Color.White, Color.Gainsboro);
            myPdfTable.SetBorders(Color.Black, 1, BorderType.CompleteGrid);

            //// With just one method we can set the proportional width of the columns.
            //// It's a "percentage like" assignment, but the sum can be different from 100.
            //myPdfTable.SetColumnsWidth(new int[] { 5, 25, 16, 20, 20, 15 });

            //// You can also set colors for a range of cells, in this case, a row:
            //myPdfTable.Rows[7].SetColors(Color.Black, Color.LightGreen);

            // Now we set some alignment... for the whole table and then, for a column.
            myPdfTable.SetContentAlignment(ContentAlignment.MiddleCenter);
            myPdfTable.Columns[1].SetContentAlignment(ContentAlignment.MiddleLeft);

            // Here we start the loop to generate the table...
            while (!myPdfTable.AllTablePagesCreated)
            {
                // we create a new page to put the generation of the new TablePage:
                PdfPage newPdfPage = myPdfDocument.NewPage();
                PdfTablePage newPdfTablePage = myPdfTable.CreateTablePage(new PdfArea(myPdfDocument, 48, 120, 500, 670));

                // we also put a Label 
                PdfTextArea pta = new PdfTextArea(new Font("Arial", 26, FontStyle.Bold), Color.Red
                    , new PdfArea(myPdfDocument, 0, 20, 595, 120), ContentAlignment.MiddleCenter, pdfTitle);

                // nice thing: we can put all the objects in the following lines, so we can have
                // a great control of layer sequence... 
                newPdfPage.Add(newPdfTablePage);
                newPdfPage.Add(pta);

                // we save each generated page before start rendering the next.
                newPdfPage.SaveToDocument();
            }

            //myPdfDocument.SaveToFile("Example1.pdf");
            var stream = new MemoryStream();
            myPdfDocument.SaveToStream(stream);
            return stream;
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)


HtmlDocExport 导出word 这个是直接导出html table,不是真正的word,如果要用真正的word要利用DocX来实现,我还没来的及写,以后再贴出来吧

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Zephyr.Core
{
    public class HtmlDocExport:IExport
    {
        public string suffix { get {return "doc"; } }

        private StringBuilder sBuilder;
        private int rowIndex;
        private Dictionary row; 

        public void Init(object data)
        {
            rowIndex = 0;
            row = new Dictionary();
            sBuilder = new StringBuilder();
            sBuilder.Append("");
            sBuilder.Append("");
        }

        public void MergeCell(int x1,int y1,int x2,int y2)
        {
            throw new Exception("htmldoc未实现多选title");
        }

        public virtual void FillData(int x, int y,string field, object value)
        {
            if (rowIndex  m.Key).Select(m => m.Value).ToArray());
                row = new Dictionary();
                rowIndex++;
            }

            row[x] = value;
        }

        public virtual void SetHeadStyle(int x1, int y1, int x2, int y2)
        {
           
        }

        public virtual void SetRowsStyle(int x1, int y1, int x2, int y2)
        {
            
        }

        public Stream SaveAsStream()
        {
            AppendRow(row.OrderBy(m => m.Key).Select(m => m.Value).ToArray());
            sBuilder.Append("");
            foreach(var value in values)
                sBuilder.Append(string.Format("", value??string.Empty ));
            sBuilder.Append("");
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

ZipCompress利用Ionic.Zip实现压缩

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Zephyr.Utils.Ionic.Zip;

namespace Zephyr.Core
{
    public class ZipCompress: ICompress
    {
        public string Suffix(string orgSuffix)
        {
            return "zip";
        }

        public Stream Compress(Stream fileStream,string fullName)
        {
            using (var zip = new ZipFile())
            {
                zip.AddEntry(fullName, fileStream);
                Stream zipStream = new MemoryStream();
                zip.Save(zipStream);
                return zipStream;
            }
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

Formatter实现示例

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
using System;

namespace Zephyr.Core
{
    public class SexFormatter:IFormatter
    {
        public object Format(object value)
        {
            switch(Convert.ToString(value))
            {
                case "0":
                    return "纯爷们";
                case "1":
                    return "女汉子";
                default:
                    return "春哥";
            }
        }
    }
}
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

 

实现了以上这样接口,那么这个Exporter类的功能基本就OK了,如果要拓展一些其它格式以及自定义一些只要实现这些接口就可以,使用很方便了。 
那么我们就应用吧,MVC 及webform都可以,我使用的是mvc,在HomeController下添加一个Download的Action,只要添加一句代码就可以实现了

public void Download()
{
    Exporter.Instance().Download();
}

除了在设计中说的到那些功能,这个Instance方法要再说一下,可以参照Exporter中的代码看,Instance中我有去请求中取参数titles dataGetter fileType compressType等参数并且实现。所以下载action中只需要这么简单的一句代码就搞定了。我们继续看前台吧

二、前台实现 
前台只有一段共通的脚本,很简单

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
com.exporter = function (opt) {
    var self = this;

    var defaultOptiOns= {
        action: "/home/download",
        dataGetter: "api",
        dataAction: "",
        dataParams: {},
        titles: [[]],
        fileType: 'xls',
        compressType: 'none'
    };
 
    this.paging = function (page,rows) {
        self.params.dataParams.page = page;
        self.params.dataParams.rows = rows;
        return self;
    };

    this.compress = function () {
        self.params.compressType = 'zip';
        return self;
    };

    this.title = function (filed,title) {
        self.params.titles[0][filed] = title;
        return self;
    };

    this.download = function (suffix) {
        self.params.fileType = suffix || "xls";
        self.params.dataParams = JSON.stringify(self.params.dataParams);
        self.params.titles = JSON.stringify(self.params.titles);
        var downloadHelper = $('').appendTo('body')[0];
        var doc = downloadHelper.contentWindow.document;
        if (doc) {
            doc.open();
            doc.write('')//微软为doc.clear()有时会出bug
            doc.writeln(utils.formatString(""
, self.params.action));
            for (var key in self.params) 
                doc.writeln(utils.formatString("", key, self.params[key]));
            doc.writeln('<\/form><\/body><\/html>');
            doc.close();
            var form = doc.forms[0];
            if (form) {
                form.submit();
            }
        }
    };

    initFromGrid = function (grid) {
        var optiOns= grid.$element().datagrid('options');
        if (grid.treegrid)
            options.url = options.url || grid.treegrid('options').url;

        var titles = [[]], length = Math.max(options.frozenColumns.length, options.columns.length);
        for (var i = 0; i 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

大家基本都能看懂,不需要我再解释了。下载的原理是动态创建了一个iframe把参数写到input中提交到后台。


功能测试


通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

测试 html代码

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
Excel2003表格所有页
Excel2003表格指定页
Excel2003压缩zip
Excel2007/2010
PDF
Word
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

测试 js代码

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
        this.downloadClick1 = function(){
            com.exporter(self.grid).download("xls");
        };
        this.downloadClick2 = function(){
            com.exporter(self.grid).paging(2,3).download("xls"); 只做了5条数据,就3条一页吧,导出第2页
        };
        this.downloadClick3 = function(){
            com.exporter(self.grid).compress('zip').download("xls");
        };
        this.downloadClick4 = function(){
            com.exporter(self.grid).download("xlsx");
        };
        this.downloadClick5 = function(){
            com.exporter(self.grid).download("pdf");
        };
        this.downloadClick6 = function(){
            com.exporter(self.grid).download("doc");
        };
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

测试结果 
1 Excel2003表格所有页 com.exporter(self.grid).download("xls"); 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

2 Excel2003表格指定页  com.exporter(self.grid).page(2,3).download("xls"); 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等) 

3 Excel2003压缩zip com.exporter(self.grid).compress('zip').download("xls"); 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

4 Excel2007/2010  com.exporter(self.grid).download("xlsx"); 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

5 PDF导出 com.exporter(self.grid).download("pdf"); Gios这个组件出现中文会乱码,我想了很多办法都解决不了,没办法,可能要找一另一个pdf组件,先隐藏中文的字段截个图给大家看吧 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

6 Word导出 com.exporter(self.grid).download("doc"); 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

测试导出多行题头,比如这个页面是多行的 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

1 导出excel2003 多行题头 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

2 导出excel2007 多行题头 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

还有一些其它的功能我就不一一测试了,大家有兴趣可以自己再研究

在我们的材料管理的系统中导出一般只用几个选项,1 导出全部页excel2003 2 导出全部页excel2007/2010 3导出全部页word 这三个 
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)

所代码也很简单,代码如下:

通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
Excel2003
Excel2007
Word2003
通用的web系统数据导出功能设计实现(导出excel2003/2007 word pdf zip等)
this.downloadClick = function (vm, event) {
    com.exporter(self.grid).download($(event.currentTarget).attr("suffix"));
};

在我之前的博客中写共通的查询viewModel中有提到导出功能,但都只有上面的一句代码。估计大家看了这篇博客才能明白。


推荐阅读
  • 主调|大侠_重温C++ ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 深入解析Redis内存对象模型
    本文详细介绍了Redis内存对象模型的关键知识点,包括内存统计、内存分配、数据存储细节及优化策略。通过实际案例和专业分析,帮助读者全面理解Redis内存管理机制。 ... [详细]
  • 本文详细探讨了HTML表单中GET和POST请求的区别,包括它们的工作原理、数据传输方式、安全性及适用场景。同时,通过实例展示了如何在Servlet中处理这两种请求。 ... [详细]
  • 在创建新的Android项目时,您可能会遇到aapt错误,提示无法打开libstdc++.so.6共享对象文件。本文将探讨该问题的原因及解决方案。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • Asp.net MVC 中 Bundle 配置详解:合并与压缩 JS 和 CSS 文件
    本文深入探讨了 Asp.net MVC 中如何利用 Bundle 功能来合并和压缩 JavaScript 和 CSS 文件,提供了详细的配置步骤和示例代码,适合开发人员参考学习。 ... [详细]
  • 解析SQL查询结果的排序问题及其解决方案
    本文探讨了为什么某些SQL查询返回的数据集未能按预期顺序排列,并提供了详细的解决方案,帮助开发者理解并解决这一常见问题。 ... [详细]
  • Struts与Spring框架的集成指南
    本文详细介绍了如何将Struts和Spring两个流行的Java Web开发框架进行整合,涵盖从环境配置到代码实现的具体步骤。 ... [详细]
  • 对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ... [详细]
  • CentOS 6.5 上安装 MySQL 5.7.23 的详细步骤
    本文详细介绍如何在 CentOS 6.5 系统上成功安装 MySQL 5.7.23,包括卸载旧版本、下载安装包、配置文件修改及启动服务等关键步骤。 ... [详细]
  • 本文详细介绍了如何解压并安装MySQL集群压缩包,创建用户和组,初始化数据库,配置环境变量,并启动相关服务。此外,还提供了详细的命令行操作步骤和常见问题的解决方案。 ... [详细]
  • 精选多款高效实用软件及工具推荐
    本文介绍并推荐多款高效实用的软件和工具,涵盖系统优化、网络加速、多媒体处理等多个领域,并提供安全可靠的下载途径。 ... [详细]
  • 远程过程调用(RPC)是一种允许客户端通过网络请求服务器执行特定功能的技术。它简化了分布式系统的交互,使开发者可以像调用本地函数一样调用远程服务,并获得返回结果。本文将深入探讨RPC的工作原理、发展历程及其在现代技术中的应用。 ... [详细]
  • 本文探讨了在QT框架中如何有效遍历文件内容,并解决了一个常见的错误,即文件内容读取为空时弹窗无法正常显示的问题。 ... [详细]
author-avatar
mbe5757086
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有
     
{0}