java封裝實現Excel建表讀寫操作

来源:https://www.cnblogs.com/yumiaoxia/archive/2018/08/28/9545750.html
-Advertisement-
Play Games

對 Excel 進行讀寫操作是生產環境下常見的業務,網上搜索的實現方式都是基於POI和JXL第三方框架,但都不是很全面。小編由於這兩天剛好需要用到,於是就參考手寫了一個封裝操作工具,基本涵蓋了Excel表(分有表頭和無表頭)的創建,並對它們進行讀寫操作。為方便大家,有需要者可以點擊文後點解下載直接使 ...


  對 Excel 進行讀寫操作是生產環境下常見的業務,網上搜索的實現方式都是基於POI和JXL第三方框架,但都不是很全面。小編由於這兩天剛好需要用到,於是就參考手寫了一個封裝操作工具,基本涵蓋了Excel表(分有表頭和無表頭)的創建,並對它們進行讀寫操作。為方便大家,有需要者可以點擊文後點解下載直接使用哦,當然也可以根據自己需求舉一反三自己定製,相信對於聰明的你也不是什麼難事。話不多說,直接貼源碼

pom.xml 文件:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.17</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.8.0-beta2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.8.0-beta2</version>
    </dependency>
  </dependencies>

建表工具類:ExcelBuider.java

 /**
         * 建表工具類
         * @author Sherman
         * email:[email protected]
         * created in 2018/8/24
         */
        @Slf4j
        public class ExcelBuilder {

            private static HSSFSheet sheet;
            private static HSSFWorkbook wb;
            private static boolean hasHeader;

            /**
             * 初始化
             * @param excellName 表名
             */
            public ExcelBuilder(String excellName) {
                wb = new HSSFWorkbook();
                sheet = wb.createSheet(excellName);
            }

            /**
             *  設置表頭,裝配表頭數據
             * @param value 字元串數組,用來作為表頭的值
             *
             */
            public ExcelBuilder header(String... value) {
                if (value != null && value.length != 0) {
                    //設置表頭樣式
                    HSSFCellStyle cellStyle = wb.createCellStyle();
                    cellStyle.setFont(font("黑體", true, 12));
                    HSSFRow row = sheet.createRow(0);
                    for (int i = 0; i < value.length; i++) {
                        HSSFCell cell = row.createCell(i);
                        cell.setCellValue(value[i]);
                        cell.setCellStyle(cellStyle);
                    }
                    hasHeader = true;
                }
                return this;
    }

    /**
     * excel 表內容裝配
     * @param content 待裝配表格內容的二維數組
     * @return
     */
    public ExcelBuilder content(List<List<Object>> content) {
        if (content != null && !content.isEmpty()) {
            int index;
            for (int i = 0; i < content.size(); i++) {
                index = hasHeader == false ? i : i + 1;
                HSSFRow row = sheet.createRow(index);
                for (int j = 0; j < content.get(i).size(); j++) {
                    String r = "";
                    Object value = content.get(i).get(j);
                    //根據數據類型裝配
                    if (value instanceof String) {
                        r = (String) value;
                    } else if (value instanceof Number) {
                        r = String.valueOf(value);
                    } else if (value instanceof BigDecimal) {
                        r = String.valueOf(value);
                    } else {
                        if (!(value instanceof Date) && !(value instanceof Timestamp)) {
                            if (!(value instanceof ZonedDateTime) && !(value instanceof LocalDateTime)) {
                                if (value instanceof Enum) {
                                    r = ((Enum) value).name();
                                } else if (value != null) {

                                   log.info("Error of create row, Unknow field type: " + value.getClass().getName());
                                }
                            } else {
                                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                                r = formatter.format((TemporalAccessor) value);
                            }
                        } else {
                            DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                            r = sdf.format(value);
                        }
                    }

                    row.createCell(j).setCellValue(r);
                }
            }
        }
        return this;
    }

    /**
     * 自動調整列寬大小
     */
    public ExcelBuilder autoColumnWidth() {
        for (int j = 0; j < sheet.getRow(0).getLastCellNum(); j++) {
            int maxLength = 0;
            for (int i = 0; i <= sheet.getLastRowNum(); i++) {
                String value = sheet.getRow(i).getCell(j).getStringCellValue();
                int length = 0;
                if (value != null) {
                    length = value.getBytes().length;
                }
                if (length > maxLength) {
                    maxLength = length;
                }
            }
            sheet.setColumnWidth(j, maxLength > 30 ? (30 * 256 + 186) : (maxLength * 256 + 186));
        }
        return this;
    }

    /**
     * 實例化
     * @param hasHeader 是否有表頭
     * @return Excel表格
     */
    public AbstractExcel build(Boolean hasHeader) {
        return hasHeader ? new HeaderExcel(sheet) : new NoHeaderExcel(sheet);
    }

    /**
     *
     * @param fontName 字體名字
     * @param isBold  是否粗體
     * @param fontSize 字體大小
     * @return 字體
     */
    private HSSFFont font(String fontName, boolean isBold, int fontSize) {
        HSSFFont font = wb.createFont();
        if (fontName != null) font.setFontName(fontName);
        else font.setFontName("黑體");
        font.setBold(isBold);
        font.setFontHeightInPoints((short) fontSize);
        return font;
    }

}

 

excel的抽象父類:

/**
 * @author Sherman
 * created in 2018/8/24
 */

public abstract class AbstractExcel {
    private final HSSFSheet sheet;

    public AbstractExcel() {
        HSSFWorkbook wb = new HSSFWorkbook();
        sheet = wb.createSheet();
    }

    public AbstractExcel(String sheetName){
        HSSFWorkbook wb = new HSSFWorkbook();
        sheet = wb.createSheet(sheetName);
    }

    public AbstractExcel(HSSFSheet sheet) {
        this.sheet = sheet;
    }



    public abstract List<Map<String, String>> getPayload();


    public void write(OutputStream op) throws IOException {
        sheet.getWorkbook().write(op);
        sheet.getWorkbook().close();
    }

    public String getStringFormatCellValue(HSSFCell cell) {
        String cellVal = "";
        DecimalFormat df = new DecimalFormat("#");
        switch (cell.getCellTypeEnum()) {
            case STRING:
                cellVal = cell.getStringCellValue();
                break;
            case NUMERIC:
                String dataFormat = cell.getCellStyle().getDataFormatString();
                if (DateUtil.isCellDateFormatted(cell)) {
                    cellVal = df.format(cell.getDateCellValue());
                } else if ("@".equals(dataFormat)) {
                    cellVal = df.format(cell.getNumericCellValue());
                } else {
                    cellVal = String.valueOf(cell.getNumericCellValue());
                    df = new DecimalFormat("#.#########");
                    cellVal = df.format(Double.valueOf(cellVal));
                }
                break;
            case BOOLEAN:
                cellVal = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA:
                cellVal = String.valueOf(cell.getCellFormula());
                break;
            default:
                cellVal = "";
        }
        return cellVal;
    }


}

有表頭實現類

/**
 * @author Sherman
 * created in 2018/8/24
 */

public class HeaderExcel extends AbstractExcel {
    private final static boolean hasHeader = true;
    private final HSSFSheet sheet;

    public HeaderExcel(HSSFSheet sheet) {
        super(sheet);
        this.sheet = sheet;
    }

    public HeaderExcel(String sheetName, String excelPath) {
        HSSFWorkbook wb = null;
        try {
            wb = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelPath)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        sheet = sheetName == null || sheetName.isEmpty() ? wb.getSheetAt(0) : wb.getSheet(sheetName);
    }

    @Override
    public List<Map<String, String>> getPayload() {
        List<Map<String, String>> payLoad = new ArrayList<>();
        HSSFRow headRow = sheet.getRow(0);
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            HSSFRow currentRow = sheet.getRow(i);
            Map<String, String> map = new HashMap<>();
            for (int j = 0; j < sheet.getRow(i).getLastCellNum(); j++) {
                map.put(getStringFormatCellValue(headRow.getCell(j)), getStringFormatCellValue(currentRow.getCell(j)));
            }
            payLoad.add(map);
        }
        return payLoad;
    }


}

無表頭實現類

/**
 * @author Sherman
 * created in 2018/8/24
 */

public class NoHeaderExcel extends AbstractExcel {
    private final static boolean hasHeader = false;
    private HSSFSheet sheet;

    public NoHeaderExcel(HSSFSheet sheet) {
        super(sheet);
        this.sheet = sheet;
    }

    public NoHeaderExcel(String sheetName, String excelPath) {
        HSSFWorkbook wb = null;
        try {
            wb = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelPath)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        sheet = sheetName == null || sheetName.isEmpty() ? wb.getSheetAt(0) : wb.getSheet(sheetName);
    }


    @Override
    public List<Map<String, String>> getPayload() {
        List<Map<String, String>> payLoad = new ArrayList<>();
        for (int i = 0; i < sheet.getLastRowNum(); i++) {
            HSSFRow currentRow = sheet.getRow(i);
            Map<String, String> map = new HashMap<>();
            for (int j = 0; j <= sheet.getRow(i).getLastCellNum(); j++) {
                map.put(String.valueOf(j), getStringFormatCellValue(currentRow.getCell(j)));
            }
            payLoad.add(map);
        }
        return payLoad;
    }


}

測試工具類:

/**
 * Unit test for simple App.
 */
public class AppTest 
{
    /**
     * 測試建表,寫表操作
     */
    @Test
    public void testExportExcel()
    {
        //測試數據
     String[] headers = new String[]{"A","B","C","D","E"};
         List<List<Object>> valueList = new LinkedList<>();
        for (char i = 'A'; i <= 'E' ; i++) {
            List<Object> rowList = new LinkedList<>();
            for (int j = 0; j <= 4; j++) {
                rowList.add(i+String.valueOf(j));
            }
            valueList.add(rowList);
        }

    AbstractExcel excel = new ExcelBuilder("報名錶")
            .header(headers)
            .content(valueList)
            .autoColumnWidth()
            .build(true);

        try {
            File file = new File("E:\\excel\\test.xls");
            FileOutputStream op = new FileOutputStream(file);
            excel.write(op);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 測試讀取表數據操作
     */
    @Test
    public void testImportExcel(){
        AbstractExcel excel = new HeaderExcel(null,"E:/excel/test.xls");
       List<Map<String,String>> values = excel.getPayload();
       values.forEach(stringStringMap -> {
           stringStringMap.entrySet().forEach(stringStringEntry -> {
               System.out.println(stringStringEntry.getKey()+"---->"+stringStringEntry.getValue());
           });

       });
    }

}

附圖:

測試1

 

測試二:

 

 看起來效果還不錯,當然還有很多不完善的地方,有需要的朋友可以在此基礎上擴展定製,例如讀取表數據結構方式,實現行數增刪改查據或者創建表標題等等。

或者有朋友有更好的實現方案,歡迎前來交流!

最後的最後,當然忘不了附上笨工具的源碼啦!

 https://github.com/yumiaoxia/excel-commom-demo.git

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們用原生JS進行開發時,經常會用到兩種更新DOM節點的方法:innerHTML 和 appendChild() 。其中 innerHTML 會完全替換掉原先的節點內容,如果我們是想向元素追加子節點的話,那麼 innerHTML 顯然滿足不了需求。 轉而我們就會想到 appendChild() 方法 ...
  • 從很久之前就已經接觸過了angularjs了,當時就已經瞭解到,angularjs是通過臟檢查來實現數據監測以及頁面更新渲染。之後,再接觸了vue.js,當時也一度很好奇vue.js是如何監測數據更新並且重新渲染頁面。今天,就我們就來一步步解析vue.js響應式的原理,並且來實現一個簡單的demo。 ...
  • Apache Kafka是分散式發佈-訂閱消息系統,在 kafka官網上對 kafka 的定義:一個分散式發佈-訂閱消息傳遞系統。 它最初由LinkedIn公司開發. Linkedin於2010年貢獻給了Apache基金會併成為頂級開源項目。Kafka是一種快速、可擴展的、設計內在就是分散式的,分區 ...
  • 在本篇文章中,讓我們看看什麼是DevOps,為什麼它如此重要! 我們將首先跟蹤導致DevOps的軟體開發方法的演變,然後探索什麼是DevOps及其生命周期,並通過評估世界頂級公司如何使用DevOps來獲得益處。 ...
  • 題意 給出$n$個矩形,找出一個點,使得至少在$n$個矩陣內 Sol 呵呵噠,昨天cf半夜場,一道全場切的題,我沒做出來。。不想找什麼理由,不會做就是不會做。。 一個很顯然的性質,如果存在一個點 / 矩形在$n - 1$個矩形內的話 它們的交集不會是空集。 然後我們去枚舉每個點,假設他不與$(n - ...
  • 1、Object 2、String 3、StringBuilder ...
  • 一、匿名函數 什麼匿名是函數: 不需要使用def函數名的函數或者子程式 函數語法: lambda 參數:表達式 函數特點: 1、lamdba只是一個表達式,省去定義函數過程,讓代碼更精簡 2、lamdba 在表達式中封裝的邏輯有限 3、不能訪問自己參數序列外或者全局命名空間的參數 舉例: 二、內建m ...
  • c/c++ 模板與STL小例子系列 自建Array數組 自建的Array數組,提供如下對外介面 | 方法 | 功能描述 | | | | | Array() | 無參數構造方法,構造元素個數為模板參數個的數組 | | Array(int length) | 有參數構造方法,構造元素個數為參數lengt ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...