import gy.oa.commons.util.ClientInfo; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFPatriarch; import org.apache.poi.hssf.usermodel.HSSFRichTextString; 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.hssf.util.CellRangeAddress; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.poifs.filesystem.POIFSFileSystem; /** * 表示一个Excel文件,封装了常用操作 * @author lxp * */ public final class ExcelFile { private HSSFWorkbook workBook; private HSSFCellStyle borderStyle; /** * 新建一个Excel文件 */ public ExcelFile() { workBook = new HSSFWorkbook(); init(); } /** * 用一个Excel文件作为模板创建一个Excel * * @param excelPath * 模板文件路径,如果模板文件不存在则创建一个空Excel文件 */ public ExcelFile(String excelPath) { workBook = readExcel(excelPath); if (workBook == null) { workBook = new HSSFWorkbook(); } init(); } // public ExcelFile(String sql, Object[] params) throws Exception { // JdbcTemplate jdbcTemplate = getJdbcTemplate(); // try { // List<Map<String, Object>> rs = jdbcTemplate.queryForList(sql, // params); // // // 创建新的Excel 工作簿 // HSSFWorkbook workbook = new HSSFWorkbook(); // // 在Excel工作簿中建一工作表,其名为缺省值 // HSSFSheet sheet = workbook.createSheet("ody"); // int i = 0; // int j = 0; // HSSFRow row = sheet.createRow(0); // HSSFCell cell; // for (Entry<String, Object> entry : rs.get(0).entrySet()) { // cell = row.createCell(j++); // cell.setCellType(HSSFCell.CELL_TYPE_STRING); // cell.setCellValue(new HSSFRichTextString(entry.getKey())); // } // j = 0; // Object val = null; // for (Map<String, Object> map : rs) { // // 在索引i+1的位置创建行 // row = sheet.createRow(i + 1); // for (Entry<String, Object> entry : map.entrySet()) { // // 在索引j的位置创建单元格 // cell = row.createCell(j++); // // val = entry.getValue() == null ? "" : entry.getValue(); // setCellValue(cell, val, false); // } // i++; // j = 0; // } // // } catch (Exception e) { // e.printStackTrace(); // throw e; // } // } private void init() { borderStyle = workBook.createCellStyle(); borderStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); borderStyle.setBottomBorderColor(HSSFColor.BLACK.index); borderStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); borderStyle.setLeftBorderColor(HSSFColor.BLACK.index); borderStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); borderStyle.setRightBorderColor(HSSFColor.BLACK.index); borderStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); borderStyle.setTopBorderColor(HSSFColor.BLACK.index); borderStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); borderStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); } /** * 读取模板 * * @param templatePath * 模板文件路径 * @return HSSFWorkbook 返回Excel工作簿对象 */ private HSSFWorkbook readExcel(String excelPath) { HSSFWorkbook result = null; try { POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream( excelPath)); result = new HSSFWorkbook(fs); } catch (Exception ex) { ex.printStackTrace(); } return result; } /** * 返回第n个工作表,如果不存在则新建一个 * * @param wbook * 工作簿对象 * @return 第n个工作表 */ public HSSFSheet getSheetByIndex(int index) { HSSFSheet sheet = null; try { sheet = workBook.getSheetAt(index); } catch (Exception e) { sheet = workBook.createSheet(); } return sheet; } /** * 设置单元格的值 * * @param cell * 单元格对象 * @param value * 值 */ private void setCellValue(HSSFCell cell, Object value, boolean hasBorder) { if (value instanceof Double || value instanceof Float || value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof BigDecimal) { cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); cell.setCellValue(null2Double(value.toString())); } else { if (value != null && value.toString().startsWith("=")) { cell.setCellType(HSSFCell.CELL_TYPE_FORMULA); cell.setCellFormula(value.toString().substring(1)); } else { cell.setCellType(HSSFCell.CELL_TYPE_STRING); cell.setCellValue(new HSSFRichTextString(value == null ? "" : value.toString())); } } if (hasBorder) { cell.setCellStyle(borderStyle); } } /** * 转换成浮点数 * @param s * @return */ private static double null2Double(Object s) { double v = 0; if (s != null) { try { v = Double.parseDouble(s.toString()); } catch (Exception e) { } } return v; } /** * 获取单元格对象 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @return row行col列的单元格对象 */ private HSSFCell getCell(int sheetIndex, int row, int col){ // HSSFSheet sheet = getSheetByIndex(sheetIndex); // HSSFRow r = sheet.getRow(row); // r = r == null ? sheet.createRow(row) : r; HSSFRow r = getRow(sheetIndex, row); HSSFCell c = r.getCell(col); c = c == null ? r.createCell(col) : c; return c; } /** * 获取行对象 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @return 指定行的对象 */ private HSSFRow getRow(int sheetIndex, int row){ HSSFSheet sheet = getSheetByIndex(sheetIndex); HSSFRow r = sheet.getRow(row); r = r == null ? sheet.createRow(row) : r; return r; } /** * 设置n行m列单元格的值 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param row * 行,从0开始 * @param col * 列,从0开始 * @param value * 值 * @param hasBorder * true有边框,false无边框 */ public void setCellValue(int sheetIndex, int row, int col, Object value, boolean hasBorder) { // HSSFSheet sheet = getSheetByIndex(sheetIndex); // HSSFRow r = sheet.getRow(row); // r = r == null ? sheet.createRow(row) : r; // HSSFCell c = r.getCell(col); // c = c == null ? r.createCell(col) : c; setCellValue(getCell(sheetIndex, row, col), value, hasBorder); } /** * 设置n行m列单元格的值 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param row * 行,从0开始 * @param col * 列,从0开始 * @param value * 值 * @param hasBorder * true有边框,false无边框 */ public void setCellValue(int sheetIndex, int row, int col, Object value) { setCellValue(sheetIndex, row, col, value, false); } /** * 在工作表sheet中插入一行,startCol指定从第几列开始插入,如果要插入excel函数则要以“=”开头 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param rowData * 待插入的数据 * @param keys * 要插入Map的键,数据插入顺序和键的顺序一致 * @param rownum * 插入的行号 * @param startCol * 开始插入的列,从0开始 * @param hasBorder * true有边框,false无边框 * @return 插入的HSSFRow */ public HSSFRow insertRow(int sheetIndex, Map<String, Object> rowData, String[] keys, int rownum, short startCol, boolean hasBorder) { return insertData( sheetIndex, rowData, keys, rownum, startCol, hasBorder, true); } /** * 插入数据 * @param sheetIndex 操作第n个数据表,从0开始 * @param rowData 待插入的数据 * @param keys 要插入Map的键,数据插入顺序和键的顺序一致 * @param rownum 插入的行号 * @param startCol 开始插入的列,从0开始 * @param hasBorder true有边框,false无边框 * @param shiftRow 是否覆盖该行数据 * @return */ private HSSFRow insertData(int sheetIndex, Map<String, Object> rowData, String[] keys, int rownum, short startCol, boolean hasBorder, boolean shiftRow) { HSSFRow row = null; HSSFSheet sheet = getSheetByIndex(sheetIndex); try { if (shiftRow) { sheet.shiftRows(rownum, sheet.getLastRowNum(), 1,true,false); } row = sheet.createRow(rownum); HSSFCell cell; Object obj; for (int i = 0; i < keys.length; i++) { obj = rowData.get(keys[i]); cell = row.createCell(startCol + i); setCellValue(cell, obj, hasBorder); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); row = null; } return row; } /** * 在工作表sheet中插入一行,startCol指定从第几列开始插入,如果要插入excel函数则要以“=”开头 例:Object[] rowData * = {"你好","=row()","你好","你好","你好"}; insertRow(sheet, rowData, 5, (short)3); * * @param sheetIndex * 操作第n个数据表,从0开始 * @param rowData * 待插入的数据 * @param rownum * 插入的行号 * @param startCol * 开始插入的列,从0开始 * @param hasBorder * true有边框,false无边框 * @return 插入的HSSFRow * @throws Exception */ public HSSFRow insertRow(int sheetIndex, Object[] rowData, int rownum, int startCol, boolean hasBorder) throws Exception { return insertData(sheetIndex, rowData, rownum, startCol, hasBorder, true); } /** * 插入数据 * @param sheetIndex * 操作第n个数据表,从0开始 * @param rowData * 待插入的数据 * @param rownum * 插入的行号 * @param startCol * 开始插入的列,从0开始 * @param hasBorder * true有边框,false无边框 * @param shiftRow * 是否覆盖该行数据 * @return 插入的HSSFRow * @throws Exception */ private HSSFRow insertData(int sheetIndex, Object[] rowData, int rownum, int startCol, boolean hasBorder, boolean shiftRow) throws Exception { HSSFRow row = null; HSSFSheet sheet = getSheetByIndex(sheetIndex); try { if (shiftRow) { sheet.shiftRows(rownum, sheet.getLastRowNum(), 1,true,false); } row = sheet.createRow(rownum); HSSFCell cell; short i = 0; for (Object obj : rowData) { cell = row.createCell(startCol + i); setCellValue(cell, obj, hasBorder); i++; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); row = null; throw e; } return row; } /** * 在后面添加一行数据 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param rowData * 待插入的数据 * @param startCol * 开始插入的列,从0开始 * @param hasBorder * true有边框,false无边框 * @return 插入的HSSFRow * @throws Exception */ public HSSFRow appendRow(int sheetIndex, Object[] rowData, int startCol, boolean hasBorder) throws Exception { HSSFSheet sheet = getSheetByIndex(sheetIndex); int nextRow = sheet.getLastRowNum(); if (nextRow == 0) { nextRow = sheet.getPhysicalNumberOfRows(); } else { nextRow++; } return insertData(sheetIndex, rowData, nextRow, startCol, hasBorder, false); } /** * 在后面添加一行数据,从第一列开始插入,无边框 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param rowData * 待插入的数据 * @return 插入的HSSFRow * @throws Exception */ public HSSFRow appendRow(int sheetIndex, Object[] rowData) throws Exception{ return appendRow(sheetIndex,rowData,0,false); } /** * 合并一个区域的单元格 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param firstRow * 开始行,不能大于结束行 * @param lastRow * 结束行 * @param firstCol * 开始列,不能大于结束列 * @param lastCol * 结束列 */ public void addMergedRegion(int sheetIndex, int firstRow, int lastRow, int firstCol, int lastCol) { HSSFSheet sheet = getSheetByIndex(sheetIndex); CellRangeAddress range = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); HSSFRow row = getRow(sheetIndex, firstRow); HSSFCellStyle regionStyle; regionStyle = row.getCell(firstCol).getCellStyle(); regionStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); regionStyle.setBottomBorderColor(HSSFColor.BLACK.index); regionStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); regionStyle.setLeftBorderColor(HSSFColor.BLACK.index); regionStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); regionStyle.setRightBorderColor(HSSFColor.BLACK.index); regionStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); regionStyle.setTopBorderColor(HSSFColor.BLACK.index); regionStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); regionStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); row.getCell(firstCol).setCellStyle(regionStyle); sheet.addMergedRegion(range); } /** * 插入一张图片 * * @param sheetIndex * 操作第n个数据表,从0开始 * @param imgPath * 图像地址 * @param firstRow * 开始行,不能大于结束行 * @param lastRow * 结束行 * @param firstCol * 开始列,不能大于结束列 * @param lastCol * 结束列 * @return true插入成功,false失败 */ public boolean insertImage(int sheetIndex, String imgPath, int firstRow, int lastRow, short firstCol, short lastCol) { HSSFSheet sheet = getSheetByIndex(sheetIndex); ByteArrayOutputStream byteArrayOut = null; BufferedImage bufferImg = null; try { byteArrayOut = new ByteArrayOutputStream(); if(imgPath.startsWith("http")) { URL url = new URL(imgPath); URLConnection conn = url.openConnection(); bufferImg = ImageIO.read(conn.getInputStream()); } else { bufferImg = ImageIO.read(new File(imgPath)); } ImageIO.write(bufferImg, "JPEG", byteArrayOut); HSSFClientAnchor anchor = new HSSFClientAnchor(5, 5, 0, 0, firstCol, firstRow, lastCol, lastRow); HSSFPatriarch patri = sheet.createDrawingPatriarch(); patri.createPicture(anchor, workBook.addPicture(byteArrayOut .toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); return true; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { byteArrayOut.close(); } catch (Exception e) { } } return false; } /** * 保存Excel文件 * * @param excelPath * 保存路径 * @return true保存成功,false失败 */ public boolean saveExcel(String excelPath) { boolean result = false; FileOutputStream fileOut = null; try { fileOut = new FileOutputStream(excelPath); workBook.write(fileOut); result = true; } catch (Exception e) { } finally { try { fileOut.flush(); fileOut.close(); } catch (Exception e) { result = false; } } return result; } /** * 下载该Excel文件到客户端 * @param dlFileName 文件名,可为空 * @param request * @param response */ public void download(String dlFileName, HttpServletRequest request, HttpServletResponse response) { OutputStream fOut = null; try { response.setContentType("application/x-download"); String browser = ClientInfo.getClientBrowser(request); if (dlFileName == null || dlFileName.equals("")) { dlFileName = "导出Excel文档.xls"; } if (browser.startsWith("MSIE")) { dlFileName = new String(dlFileName.getBytes("GBK"), "ISO-8859-1"); } else { dlFileName = new String(dlFileName.getBytes("UTF-8"), "ISO-8859-1"); } response.setHeader("Content-Disposition", "attachment;filename=/"" + dlFileName + "/""); fOut = response.getOutputStream(); workBook.write(fOut); fOut.flush(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { fOut.close(); } catch (IOException e) { fOut = null; e.printStackTrace(); } } } /** * 获取单元格的字体对象,获取该对象后可对单元格的字体进行设置<br/> * 注意:如果多次调用该方法获取同一个单元格的字体对象,则后设置的会覆盖之前的设置 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @return */ public HSSFFont getCellFont(int sheetIndex, int row, int col){ HSSFCell cell = getCell(sheetIndex, row, col); HSSFFont font = workBook.createFont(); HSSFCellStyle style = copyStyle(cell); cell.setCellStyle(style); style.setFont(font); return font; } /** * 获取一行的字体对象,获取该对象后可对单元格的字体进行设置<br/> * 注意:如果多次调用该方法获取同一个单元格的字体对象,则后设置的会覆盖之前的设置 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @return */ public HSSFFont getRowFont(int sheetIndex, int row){ HSSFRow theRow = getRow(sheetIndex, row); HSSFFont font = workBook.createFont(); for(int i=0;i<theRow.getLastCellNum();i++){ HSSFCellStyle style = copyStyle(theRow.getCell(i)); style.setFont(font); theRow.getCell(i).setCellStyle(style); } return font; } /** * 设置单元格水平对齐方式 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @param align 对齐方式。HSSFCellStyle.ALIGN_CENTER、ALIGN_LEFT、ALIGN_RIGHT…… */ public void setCellAlign(int sheetIndex, int row, int col, Short align){ HSSFCell cell = getCell(sheetIndex, row, col); HSSFCellStyle style = copyStyle(cell); style.setAlignment(align); cell.setCellStyle(style); } /** * 设置一行单元格的水平对齐方式 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param align 对齐方式。HSSFCellStyle.ALIGN_CENTER、ALIGN_LEFT、ALIGN_RIGHT…… */ public void setRowAlign(int sheetIndex, int row, Short align){ HSSFRow theRow = getRow(sheetIndex, row); for(int i=0;i<theRow.getLastCellNum();i++){ setCellAlign(sheetIndex, row, i, align); } } /** * 设置单元格垂直对齐方式 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @param align 对齐方式。HSSFCellStyle.VERTICAL_BOTTOM、VERTICAL_CENTER 、VERTICAL_TOP…… */ public void setCellVerticalAlign(int sheetIndex, int row, int col, Short align){ HSSFCell cell = getCell(sheetIndex, row, col); HSSFCellStyle style = copyStyle(cell); style.setVerticalAlignment(align); cell.setCellStyle(style); } /** * 设置一行单元格的垂直对齐方式 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param align 对齐方式。HSSFCellStyle.VERTICAL_BOTTOM、VERTICAL_CENTER 、VERTICAL_TOP…… */ public void setRowVerticalAlign(int sheetIndex, int row, Short align){ HSSFRow theRow = getRow(sheetIndex, row); for(int i=0;i<theRow.getLastCellNum();i++){ setCellVerticalAlign(sheetIndex, row, i, align); } } /** * 设置单元格背景色 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @param bg 颜色。比如蓝色:HSSFColor.BLUE.index */ public void setCellBackgroundColor(int sheetIndex, int row, int col, short bg){ HSSFCell cell = getCell(sheetIndex, row, col); HSSFCellStyle style = copyStyle(cell); style.setFillForegroundColor(bg); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); cell.setCellStyle(style); } /** * 设置一行单元格的格背景色 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param bg 颜色。比如蓝色:HSSFColor.BLUE.index */ public void setRowBackgroundColor(int sheetIndex, int row, short bg){ HSSFRow theRow = getRow(sheetIndex, row); for(int i=0;i<theRow.getLastCellNum();i++){ setCellBackgroundColor(sheetIndex, row, i, bg); } } /** * 设置单元格边框 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @param borderStyle 边框样式。比如细线边框:HSSFCellStyle.BORDER_THIN * @param borderColor 边框颜色。比如蓝色:HSSFColor.BLUE.index */ public void setCellBorder(int sheetIndex, int row, int col, short borderStyle, short borderColor){ HSSFCell cell = getCell(sheetIndex, row, col); HSSFCellStyle style = copyStyle(cell); style.setBorderBottom(borderStyle); style.setBorderLeft(borderStyle); style.setBorderRight(borderStyle); style.setBorderTop(borderStyle); style.setBottomBorderColor(borderColor); style.setLeftBorderColor(borderColor); style.setRightBorderColor(borderColor); style.setTopBorderColor(borderColor); cell.setCellStyle(style); } /** * 设置单元格边框,黑色边框 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param col 列,从0开始 * @param borderStyle 边框样式。比如细线边框:HSSFCellStyle.BORDER_THIN */ public void setCellBorder(int sheetIndex, int row, int col, short borderStyle){ setCellBorder(sheetIndex, row, col, borderStyle, HSSFColor.BLACK.index); } /** * 设置一行单元格的边框 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param borderStyle 边框样式。比如细线边框:HSSFCellStyle.BORDER_THIN * @param borderColor 边框颜色。比如蓝色:HSSFColor.BLUE.index */ public void setRowBorder(int sheetIndex, int row, short borderStyle, short borderColor){ HSSFRow theRow = getRow(sheetIndex, row); for(int i=0;i<theRow.getLastCellNum();i++){ setCellBorder(sheetIndex, row, i, borderStyle, borderColor); } } /** * 设置一行单元格的边框,黑色边框 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 * @param borderStyle 边框样式。比如细线边框:HSSFCellStyle.BORDER_THIN */ public void setRowBorder(int sheetIndex, int row, short borderStyle){ setRowBorder(sheetIndex, row, borderStyle, HSSFColor.BLACK.index); } /** * 从第一列开始设置列的宽度 * @param sheetIndex 操作第n个数据表,从0开始 * @param widths 可变长参数,输入若干个长度。1表示一个文字宽度的1/256 */ public void setColumnWidth(int sheetIndex, int... widths){ HSSFSheet sheet = getSheetByIndex(sheetIndex); HSSFRow theRow = getRow(sheetIndex, 0); for(int i=0;i<theRow.getLastCellNum() && i< widths.length;i++){ sheet.setColumnWidth(i, widths[i]); } } /** * 设置某一列的宽度 * @param sheetIndex 操作第n个数据表,从0开始 * @param columnIndex 列,从0开始 * @param width 要设置的宽度。1表示一个文字宽度的1/256 */ public void setColumnWidth(int sheetIndex, int columnIndex, int width){ HSSFSheet sheet = getSheetByIndex(sheetIndex); sheet.setColumnWidth(columnIndex, width); } /** * 根据某一行的内容自动设置列宽度。自动计算宽度性能比较低,因此建议在操作完数据后调用一次 * @param sheetIndex 操作第n个数据表,从0开始 * @param row 行,从0开始 */ public void autoWidthColumn(int sheetIndex){ HSSFSheet sheet = getSheetByIndex(sheetIndex); HSSFRow theRow = getRow(sheetIndex, 0); for(int i=0;i<theRow.getLastCellNum();i++){ sheet.autoSizeColumn((short)i, false); sheet.setColumnWidth(i, sheet.getColumnWidth(i)+1000); } } /** * 缓存style对象 */ private Map<Integer, HSSFCellStyle> styleMap = new HashMap<Integer, HSSFCellStyle>(); /** * 复制单元格的样式 * @param cell 被复制的单元格 * @return 新建的样式 */ private HSSFCellStyle copyStyle(HSSFCell cell){ HSSFCellStyle oldStyle = cell.getCellStyle(); HSSFCellStyle style = styleMap.get(oldStyle.hashCode()); if(style == null){ style = workBook.createCellStyle(); } style.cloneStyleFrom(cell.getCellStyle()); return style; } } 工具类: import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; public class ClientInfo { public static String getClientOS(HttpServletRequest request){ String agent = request.getHeader("user-agent"); StringTokenizer st = new StringTokenizer(agent,";"); st.nextToken(); st.nextToken(); String useros = st.nextToken(); return useros; } public static String getClientBrowser(HttpServletRequest request){ String agent = request.getHeader("user-agent"); StringTokenizer st = new StringTokenizer(agent,";"); st.nextToken(); String userbrowser = st.nextToken().trim(); return userbrowser; } }