为了方便地使用poi操作excel,在这里,使用类BubbleSheet对Poi中的Sheet进行封装,BubbleSheet类如下所示:
import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.RegionUtil; import java.util.ArrayList; import java.util.List; public class BubbleSheet { private Sheet sheet; private Row nowRow; private Integer nowRowNo; private HSSFWorkbook wb; private List<HSSFCellStyle> cellStylesList = new ArrayList<HSSFCellStyle>(); BubbleSheet(HSSFWorkbook wb) { this.wb = wb; this.sheet = wb.createSheet(); createCellStyleList(); nowRowNo = -1; setNowRowWithRowNo(0); } private HSSFCellStyle createCellStyle(int poiColorIndex, int r, int g, int b) { HSSFCellStyle cellStyle = wb.createCellStyle(); cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框 cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); //左边框 cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); //上边框 cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); //右边框 HSSFPalette palette = wb.getCustomPalette(); palette.setColorAtIndex((short)poiColorIndex, (byte) r, (byte) g, (byte) b); cellStyle.setFillForegroundColor((short)poiColorIndex); cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); return cellStyle; } private void createCellStyleList() { cellStylesList.add(createCellStyle(HSSFColor.LIME.index, 255, 255, 255)); // 默认的白色 cellStylesList.add(createCellStyle(HSSFColor.BLUE.index, 211, 209, 207)); // 内容浅灰色 cellStylesList.add(createCellStyle(HSSFColor.GREEN.index, 186, 210, 170)); // 表头浅绿色 } public void mergeCells(Integer firstRow, Integer lastRow, Integer firstCol, Integer lastCol, String content, int colorIndex) { CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); //在sheet里增加合并单元格 sheet.addMergedRegion(cra); Cell cell_1 = nowRow.createCell(firstCol); // 选择第一行的第一个单元格,因为位置在这个位置,所以设置的是合并的单元格 cell_1.setCellStyle(cellStylesList.get(colorIndex)); // 设置单元格的内容 cell_1.setCellValue(content); // 设置合并单元格的边框 RegionUtil.setBorderBottom(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 下边框 RegionUtil.setBorderLeft(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 左边框 RegionUtil.setBorderRight(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 有边框 RegionUtil.setBorderTop(HSSFCellStyle.BORDER_THIN, cra, sheet, wb); // 上边框 } public void setLineValues(Integer col, String[] titleNames, int colorIndex) { for(String stp: titleNames) { Cell ctp = nowRow.createCell(col ++); ctp.setCellValue(stp); ctp.setCellStyle(cellStylesList.get(colorIndex)); } } public void setNowRowWithRowNo(Integer rowNo) { // 这里的逻辑感觉很奇怪,主要是在getRow、createRow以及样式设置上的相互作用的结果。 if(rowNo == null) rowNo = 0 ; if(nowRowNo.equals(rowNo)) { // 如果是合并单元格行后面的创建单元时,不需要重新生成这行了。 return ; } Row row = sheet.getRow(rowNo); // 使用这个的原因是:需要设置合并单元格的外边框样式,如果不用这个会出错。 if(row == null){ row = sheet.createRow(rowNo); } nowRowNo = rowNo; setNowRow(row); } private void setNowRow(Row nowRow) { this.nowRow = nowRow; } public void createFreezePane(int startRowNo, int endRowNo, int startColNo, int endColNo) { sheet.createFreezePane( startRowNo, endRowNo, startColNo, endColNo); } }
接下来使用BubbleSheet方便操作表格的例子如下:
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; public class bubbleSheet_ex { static final private String[] titleNames = { "广告位", "月度", "项目名称", "预定量", "预计本月金额", "直客公司", "所属区域", "对应销售", "媒介", "当月比例"}; public static int stepHigh = 0; public static void main(String[] args) { HSSFWorkbook wb = new HSSFWorkbook(); BubbleSheet bs = new BubbleSheet(wb); bs.setNowRowWithRowNo(0); // 设置要操作哪一行 bs.mergeCells(0, 0, 0, 1, titleNames[0], 0); // 设置第一行第一个标题 final String[] titleNames_temp = Arrays.copyOfRange(titleNames, 1, titleNames.length); bs.setNowRowWithRowNo(0); // 设置要操作哪一行 bs.setLineValues(2, titleNames_temp, 0); // 设置第一行除第一个以外的标题 stepHigh = 10; int firstRow_temp = 1; bs.setNowRowWithRowNo(firstRow_temp); // 设置要操作哪一行 bs.mergeCells(firstRow_temp, firstRow_temp + stepHigh, 0, 1, "模块1", 1); firstRow_temp = 13; bs.setNowRowWithRowNo(firstRow_temp); // 设置要操作哪一行 bs.mergeCells(firstRow_temp, firstRow_temp + stepHigh, 0, 1, "模块2", 2); saveexcel(wb, "e:/test_bs.xls"); } private static void saveexcel(HSSFWorkbook wb, String filename) { // 保存文件 File file = new File(filename); try { file.createNewFile(); // 创建文件 } catch (IOException e) { e.printStackTrace(); } try { FileOutputStream fos = new FileOutputStream(file); try { wb.write(fos); fos.close(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } } }
从例子中可以看出,BubbleSheet经常用的方法有mergeCells以及setLineValues,从名字可以看出两者的用途,在使用这两个方法之前,都要用setNowRowWithRowNo方法,用来指明是要操作哪一行的。
在我的工作中检验发现,BubbleSheet是可靠的,且在操作表格时非常便捷。