成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

poi幾多愁,恰似源碼的溫柔

zhiwei / 1841人閱讀

摘要:拿到值后,創(chuàng)建當(dāng)前單元格,把數(shù)據(jù)填充進(jìn)去。首先判斷當(dāng)前單元格的數(shù)據(jù)是不是數(shù)字型的,如果是數(shù)字型的,在判斷是不是日期類型的,如果是日期類型,再轉(zhuǎn)為日期類型。

導(dǎo)讀

最近,公司在做導(dǎo)入導(dǎo)出的項(xiàng)目,首先想到的是poi的導(dǎo)入和導(dǎo)出。如果每次導(dǎo)入和導(dǎo)出都要重寫的話,那么,實(shí)在是浪費(fèi)時(shí)間和精力。于是,封裝了原生的poi的導(dǎo)入和導(dǎo)出。在封裝的時(shí)候,就會(huì)出現(xiàn)一系列的問題。

在進(jìn)行導(dǎo)入和導(dǎo)出的時(shí)候,我們必須要熟悉Excel,尤其是它所支持的類型,如圖所示:

因?yàn)槲矣玫氖莏ava,這要和java語(yǔ)言相匹配。java有八大基本類型(包裝類型)、字符串類型、日期類型、時(shí)間戳類型等。Excel類型要和這些類型相匹配,否則,就會(huì)出現(xiàn)導(dǎo)入和導(dǎo)出的問題。

導(dǎo)出 導(dǎo)出的思想

采用hibernate或mybatis框架,從數(shù)據(jù)庫(kù)中取出數(shù)據(jù),假設(shè)名字為originalList

使用appach下面的beanutils框架的PropertyUtils.getProperty((Object bean, String name))方法過濾數(shù)據(jù)。它是通過對(duì)象的屬性名稱拿到對(duì)象的屬性值。這里面用到的反射。

將過濾后的數(shù)據(jù)放到JsonObject集合中,key是當(dāng)前對(duì)象的屬性名,value是屬性對(duì)應(yīng)的屬性值。假設(shè)名為dataList。

使用LinkedHashMap封裝Excel表的表頭,也就是上圖中的第一行數(shù)據(jù)。key值是上述對(duì)象的數(shù)值名,value值表頭的中文名。假設(shè)名為headerMap。為什么使用LinkedHashMap,而不是HashMap?這個(gè)在下文說

實(shí)例化poi導(dǎo)出的各個(gè)對(duì)象,便于操作。

遍歷headerMap,獲取當(dāng)前的key值。

遍歷dataList,如果list中的當(dāng)前對(duì)象是JsonObject對(duì)象,直接獲取與key值相同的屬性值。如果不是JsonObject對(duì)象,可以通過PropertyUtils.getProperty((Object bean, String name))獲取值。

拿到值后,創(chuàng)建當(dāng)前單元格,把數(shù)據(jù)填充進(jìn)去。

響應(yīng)客戶端的導(dǎo)出請(qǐng)求

解決“為什么使用LinkedHashMap,而不是HashMap?”這個(gè)問題

1、 因?yàn)镠ashMap的key值是對(duì)象的hashCode值,hashCode值是散列值。這樣存儲(chǔ)方式是散列存儲(chǔ),就像浴缸中的魚一樣,它的位置是不確定的,因而,輸出結(jié)果具有很多不確定性。也就是說,輸出結(jié)果的順序和我們存儲(chǔ)的順序不一致,如圖所示:

2、但是,LinkedHashMap采用的是鏈表,鏈表節(jié)點(diǎn)的存儲(chǔ)的是下一個(gè)引用對(duì)象的首地址。就像是一根繩子上節(jié)點(diǎn),系在哪兒就在哪那兒,位置不會(huì)改變的,如圖所示:

上述思想的方法
 /**
     * Created By zby on 18:22 2019/3/9
     *
     * @param response  響應(yīng)客戶端的導(dǎo)出請(qǐng)求
     * @param headerMap 創(chuàng)建表頭
     * @param dataList  數(shù)據(jù)集
     * @param excelName excel表名
     */
    public static void exportSimpleExcel(HttpServletResponse response, LinkedHashMap headerMap, List dataList, String excelName) {
        // 創(chuàng)建個(gè)workbook
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 創(chuàng)建一個(gè)sheet
        XSSFSheet sheet = workbook.createSheet();
        Pattern chinese_pattern = Pattern.compile("[u4e00-u9fa5]");
        if (sheet != null) {
            try {
                // 寫數(shù)據(jù)
                Integer i = 0;
                for (Map.Entry entry : headerMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    Row headRow = sheet.getRow(0);
                    if (isNull(headRow)) {
                        headRow = sheet.createRow(0);
                    }
                    CellStyle cellStyle = workbook.createCellStyle();
                    cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下邊框
                    cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左邊框
                    cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上邊框
                    cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右邊框
                    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);//居中
                    cellStyle.setFillBackgroundColor(HSSFColor.GREY_40_PERCENT.index);
                    
                    //創(chuàng)建標(biāo)題行,如果第一遍已經(jīng)創(chuàng)建了,就直接根據(jù)下標(biāo)獲取行,
                    // 如果沒有創(chuàng)建標(biāo)題行,就根據(jù)當(dāng)前下標(biāo)創(chuàng)建當(dāng)前行,以下相同。
                    Cell headCell = headRow.createCell(i);
                    headCell.setCellValue(value);
                    headCell.setCellStyle(cellStyle);
                    
                    //設(shè)置標(biāo)題下的數(shù)據(jù),每創(chuàng)建標(biāo)題的一個(gè)單元格,就創(chuàng)建該單元格下的所有列
                    //行數(shù)就是一行標(biāo)題單元格+數(shù)據(jù)單元格的個(gè)數(shù),即merginRow+j
                    for (int j = 0; j < dataList.size(); j++) {
                        Object obj = dataList.get(j);
                        //需要判斷json是否是jsonObject的實(shí)例化對(duì)象,別人在調(diào)用這個(gè)方法時(shí),
                        // 我們不清楚jsons集合中是否存在其他類的對(duì)象,因?yàn)樾枰鱾€(gè)驗(yàn)證
                        Object val = null;
                        if (obj instanceof JSONObject) {
                            JSONObject json = (JSONObject) obj;
                            val = json.get(key);
                        } 
//                    else {這里如果不是JsonObject對(duì)象,就用這種方式獲取
//                            try {
//                                //這是appach下的方法,其通過屬性名稱,反射得到當(dāng)前對(duì)象屬性的數(shù)值
//                                //json當(dāng)中的key就相當(dāng)于其屬性,其值就是value值
//                                val = getProperty(obj, key);
//                            } catch (Exception e) {
//                                if (obj != null) {
//                                    LogUtil.warn(logger, "類: " + obj.getClass() + ",  屬性: " + key);
//                                }
//                                val = null;
//                            }
//                        }

                        Row row = sheet.getRow(1 + j);
                        if (isNull(row)) {
                            row = sheet.createRow(1 + j);
                        }
                        Cell cell = row.createCell(i);
                        cell.setCellStyle(cellStyle);
                        if (val instanceof Double) {
                            cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                            cell.setCellValue(((Double) val).doubleValue());
                        } else if (val instanceof Integer) {
                            cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                            cell.setCellValue(((Integer) val).intValue());
                        } else if (val instanceof Date) {
                            cell.setCellValue(ISO_DATETIME_FORMAT.format(val));
                        } else if (val instanceof Calendar) {
                            cell.setCellValue((Calendar) val);
                        } else if (val instanceof Boolean) {
                            cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
                            cell.setCellValue(((Boolean) val).booleanValue());
                        } else if (val instanceof String || val instanceof RichTextString) {
                            cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                            String cellValue = (String) val;
                            int width = cellValue.length();
                            Matcher matcher = chinese_pattern.matcher(cellValue);
                            while (matcher.find()) {
                                width++;
                            }
                            width = (width > 6) ? ((width < 80) ? width : 80) : 6;
                            sheet.setColumnWidth(i, (256 * width + 184) + 500);
                            cell.setCellValue(cellValue);
                        } else {
                            cell.setCellValue("");
                        }
                    }
                    i++;
                }
                String realPath = (getSispPath() + "uploadExcelRecord");
                // 新的文件名
                String newFileName = excelName + DateUtil.ISO_DATETIME_FORMAT_NONE.format(new Date()) + ".xlsx";
                // 判斷路徑是否存在
                File dir = new File(realPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                // 寫入到新的excel
                File newFile = new File(realPath, newFileName);
                FileOutputStream fos = new FileOutputStream(newFile);
                workbook.write(fos);
                fos.flush();
                fos.close();
                downloadExcel(response, newFile, excelName);
                deleteFile(newFile);
            } catch (Exception e) {
                logger.error("——————————————————————————數(shù)據(jù)寫入表格失敗————————————————————————————");
            }
        }
    }
注意事項(xiàng)
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
cell.setCellValue(((Double) val).doubleValue());

針對(duì)這兩句,我們查看poi的cell.setCellValue()方法的底層是如何實(shí)現(xiàn)的。

 void setCellValue(double var1);

 void setCellValue(Date var1);

 void setCellValue(Calendar var1);

 void setCellValue(RichTextString var1);

 void setCellValue(String var1);

 void setCellValue(boolean var1);

在java的八大類型當(dāng)中,poi支持浮點(diǎn)型的double類型,整型的integer類型。為什么是這兩種類型?這兩種格式是java的默認(rèn)類型。double可以轉(zhuǎn)整型的。
所有,我們?cè)谶M(jìn)行數(shù)據(jù)導(dǎo)出時(shí),一定要主營(yíng)待導(dǎo)出對(duì)象的數(shù)據(jù)類型,避免數(shù)據(jù)無法導(dǎo)出。

導(dǎo)入 導(dǎo)入的思想

在導(dǎo)入時(shí),接收到客戶端發(fā)出的導(dǎo)入請(qǐng)求。

設(shè)置導(dǎo)入數(shù)據(jù)的開始行和結(jié)束行,開始行默認(rèn)是0,結(jié)束行調(diào)用者給出的參數(shù)

設(shè)計(jì)導(dǎo)入的開始列和結(jié)束列,開始列一般是0,結(jié)束列一般是調(diào)用給出的列

獲取導(dǎo)入的文件,判斷Excel的版本。

導(dǎo)入的方法
 /**
     * Created By zby on 19:24 2019/3/9
     *
     * @param request           客戶端發(fā)出的導(dǎo)入請(qǐng)求
     * @param sheetDataStartRow 導(dǎo)入的開始行
     * @param sheetDataEndCol   導(dǎo)入的結(jié)束列
     */
    public static LinkedHashMap> importMultiSheetExcel(HttpServletRequest request, Integer sheetDataStartRow, String sheetDataEndCol) {
        //創(chuàng)建導(dǎo)入和行和列
        LinkedHashMap sheetDataEndColMap = new LinkedHashMap<>();
        LinkedHashMap sheetFirstDataRowMap = new LinkedHashMap();
        sheetDataEndColMap.put(0, sheetDataEndCol);
        sheetFirstDataRowMap.put(0, sheetDataStartRow);
        LinkedHashMap> resMap = new LinkedHashMap<>();
        try {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            ifNullThrow(multipartRequest, ResultCodeEnum.ILLEGAL_PARAM);
            MultipartFile file = multipartRequest.getFile("file");
            Workbook work = getWorkbook(file.getInputStream(), file.getOriginalFilename());
            ifNullThrow(work, ResultCodeEnum.ILLEGAL_PARAM);
            Sheet sheet = null;
            Row row = null;
            Cell cell = null;
            //遍歷Excel中所有的sheet
            for (int i = 0; i < work.getNumberOfSheets(); i++) {
                sheet = work.getSheetAt(i);
                if (null == sheet) {
                    continue;
                }
                String sheetDataEndCo = sheetDataEndColMap.get(i);
                Integer sheetFirstDataRow = sheetFirstDataRowMap.get(i);
                sheetDataEndCo = isNotBlank(sheetDataEndCo) ? sheetDataEndCo.toUpperCase() : null;
                sheetFirstDataRow = isNotNull(sheetFirstDataRow) ? sheetFirstDataRow : 1;
                List list = new ArrayList<>();
                //遍歷當(dāng)前sheet中的所有行
                for (int j = 0; j <= sheet.getLastRowNum(); j++) {
                    row = sheet.getRow(j);
                    if (row == null) {
                        continue;
                    }
                    if (j >= sheetFirstDataRow.intValue()) {
                        JSONObject json = new JSONObject();
                        //導(dǎo)入限制最大列索引數(shù)為200,正常根據(jù)sheetDataEndCol確定,最大列索引數(shù)限制只用來防止傳入錯(cuò)誤
                        for (int k = 0; k < 200; k++) {
                            String colName = CellReference.convertNumToColString(k);
                            cell = row.getCell(k);
                            if (isNotNull(cell)) {
                                if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                                    cell.setCellType(Cell.CELL_TYPE_STRING);
                                    json.put(colName, cell.getStringCellValue().trim());
                                } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                        json.put(colName, cell.getDateCellValue());
                                    } else {
                                        cell.setCellType(Cell.CELL_TYPE_STRING);
                                        json.put(colName, cell.getStringCellValue().trim());
                                    }
                                }
                            } else {
                                json.put(colName, null);
                            }
                            if (colName.equals(sheetDataEndCo)) {
                                break;
                            }
                        }
                        list.add(json);
                    }
                }
                resMap.put("sheet" + i, list);
            }
            return resMap;
        } catch (Exception e) {
            throw new GeneralBizException("Excel導(dǎo)入異常:" + e.getMessage());
        }
    }
注意事項(xiàng)

因?yàn)镋xcel格式的時(shí)間和java的時(shí)間不一致,我們?cè)趯?dǎo)入時(shí)需要注意Excel的格式。首先判斷當(dāng)前單元格的數(shù)據(jù)是不是數(shù)字型的,如果是數(shù)字型的,在判斷是不是日期類型的,如果是日期類型,再轉(zhuǎn)為日期類型。否則,全部是字符型的數(shù)據(jù)。

if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
    cell.setCellType(Cell.CELL_TYPE_STRING);
    json.put(colName, cell.getStringCellValue().trim());
} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
    if(HSSFDateUtil.isCellDateFormatted(cell)){
        json.put(colName, cell.getDateCellValue());
    }else {
        cell.setCellType(Cell.CELL_TYPE_STRING);
        json.put(colName, cell.getStringCellValue().trim());
    }
}

這里為什么不做數(shù)值型的判斷,因?yàn)?,字符串可以轉(zhuǎn)為各中數(shù)值型的數(shù)據(jù)。

結(jié)束語(yǔ)

任何框架的搭建,都需要扎實(shí)的基礎(chǔ),只有基礎(chǔ)足夠強(qiáng)大,再加上靈活的設(shè)計(jì)思想,就能夠解決很多事情。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73626.html

相關(guān)文章

  • 慕課網(wǎng)_《解密JAVA實(shí)現(xiàn)Excel導(dǎo)入導(dǎo)出》學(xué)習(xí)總結(jié)

    時(shí)間:2017年07月06日星期四說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 預(yù)備知識(shí) 基礎(chǔ)知識(shí) struts2框架(上傳下載功能) xml解析技術(shù)(導(dǎo)入模板) JQuery EasyUI(前臺(tái)美觀) 課程目錄 實(shí)現(xiàn)方式 定制導(dǎo)入模版 導(dǎo)入文件 導(dǎo)...

    enrecul101 評(píng)論0 收藏0
  • 【譯】使用 Webpack 和 Poi 構(gòu)建更好 JavaScript 應(yīng)用

    摘要:將處理所有相關(guān)的東西并且在上部署該文件。這里將使用上一節(jié)已經(jīng)創(chuàng)建的文件。使用構(gòu)建應(yīng)用使用構(gòu)建同樣非常簡(jiǎn)單。使用構(gòu)建包如要使用打包項(xiàng)目,只需在終端中執(zhí)行命令,即可在項(xiàng)目目錄中得到文件夾。其在社區(qū)也得到了廣泛的使用。 譯者注:最近看到 Poi 這個(gè)也是打著零配置特點(diǎn)(Parcel:莫名躺槍?)的 JavaScript 打包工具,發(fā)現(xiàn)其在 Github 有著 3000+ Star 的同時(shí)在中...

    30e8336b8229 評(píng)論0 收藏0
  • springboot批量導(dǎo)入excel數(shù)據(jù)

    摘要:背景小白今天閑著沒事,在公司摸魚,以為今天有事無聊的一天,突然上頭說小子,今天實(shí)現(xiàn)一下批量導(dǎo)入數(shù)據(jù)吧,當(dāng)時(shí)我的內(nèi)心是拒絕的,然后默默打開。介紹框架本身并不支持讀取,所有讀取需要借助一些框架。 1 背景 小白今天閑著沒事,在公司摸魚,以為今天有事無聊的一天,突然上頭說小子,今天實(shí)現(xiàn)一下批量導(dǎo)入Excel數(shù)據(jù)吧,當(dāng)時(shí)我的內(nèi)心是拒絕的,然后默默打開idea。 2 介紹 2.1 框架 java...

    Bmob 評(píng)論0 收藏0
  • POI使用及導(dǎo)出excel報(bào)表

    摘要:的使用及導(dǎo)出報(bào)表首先,了解是什么一基本概念是軟件基金會(huì)的開放源碼函式庫(kù),提供給程序?qū)Ω袷綑n案讀和寫的功能。 POI的使用及導(dǎo)出excel報(bào)表 首先,了解poi是什么? 一、基本概念 ? Apache POI是Apache軟件基金會(huì)的開放源碼函式庫(kù),POI提供API給Java程序?qū)icrosoft Office格式檔案讀和寫的功能。 二、基本結(jié)構(gòu) ? HSSF - 提供讀寫...

    Ilikewhite 評(píng)論0 收藏0
  • poi導(dǎo)出excel

    摘要:積分消費(fèi)明細(xì)對(duì)賬單其中,有四個(gè)參數(shù),分別是,,,。導(dǎo)出讀取數(shù)據(jù)庫(kù)的信息,轉(zhuǎn)成。 public void detailExport() { String sourceSystem = getPara(source_system); String dataDate = getPara(data_date); Integer pointsType = get...

    RayKr 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

zhiwei

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<