java往固定模板excel写入数据,最后导出

本文介绍了一种使用Java反射机制将实体类数据写入Excel的方法,适用于需要批量处理数据并将其导入Excel表格的场景。文章详细解释了如何通过反射获取实体类的字段,并将这些字段的数据写入指定的Excel单元格。

package cn.windy.samary.utils.excelUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import cn.windy.samary.module.shop.Vo.AliVo;
import cn.windy.samary.utils.DateUtil;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

/**

  • @Auther: kxs

  • @Date: 2019/8/19 08:51

  • @Description:
    */
    public class NewExcelUtils {

    private static final Logger logger = Logger.getLogger(NewExcelUtils.class);

    /**

    • 利用java反射,将java实体类中的数据写入到excel表格中

    • @param excelUrl 要写入数据的excel表格的绝对路径

    • @param dateList 要写入excel表格的数据集

    • @param classType 封装数据的实体类类型

    • @param startRow 从excel表格的第 startRow行开始写入数据。假如是从第三行开始写入数据,那么startRow=2

    • @param total 写入实体类中的前 total 个字段的数据,因为一个实体类可能有很多字段,但是只有部分字段是需要使用的,并且,实体类中的字段顺序应保持与excel表中每个指定单元格的位置一致,否则会造成写入的数据混乱或失败
      */
      public static void appendDateToExcel(String excelUrl, List<?> dateList, Class<?> classType,
      int startRow, int total) throws Exception {

      FileInputStream fs = null;
      FileOutputStream out = null;
      HSSFWorkbook wb = null;
      try {

       Field[] fields = classType.getDeclaredFields();// 得到对象中的字段
      
       fs = new FileInputStream(excelUrl); // 获取head.xls
      
       POIFSFileSystem ps = new POIFSFileSystem(fs); // 使用POI提供的方法得到excel的信息
       wb = new HSSFWorkbook(ps);
       HSSFSheet sheet = wb.getSheetAt(0); // 获取到工作表,因为一个excel可能有多个工作表
      
       out = new FileOutputStream(excelUrl); // 向head.xls中写数据
       // 利用反射获取对象中的所有字段
       Field field = null;
       String fieldName = null;
       String getMethodName = null;
       Method getMethod = null;
       HSSFRow row = null;
       String type = null;
       Object obj = null;
       Object o = null;
      
       int num=0;
       // 遍历所有的对象
       for (int i = 0, k = startRow; i < dateList.size(); i++, k++) {
           o = dateList.get(i);
      
           // 从指定行开始写入,如果是第3行开始写,则k=2(excel中的行默认从0开始)
           row = sheet.createRow((short) (k));
      
           //因为我的excel表中每一行的第一个单元格都是序号,此处可按需要修改
          // row.createCell(0).setCellValue(++num);
      
           // 一个实体类中可能有很多字段,但是只有部分字段才是我们需要的,将需要的字段放在实体类中的最前面,并设置读取位置
           for (int j = 0; j < total; j++) {
      
               field = fields[j];
               fieldName = field.getName();
               getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
               getMethod = classType.getMethod(getMethodName);
      
               obj = getMethod.invoke(o);// 调用对象的getXXX方法
      
               // 这个字段是空值,就取消写入
               if (obj == null) {
                   continue;
               }
      
      
               // 获取属性类型
               type = field.getGenericType().toString();
      
               switch (type) {
                   case "class java.lang.String":
                       row.createCell(j).setCellValue(rvZeroAndDot((String) obj));
                       break;
                   case "class java.lang.Integer":
                       row.createCell(j).setCellValue((Integer) obj);
                       break;
                   case "class java.lang.Double":
                       row.createCell(j).setCellValue((Double) obj);
                       break;
                   case "class java.lang.Boolean":
                       row.createCell(j).setCellValue((Boolean) obj);
                       break;
                   case "class java.util.Date"://日期类型的数据直接转换成字符串格式写入,否则读到excel表后可能无法识别
                       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                       row.createCell(j).setCellValue(sdf.format((Date) obj));
                       break;
                   default:
                       row.createCell(j).setCellValue((String) obj);
                       break;
               }
           }
       }
      

      } catch (Exception e) {
      logger.info(“往excel表中写入数据异常:” + e.getMessage());
      throw e;
      } finally {
      try {
      if (out != null) {
      out.flush();
      }

           if (wb != null) {
               wb.write(out);
           }
      
           if (out != null) {
               out.close();
           }
       } catch (Exception e) {
           logger.info("往excel表格写入数据异常:"+e.getMessage());
       }
      

      }

    }

    //去除数后面多余的0
    public static String rvZeroAndDot(String s){
    if (s.isEmpty()) {
    return “null”;
    }
    if(s.indexOf(".") > 0){
    s = s.replaceAll(“0+?","");//去掉多余的0s=s.replaceAll("[.]", "");//去掉多余的0 s = s.replaceAll("[.]","");//0s=s.replaceAll("[.]”, “”);//如最后一位是.则去掉
    }
    return s;
    }

    /**

    • 复制excel表格,该excel表格的格式应该是.xls

    • @param modelExcel 模板excel文件的路径

    • @param newExcel 新复制的excel文件需要保存的路径

    • @param newName 新复制的excel文件的文件名
      */
      public static void copyExcel(String modelExcel, String newExcel,String newName) {
      HSSFWorkbook wb = null;
      FileInputStream fis = null;
      FileOutputStream fos = null;
      try {

       File file=new File(newExcel);
       if(!file.exists()){
           file.mkdirs();
       }
       fis = new FileInputStream(modelExcel);
       fos = new FileOutputStream(newExcel+"/"+newName);
       wb = new HSSFWorkbook(fis);
       wb.write(fos);
      

      } catch (Exception e) {
      logger.info(“复制excel表格异常1:” + e.getMessage());
      } finally {
      try {
      if (fis != null) {
      fis.close();
      }
      if (fos != null) {
      fos.close();
      }
      } catch (IOException e) {
      logger.info(“复制excel表格异常2:” + e.getMessage());
      }
      }
      }

    /* public static void main(String[] args) {
    try {

             List<AliVo> list = new ArrayList<>();
             for (int i = 0; i <10; i++) {
                 AliVo aliVo =  new AliVo();
                 aliVo.setId("id"+i);
                 aliVo.setName("name"+i);
                 aliVo.setRemark("remark"+i);
                 aliVo.setAliPhone("phone"+i);
                 aliVo.setMoney("money"+i);
                 list.add(aliVo);
             }
             System.out.println(list);
             //模板文件的绝对路径
             String modelExcel = "D:\\aaa\\haha.xls";
    
             String fileName="newfile.xls";
    
             //复制模板
             NewExcelUtils.copyExcel(modelExcel, "D:\\aaa\\",fileName);
    
             //新文件的路径
             fileName="D:\\aaa\\"+fileName;
    
             //往文件中写数据
             NewExcelUtils.appendDateToExcel(fileName, list, AliVo.class, 2, 5);
    
             //此处隐藏核心业务
    
         } catch (Exception e) {
             System.out.println(e);
         }
     }*/
    

}

Controller层
List aliVoList =自己查询出来的数据

try {
if(CollectionUtils.isEmpty(aliVoList)) aliVoList =new ArrayList<>();
//模板文件的绝对路径
String modelExcel = Test.class.getClassLoader().getResource(“excel/ali.xls”).getPath();
String url =Test.class.getClassLoader().getResource(“excel/”).getPath();
String orderNo = getOrderNo();
String fileName=orderNo+".xls";
//复制模板
NewExcelUtils.copyExcel(modelExcel, url,fileName);
//新文件的路径
fileName=url+fileName;
//往文件中写数据
NewExcelUtils.appendDateToExcel(fileName, aliVoList, AliVo.class, 2, 5);
//此处隐藏核心业务
String excelName =fileName;
this.exportExcel(orderNo,excelName);
} catch (Exception e) {
e.printStackTrace();
}

//下载excel
public void exportExcel(String menuName,String excelName){
//导出的excel名称
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
HttpServletResponse response = getResponse();
response.addHeader(“Content-Disposition”,
“attachment;filename=” + new String(menuName.getBytes(“gb2312”), “ISO8859-1”) + “.xls”);
os = response.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(excelName));
int i = 0;
while ((i = bis.read(buff)) != -1) {
os.write(buff, 0, i);
os.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

### 导出数据到已有 Excel 模板Java 中,向已有 Excel 模板写入数据导出可以通过多种方式实现,例如使用 Apache POI 或 Alibaba 的 EasyExcel。以下将分别介绍这两种方法,并提供代码示例。 --- #### 使用 Apache POI Apache POI 是一个功能强大的库,用于操作 Microsoft Office 文档,包括 Excel 文件。以下是使用 Apache POI 向已有 Excel 模板写入数据的示例代码: ```java import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class PoiExcelWriter { public static void main(String[] args) { String templatePath = "path/to/your/template.xlsx"; String outputPath = "path/to/output.xlsx"; try (FileInputStream fis = new FileInputStream(templatePath); Workbook workbook = WorkbookFactory.create(fis)) { Sheet sheet = workbook.getSheetAt(0); // 获取第一个sheet页 // 假设我们要在第2第1列写入数据 Row row = sheet.getRow(1); // 第二 if (row == null) { row = sheet.createRow(1); // 如果不存在则创建 } Cell cell = row.getCell(0); // 第一列 if (cell == null) { cell = row.createCell(0); // 如果单元格不存在则创建 } cell.setCellValue("Hello, World!"); // 写入数据 try (FileOutputStream fos = new FileOutputStream(outputPath)) { workbook.write(fos); // 写出到输出文件 } } catch (IOException e) { e.printStackTrace(); } } } ``` --- #### 使用 EasyExcel EasyExcel 是阿里巴巴开源的一个轻量级 Excel 处理工具,特别适合处理大数据量的 Excel 文件。以下是使用 EasyExcel 向已有 Excel 模板写入数据的示例代码: 首先,定义一个数据模型类: ```java public class DemoData { @ExcelProperty("姓名") private String name; @ExcelProperty("年龄") private int age; // 构造方法、getter和setter } ``` 然后,编写导出代码: ```java import com.alibaba.easyexcel.EasyExcel; import com.alibaba.easyexcel.write.metadata.WriteSheet; import java.util.ArrayList; import java.util.List; public class EasyExcelWriter { public static void main(String[] args) { String templatePath = "path/to/your/template.xlsx"; String outputPath = "path/to/output.xlsx"; List<DemoData> dataList = new ArrayList<>(); // 添加测试数据 dataList.add(new DemoData("张三", 25)); dataList.add(new DemoData("李四", 30)); WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build(); EasyExcel.write(outputPath, DemoData.class) .withTemplate(templatePath) .sheet("Sheet1") .doWrite(dataList); } } ``` --- #### 动态填充多个 Sheet 页 如果你的模板包含多个 Sheet 页,并且每个 Sheet 页需要填充不同的数据,可以按照以下方式进: ```java // 假设有两个数据列表 List<DemoData> dataList1 = ...; // 第一个Sheet的数据 List<DemoData> dataList2 = ...; // 第二个Sheet的数据 // 写入第一个Sheet EasyExcel.write(outputPath, DemoData.class) .withTemplate(templatePath) .sheet("Sheet1") .doWrite(dataList1); // 写入第二个Sheet EasyExcel.write(outputPath, DemoData.class) .withTemplate(templatePath) .sheet("Sheet2") .doWrite(dataList2); ``` --- #### 注意事项 - **模板路径**:确保模板文件路径正确,并且模板文件存在。 - **依赖管理**:如果使用 Maven 或 Gradle,确保在构建文件中添加了相应的依赖项。 - **性能优化**:对于大数据量的导出,建议使用 EasyExcel,因为它在内存管理和性能方面表现更好。 --- #### 相关问题 1. 如何在 Java 中使用 Apache POI 读取 Excel 文件? 2. EasyExcel 支持哪些 Excel 版本? 3. 如何在 Java 中处理 Excel 文件中的多个 Sheet 页? 4. 如何在导出 Excel 时设置单元格样式? 5. 如何在 Java 中实现 Excel 文件的批量导出
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值