POI动态生成Excel

实习第二周 No.2

项目功能里要求能够将展示的报表导出excel,因为报表的数据都是动态从list传进来的,所以使用了POI技术来动态构建excel文件。
百科里说POI是介个样子的
“ApachePOI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对MicrosoftOffice格式档案读和写的功能”
简单来说就是通过它的API可以进行创建/读取文档,sheet,行列单元格等操作,也可以设置文档的各个样式。
刚接触这个任务的时候查了很多资料,最后主要是参考了这篇文章,程序复制粘贴就跑得通,对POI的整个理解可以得到很好地提升。
详解JAVA POI导出EXCEL报表的操作(包括各种格式及样式的实现)
然后参考着就实现了项目里要求的样子啦

    private static HSSFWorkbook wb = new HSSFWorkbook(); 
    private static HSSFSheet sheet = wb.createSheet(); 
    public boolean exportTrstatistics(List<Map<String,Object>>headList,List<Map<String,Object>>headerList,List<Map<String,Object>>dicList) throws Exception {
   //ExportExcel 即上文作者编写的工具类。
        ExportExcel exportExcel = new ExportExcel(wb, sheet); 
            // 计算该报表的列数 
            int number=headList.size();
            int t=0;
            for(int i=0;i<headList.size();i++)
            {
                BigInteger te=(BigInteger) headList.get(i).get("chilNum");
                t=te.intValue();
                if(t!=0)
//因为第一行表头有可能包含第二行表头,而如果有第二列表头的时候以第二行表头的个数为准,这里多算了一个第一行表头,所以需要-1
                    number=number+t-1;
            }        
            System.out.println(number);     
            // 给工作表列定义列宽(实际应用自己更改列数) 
            for (int i = 0; i < number; i++) { 
            sheet.setColumnWidth(i, 3000); 

            } 
//因为项目对单元格样式的要求不高,所以这里直接拿来主义了
            // 创建单元格样式 
            HSSFCellStyle cellStyle = wb.createCellStyle(); 
            // 指定单元格居中对齐 
            cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); 
            // 指定单元格垂直居中对齐 
            cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); 
            // 指定当单元格内容显示不下时自动换行 
            cellStyle.setWrapText(true); 
            // 设置单元格字体 
            HSSFFont font = wb.createFont(); 
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 
            font.setFontName("宋体"); 
            font.setFontHeight((short) 200); 
            cellStyle.setFont(font); 
            // 创建报表头部 
            createNormalHead("各单位各类培训持证人数汇总报表", number); 
            // 设置列头 
            HSSFRow row2 = sheet.createRow(2); 
// 设置行高 
            row2.setHeight((short) 500); 
            HSSFCell cell0 = row2.createCell(0); 
            cell0.setCellStyle(cellStyle); 
            cell0.setCellValue(new HSSFRichTextString("公司/单位名称")); 
            HSSFRow row3 = sheet.createRow(3); 
            // 设置行高 
            row3.setHeight((short) 500); 
            HSSFCell row3Cell = null; 
            int childnum=0;
            int childstartnum=0;
            int count2=1;   //记录单元格应放置位置的指针
            List<Integer>mergeList=new ArrayList<Integer>();
            for(int i=0;i<headList.size();i++)
            {
                BigInteger childnum1=(BigInteger) headList.get(i).get("chilNum");
                childnum=childnum1.intValue();
                if(childnum!=0){
//第一行表头包含第二行表头的情况,因为第一行表头和它内部的第二行表头的第一个值是上下行同列的关系,所以这里couunt2没有++;
                    HSSFCell cell1 = row2.createCell(count2); 
                    cell1.setCellStyle(cellStyle); 
                    cell1.setCellValue(new HSSFRichTextString((String) headList.get(i).get("dicInfoName"))); 
                    int counttemp=count2;
                    for(int j=0;j<childnum;j++)
                    {
//每次给第二行表头添加信息以及没有子项的第一行表头添加信息的时候指针要向后移
                        row3Cell = row3.createCell(count2++); 
                        row3Cell.setCellStyle(cellStyle); 
                        row3Cell.setCellValue(new HSSFRichTextString((String) headerList.get(childstartnum++).get("dicInfoName"))); 
                    }
//记录带子项的第一行表头的起始位置和结束位置,以便之后合并单元格
                    mergeList.add(counttemp);
                    mergeList.add(count2-1);

                }else{
                    
                    HSSFCell cell1 = row2.createCell(count2++); 
                    cell1.setCellStyle(cellStyle); 
                    cell1.setCellValue(new HSSFRichTextString((String) headList.get(i).get("dicInfoName"))); 
                }
            }
            // 合并单元格 
            // 合并第三行到第四行的第一列 
                sheet.addMergedRegion(new Region(2, (short) 0, 3, (short) 0)); 
            // 合并第三行到第四行的第二列,三列
            sheet.addMergedRegion(new Region(2, (short) 1, 3, (short) 1)); 

            sheet.addMergedRegion(new Region(2, (short) 2, 3, (short) 2)); 
            
            for(int i=0;i<mergeList.size();i++)
            {
                System.out.println(mergeList.get(i).intValue());
            }
//给第一行表头设置合并单元格
        for(int i=0;i<mergeList.size();i=i+2)
{

  sheet.addMergedRegion(new Region(2, (short)( mergeList.get(i).intValue()), 2, (short)(mergeList.get(i+1).intValue()))); 

}

//之后的代码就是用同样的方式拼装ExcelUtils的标签
              HSSFRow row4 = sheet.createRow(4); 
              HSSFRow row5 = sheet.createRow(5); 
              HSSFRow row6 = sheet.createRow(6); 
              HSSFRow row7 = sheet.createRow(7); 
              HSSFCell cell4 = row4.createCell(0); 
              cell4.setCellStyle(cellStyle); 
              cell4.setCellValue(new HSSFRichTextString("合计")); 
             // for(int i=0;i<dicList.size();i++)
             // {
                 // HSSFCell cellsum = row4.createCell(i+1); 
    
             // }
              HSSFCell cell41 = row5.createCell(0); 
              cell41.setCellStyle(cellStyle); 
              cell41.setCellValue(new HSSFRichTextString("#foreach obj in ${list}"));
                  
              HSSFCell cell51 = row6.createCell(0); 
              cell51.setCellStyle(cellStyle); 
              cell51.setCellValue(new HSSFRichTextString("${obj.orgName}"));
                for(int i=0;i<dicList.size();i++)
                {
                    cell51 = row6.createCell(i+1); 
                    cell51.setCellStyle(cellStyle); 
                    cell51.setCellValue(new HSSFRichTextString("${obj."+(String) dicList.get(i).get("dicInfoCode")+"}"));
                    System.out.println((String) dicList.get(i).get("dicInfoCode"));
                }
                //求和
                  HSSFCell cellsum = row4.createCell(1); 
                  cellsum.setCellStyle(cellStyle);  
                  String letter = String.valueOf((char) (1+ 65));
                  cellsum.setCellValue("#formula SUMPRODUCT(--" + letter + "${objStartRowNo}:" + letter + "${objEndRowNo})");
               HSSFCell cell61 = row7.createCell(0); 
                cell61.setCellStyle(cellStyle); 
                cell61.setCellValue(new HSSFRichTextString("#end")); 
                
                exportExcel.outputExcel(ServletActionContext.getServletContext().getRealPath("template")+"\\trstatisticsNum.xls"); 
                System.out.println(ServletActionContext.getServletContext().getRealPath("template")+"\\trstatisticsNum.xls");
                return true;
    }

=======================================================
百科中的示例附上作为下次使用的备忘。
创建Excel 文档

示例1将演示如何利用Jakarta POI API 创建Excel 文档。

示例1程序如下:

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.hssf.usermodel.HSSFSheet;

import org.apache.poi.hssf.usermodel.HSSFRow;

import org.apache.poi.hssf.usermodel.HSSFCell;

import java .io.FileOutputStream;

public class CreateXL {

/** Excel 文件要存放的位置,假定在D盘下*/

public static String outputFile="D:\test.xls";

public static void main(String argv[]){

try{

// 创建新的Excel 工作簿

HSSFWorkbook workbook = new HSSFWorkbook();

// 在Excel工作簿中建一工作表,其名为缺省值

// 如要新建一名为"效益指标"的工作表,其语句为:

// HSSFSheet sheet = workbook.createSheet("效益指标");

HSSFSheet sheet = workbook.createSheet();

// 在索引0的位置创建行(最顶端的行)

HSSFRow row = sheet.createRow((short)0);

//在索引0的位置创建单元格(左上端)

HSSFCell cell = row.createCell((short) 0);

// 定义单元格为字符串类型

cell.setCellType(HSSFCell.CELL_TYPE_STRING);

// 在单元格中输入一些内容

cell.setCellValue("增加值");

// 新建一输出文件流

FileOutputStream fOut = new FileOutputStream(outputFile);

// 把相应的Excel 工作簿存盘

workbook.write(fOut);

fOut.flush();

// 操作结束,关闭文件

fOut.close();

System.out.println("文件生成...");

}catch(Exception e) {

System.out.println("已运行 xlCreate() : " + e );

}

}

}

读取Excel文档中的数据

示例2将演示如何读取Excel文档中的数据。假定在D盘JTest目录下有一个文件名为test1.xls的Excel文件。

示例2程序如下:

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.hssf.usermodel.HSSFSheet;

import org.apache.poi.hssf.usermodel.HSSFRow;

import org.apache.poi.hssf.usermodel.HSSFCell;

import java .io.FileInputStream;

public class ReadXL {

/** Excel文件的存放位置。注意是正斜线*/

public static String fileToBeRead="D:\test1.xls";

public static void main(String argv[]){

try{

// 创建对Excel工作簿文件的引用

HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(fileToBeRead));

// 创建对工作表的引用。

// 本例是按名引用(让我们假定那张表有着缺省名"Sheet1")

HSSFSheet sheet = workbook.getSheet("Sheet1");

// 也可用getSheetAt(int index)按索引引用,

// 在Excel文档中,第一张工作表的缺省索引是0,

// 其语句为:HSSFSheet sheet = workbook.getSheetAt(0);

// 读取左上端单元

HSSFRow row = sheet.getRow(0);

HSSFCell cell = row.getCell((short)0);

// 输出单元内容,cell.getStringCellValue()就是取所在单元的值

System.out.println("左上端单元是: " + cell.getStringCellValue());

}catch(Exception e) {

System.out.println("已运行xlRead() : " + e );

}

}

}

设置单元格格式

在这里,我们将只介绍一些和格式设置有关的语句,我们假定workbook就是对一个工作簿的引用。在Java中,第一步要做的就是创建和设置 字体和单元格的格式,然后再应用这些格式:

1、创建字体,设置其为红色、粗体:

HSSFFont font = workbook.createFont();

font.setColor(HSSFFont.COLOR_RED);

font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

2、创建格式

HSSFCellStyle cellStyle= workbook.createCellStyle();

cellStyle.setFont(font);

3、应用格式

HSSFCell cell = row.createCell((short) 0);

cell.setCellStyle(cellStyle);

cell.setCellType(HSSFCell.CELL_TYPE_STRING);

cell.setCellValue("标题 ");

处理WORD文档

import java .io.*;

import org.apache.poi.hwpf.extractor.WordExtractor;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.hssf.usermodel.HSSFSheet;

import org.apache.poi.hssf.usermodel.HSSFRow;

import org.apache.poi.hssf.usermodel.HSSFCell;

public class TestPoi {

public TestPoi() {

}

public static void main(String args[]) throws Exception

{

FileInputStream in = new FileInputStream ("D:\a.doc");

WordExtractor extractor = new WordExtractor();

String str = extractor.extractText(in);

//System.out.println("the result length is"+str.length());

System.out.println(str);

}

}

搜集链接 方便以后查阅
POI操作Excel常用方法总结

自己封装的poi操作excel工具类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容