POI學習記錄

做爲一個搞編程開發的朋友,千萬不要告訴朋友親戚,你是幹這個的.

不然你就會遇到很多這樣的問題(當然我們都很樂於助人的,可愛的程序員):

我的電腦怎麼沒有聲音了,又或者是我的電腦怎麼沒有顯示了,又或者是下面這樣的.


需求:

a.統計excel表中,每個sheet總,每個項目的費時

   a.1:每個sheet中,可能有不同的項目,或者相同的項目

   a.2:每個sheet中的項目,又分爲不同類型的項目(不同類型,主要區別于格式不同,然後去判斷是否有重複時得按,sheet,然後類型來區分)

b.將統計的結果,按不同類型的格式,產生一個"彙總"sheet


代碼(POI操作包括,上下合併單元格,左右合併單元格,設置單元格基本格式,寫入公式簡單操作,做個備份記錄學習用):

package com.deal;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;


/**
 * 讀取excel2007文檔
 * 
 * @author Administrator
 */

@SuppressWarnings("serial")
public class ReadXlsX {
    /** 日期 總 項目*/
    private static Map<String,String> part1 = new LinkedHashMap<String, String>(){
        {
            put("日期","日期");
            put("總","總");
            put("項目","項目");
        }
    };
    /**設計項目前面那幾個*/
    private static Map<String,String> part2 = new LinkedHashMap<String, String>();
    /**設計項目*/
    private static Map<String,String> part3 = new LinkedHashMap<String, String>();
    /**銷售配合*/
    private static Map<String,String> part4 = new LinkedHashMap<String, String>();
    /**施工配合*/
    private static Map<String,String> part5 = new LinkedHashMap<String, String>();
    /**最後面那幾個*/
    private static Map<String,String> part6 = new LinkedHashMap<String, String>();
    
    /** 用戶式耗時 Map<sheetName(即人名),Map<部分標識,Map<項目名,Map<階段名,加總列行號,及列號>>>>*/
    private static Map<String,Map<Integer,Map<String,Map<String,int[]>>>> personTime = new HashMap<String, Map<Integer,Map<String,Map<String,int[]>>>>();
    private static List<String> sheetNameList = new ArrayList<String>();
    private static String[] columnNumChar = null;
    
    
    private static List<String> item = new ArrayList<String>(){
        {
            add("方案前期");add("方案");add("初步設計");add("施工圖設計");add("投標配合");
        }
    };
    
    private static int employNum = 0;
    
    
    public String dealXlsX(String filePath) {
        try {
            this.copy(filePath);
            FileInputStream input = new FileInputStream(filePath);
            Workbook xlsFile = WorkbookFactory.create(input); 
            int sheetNum = xlsFile.getNumberOfSheets();
            
            if(this.isHaveTotalSheet(xlsFile, sheetNum-1)){
                sheetNum -=1;
                xlsFile.removeSheetAt(sheetNum);
            }
            employNum =sheetNum;
            
            for (int i = 0; i < sheetNum; i++) {
                Sheet sheet = xlsFile.getSheetAt(i);
                int rowNum = sheet.getPhysicalNumberOfRows();
                String titleIndexStr = this.getCellValue(sheet,0,null,0,rowNum-1,null);
                sheetNameList.add(sheet.getSheetName());
//                System.out.println(sheet.getSheetName()+ ":"+titleIndexStr);
                
                if(!titleIndexStr.equals("")){
                    String[] indexTemp = titleIndexStr.split(",");
                    int[] index = new int[indexTemp.length];
                    for (int j = 0; j < indexTemp.length; j++) {
                        index[j] = Integer.parseInt(indexTemp[j]);
                    }
                    
                    //得到第二部分3-->index[0];日期後面的
                    this.getCellValue(sheet, 1, part2, 2, rowNum-1,new int[]{3,index[0]});
                    //得到第三部分index[0]-->index[1] 設計項目
                    this.getCellValue(sheet, 1, part3, 3, rowNum-1,new int[]{index[0],index[1]});
                    //得到第四部分i1 -->i2 銷售配合
                    this.getCellValue(sheet, 1, part4, 4, rowNum-1,new int[]{index[1],index[2]});
                    //得到第五部分i2-->第一個增加項  施工配合
                    String index5 = this.getCellValue(sheet, 1, part5, 5, rowNum-1,new int[]{index[2],0});
                    //得到第六部分:第一個增加項-->末尾  末尾
                    this.getCellValue(sheet, 1, part6, 6, rowNum-1,new int[]{Integer.parseInt(index5)+1,0});
                }
            }
            
            Sheet totalSheet = this.createSheet(xlsFile, "彙總");
            totalSheet.setForceFormulaRecalculation(true);
            
            this.writeCell(totalSheet);
            
            xlsFile.setActiveSheet(xlsFile.getNumberOfSheets()-1);
            
            FileOutputStream fileOut = new FileOutputStream(filePath);
            xlsFile.write(fileOut);
            input.close();
            fileOut.close();
            return "0";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }
    
    
    
    public static void main(String[] args){
        String filePath = "D:\\aa.xlsx";
        new ReadXlsX().dealXlsX(filePath);
    }
    
    //////////////////////////////////REDA FUNCTION////////////////////////////////////////////////////////////
    public String getCellValue(Sheet sheet,int rowIndex,Map<String,String> content,int part,int totalRow,int... cellIndex){
        StringBuilder indexStr = new StringBuilder();
        Row row = sheet.getRow(rowIndex);
        if(row != null){
            int cellNum = row.getPhysicalNumberOfCells();
            int i = 0;
            if(cellIndex != null){
                i = cellIndex[0];                //start point
                //end point
                if(part <5){
                    cellNum = cellIndex[1];            
                }
            }
            
            for (; i < cellNum; i++) {
                Cell cell = row.getCell(i);
                if(cell != null && !cell.toString().equals("")){
                    if(part == 0){
                        indexStr.append(i+",");
                    }else{
                        int[] rowAndColumn = new int[]{totalRow,i};
                        this.putPersonIntoMap(sheet.getSheetName(), cell.toString(), part, rowAndColumn);
                        if(!content.containsKey(cell.toString())){
                            content.put(cell.toString(), cell.toString());
                        }
                        
                        if(part == 5){
                            if(cell.toString().equals("增加項")){
                                return indexStr.append(i).toString();
                            }
                        }
                    }
                }
            }
        }
        return indexStr.toString();
    }
    
    /** 用戶式耗時 Map<sheetName(即人名),Map<部分標識,Map<項目名,Map<階段名,加總列行號,及列號>>>>*/
    public void putPersonIntoMap(String personName,String projectName,int part,int[] rowAndColunm){
        String proName = "N/A";            //階段名稱
        if(part == 3 || part == 4){
            for (int i = 0; i < item.size(); i++) {
                proName = item.get(i);
                this.putDataToMap(personName, projectName, proName, part, rowAndColunm[0],rowAndColunm[1]);
                rowAndColunm[1] +=1;
            }
        }else{
            this.putDataToMap(personName, projectName, proName, part, rowAndColunm[0],rowAndColunm[1]);
        }
    }
    
    /** 用戶式耗時 Map<sheetName(即人名),Map<部分標識,Map<項目名,Map<階段名,加總列行號,及列號>>>>*/
//    private static Map<String,Map<Integer,Map<String,Map<String,int[]>>>>
    public void putDataToMap(String personName,String projectName,String proName,int part,int row,int column){
        int[] rowAndColunm = new int[]{row,column};
        if(personTime.containsKey(personName)){
            Map<Integer,Map<String,Map<String,int[]>>> personMap= personTime.get(personName);
            if(personMap.containsKey(part)){
                Map<String,Map<String,int[]>> partMap = personMap.get(part);
                if(partMap.containsKey(projectName)){
                    Map<String,int[]> projectAllPro = partMap.get(projectName);
                    projectAllPro.put(proName, rowAndColunm);
                }else{
                    Map<String, int[]> proMap = new HashMap<String, int[]>();
                    proMap.put(proName, rowAndColunm);
                    
                    partMap.put(projectName, proMap);
                }
                
            }else{
                Map<String, int[]> proMap = new HashMap<String, int[]>();
                proMap.put(proName, rowAndColunm);
                
                Map<String,Map<String, int[]>> projectMap = new HashMap<String, Map<String,int[]>>();
                projectMap.put(projectName, proMap);
                
                personMap.put(part, projectMap);
            }
            
        }else{
            Map<String, int[]> proMap = new HashMap<String, int[]>();
            proMap.put(proName, rowAndColunm);
            
            Map<String,Map<String, int[]>> projectMap = new HashMap<String, Map<String,int[]>>();
            projectMap.put(projectName, proMap);
            
            Map<Integer,Map<String,Map<String,int[]>>> partMap= new HashMap<Integer, Map<String,Map<String,int[]>>>();
            partMap.put(part, projectMap);
            
            personTime.put(personName,partMap);
        }
//        this.printTime();
    }
    
    //////////////////////////////////WRITE FUNCTION///////////////////////////////////////////////////////////
    /**
     * 創建彙總表
     * @param xlsFile
     * @param sheeName
     * @return
     */
    public Sheet createSheet(Workbook xlsFile,String sheeName){
        Sheet newSheet = xlsFile.createSheet(sheeName);
        newSheet.autoSizeColumn(1);
        
        int rowNum = employNum+7;
        int colNum = part1.size()+part2.size()+(part3.size()*5)
        +(part4.size()*5)+(part5.size())+part6.size();
//        System.out.println("總列數"+colNum);
        
        CellStyle style = xlsFile.createCellStyle();
        Font font = xlsFile.createFont();
        font.setFontHeightInPoints((short) 10);  //設置爲10號字體
        
        style.setWrapText(true);                //自動換行
        style.setFont(font);
        style.setBorderTop(CellStyle.BORDER_DOTTED);        //實線BORDER_THIN 虛線BORDER_DOTTED
        style.setBorderBottom(CellStyle.BORDER_DOTTED);
        style.setBorderBottom(CellStyle.BORDER_DOTTED);
        style.setBorderRight(CellStyle.BORDER_DOTTED);
        style.setAlignment(CellStyle.ALIGN_CENTER);        //文體居中對齊
        
        for (int i = 0; i < rowNum; i++) {
            Row newRow = newSheet.createRow(i);
            for (int j = 0; j < colNum; j++) {
                Cell cell = newRow.createCell(j);
                cell.setCellStyle(style);
                if(j <=2){
                    newSheet.setColumnWidth(j, 1000);            //設置列寬
                }else{
                    newSheet.setColumnWidth(j, 900);            //設置列寬
                }
            }
        }
        return newSheet;
    }
    
    public void writeCell(Sheet sheet){
        int startPoint=part1.size()+part2.size();
        int endPoint1 = startPoint+(part3.size()*5);    //設計項目
        int endPoint2 = endPoint1+(part4.size()*5);        //銷售配合
        int endPoint3 = endPoint2+(part5.size());        //施工配合
//        System.out.println("分界點:"+startPoint+","+endPoint1+","+endPoint2+","+endPoint3);
        
        int[] point = new int[]{startPoint,endPoint1,endPoint2,endPoint3};
        
        this.writeTitle(sheet, point);
        this.writeEmployName(sheet);
        this.writePart1(sheet);
        this.writePart2(sheet);
        this.writeItemS(sheet, startPoint,part3,3);
        this.writeItemS(sheet, endPoint1, part4,4);
        this.writePart5(sheet, endPoint2, part5);
        this.writePart6(sheet, endPoint3, part6);
        
        //寫入公式示例
//        this.writeCellValue(sheet, "xxxx", 6, 0, true);
//        this.writeCellValue(sheet, "A7", 3, 2, false);
    }
    
    public void writeTitle(Sheet sheet,int[] point){
        Row titleRow = sheet.getRow(0);
        
        //先合併單元格,再寫
        this.mergeCell(sheet, 0, 0, point[0], point[1]-1);
        titleRow.getCell(point[0]).setCellValue("設計項目");
//        
        this.mergeCell(sheet, 0, 0, point[1], point[2]-1);
        titleRow.getCell(point[1]).setCellValue("銷售配合");
//        
        this.mergeCell(sheet, 0, 0, point[2], point[3]-1);
        titleRow.getCell(point[2]).setCellValue("施工配合");
    }
    
    /**
     * 將第一部分內容(日期,總,項目 固定的三個值)寫入第二列
     * @param sheet
     */
    public void writePart1(Sheet sheet){
        List<String> part1List = this.mapKeyToList(part1);
        Row secRow = sheet.getRow(1);
        for (int i = 0; i < part1.size(); i++) {
            secRow.getCell(i).setCellValue(part1List.get(i));
        }
    }
    
    public void writePart2(Sheet sheet){
        List<String> part2List = this.mapKeyToList(part2);
        int size = part2List.size();
        int z =0;
        for (int i = 0; i < size; i++) {
            String value = part2List.get(i);
            this.mergeCell(sheet, 1, 2, 3+i, 3+i);
            if(value.equals("增加項")){
                continue;
            }
            this.writeCellValue(sheet, value, 1, z+3,true);
            
            this.writePersonFor(sheet, 2, value, "N/A", z+3);
            z++;
        }
        this.writeCellValue(sheet, "增加項", 1, z+3,true);
        this.writePersonFor(sheet, 2, "增加項", "N/A", z+3);
    }
    
    /**
     * 寫設計項目與銷售配合部分的第一個方法.
     * 循環得到要寫的項目,如果爲增加項,則跳過.
     * 否則寫入該項目.
     * 寫完所有項目之後,添加一下增加項
     * @param sheet
     * @param startPoint
     * @param dataMap
     */
    public void writeItemS(Sheet sheet,int startPoint,Map<String,String> dataMap,int part){
        List<String> partList = this.mapKeyToList(dataMap);
        for (int i = 0; i < partList.size(); i++) {
            String value = partList.get(i);
            if(!value.equals("增加項")){
                int endPoint = startPoint+4;
                this.writeItem(sheet, 1, 1, startPoint, endPoint, value,part);
                startPoint = endPoint+1;
            }else{
                continue;
            }
        }
        this.writeItem(sheet, 1, 1, startPoint, startPoint+4, "增加項",part);
    }
    
    /**
     * 寫設計項目與銷售配合部分的主體方法.
     * 先合併第2行橫着的5列,寫入值
     * 然後再第3行的依次寫入5個固定的值.
     * @param sheet
     * @param startRow
     * @param endRow
     * @param startColumn
     * @param endColumn
     * @param value
     */
    public void writeItem(Sheet sheet,int startRow,int endRow,int startColumn,int endColumn,String value,int part){
        this.mergeCell(sheet, startRow, endRow, startColumn,endColumn);
        this.writeCellValue(sheet, value, startRow, startColumn,true);
        for (int i = 0; i < 5; i++) {
            this.writeCellValue(sheet, item.get(i), startRow+1, startColumn+i,true);
            this.writePersonFor(sheet, part, value, item.get(i), startColumn+i);
        }
    }
    /**
     * 寫施工配合部分
     * @param sheet
     * @param startPoint
     * @param dataMap
     */
    public void writePart5(Sheet sheet,int startPoint,Map<String,String> dataMap){
        List<String> part5List = this.mapKeyToList(dataMap);
        for (String string : part5List) {
            System.out.println(string);
        }
        for (int i = 0; i < part5List.size(); i++) {
            this.write2RowItem(sheet, 1, 1+1, startPoint+i, part5List.get(i),5);
        }
//        if(part5List.size() == 1){
            
//        }else{
//            this.writeItemS(sheet, startPoint, dataMap,5);
//        }
    }
    
    /**
     * 將表格的最後一部寫進去
     * @param sheet
     * @param startPoint
     * @param dataMap
     */
    public void writePart6(Sheet sheet,int startPoint,Map<String,String> dataMap){
        List<String> part6List = this.mapKeyToList(dataMap);
        for (int i = 0; i < part6List.size(); i++) {
            this.write2RowItem(sheet, 1, 1+1, startPoint+i, part6List.get(i),6);
        }
    }
    
    /**
     * 合併豎着的兩行,然後再寫入字符串
     * @param sheet
     * @param startRow
     * @param endRow
     * @param startColumn
     * @param value
     */
    public void write2RowItem(Sheet sheet,int startRow,int endRow,int startColumn,String value,int part){
        this.mergeCell(sheet, startRow, endRow, startColumn, startColumn);
        this.writeCellValue(sheet, value, startRow, startColumn,true);
        this.writePersonFor(sheet, part, value, "N/A", startColumn);
    }
    
    /**
     * 向單元格寫入值
     * @param sheet        操作的sheet
     * @param value        寫的值
     * @param row        行號(第一行爲0)
     * @param column    列號
     * @param flag        是否爲公式 true:爲String,false:公式
     */
    public void writeCellValue(Sheet sheet,String value,int row,int column,boolean flag){
        Row rowD = sheet.getRow(row);
        if(flag){
            rowD.getCell(column).setCellValue(value);
        }else{
            rowD.getCell(column).setCellType(Cell.CELL_TYPE_FORMULA);
            rowD.getCell(column).setCellFormula(value);
        }
    }
    
    /**
     * 合併單元格
     * @param sheet        操作的sheet
     * @param sRow         開始行號(第一行爲0)
     * @param endRow    結束行號(第一行爲0)
     * @param sCol        開始列號(第一列爲0)
     * @param endCol    結束列號(第一列爲0)
     */
    public void mergeCell(Sheet sheet,int sRow,int endRow,int sCol,int endCol){
        sheet.addMergedRegion(new CellRangeAddress(sRow,endRow,sCol,endCol));
    }
    
    public void writeEmployName(Sheet sheet){
        for (int i = 0; i < sheetNameList.size(); i++) {
            this.writeCellValue(sheet, sheetNameList.get(i), i+3, 1,true);
            this.writeCellValue(sheet, "總", i+3, 0, true);
        }
        this.writeCellValue(sheet, "項目總用時", sheetNameList.size()+3, 1, true);
        this.writeCellValue(sheet, "設計師用時", sheetNameList.size()+5, 1, true);
        this.writeCellValue(sheet, "設計助理用時", sheetNameList.size()+6, 1, true);
        sheet.setColumnWidth(1, 1500);
    }
    
    /** 用戶式耗時 Map<sheetName(即人名),Map<部分標識,Map<項目名,Map<階段名,加總列行號,及列號>>>>*/
    public void writePersonFor(Sheet sheet,int part,String projectName,String proName,int column){
        if(columnNumChar == null){
            columnNumChar = this.initColumnChar(sheet);
        }
        for (int i = 0; i < sheetNameList.size(); i++) {
//            Row row = sheet.getRow(arg0)
            int writeRowNum = i+3;
            Row writeRow = sheet.getRow(writeRowNum);
            String personName = writeRow.getCell(1).toString();            //得到人名
            Map<String,Map<String,int[]>> partProjectMap =  personTime.get(personName).get(part);
            String value = "N/A";
//                System.out.println(columnNumChar.length+"--->"+personName+"--->"+projectName+"-->"+proName);
            if(partProjectMap.containsKey(projectName)){
                int[] srcCell = partProjectMap.get(projectName).get(proName);
//                System.out.println(columnNumChar.length+"--->"+personName+"--->"+projectName+"-->"+proName+"--->"+srcCell[0]+","+srcCell[1]);
                value = personName+"!"+columnNumChar[srcCell[1]]+""+(srcCell[0]+1);
                this.writeCellValue(sheet, value, writeRowNum, column, false);
            }else{
                this.writeCellValue(sheet, value, writeRowNum, column, true);
            }
        }
        //計算項目總用時:
        int totalRow = 3+sheetNameList.size()+1;
        String value="SUM("+columnNumChar[column]+"4"+":"+columnNumChar[column]+(totalRow-1)+")";
        this.writeCellValue(sheet, value, totalRow-1, column, false);
    }
    
    
    ///////////////////////////////////////UTIL FUNCTION///////////////////////////////////////////////////////
    public static void testPrint(String str,Map<String,String> map){
        Set<String> key = map.keySet();
        for (String item : key) {
            System.out.print(item+",");
        }
//        System.out.println(str+map.size());
        System.out.println();
        System.out.println();
    }
    
    /**
     * 返回由Map所有的key轉換爲的List
     * @param partMap
     * @return
     */
    public List<String> mapKeyToList(Map<String,String> partMap){
        List<String> reList = new ArrayList<String>();
        Set<String> keys = partMap.keySet();
        for (String item : keys) {
            reList.add(item);
        }
        return reList;
    }
    
    public boolean isHaveTotalSheet(Workbook xlsFile,int index){
        if(xlsFile.getSheetAt(index).getSheetName().equals("彙總")){
            return true;
        }
        return false;
    }
    
    public String[] initColumnChar(Sheet sheet){
        int maxColnum = sheet.getRow(1).getPhysicalNumberOfCells();
//        System.out.println("第二列長度爲"+maxColnum);
        String[] columnChar = new String[maxColnum];
        String[] baseChar = new String[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
        for (int i = 0; i < columnChar.length; i++) {
            if(i>=26){
                columnChar[i] = baseChar[i/26-1]+baseChar[i%26];
            }else{
                columnChar[i] = baseChar[i%26];
            }
        }
        return columnChar;
    }
    
    
    public void printTime(){
        Set<String> names = personTime.keySet();
        for (String name : names) {
            Set<Integer> parts = personTime.get(name).keySet();
            for (Integer part : parts) {
                Set<String> projects = personTime.get(name).get(part).keySet();
                for (String project : projects) {
                    Set<String> pros = personTime.get(name).get(part).get(project).keySet();
                    for (String pro : pros) {
                        int[] cell = personTime.get(name).get(part).get(project).get(pro);
                        System.out.println(name+"--->"+part+"--->"+project+"--->"+pro+cell[0]+","+cell[1]);
                    }
                }
            }
        }
        System.out.println();
        System.out.println();
    }
    
     public void copy(String file) throws IOException {
            FileInputStream fin = new FileInputStream(new File(file));
            String newFileName = file.substring(0,file.lastIndexOf("."))+"bak"+file.substring(file.lastIndexOf("."));
            FileOutputStream fout = new FileOutputStream(new File(newFileName));
            int bytesRead;
            byte[] buf = new byte[4 * 1024];  // 4K
            while ((bytesRead = fin.read(buf)) != -1) {
                fout.write(buf, 0, bytesRead);
            }
            fout.flush();
            fout.close();
            fin.close();
        } 
    
}

代碼及excel表格:http://download.csdn.net/detail/ilyzj/4542743


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章