/** * Copyright (c) 2013-Now http://jeesite.com All rights reserved. */ package com.ruoyi.common.core.excel; import org.apache.poi.hssf.util.CellReference; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.*; import java.util.Calendar; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * Excel超大数据写入,抽象excel2007读入器,先构建.xlsx一张模板,改写模板中的sheet.xml, * 使用这种方法 写入.xlsx文件,不需要太大的内存 * @version 2014-9-2 */ public abstract class ExcelWriter { private SpreadsheetWriter sw; /** * 写入电子表格的主要流程 * * @param fileName * @throws Exception */ @SuppressWarnings("resource") public void process(String fileName) throws Exception { // 建立工作簿和电子表格对象 XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet("sheet1"); // 持有电子表格数据的xml文件名 例如 /xl/worksheets/sheet1.xml String sheetRef = sheet.getPackagePart().getPartName().getName(); // 保存模板 FileOutputStream os = new FileOutputStream("template.xlsx"); wb.write(os); os.close(); // 生成xml文件 File tmp = File.createTempFile("sheet", ".xml"); Writer fw = new FileWriter(tmp); sw = new SpreadsheetWriter(fw); generate(); fw.close(); // 使用产生的数据替换模板 File templateFile = new File("template.xlsx"); FileOutputStream out = new FileOutputStream(fileName); substitute(templateFile, tmp, sheetRef.substring(1), out); out.close(); // 删除文件之前调用一下垃圾回收器,否则无法删除模板文件 System.gc(); // 删除临时模板文件 if (templateFile.isFile() && templateFile.exists()) { templateFile.delete(); } } /** * 类使用者应该使用此方法进行写操作 * * @throws Exception */ public abstract void generate() throws Exception; public void beginSheet() throws IOException { sw.beginSheet(); } public void insertRow(int rowNum) throws IOException { sw.insertRow(rowNum); } public void createCell(int columnIndex, String value) throws IOException { sw.createCell(columnIndex, value, -1); } public void createCell(int columnIndex, double value) throws IOException { sw.createCell(columnIndex, value, -1); } public void endRow() throws IOException { sw.endRow(); } public void endSheet() throws IOException { sw.endSheet(); } /** * * @param zipfile the template file * @param tmpfile the XML file with the sheet data * @param entry the name of the sheet entry to substitute, e.g. xl/worksheets/sheet1.xml * @param out the stream to write the result to */ private static void substitute(File zipfile, File tmpfile, String entry, OutputStream out) throws IOException { try ( ZipFile zip = new ZipFile(zipfile); ZipOutputStream zos = new ZipOutputStream(out); InputStream is = new FileInputStream(tmpfile); ){ @SuppressWarnings("unchecked") Enumeration en = (Enumeration) zip.entries(); while (en.hasMoreElements()) { ZipEntry ze = en.nextElement(); if (!ze.getName().equals(entry)) { zos.putNextEntry(new ZipEntry(ze.getName())); try (InputStream is2=zip.getInputStream(ze)){ copyStream(is2, zos); } } } zos.putNextEntry(new ZipEntry(entry)); copyStream(is, zos); } } private static void copyStream(InputStream in, OutputStream out) throws IOException { byte[] chunk = new byte[1024]; int count; while ((count = in.read(chunk)) >= 0) { out.write(chunk, 0, count); } } /** * 在写入器中写入电子表格 * */ public static class SpreadsheetWriter { private final Writer _out; private int _rownum; private static String LINE_SEPARATOR = System .getProperty("line.separator"); public SpreadsheetWriter(Writer out) { _out = out; } public void beginSheet() throws IOException { _out.write("" + ""); _out.write("" + LINE_SEPARATOR); } public void endSheet() throws IOException { _out.write(""); _out.write(""); } /** * 插入新行 * * @param rownum * 以0开始 */ public void insertRow(int rownum) throws IOException { _out.write("" + LINE_SEPARATOR); this._rownum = rownum; } /** * 插入行结束标志 */ public void endRow() throws IOException { _out.write("" + LINE_SEPARATOR); } /** * 插入新列 * * @param columnIndex * @param value * @param styleIndex * @throws IOException */ public void createCell(int columnIndex, String value, int styleIndex) throws IOException { String ref = new CellReference(_rownum, columnIndex) .formatAsString(); _out.write(""); _out.write("" + encoderXML(value) + ""); _out.write(""); } public void createCell(int columnIndex, String value) throws IOException { createCell(columnIndex, value, -1); } public void createCell(int columnIndex, double value, int styleIndex) throws IOException { String ref = new CellReference(_rownum, columnIndex) .formatAsString(); _out.write(""); _out.write("" + value + ""); _out.write(""); } public void createCell(int columnIndex, double value) throws IOException { createCell(columnIndex, value, -1); } public void createCell(int columnIndex, Calendar value, int styleIndex) throws IOException { createCell(columnIndex, DateUtil.getExcelDate(value, false), styleIndex); } } // XML Encode private static final String[] xmlCode = new String[256]; static { // Special characters xmlCode['\''] = "'"; xmlCode['\"'] = "\""; // double quote xmlCode['&'] = "&"; // ampersand xmlCode['<'] = "<"; // lower than xmlCode['>'] = ">"; // greater than } /** *

* Encode the given text into xml. *

* * @param string the text to encode * @return the encoded string */ public static String encoderXML(String string) { if (string == null) { return ""; } int n = string.length(); char character; String xmlchar; StringBuffer buffer = new StringBuffer(); // loop over all the characters of the String. for (int i = 0; i < n; i++) { character = string.charAt(i); // the xmlcode of these characters are added to a StringBuffer // one by one try { xmlchar = xmlCode[character]; if (xmlchar == null) { buffer.append(character); } else { buffer.append(xmlCode[character]); } } catch (ArrayIndexOutOfBoundsException aioobe) { buffer.append(character); } } return buffer.toString(); } // /** // * 测试方法 // */ // public static void main(String[] args) throws Exception { // // String file = "E:/测试导出数据.xlsx"; // // ExcelWriter writer = new ExcelWriter() { // @Override // public void generate() throws Exception { // // // 电子表格开始 // this.beginSheet(); // // for (int rownum = 0; rownum < 100; rownum++) { // // 插入新行 // this.insertRow(rownum); // // // 建立新单元格,索引值从0开始,表示第一列 // this.createCell(0, "第 " + rownum + " 行"); // this.createCell(1, 34343.123456789); // this.createCell(2, "23.67%"); // this.createCell(3, "12:12:23"); // this.createCell(4, "2014-10-11 12:12:23"); // this.createCell(5, "true"); // this.createCell(6, "false"); // // // 结束行 // this.endRow(); // } // // // 电子表格结束 // this.endSheet(); // } // }; // writer.process(file); // } }