参考博客:

  http://www.oschina.net/code/snippet_565430_15074

  增加了多sheet,多列的自动合并。

  修改了部分过时方法和导出逻辑。

  优化了标题,导出信息等

先看下效果,如果正常导出是这样子:

  excel poi 文件导出,支持多sheet、多列自动合并。

自动合并后是:

  excel poi 文件导出,支持多sheet、多列自动合并。

动态图示例:

  excel poi 文件导出,支持多sheet、多列自动合并。

poi导出并不是一件很麻烦的事情,只是逻辑相对复杂,要考虑到各种情况。我把代码贴上,有用得到的可以帮助一下。

导出类:

  1 package com.centit.njld.commons.testexcel;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.text.SimpleDateFormat;
  5 import java.util.Date;
  6 import java.util.LinkedHashMap;
  7 import java.util.List;
  8 import java.util.Map.Entry;
  9 import java.util.Set;
 10 
 11 import org.apache.poi.hssf.usermodel.HSSFCell;
 12 import org.apache.poi.hssf.usermodel.HSSFRow;
 13 import org.apache.poi.hssf.usermodel.HSSFSheet;
 14 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 15 import org.apache.poi.ss.usermodel.CellStyle;
 16 import org.apache.poi.ss.usermodel.Font;
 17 import org.apache.poi.ss.usermodel.IndexedColors;
 18 import org.apache.poi.ss.util.CellRangeAddress;
 19 
 20 import com.centit.njld.commons.testexcel.TestExcel_Reflection;
 21 
 22 public class TestExcel_Export {
 23 
 24     private static HSSFWorkbook wb;
 25 
 26     private static CellStyle titleStyle; // 标题行样式
 27     private static Font titleFont; // 标题行字体
 28     private static CellStyle dateStyle; // 日期行样式
 29     private static Font dateFont; // 日期行字体
 30     private static CellStyle headStyle; // 表头行样式
 31     private static Font headFont; // 表头行字体
 32     private static CellStyle contentStyle; // 内容行样式
 33     private static Font contentFont; // 内容行字体
 34 
 35     /**
 36      * 导出文件
 37      */
 38     public static boolean export2File(ExcelExportData setInfo,
 39             String outputExcelFileName) throws Exception {
 40         return TestExcel_FileUtil.write(outputExcelFileName, export2ByteArray(setInfo),
 41                 true, true);
 42     }
 43 
 44     /**
 45      * 导出到byte数组
 46      */
 47     public static byte[] export2ByteArray(ExcelExportData setInfo)
 48             throws Exception {
 49         return export2Stream(setInfo).toByteArray();
 50     }
 51 
 52     /**
 53      * 导出到流
 54      */
 55     public static ByteArrayOutputStream export2Stream(ExcelExportData setInfo)
 56             throws Exception {
 57         init();
 58         
 59         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 60 
 61         Set<Entry<String, List<?>>> set = setInfo.getDataMap().entrySet();
 62         String[] sheetNames = new String[setInfo.getDataMap().size()];
 63         int sheetNameNum = 0;
 64         for (Entry<String, List<?>> entry : set) {
 65             sheetNames[sheetNameNum] = entry.getKey();
 66             sheetNameNum++;
 67         }
 68         HSSFSheet[] sheets = getSheets(setInfo.getDataMap().size(), sheetNames);
 69         int sheetNum = 0;
 70         int k = 0;
 71         
 72         for (Entry<String, List<?>> entry : set) {
 73             // Sheet
 74             List<?> objs = entry.getValue();
 75 
 76             // 标题行
 77             createTableTitleRow(setInfo, sheets, sheetNum);
 78 
 79             // 日期行
 80             createTableDateRow(setInfo, sheets, sheetNum);
 81 
 82             // 表头
 83             creatTableHeadRow(setInfo, sheets, sheetNum);
 84 
 85             // 表体
 86             String[] fieldNames = setInfo.getFieldNames().get(sheetNum);
 87             
 88             int rowNum = 3;
 89             for (Object obj : objs) {
 90                 HSSFRow contentRow = sheets[sheetNum].createRow(rowNum);
 91                 contentRow.setHeight((short) 300);
 92                 HSSFCell[] cells = getCells(contentRow, setInfo.getFieldNames().get(sheetNum).length);
 93                 int cellNum = 1; // 去掉一列序号,因此从1开始
 94                 if (fieldNames != null) {
 95                     for (int num = 0; num < fieldNames.length; num++) {
 96                         Object value = TestExcel_Reflection.invokeGetterMethod(obj,fieldNames[num]);
 97                         cells[cellNum].setCellValue(value == null ? "" : value.toString());
 98                         cellNum++;
 99                     }
100                 }
101                 rowNum++;
102             }
103             
104             k++;
105             String[] groupColumns = null;
106             if(setInfo.getGroupColumn().size()!=0){
107                 if(setInfo.getGroupColumn().size() >= k){
108                     groupColumns = setInfo.getGroupColumn().get(sheetNum);
109                 }
110             }
111             
112             if(groupColumns!=null){
113                 int n=0;
114                 for (int i = 0; i < groupColumns.length; i++) {
115                     
116                     String[] fieldName = setInfo.getFieldNames().get(sheetNum);
117                     for (int j = 0; j < fieldName.length; j++) {
118                         if(groupColumns[i].equals(fieldName[j])){
119                             j++;
120                             n=j;
121                             break;
122                         }
123                     }
124                     int x = 0;
125                     int y = 0;
126                     int z = 3;
127                     int m = objs.size();
128                     boolean flag = false;
129                     Object val = null;
130                     CellRangeAddress dateRange = null;
131                     for (Object obj : objs) {
132                         y++;
133                         Object value = TestExcel_Reflection.invokeGetterMethod(obj,groupColumns[i]);
134                         if(x==0){
135                             x++;
136                             val=value;
137                         }else if(val.toString().equals(value.toString())){
138                             x++;
139                             if(m==y){
140                                 dateRange = new CellRangeAddress(z, x+3, n, n);
141                                 sheets[sheetNum].addMergedRegion(dateRange);
142                             }
143                         }else{
144                             val=value;
145                             if(flag){
146                                 dateRange = new CellRangeAddress(z, x+3, n, n);
147                                 z=x+4;
148                                 x=x+1;
149                             }else{
150                                 dateRange = new CellRangeAddress(z, x+2, n, n);
151                                 z=x+3;
152                             }
153                             sheets[sheetNum].addMergedRegion(dateRange);
154                             flag=true;
155                         }
156                     }
157                 }
158             }
159             
160 //            CellRangeAddress dateRange = new CellRangeAddress(3, 10, 1, 1);
161 //            sheets[sheetNum].addMergedRegion(dateRange);
162 //            
163 //            CellRangeAddress aa = new CellRangeAddress(11, 15, 1, 1);
164 //            sheets[sheetNum].addMergedRegion(aa);
165 //            
166 //            CellRangeAddress bb = new CellRangeAddress(3, 5, 2, 2);
167 //            sheets[sheetNum].addMergedRegion(bb);
168             
169 //            
170 //            CellRangeAddress aaa = new CellRangeAddress(16, 18, 1, 1);
171 //            sheets[sheetNum].addMergedRegion(aaa);
172             
173             adjustColumnSize(sheets, sheetNum, fieldNames); // 自动调整列宽
174             sheetNum++;
175         }
176         wb.write(outputStream);
177         return outputStream;
178     }
179 
180     /**
181      * @Description: 初始化
182      */
183     private static void init() {
184         wb = new HSSFWorkbook();
185 
186         titleFont = wb.createFont();
187         titleStyle = wb.createCellStyle();
188         dateStyle = wb.createCellStyle();
189         dateFont = wb.createFont();
190         headStyle = wb.createCellStyle();
191         headFont = wb.createFont();
192         contentStyle = wb.createCellStyle();
193         contentFont = wb.createFont();
194 
195         initTitleCellStyle();
196         initTitleFont();
197         initDateCellStyle();
198         initDateFont();
199         initHeadCellStyle();
200         initHeadFont();
201         initContentCellStyle();
202         initContentFont();
203     }
204 
205     /**
206      * @Description: 自动调整列宽
207      */
208     private static void adjustColumnSize(HSSFSheet[] sheets, int sheetNum,
209             String[] fieldNames) {
210         for (int i = 0; i < fieldNames.length + 1; i++) {
211             sheets[sheetNum].autoSizeColumn(i, true);
212         }
213     }
214 
215     /**
216      * @Description: 创建标题行(需合并单元格)
217      */
218     private static void createTableTitleRow(ExcelExportData setInfo, HSSFSheet[] sheets, int sheetNum) {
219         CellRangeAddress titleRange = new CellRangeAddress(0, 0, 0, setInfo.getFieldNames().get(sheetNum).length);
220         sheets[sheetNum].addMergedRegion(titleRange);
221         HSSFRow titleRow = sheets[sheetNum].createRow(0);
222         titleRow.setHeight((short) 800);
223         HSSFCell titleCell = titleRow.createCell(0);
224         titleCell.setCellStyle(titleStyle);
225         titleCell.setCellValue(setInfo.getTitles()[sheetNum]);
226     }
227 
228     /**
229      * @Description: 创建日期行(需合并单元格)
230      */
231     private static void createTableDateRow(ExcelExportData setInfo,HSSFSheet[] sheets, int sheetNum) {
232         CellRangeAddress dateRange = new CellRangeAddress(1, 1, 0, setInfo.getFieldNames().get(sheetNum).length);
233         sheets[sheetNum].addMergedRegion(dateRange);
234         HSSFRow dateRow = sheets[sheetNum].createRow(1);
235         dateRow.setHeight((short) 350);
236         HSSFCell dateCell = dateRow.createCell(0);
237         dateCell.setCellStyle(dateStyle);
238         dateCell.setCellValue(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
239     }
240 
241     /**
242      * @Description: 创建表头行(需合并单元格)
243      */
244     private static void creatTableHeadRow(ExcelExportData setInfo,
245             HSSFSheet[] sheets, int sheetNum) {
246         // 表头
247         HSSFRow headRow = sheets[sheetNum].createRow(2);
248         headRow.setHeight((short) 350);
249         // 序号列
250         HSSFCell snCell = headRow.createCell(0);
251         snCell.setCellStyle(headStyle);
252         snCell.setCellValue("序号");
253         // 列头名称
254         for (int num = 1, len = setInfo.getColumnNames().get(sheetNum).length; num <= len; num++) {
255             HSSFCell headCell = headRow.createCell(num);
256             headCell.setCellStyle(headStyle);
257             headCell.setCellValue(setInfo.getColumnNames().get(sheetNum)[num - 1]);
258         }
259     }
260 
261     /**
262      * @Description: 创建所有的Sheet
263      */
264     private static HSSFSheet[] getSheets(int num, String[] names) {
265         HSSFSheet[] sheets = new HSSFSheet[num];
266         for (int i = 0; i < num; i++) {
267             sheets[i] = wb.createSheet(names[i]);
268         }
269         return sheets;
270     }
271 
272     /**
273      * @Description: 创建内容行的每一列(附加一列序号)
274      */
275     private static HSSFCell[] getCells(HSSFRow contentRow, int num) {
276         HSSFCell[] cells = new HSSFCell[num + 1];
277 
278         for (int i = 0, len = cells.length; i < len; i++) {
279             cells[i] = contentRow.createCell(i);
280             cells[i].setCellStyle(contentStyle);
281         }
282 
283         // 设置序号列值,因为出去标题行和日期行,所有-2
284         cells[0].setCellValue(contentRow.getRowNum() - 2);
285 
286         return cells;
287     }
288 
289     /**
290      * @Description: 初始化标题行样式
291      */
292     private static void initTitleCellStyle() {
293         titleStyle.setAlignment(CellStyle.ALIGN_CENTER);
294         titleStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
295         titleStyle.setFont(titleFont);
296         titleStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.getIndex());
297     }
298 
299     /**
300      * @Description: 初始化日期行样式
301      */
302     private static void initDateCellStyle() {
303         dateStyle.setAlignment(CellStyle.ALIGN_CENTER_SELECTION);
304         dateStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
305         dateStyle.setFont(dateFont);
306         dateStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.getIndex());
307     }
308 
309     /**
310      * @Description: 初始化表头行样式
311      */
312     private static void initHeadCellStyle() {
313         headStyle.setAlignment(CellStyle.ALIGN_CENTER);
314         headStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
315         headStyle.setFont(headFont);
316         headStyle.setFillBackgroundColor(IndexedColors.YELLOW.getIndex());
317         headStyle.setBorderTop(CellStyle.BORDER_MEDIUM);
318         headStyle.setBorderBottom(CellStyle.BORDER_THIN);
319         headStyle.setBorderLeft(CellStyle.BORDER_THIN);
320         headStyle.setBorderRight(CellStyle.BORDER_THIN);
321         headStyle.setTopBorderColor(IndexedColors.BLUE.getIndex());
322         headStyle.setBottomBorderColor(IndexedColors.BLUE.getIndex());
323         headStyle.setLeftBorderColor(IndexedColors.BLUE.getIndex());
324         headStyle.setRightBorderColor(IndexedColors.BLUE.getIndex());
325     }
326 
327     /**
328      * @Description: 初始化内容行样式
329      */
330     private static void initContentCellStyle() {
331         contentStyle.setAlignment(CellStyle.ALIGN_CENTER);
332         contentStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
333         contentStyle.setFont(contentFont);
334         contentStyle.setBorderTop(CellStyle.BORDER_THIN);
335         contentStyle.setBorderBottom(CellStyle.BORDER_THIN);
336         contentStyle.setBorderLeft(CellStyle.BORDER_THIN);
337         contentStyle.setBorderRight(CellStyle.BORDER_THIN);
338         contentStyle.setTopBorderColor(IndexedColors.BLUE.getIndex());
339         contentStyle.setBottomBorderColor(IndexedColors.BLUE.getIndex());
340         contentStyle.setLeftBorderColor(IndexedColors.BLUE.getIndex());
341         contentStyle.setRightBorderColor(IndexedColors.BLUE.getIndex());
342         contentStyle.setWrapText(true); // 字段换行
343     }
344 
345     /**
346      * @Description: 初始化标题行字体
347      */
348     private static void initTitleFont() {
349         titleFont.setFontName("华文楷体");
350         titleFont.setFontHeightInPoints((short) 20);
351         titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
352         titleFont.setCharSet(Font.DEFAULT_CHARSET);
353         titleFont.setColor(IndexedColors.BLUE_GREY.getIndex());
354     }
355 
356     /**
357      * @Description: 初始化日期行字体
358      */
359     private static void initDateFont() {
360         dateFont.setFontName("隶书");
361         dateFont.setFontHeightInPoints((short) 10);
362         dateFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
363         dateFont.setCharSet(Font.DEFAULT_CHARSET);
364         dateFont.setColor(IndexedColors.BLUE_GREY.getIndex());
365     }
366 
367     /**
368      * @Description: 初始化表头行字体
369      */
370     private static void initHeadFont() {
371         headFont.setFontName("宋体");
372         headFont.setFontHeightInPoints((short) 10);
373         headFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
374         headFont.setCharSet(Font.DEFAULT_CHARSET);
375         headFont.setColor(IndexedColors.BLUE_GREY.getIndex());
376     }
377 
378     /**
379      * @Description: 初始化内容行字体
380      */
381     private static void initContentFont() {
382         contentFont.setFontName("宋体");
383         contentFont.setFontHeightInPoints((short) 10);
384         contentFont.setBoldweight(Font.BOLDWEIGHT_NORMAL);
385         contentFont.setCharSet(Font.DEFAULT_CHARSET);
386         contentFont.setColor(IndexedColors.BLUE_GREY.getIndex());
387     }
388 
389     /**
390      * Excel导出数据类
391      * @author jimmy
392      */
393     public static class ExcelExportData {
394 
395         /**
396          * 导出数据 key:String 表示每个Sheet的名称 value:List<?> 表示每个Sheet里的所有数据行
397          */
398         private LinkedHashMap<String, List<?>> dataMap;
399 
400         /**
401          * 每个Sheet里的顶部大标题
402          */
403         private String[] titles;
404 
405         /**
406          * 单个sheet里的数据列标题
407          */
408         private List<String[]> columnNames;
409 
410         /**
411          * 单个sheet里每行数据的列对应的对象属性名称
412          */
413         private List<String[]> fieldNames;
414 
415         private List<String[]> groupColumn;
416         
417         public List<String[]> getFieldNames() {
418             return fieldNames;
419         }
420 
421         public void setFieldNames(List<String[]> fieldNames) {
422             this.fieldNames = fieldNames;
423         }
424 
425         public String[] getTitles() {
426             return titles;
427         }
428 
429         public void setTitles(String[] titles) {
430             this.titles = titles;
431         }
432 
433         public List<String[]> getColumnNames() {
434             return columnNames;
435         }
436 
437         public void setColumnNames(List<String[]> columnNames) {
438             this.columnNames = columnNames;
439         }
440 
441         public LinkedHashMap<String, List<?>> getDataMap() {
442             return dataMap;
443         }
444 
445         public void setDataMap(LinkedHashMap<String, List<?>> dataMap) {
446             this.dataMap = dataMap;
447         }
448 
449         public List<String[]> getGroupColumn() {
450             return groupColumn;
451         }
452 
453         public void setGroupColumn(List<String[]> groupColumn) {
454             this.groupColumn = groupColumn;
455         }
456     }
457     
458 }
View Code

相关文章:

  • 2022-12-23
  • 2021-05-20
  • 2022-12-23
  • 2021-08-30
  • 2021-11-27
  • 2022-12-23
  • 2021-12-17
猜你喜欢
  • 2022-01-19
  • 2022-03-04
  • 2021-06-02
  • 2022-01-31
  • 2022-12-23
  • 2021-06-24
相关资源
相似解决方案