NPOI导出表格

数据展示一般用网格,有时要导出到客户端本地处理,本文试用NPOI控件实现;

1、前端方法一,XMLHttpRequest

因为$.ajax参数dataType选项不支持blob,使用了XMLHttpRequest对象;

<script type="text/javascript">
        //判断是否IE
        function _isIE() {
            if (!!window.ActiveXObject || "ActiveXObject" in window)
                return true;
            else
                return false;
        }

        //导出Excel响应操作
        $("#btnconfirm").click(function () {
            //导出选中字段
            var $selected = $("#selecteditem>select option");
            var data = [];
            //构造json数组
            for (var i = 0; i < $selected.length; i++) {
                data.push({ "value": $selected.eq(i).attr("value"), "text": $selected.eq(i).text() });
            }
            //转换为字符串
            var paramStr = JSON.stringify(data);

            //获取查询字符串
            var ClassId = window.location.search;
            //请求地址
            var url = '../Handlers/ExportExcel.ashx' + ClassId;
            //实例化对象xhr
            var xhr = new XMLHttpRequest();
            //打开链接
            xhr.open('post', url, true);
            //设置响应类型为blob,只能用小写
            xhr.responseType = 'blob';

            //导出Excel文件
            xhr.onload = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    //获取响应头信息、文件名
                    var ContentDisposition =decodeURI(xhr.getResponseHeader("Content-Disposition"));
                    var filename = ContentDisposition.substring(ContentDisposition.lastIndexOf('filename=')+9);

                    //接收响应数据
                    var content = this.response;
                    //流数据转为Blob
                    var blob = new Blob([content]);

                    saveAs(blob, filename);
                }
            };
            //设置http请求头
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            //带参发送请求
            xhr.send("param=" + paramStr);
        });

        //输出文件链接
        function saveAs(blob, filename) {
            //生成一个a标签
            var a = document.createElement('a');
            a.style.display = 'none';
            a.download = filename;
            a.id = "aexport";
            //生成一个label标签,用于触发a标签点击事件
            var lb = document.createElement('label');
            lb.for = "aexport";
            a.appendChild(lb);
            //创建一个URL对象,指向Blob对象
            var objectURL = window.URL.createObjectURL(blob);
            a.href = objectURL;

            //把a标签加入body
            document.body.appendChild(a);
            //触发a标签点击事件
            lb.click();
            //IE不支持createObjectURL,特殊处理
            if (_isIE()) {
                window.navigator.msSaveOrOpenBlob(blob, filename);
            }
            //删除a标签
            document.body.removeChild(a);
            //回收内存
            URL.revokeObjectURL(objectURL);
        }
</script>

2、前端方法二,表单模拟

文件名为响应头信息中filename;如果返回字符串,可以使用iframe接收,即 form.target = iframe.name ,iframe接收完成后, iframe.onload=function(){} 获取返回字符串处理;

<script type="text/javascript">
            //导出Excel响应操作
            $("#btnconfirm").click(function () {
                //导出选中字段
                var $selected = $("#selecteditem>select option");
                var data = [];
                //构造json数组,value为字段名,text为字段描述
                for (var i = 0; i < $selected.length; i++) {
                    data.push({ "value": $selected.eq(i).attr("value"), "text": $selected.eq(i).text() });
                }
                //转换为字符串,作为post上传参数
                var paramStr = JSON.stringify(data);

                //获取查询字符串
                var ClassId = window.location.search;
                //请求地址
                var url = '../Handlers/ExportExcel.ashx' + ClassId;

                //生成一个input标签,用于读取数据
                var input = document.createElement('input');
                input.type = 'text';
                input.name = 'param';
                input.value = paramStr;
                //生成一个form标签,用于发送数据
                var form = document.createElement('form');
                form.method = 'post';
                form.action = url;
                form.hidden = 'hidden';
                //把input加入表单
                form.appendChild(input);
                //把表单加入body
                document.body.appendChild(form);
                //表单提交
                form.submit();
document.body.removeChild(form); });
</script>

3、前端方法三,直接跳转

如果固定导出格式,没有需要上传的参数,或者用Get方式传递参数,直接跳转也可以,文件名为响应头信息中filename;

<input type="button" value="导出学生到Excel" id="btnExportExcelStu" hidden/>
//测试导出
var btnExportExcelStu = document.getElementById('btnExportExcelStu');
btnExportExcelStu.onclick = function() {
    window.location.href = "@Url.Content("~ / Handlers / ExportExcel.ashx ? ClassId = 2 ")";
}

4、后端采用一般处理程序

    public class ExportExcel : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            //获取传入参数
            string param = context.Request["param"];
            //反序列化字符串,存入字典列表,内容为待导出字段,value为字段名,text为字段描述
            List<Dictionary<string, string>> listDic = null;
            if (!(param.Length==0))
            {
                JavaScriptSerializer jss = new JavaScriptSerializer();
                listDic = jss.Deserialize<List<Dictionary<string, string>>>(param);
            }

            //设置输出类型
            context.Response.ContentType = "blob";
            //将HTTP头添加到输出流,设置导出文件名
            string filename = HttpUtility.UrlEncode(DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ffff")+".xls");
            context.Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);

            //创建Excel工作簿和工作表
            HSSFWorkbook workbook = new HSSFWorkbook();
            ISheet worksheet = workbook.CreateSheet("Sheet1");

            //添加批注
            HSSFPatriarch patr = (HSSFPatriarch)worksheet.CreateDrawingPatriarch();
            List<HSSFComment> listcomm = new List<HSSFComment>();
            
            //动态生成列批注
            string value = "";
            for (int i = 0; i < listDic.Count(); i++)
            {
                /*参考网站如下,2019-11-20
                 * https://www.cnblogs.com/zhuangjolon/p/9300704.html
                 * 关于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的参数,有必要在这里说明一下:
                 * dx1:起始单元格的x偏移量;
                 * dy1:起始单元格的y偏移量;
                 * dx2:终止单元格的x偏移量;
                 * dy2:终止单元格的y偏移量;
                 * col1:起始单元格列序号;
                 * row1:起始单元格行序号;
                 * col2:终止单元格列序号;
                 * row2:终止单元格行序号;

                 * 其实主要是前四个是偏移量,后四个关系到批注的位置和大小。
                 */
                listcomm.Add(patr.CreateComment(new HSSFClientAnchor(7, 12, 0, 0, i + 1, 1, i + 3, 5)));
                //获取导出字段名,设置为列批注
                listDic[i].TryGetValue("value", out value);
                listcomm[i].String = new HSSFRichTextString(value);
            }

            //创建工作表表头
            IRow rowHeader = worksheet.CreateRow(1);
            //动态生成列标题
            for (int i = 0; i < listDic.Count(); i++)
            {
                //获取导出字段描述,设置列标题和批注
                listDic[i].TryGetValue("text", out value);
                ICell rowHeadercell = rowHeader.CreateCell(i, CellType.String);
                rowHeadercell.SetCellValue(value);
                rowHeadercell.CellComment = listcomm[i];
            }

            //获取参数
            string ClassId = context.Request.QueryString["ClassId"];
            //查询数据
            List<StudentExt> stulist = new ScoreListService().GetScoreByClass(ClassId);
            
            //创建数据行
            for (int i = 0; i < stulist.Count; i++)
            {
                IRow rowContent = worksheet.CreateRow(i + 2);
                for (int k = 0; k < listDic.Count(); k++)
                {
                    //获取导出字段名
                    listDic[k].TryGetValue("value", out value);
                    //返回实例类型
                    Type t = stulist[i].GetType();
                    //获取value属性并取值
                    var proValue = t.GetProperty(value).GetValue(stulist[i], null);
                    string proType = proValue.GetType().Name;
                    //单元格赋值
                    string cellValue = string.Empty;
                    //日期只要年月日
                    if (proType != "DateTime")
                    {
                        cellValue = proValue.ToString();
                    }else
                    {
                        cellValue = Convert.ToDateTime(proValue).ToString("yyyy-MM-dd");
                    }
                    rowContent.CreateCell(k, CellType.String).SetCellValue(cellValue);
                }
            }

            //将Excel工作簿写入输出流
            workbook.Write(context.Response.OutputStream);
        }
    }

 5、后端采用MVC

//将Excel工作簿写入输出流
MemoryStream ms = new MemoryStream();
workbook.Write(ms);
string fileDownloadName = HttpUtility.UrlEncode(filename + '.' + filetype);
var fcr = File(ms.ToArray(), "appliction/x-excel", fileDownloadName);
return fcr;

 


参考资料:
posted @ 2019-11-20 00:40  老余的水壶  阅读(381)  评论(0)    收藏  举报