jxl和poi处理excel之比较

     功能需求是根据客户提供的excel模板,程序动态填充其中的一些数据。该模板包含大量的宏,刚拿到的时候头都要晕了,本人虽天天和电脑打交道,但是excel咱不是高手啊,什么宏,之前光听过,听着都觉得是高级的东西,就晕,但作为富有责任心的程序员,咱得攻克,也真的攻克了,现在鄙人去搞财务也没问题啊。

之前看各种评论说poi普遍对excel的支持更多一些,比较好用,具体jxl不好用在哪里,没有具体的说法,我就以为无伤大雅,而且项目之前的一些功能都是用jxl的,我就继续沿用jxl。首先来说下流程:

1.根据excel模板创建新工作簿,本质就是copy一份新的,在新的上面进行后续操作。

2.读取其中两个sheet页,对其中内容进行修改。

3.设置密码保护。

4.给第一个sheet页设置选中状态。

5.写出excel文件,关闭流之类的。

下面直接贴代码,这都是沥心之作啊,一笔一画都是心血,程序猿亏心亏脑啊,天气炎热,得好好休养。

首先是变量,这玩意是我自己项目需要,贴出来只为大家看代码看的明白,没啥意思的哈。

 int colRefNo = 8;        //RefNo所在列,列数是从0开始
 int colVari = 9;      //Variables所在列
 int colChannel = 10;  //Channel所在列
 
 int colAFYP= 11;  //AFYP所在列
 int colNBSP= 12;    //NBSP所在列
 int colVONB= 14;   //VONB所在列
 
 int channelNum = 8; //excel模板channel的个数 
 int channelPart = 35;  //每个channel的部分占多少行
 int startRow = 18;    //excel模板上数据的起始行,行数从0开始的

先贴jxl,断断续续搞了近一个月,中间端午回家,要不是因为它,我完全可以毫无牵挂地休上半个月到一个月的,说起都是泪啊。

 public String modifyExcel(){
  String infilepath = "c:/AA.xls";//模板文件位置
  String filePath = "c:/test/";
  String fileName = "jxlFile.xls";
  String targetfile = filePath + fileName;//生成文件位置
  File file = new File(targetfile);
  //判断文件夹是否存在,不存在就创建
  File parent = file.getParentFile();
  if (parent != null && !parent.exists()) {
   parent.mkdirs();
  }
  //创建新工作簿
  Workbook rw = null;
  WritableWorkbook  wwb = null;
  
  try {
   rw = Workbook.getWorkbook(new File(infilepath)); //读入excel模板
  } catch (Exception e) {
   e.printStackTrace();
   return e.getMessage();
  }
  try {
   wwb = Workbook.createWorkbook(file, rw); //根据现有只读文件创建一个可写入的Excel工作薄对象
  } catch (Exception e) {
   e.printStackTrace();
   return e.getMessage();
  }
  //读取第一张隐藏的工作表,取消隐藏属性
  WritableSheet ws0 = wwb.getSheet(0);  
  ws0.setHidden(true);
  System.out.println("===ws0.isHidden()="+ws0.isHidden()+"==ws0.isProtected()==="+ws0.isProtected());
  
  WritableSheet wsPP = wwb.getSheet(2);    //读取第三张工作表,PP
  
  WritableSheet wsNP = wwb.getSheet(3);   //读取第四张工作表,NP
   
  wsPP = modifySheet(wsPP,"PP");   //对PP修改内容
  wsNP = modifySheet(wsNP,"NP");   //对NP修改内容
  
  SheetSettings ssPP = wsPP.getSettings();//设置PP的密码保护
  ssPP.setPassword("ABCDEFG");
  ssPP.setProtected(true);
  
  SheetSettings ssNP = wsNP.getSettings();//设置NP的密码保护
  ssNP.setPassword("ABCDEFG");
  ssNP.setProtected(true);
  
  ssNP.setSelected(false);
  //读取第二张的工作表,设置选中状态
  WritableSheet ws1 = wwb.getSheet(1);  
  ws1.getSettings().setSelected(true);
  
  //写入Excel对象
  try {
   wwb.write();
  } catch (Exception e) {
   return e.getMessage();
  }
  //关闭可写入的Excel对象
  try {
   wwb.close();
  } catch (Exception e) {
   e.printStackTrace();
   return e.getMessage();
  }
  //关闭只读的Excel对象
  rw.close();  
  return "文件"+fileName+"已生成在"+filePath+"下!";
 }

 private WritableSheet modifySheet(WritableSheet ws,String pnp) {
  
  int start = startRow;
  DailySalesBean dsb = new DailySalesBean();
  dsb.setPnp(pnp);

  for (int j= 0 ; j< channelNum; j++){
   int end = start+channelPart;
   for(int i= start;i< end;i++){

    Cell cellRefNo = ws.getCell(colRefNo, i);
    Cell cellVari = ws.getCell(colVari, i);
    Cell cellChannel = ws.getCell(colChannel, i);
    //获取excel中某些列的值作为查询条件
    dsb.setRefno(ObjectUtil.isEmpty(cellRefNo.getContents())?"":cellRefNo.getContents());
    dsb.setVari(ObjectUtil.isEmpty(cellVari.getContents())?"":cellVari.getContents());
    dsb.setChannel(ObjectUtil.isEmpty(cellChannel.getContents())?"":cellChannel.getContents());
    //根据条件得出数据结果
    DailySalesBean dsb2 = getDailyData(dsb);

    WritableCell afypCell = ws.getWritableCell(colAFYP,i);
    if(afypCell.getType() == CellType.NUMBER ){//单元格的数据格式,保证是number类型,涉及到自动计算
     Number afyp = (Number)afypCell;
     afyp.setValue(Double.parseDouble(dsb2.getAfyp()));//修改单元格的数值
    }
    WritableCell nbspCell = ws.getWritableCell(colNBSP,i);
    if(nbspCell.getType() == CellType.NUMBER ){
     Number nbsp = (Number)nbspCell;
     nbsp.setValue(Double.parseDouble(dsb2.getNbsp()));
    }
    WritableCell vonbCell = ws.getWritableCell(colVONB,i);
    if(vonbCell.getType() == CellType.NUMBER ){
     Number vonb = (Number)vonbCell;
     vonb.setValue(Double.parseDouble(dsb2.getVonb()));
    }
   //上面是获取单元格,直接修改值。下面注释掉的是另外一种方法,是new一个新的单元格,设置完值之后,add到sheet页里面去,个人觉得有种多余,应该浪费资源会多一

//点。但是在将数据单元格改为字符串单元格,涉及到数据类型更改的时候,后一种方法就派上用场了。
/* CellFormat cf1 = null;
    CellFormat cf2 = null;
    CellFormat cf3 = null;
      if(j==0 && k==1 ){
     Cell afypCell_old = ws.getCell(colAFYP,i);
     Cell nbspCell_old = ws.getCell(colNBSP,i);
     Cell vonbCell_old = ws.getCell(colVONB,i);
     
     cf1 = afypCell_old.getCellFormat();
     cf2 = nbspCell_old.getCellFormat();
     cf3 = vonbCell_old.getCellFormat();//为保持原有单元格的样式,譬如边框,颜色,字体之类的,需要获取原有样式赋到新单元格上
    }
     Number afypCell = new Number(colAFYP, i, Double.parseDouble(dsb2.getAfyp()));
    afypCell.setCellFormat(cf1);
    try {
     ws.addCell(afypCell);
    } catch (Exception e) {
     e.printStackTrace();
    }
    
    Number nbspCell = new Number(colNBSP, i, Double.parseDouble(dsb2.getNbsp()));
    nbspCell.setCellFormat(cf2);
    try {
     ws.addCell(nbspCell);
    } catch (Exception e) {
     e.printStackTrace();
    }
    
    Number vonbCell = new Number(colVONB, i, Double.parseDouble(dsb2.getVonb()));
    vonbCell.setCellFormat(cf3);
    try {
     ws.addCell(vonbCell);
    } catch (Exception e) {
     e.printStackTrace();
    }
    */
   }
   start += channelPart;
  }
  return ws;
 }

再贴个简洁的POI代码:

 public String modifyExcel(){
  String infilepath = "c:/AA.xls";
  String filePath = "c:/Sales_Daily_java/";
  String fileNane = "InputTemplate-Sales_Daily_Draft.xls";
  String targetfile = filePath + fileNane;
  File file = new File(targetfile);
  //判断文件夹是否存在,不存在就创建
  File parent = file.getParentFile();
  if (parent != null && !parent.exists()) {
   parent.mkdirs();
  }
  //创建新工作簿
  HSSFWorkbook wb = null;//创建97-03版excel,如果是07-10版,则XSSFWorkbook wb = null;
  NPOIFSFileSystem fs = null;
  try {
   fs = new NPOIFSFileSystem(new File(infilepath));
  } catch (Exception e1) {
   e1.printStackTrace();
   return "读取excel模板文件失败!";
  }
  try {
   wb = new HSSFWorkbook(fs.getRoot(),true);
  } catch (Exception e1) {
   e1.printStackTrace();
   return "创建excel文件失败!";
  }

  //读取第三张工作表,PP_DailyInput
   Sheet spp = wb.getSheetAt(2);
  //读取第四张工作表,NP_DailyInput
   Sheet snp = wb.getSheetAt(3);
   
  spp = modifySheet(spp,"PP");   //对PP_DailyInput修改内容
  snp = modifySheet(snp,"NP");   //对NP_DailyInput修改内容
  
  spp.protectSheet("XDFZALDEXCAVPGS");//设置PP_DailyInput Sheet的密码保护
  snp.protectSheet("XDFZALDEXCAVPGS");//设置NP_DailyInput Sheet的密码保护
  
  snp.setSelected(false);
  //读取第二张的工作表,设置选中状态
  Sheet s1 = wb.getSheetAt(1);
  s1.setSelected(true);
  
   //输出流文件,关闭流
  FileOutputStream fileOut = null;
  try {
   fileOut = new FileOutputStream(targetfile);
   wb.write(fileOut);
   fileOut.flush();
   fileOut.close();
  } catch (Exception e) {
   e.printStackTrace();
   return "excel文件生成失败!";
  }
  try {
   fs.close();  //一定要比上面的后关闭,不然write的时候会抛异常,文件写出不了
  } catch (IOException e1) {
   e1.printStackTrace();
  }
  return "文件"+fileNane+"已生成在"+filePath+"下!";
 }
 /**
  * 获取单元格的值
  * @param cell
  * @return
  */
 private String getCellValue(Cell cell){
  String result = null;
  switch (cell.getCellType()) {
  
         case Cell.CELL_TYPE_STRING:
          
          result = cell.getRichStringCellValue().getString();
          break;
         case Cell.CELL_TYPE_NUMERIC:
          
             if (DateUtil.isCellDateFormatted(cell)) {
        result = cell.getDateCellValue().toString();
             } else {
              Double cellValue = cell.getNumericCellValue();
              DecimalFormat df = new DecimalFormat("#.#");
              result = df.format(cellValue);
             }
             break;
         case Cell.CELL_TYPE_BOOLEAN:
          
    result = Boolean.toString(cell.getBooleanCellValue());
          break;
         case Cell.CELL_TYPE_FORMULA:
          
    result = cell.getCellFormula();
             break;
         default:
          result ="";
     }
  if(StringUtils.isEmpty(result)){
   result = "";
  }
  return result;
 }
 private Sheet modifySheet(Sheet ws,String pnp) {
  
  int start = startRow;
  DailySalesBean dsb = new DailySalesBean();
  dsb.setPnp(pnp);

  for (int j= 0 ; j< channelNum; j++){
   int end = start+channelPart;
   for(int i= start;i< end;i++){
    Row row = ws.getRow(i);
    Cell cellRefNo = row.getCell(colRefNo);
    Cell cellVari = row.getCell(colVari);
    Cell cellChannel = row.getCell(colChannel);
    
    dsb.setRefno(getCellValue(cellRefNo));
    dsb.setVari(getCellValue(cellVari));
    dsb.setChannel(getCellValue(cellChannel));
    
    DailySalesBean dsb2 = getDailyData(dsb);
    
    Cell afypCell = row.getCell(colAFYP);
    afypCell.setCellValue(Double.parseDouble(dsb2.getAfyp()));
    
    Cell nbspCell = row.getCell(colNBSP);
    nbspCell.setCellValue(Double.parseDouble(dsb2.getNbsp()));
    
    Cell vonbCell = row.getCell(colVONB);
    vonbCell.setCellValue(Double.parseDouble(dsb2.getVonb()));
   }
   start += channelPart;
  }
  ws.setForceFormulaRecalculation(true);//excel中有写计算公式,数据修改之后强制重新调用里面的公式自动计算
  return ws;
 }

现在来总结下吧,之所以最后UAT发布关头改变方法,是因为jxl生成出来的excel在用office2010或07打开的时候总弹出来俩数据丢失和数据格式丢失的alert框,这玩意给客户感觉得是多不好啊,而且客户给的excel模板比较恶心,貌似因为宏的原因隐藏了个sheet页,一打开的时候下面的sheet页切换不灵光,而且原有的sheet设置的tab颜色也丢了。如果用office2003打开,那就是直接都打不开了,一打开就直接excel停止工作。琢磨了三四天,各种资料查下来都说是excel各种版本不兼容之类的问题,大家混乱的解决方案下来我也没解决问题。痛心之下抱着死马当活马医的心态,在发布UAT的前一天晚上查询poi的相关资料,对比了下jxl和poi的不同写法,第二天一早动笔修改程序,换血用poi重写代码,那边在如火如荼地发布,解决发布过程中的各种问题,我这边淡定地写着代码,终于赶在他们解决完问题之前写完了代码,中午写完,测试的时候,心情那个忐忑啊,要是还不行,我估计就得撞墙去了。颤抖着手,咽着快餐,启动服务器,测试,生成,生成的excel完美,和模板一模一样,激动的我呀,小心肝都快飞出来了。没有alert框,sheet切换正常,tab颜色也在,perfect!!!经此一事,忠实拥戴poi,看了下poi的api,齐全的,各种office操作的东西,poi都有相应的方法可供调用。

参考文献:http://poi.apache.org/spreadsheet/quick-guide.html#Iterator,著名的Busy Developers' Guide to HSSF and XSSF Features,新手必看,比看API块

 

转载于:https://www.cnblogs.com/cl1234/p/jxl-poi-excel.html

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值