记录C#实现导出时候遇到的一些坑

最近写导出Excel这个功能,开始了解过,觉得不是挺难,但实际上手写起来遇到了一些小问题,这里记录一下,防止以后再犯

目录

1.生成Excel并存入数据

2.进行导出操作

3.前台下载



1.生成Excel并存入数据

这里使用的是NPIO这个组件实现的Excel导出,用法很简单,这里贴上代码 边写边说

1.1 首先是得拿到你需要转换的数据源,这里每个人获取的数据类型不一样,可能是list,dataset,datatable其实都不影响

 StaticPagedList<E_Arc_Receip> list = bll_Rec.GetArcAllListPage(queryCond, myAccountInfo.ModelSysUser);

1.2 这一节是利用NPIO创建新的Excel来插入数据

  • HSSFWorkbook 这里引用 using NPOI.HSSF.UserModel;
  • Isheet是创建页签,就像你每次打开Excel时,左下角有默认的页签
  • cells创建表头,并且给表头赋值
  • 下面的是给每一列设置宽度,这个值自己调,而且还能设置很多别的样式,这里就自行百度了
HSSFWorkbook excelBook = new HSSFWorkbook();
NPOI.SS.UserModel.ISheet sheet = excelBook.CreateSheet("收文表");
NPOI.SS.UserModel.IRow cells = sheet.CreateRow(0);
//设置表头
cells.CreateCell(0).SetCellValue("来文编号");
cells.CreateCell(1).SetCellValue("公文标题");
cells.CreateCell(2).SetCellValue("文种");
//设置列宽
sheet.SetColumnWidth(0, 10000);
sheet.SetColumnWidth(1, 30000);
sheet.SetColumnWidth(2, 10000);

1.3 循环给每一列赋值

  • 这里从数据源拿数据,利用for循环对每一列赋值
  • 需要从i+1行开始赋值,因为第一行已经设置了表头
for (int i = 0; i <list.Count; i++)
{
    //创建行
    NPOI.SS.UserModel.IRow celllist = sheet.CreateRow(i+1);
    //添加数据
    celllist.CreateCell(0).SetCellValue(list[i].FormerNum);
    celllist.CreateCell(1).SetCellValue(list[i].Title);
    celllist.CreateCell(2).SetCellValue(list[i].ClassID);
}

2.进行导出操作

我这里的做法是前台ajax请求,然后返回一个状态码以及下载地址返回前台,在进行访问地址下载,因为ajax没有办法获取到我后台直接返回的文件流,所以没法调用到浏览器的下载。如果有别的更好的办法,也可以进行参照

2.1 先将文件保存到本地(服务器)

  • path可以跟你自己的路径来定,采用配置文件动态获取
  • 创建一个文件流,并将上面生成的Excel写入流中,最后记得关闭,不然文件存到本地但是无法打开
string fileName = "收文检索信息" + Guid.NewGuid().ToString() + ".xls";
string path = ConfigurationManager.AppSettings.Get("ExOAFileUrl");
string filePath = Path.Combine(path, fileName);
FileStream fs = new FileStream(filePath, FileMode.Create);
excelBook.Write(fs);
fs.Close();

2.2将路径以json返回到前台

  • 这里我将URL地址转换了一下,因为我的path是物理路径,得转换为相对路径才可以
  • 下面的方法仅供参考,还是需要根据自己的实际路径进行修改
filePath = "/" + urlconvertor(filePath);
return Json(new { Result = true, Message = "转换Excel成功,正在请求下载!" , FilePath =  filePath },JsonRequestBehavior.AllowGet);


 private string urlconvertor(string imagesurl1)
        {
            string tmpRootDir = Server.MapPath(System.Web.HttpContext.Current.Request.ApplicationPath.ToString());//获取程序根目录
            string imagesurl2 = imagesurl1.Replace(tmpRootDir, ""); //转换成相对路径
            imagesurl2 = imagesurl2.Replace(@"\", @"/");
            //imagesurl2 = imagesurl2.Replace(@"Aspx_Uc/", @"");
            return imagesurl2;
        }

这样一来,后台的事就结束了,剩下就是前台的事情了


3.前台下载

 

3.1前台是使用ajax请求的,就直接在success里面写代码

  • 这里我的需求不一样,因为我的文件名是随机的GUID,不能让用户下载下来就是随机字符,所以要进行一下统一替换
  • 用了一个download方法,这里面具体的替换方式可以参考代码自己研究一下,这里就不写太多
if (result.Result) 
{
    alert(result.Message);
    download(result.FilePath, '发文检索表');
    //location.href = encodeURI(result.FilePath);
    console.log(result.FilePath);
}


//附上替换方法
function getBlob(url, cb) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.onload = function () {
        if (xhr.status === 200) {
            cb(xhr.response);
        }
    };
    xhr.send();
}


function saveAs(blob, filename) {
    if (window.navigator.msSaveOrOpenBlob) {
        navigator.msSaveBlob(blob, filename);
    } else {
        var link = document.createElement('a');
        var body = document.querySelector('body');

        link.href = window.URL.createObjectURL(blob);
        link.download = filename;

        // fix Firefox
        link.style.display = 'none';
        body.appendChild(link);

        link.click();
        body.removeChild(link);

        window.URL.revokeObjectURL(link.href);
    };
}


function download(url, filename) {
    getBlob(url, function (blob) {
        saveAs(blob, filename);
    });
};

到这里就结束了一个导出功能,可能有些人会觉得这样长时间,存在服务器上的文件会越来会多,这里可以写一个定时服务,去定期删掉前一天的冗余文件,至于怎么实现,这个就后面在更新了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值