execl模板导入导出

  最近接到一个需求,公司财务有个execl里面已经写满了各种计算公式多个sheet公式嵌套等,bd直接往execl中指定的单元格填充数据,execl中的公式可以算出所有的测算结果。现在这个需要做到系统中去,由于公式过于复杂而且多变(财务会已经调整了好几个版本了),于是不将计算逻辑放在系统中实现。在模块的页面中填数据,并返回计算结果到页面。

  开始做使用npoi-2.21 时发现一个问题,在某一个单元格中计算出来数据有误差,于是做了一个实验读取execl模板转成IO流输出从页面下载出来,

对两个模板填一样的数据,发现经过  workbook = new XSSFWorkbook(execlStream);下载出的模板数据出现误差,于是升级npoi到2.3.0。重复实验这回模板正确了。

Execl中需要填写的位置坐标是已知的,于是将这些坐标做成一张配置表并存入。

    获取到workbook 并指定 将要操作的sheet;

 IWorkbook workbook= new XSSFWorkbook(execlStream);
  ISheet sheet = workbook.GetSheet("指定sheet")

接下来设置指定单元格的值

 sheet.GetRow(Y).GetCell(X).SetCellValue(value);

我们从execl中看到的坐标一般的都是 A1、B2、C3 然而GetRow()于GetCell()的参数设定为int类型,于是需要一个转换坐标将我们的A1...这些坐标做转换。

 /// <summary>
        /// 将Excel坐标转换成10进制坐标, Item1 Row ,Item2 Column
        /// </summary>
        /// <param name="strCoordinate"></param>
        /// <returns></returns>
        private Tuple<int, int> TransferCoordinate(string strCoordinate)
        {
            int rowNumber = 0, columnNumber = 0;
            string strRowNum, strColumnNum;
            //获得换行数
            MatchCollection collection = Regex.Matches(strCoordinate, @"\d+");
            strRowNum = collection[0].ToString();
            rowNumber = int.Parse(strRowNum);
            //获得列数
            collection = Regex.Matches(strCoordinate, @"[A-Z]{1,3}");
            strColumnNum = collection[0].ToString();
            columnNumber = CalColumnNum(strColumnNum);
            return new Tuple<int, int>(rowNumber - 1, columnNumber - 1); ;
        }

        /// <summary>
        /// 获得Excel 列坐标
        /// </summary>
        /// <param name="strCol"></param>
        /// <returns></returns>
        private int CalColumnNum(string strCol)
        {
            int num = 0, charNum;
            var charArr = strCol.ToUpper().Trim().ToCharArray();
            for (int i = charArr.Length - 1, j = 0; i >= 0; i--, j++)
            {
                charNum = (int)charArr[i] - 64;
                num += (int)Math.Pow(26, j) * charNum;
            }

            return num;
        }

通过转换得到   Tuple<int, int> 得到单元格的坐标赋值

sheet.GetRow(coordinate.Item1).GetCell(coordinate.Item2).SetCellValue(number);

设置 sheet.ForceFormulaRecalculation = true; npoi提供用于重新计算公式

cell.SetCellFormula()  可以在后台代码中设置单元格公式

到此处,对模板的写入已经公式计算已经完成。可以直接做流输出下载。。。

  我们的需求是将这计算的结果返回到页面中去显示,已经在内存中做了写入于公式计算,继续使用当前的workbook做值读取

IFormulaEvaluator evaluator = new XSSFFormulaEvaluator(workbook);
  foreach (var item in daseInfo)
  {
        Tuple<int, int> ElementCoordinate = TransferCoordinate(item.PostionCode);//坐标转换

      ICell cell = sheet.GetRow(ElementCoordinate.Item1).GetCell(ElementCoordinate.Item1);
       cell = evaluator.EvaluateInCell(cell);   string value =cell.NumericCellValue
 }

   本人在这个地方再次出现了读取出来的值存在误差的BUG,大概一百个单元格的读取,全都使用公式,有两个单元格值存在误差。使用上面的验证,模板转换流,流转回模板都没问题,于是发了封反馈邮件,没有出现此问题的朋友可以使用以上方式。

确认为npoi读取bug,确定使用aspose  16.12版,由于没有授权,在使用过程中发现aspose对于单元格写入做了限制,写入无效,但是读取execl是可以的,而且读写更方便,对于公式支持也足够强大,问题是要钱....钱....钱...公司不出钱,低版本的破解版对于公式的支持不足,于是将两个控件混合使用,NOPI做写入,aspose做读取。

        //将workbook转化成流        MemoryStream stream = new MemoryStream();
        workbook.Write(stream);        //aspose读取流做读取
        Aspose.Cells.Workbook work = new Aspose.Cells.Workbook(stream);
                Aspose.Cells.Cells c = work.Worksheets["填写的sheet"].Cells;
                work.CalculateFormula();////获取经过公式计算的数据------          //循环坐标 aspose支持string格式的坐标参数也就是 A1  A2foreach (var item in daseInfo)
                {
                    var value = c[item.PostionCode].StringValue;

                }
时间: 2024-08-26 13:37:00

execl模板导入导出的相关文章

基于ajaxFileUpload和Java IO的可视化项目模板导入导出功能

目前部门在做的(大)数据可视化项目中增加了一个模板功能,经过一个星期的摸索,总算是打包提交测试通过了.这里记下一些技术要点,温故知新. 1,模板文件的格式设计 模板导出和导入的文件为一个“模板名称.zip”的压缩包.包内含有一个temp.json文件和若干资源文件(图片,视频,MP3音乐等). temp.json文件格式: { “content” : ”…”, //模板内容 “thumbnail” : “…”, //模板缩略图 “name” : “…”, //模板名称 “resource” :

Asp.net中利用NPOI组件快速导入导出Execl数据

相信很多童鞋都开发过Execl的导入导出功能,最近产品中无论是后台数据分析的需要,还是前端满足用户管理的方便,都有Execl导入导出的维护需求产生. 以前做这个功能,如果是web,利用HttpContext.Current.Response.ContentType ="application/ms-excel";就可以导出html数据表格到execl中,这种方法的问题就是编码格式的兼容性太差,用Mac OS之类的 office打开直接乱码给你看.或者是调用office的COM组件,或宏

Excel导入导出的业务进化场景及组件化的设计方案(转)

1:前言 看过我文章的网友们都知道,通常前言都是我用来打酱油扯点闲情的. 自从写了上面一篇文章之后,领导就找我谈话了,怕我有什么想不开. 所以上一篇的(下)篇,目前先不出来了,哪天我异地二次回忆的时候,再分享分享. 话说最近外面IT行情飞涨还咋的,人都飞哪去了呢,听说各地的军情都进入紧急状态了. 回归下正题,今天就抽点时间,写写技术文,和大伙分享一下近年在框架设计上的取的一些技术成果. 2:项目背景 在针对运营商(移动.联通.电信.铁塔)的信息类的系统中,由于相关的从业人员习惯于Excel的办公

excel导入导出优化

对于上一篇excel中出现的问题,在excel导入导出中都做了优化.还是eclipse+jdk1.8,但是这个项目是一个web项目,需要配合Tomcat服务器,并且使用了SSH框架, I/O操作过多 首先,对于I/O操作过多,那么就不像之前一样,一条一条的添加或者更新;而且凑齐一堆,也就是一个list集合,然后统一的批量保存. 使用SessionFactory获取当前的session,然后调用session的persist方法,保存实体.只是设置了一个批量的量值.每到30条数据,就将缓存同步到数

CSDN-markdown编辑器之导入导出文档功能

CSDN-markdown编辑器支持从线上和本地导入Markdown文件.导出Markdown文件和HTML文件的功能.在工具栏上有三个按钮来实现这些功能.这三个按钮分别是:从线上导入MD文件.从本机导入MD文件.导出到本地. CSDN-markdown编辑器的导入功能让我们很方便的基于已有的Markdown文件进行重新编辑修改,然后发表博文. CSDN-markdown编辑器的导出功能让我们很容易的将在CSDN上发表的博文进行本地存档备份,或者你导出到本地后,再上传到CSDN CODE上进行在

PHP导入导出excel表格图片(转)

写excel的时候,我用过pear的库,也用过pack压包的头,同样那些利用smarty等作的简单替换xml的也用过,csv的就更不用谈了.呵呵.(COM方式不讲了,这种可读的太多了,我也写过利用wps等进行word等的生成之类的文章 )但是在读的时候,只用过一种,具体是什么忘了,要回去翻代码了.基本上导出的文件分为两种:1:类Excel格式,这个其实不是传统意义上的Excel文件,只是因为Excel的兼容能力强,能够正确打开而已.修改这种文件后再保存,通常会提示你是否要转换成Excel文件.优

PHPExcel导入导出

慕课教程 -- PHPExcel导入导出 一.PHPExcel导出操作 1.快速入门 <?php #找到当前脚本的路径 $dir = dirname(__FILE__); #引入PHPExcel插件文件 require $dir."/excel/PHPExcel.php"; #实例化PHPExcel类 $objPHPExcel = new PHPExcel(); #获得当前活动sheet的操作对象 $objSheet = $objPHPExcel->getActiveShe

将数据填充到已有的EXECL模板中

导出execl网上一大堆,最近遇到将数据导出到已有的execl模板中,具体到某行列,动态加载数据. 添加 Microsoft.Office.Interop.Excel 引用 1 /// <summary> 2 /// DataGridView 导出到execl模板中 3 /// </summary> 4 /// <param name="fileName">execl模板路径</param> 5 /// <param name=&q

Oracle数据库导入导出逻辑备份方法总结

[EXP常用参数] USERID  即用户名/密码该参数就必须且为第一个: FILE    指定数据输出文件路径: LOG     指定日志输出文件路径: TABLES  导出指定表数据: FULL    完全导出整个文件(N): ROWS    导出数据行(Y): QUERY   用于导出表的子集的 select 子句: [示例] 1.[全库模式]将数据库orcl完全导出,用户名scott密码scott数据文件导出到D:/orcl/scott.dmp,日志文件到出到D:/orcl/scott.