(最全最靈活地)利用Jxl工具包實現Excel表的內容讀取 、寫入(可向已有表中追加數據)


 

1.引子

(1)讀取

      Jxl工具比較強大,可以方便地實現Excel表的讀取和寫入。另一款工具Poi也具有相似的功能,並且功能更多,運用也相對復雜。Poi讀取Excel表內容時,需要先判斷其內容格式,如日期、數字等,再使用相對應的方法對獲取單元格內容。而Jxl則簡單得多,將所有格式的單元格格式都視為字符串,這樣一來獲取單元格內容就容易些。另外我在網上也看了一些帖子,發現傳入IO流參數時,在方法調用結束后,這個流會被自動關閉,后面不能再使用此流參數。我經過一番測試,用文件File對象作為參數,不會出現因流關閉而導致的空指針異常.

(2)寫入

1)向原有的工作表中寫入數據(不覆蓋原有數據)

Jxl向Excel中寫入數據時,相對讀取數據要復雜得多。在Excel中已存在的表中寫入數據不太容易, 此時不能用“WritableWorkbook workbook = Workbook.createWorkbook(file)"這種方法是創建一個可寫入的工作薄,調用此方法會覆蓋掉原有的工作表數據。這種情況下要先用方法"Workbook book = Workbook.getWorkbook(excel);",先獲取一個只讀的工作薄對象,再使用代碼“WritableWorkbook workbook = Workbook.createWorkbook(excel, book);",傳入兩個參數,Excel文件對象excel、只讀(剛才獲得到的)工作薄對象book。這樣就可以創建並初始化一個可追加寫入數據的工作薄對象 workbook 。

    // 可寫的工作薄
    private WritableWorkbook workbook;
    // 只讀工作薄
    private Workbook book;
    public JxlExcelWriter(File excel)
    {
        try
        {
            // Excel文件不存在時,初始化一個可寫入的工作薄
            if (!excel.exists())
            {
                File file = prepareFile(excel);
                workbook = Workbook.createWorkbook(file);
            }
            
           
            /**
             * Excel文件存在時,表明Excel中至少有一個工作表,
             *  初始化一個可向工作表追加數據且能寫入新數據的工作薄
             */
            else
            {
                book = Workbook.getWorkbook(excel);
                /**
                 * 此靜態方法通過傳入兩個參數,Excel文件對象excel、只讀工作工作薄對象book,<br/>
                 * 來創建初始化一個可追加數據的工作薄對象
                 */
                workbook = Workbook.createWorkbook(excel, book);
            }
           
        }
        catch (IOException | BiffException e)
        {
            e.printStackTrace();
        }
        
    }

2)向工作薄/工作表多次寫入數據

  • 寫入方法的調用
            網上大多數據帖子都是向工作薄/工作表一次性寫入數據,這顯然不太靈活。經過多次測試試錯終於找到了新大陸,原來只能單次寫入數據的根本原因是:過早的調用了WritableWorkbook的write()和close()方法
1   try
2         {
3             workbook.write();
4             workbook.close();
5         }
6         catch (WriteException | IOException e)
7         {
8             e.printStackTrace();
9         }

 "sheel.addCell(Lable)"方法只是將數據寫入工作表緩沖區中,而真正寫入到磁盤Excel文件又不得不調用WritableWorkbook的write()方法,另外在最后我們一般還需要將資源關閉,又得調用WritableWorkbook的colse()方法。

  WritableSheet sheet = getWritableSheet(sheetName, sheetIndex);
 jxl.write.Label lable = new jxl.write.Label(i, rowIndex, rowContent[i]);
                        sheet.addCell(lable);
  • 多次寫入數據的思路
             在一次寫入數據時調用write()和close()方法后,下一次便不能再寫入數據了。其中的原因可以理解,因為 WritableWorkbook的資源都已經被關閉了,肯定不能再次向其中添加數據,除非再次打開此資源,但WritableWorkbook對象沒有reopen()方法。換個角度看問題,可以在每次寫入數據時調用write()方法,在寫入所有所需的數據之后再調用close()方法。但這種方式也不可行,只調用write()而不調用close()會導致Excel文件格式不對,不能正常打開Excel文件。 由此可見write()和close()必須同時且一次性地調用。到此時不難想到:可以多次將數據添加到緩沖區,最終才調用write()、close()方法,將緩沖區的所有數據一次性刷新寫入到Excel文件中。

2.代碼

(1) 讀取Excel內容

代碼較長,已折疊

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

/**
 * Excel表文本數據的讀取工具類
 * 
 * @author 小伍
 */
public final class JxlExcelReader
{
    // Excel表工作薄對象
    private Workbook workbook;
    
    /**
     * <構造方法>
     * @param excel Excel表文件對象
     */
    public JxlExcelReader(File excel)
    {
        if (!excel.exists())
            throw new IllegalArgumentException("excel文件不存在");
        try
        {
            workbook = Workbook.getWorkbook(excel);
        }
        catch (BiffException | IOException e)
        {
            e.printStackTrace();
        }
        
    }
    
    /**
     * 通過索引獲得工作表
     * 
     * @param index
     * @return
     * @see [類、類#方法、類#成員]
     */
    public Sheet getSheetByIndex(int index)
    {
        Sheet sheet = null;
        if (index < workbook.getNumberOfSheets())
        {
            sheet = workbook.getSheet(index);
        }
        return sheet;
    }
    
    /**
     * 通過表名獲得工作表
     * @param name
     * @return
     * @see [類、類#方法、類#成員]
     */
    public Sheet getSheetByName(String name)
    {
        return workbook.getSheet(name);
    }
    
    /**
     * 根據工作表索引、行索引、列索引獲取一個指定單元格的文本內容
     * @param rowIndex 行索引
     * @param colIndex 列索引
     * @param sheetIndex 工作表索引
     * @return 單元格的文本內容
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public String readCellContent(int rowIndex, int colIndex, int sheetIndex)
    {
        Sheet sheet = workbook.getSheet(sheetIndex);
        if ((rowIndex < 0 || rowIndex >= sheet.getRows()) || (colIndex < 0 || colIndex >= sheet.getColumns()))
            throw new IllegalArgumentException("參數 rowIndex 或colIndex超出了行、列索引的可用范圍");
        Cell[] cells = sheet.getRow(rowIndex);
        String cellContent = cells[colIndex].getContents();
        return cellContent;
    }
    
    /**
     * 獲取指定工作表中除第一行(表頭)以外的所有單元格內容
     * 
     * @param sheetIndex 工作表索引
     * @return Map對象的key值是行索引,values值是包含每行的各單元格文本內容的字符串數組
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public Map<Integer, String[]> readContent(int sheetIndex)
    {
        Sheet sheet = workbook.getSheet(sheetIndex);
        return readData(1, sheet.getRows() - 1, 0, sheet.getColumns(), sheetIndex);
    }
    
    /**
     * 獲取指定工作表的第一行(表頭)文本內容
     * 
     * @param sheetIndex 工作表索引
     * @return 第一行的各單元格文本內容的字符串數組
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public String[] readHeader(int sheetIndex)
    {
        Sheet sheet = workbook.getSheet(sheetIndex);
        int cols = sheet.getColumns();
        Cell[] cells = sheet.getRow(0);
        String[] header = new String[cols];
        for (int j = 0; j < cols; j++)
        {
            header[j] = cells[j].getContents();
        }
        return header;
    }
    
    /**
     * 獲取指定工作表的所有單元格文本內容
     * 
     * @param sheetIndex 工作表索引
     * @return Map對象的key值是行索引,values值是包含每行的各單元格文本內容的字符串數組
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public Map<Integer, String[]> readHeaderAndContent(int sheetIndex)
    {
        Sheet sheet = workbook.getSheet(sheetIndex);
        return readData(0, sheet.getRows(), 0, sheet.getColumns(), sheetIndex);
    }
    
    /**
     * 獲取指定工作表的指定范圍的單元格文本內容
     * 
     * @param fromRowIndex 起始行的索引
     * @param rowNum 讀取表的總行數
     * @param fromColIndex 起始列的索引
     * @param colNum 讀取表的總列數
     * @param sheetIndex 工作表索引
     * @return Map對象的key值是行索引,values值是包含每行的各單元格文本內容的字符串數組
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public Map<Integer, String[]> readData(int fromRowIndex, int rowNum, int fromColIndex, int colNum,
        int sheetIndex)
    {
        Sheet sheet = workbook.getSheet(sheetIndex);
        // 總行數
        int rows = sheet.getRows();
        // 總列數
        int cols = sheet.getColumns();
        // 要讀取的最大列索引加1的值
        int endColIndex = fromColIndex + colNum;
        // 最大行索引加1的值:
        int endRowIndex = fromRowIndex + rowNum;
        if ((fromRowIndex < 0 || fromRowIndex >= rows) || (fromColIndex < 0 || fromColIndex >= cols))
            throw new IllegalArgumentException("參數 fromRow 或fromCol超出了行、列索引的可用范圍。");
        if (rowNum < 1 || colNum < 1)
            throw new IllegalArgumentException("參數rowNum 、colNum必須大於1,讀入的行總數、列總數都必須大於1");
        if (endRowIndex > rows || endColIndex > cols)
            throw new IllegalArgumentException("參數超出了Excel表可獲取的最大列數或最大行數。");
        /*
         * 儲存單元格內容的map,(TreeMap能有序排列) contents的key為行索引,value(String[])為單行各單元格的內容(string[0]為第一列的單元格)
         */
        Map<Integer, String[]> contents = new TreeMap<Integer, String[]>();
        for (int i = fromRowIndex; i < endRowIndex; i++)
        {
            Cell[] cells = sheet.getRow(i);
            // 定義一個列總數長度的字符數組,不讀取的rowContent[K]就為null;
            String[] rowContent = new String[cols];
            for (int j = fromColIndex; j < endColIndex; j++)
            {
                // 要讀取的rowContent[j],即使cell[j]為空,在添加空字符串""后rowContent[j]就不為null.
                rowContent[j] = cells[j].getContents() + "";
            }
            contents.put(i, rowContent);
        }
        return contents;
    }
    
    /**
     * 獲取指定工作表的指定行范圍的單元格文本內容
     * @param fromRowIndex 起始行的索引
     * @param rowNum 讀取表的總行數
     * @param sheetIndex 工作表索引
     * @return Map對象的key值是行索引,values值是包含每行的各單元格文本內容的字符串數組
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public Map<Integer, String[]> readData(int fromRowIndex, int rowNum, int sheetIndex)
    {
        Sheet sheet = workbook.getSheet(sheetIndex);
        return readData(fromRowIndex, rowNum, 0, sheet.getColumns(), sheetIndex);
    }
    
    /**
     * 關閉資源
     * @see [類、類#方法、類#成員]
     * @Description: TODO
     */
    public void close()
    {
        if (workbook != null)
            workbook.close();
    }
}
View Code

(2)寫入數據至Excel

代碼較長,已折疊

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Set;

import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;

/**
 * 數據寫入Excel工具類
 * 
 * @author 小伍
 */
public final class JxlExcelWriter
{
    // 可寫的工作薄
    private WritableWorkbook workbook;
    
    // 只讀工作薄
    private Workbook book;
    
    /**
     * 構造方法
     * @param excel Excel文件對象,允許其文件本身不存在<br/>
     *  若excel文件不存在,構造方法將自動創建一個文件對象對應的磁盤文件
     */
    public JxlExcelWriter(File excel)
    {
        try
        {
            // Excel文件不存在時,初始化一個可寫入的工作薄
            if (!excel.exists())
            {
                File parentFile = excel.getParentFile();
                parentFile.mkdirs();
                workbook = Workbook.createWorkbook(excel);
            }
            
            /**
             * Excel文件存在時,表明Excel中至少有一個工作表, 
             * 初始化一個可向工作表追加數據且能寫入新數據的工作薄
             */
            else
            {
                /**
                 * 此靜態方法通過傳入兩個參數,Excel文件對象excel、只讀工作工作薄對象book,<br/>
                 * 來創建初始化一個可追加數據的工作薄對象
                 */
                book = Workbook.getWorkbook(excel);
                workbook = Workbook.createWorkbook(excel, book);
            }
            
        }
        catch (IOException | BiffException e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * 將多行數據寫入到Excel緩沖區
     * 
     * @param contents 要寫入到Excel的數據(映射表),其key值表示行索引,<br/>
     *            其value值表示一行所有的單元格內容,字符串數組的每個元素對應一個單元格內容
     * @param sheetIndex 要寫入到Excel的工作表索引
     * @see [類、類#方法、類#成員]
     */
    public void write(Map<Integer, String[]> contents, int sheetIndex)
    {
        String sheetName = generateSheetName(sheetIndex);
        write(contents, sheetName, sheetIndex);
    }
    
    /**
     * 將多行數據寫入到Excel緩沖區
     * 
     * @param contents 要寫入到Excel的數據(映射表),其key值表示行索引,<br/>
     *            其value值表示一行所有的單元格內容,字符串數組的每個元素對應一個單元格內容
     * @param sheetName 要寫入到Excel的工作表名
     * @param sheetIndex 要寫入到Excel的工作表索引
     */
    public void write(Map<Integer, String[]> contents, String sheetName, int sheetIndex)
    {
        if (contents == null || contents.isEmpty())
            throw new IllegalArgumentException("參數contents不包含任何內容或為空指針");
        // 得到工作表
        WritableSheet sheet = getWritableSheet(sheetName, sheetIndex);
        // 將數據添加到工作表的緩沖區中
        try
        {
            Set<Integer> keys = contents.keySet();
            for (int rowIndex : keys)
            {
                String[] rowContent = contents.get(rowIndex);
                for (int i = 0; i < rowContent.length; i++)
                {
                    // 文本內容為空時,sheet表增加一個Blank
                    if (rowContent[i] == null)
                    {
                        jxl.write.Blank blank = new jxl.write.Blank(i, rowIndex);
                        sheet.addCell(blank);
                    }
                    else
                    {
                        jxl.write.Label lable = new jxl.write.Label(i, rowIndex, rowContent[i]);
                        sheet.addCell(lable);
                    }
                }
            }
        }
        catch (WriteException e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * 創建/獲取工作表
     * 
     * @param sheetName
     * @param sheetIndex
     * @return
     * @see [類、類#方法、類#成員]
     */
    private WritableSheet getWritableSheet(String sheetName, int sheetIndex)
    {
        WritableSheet sheet = null;
        if (sheetIndex < workbook.getNumberOfSheets())
        {
            sheet = workbook.getSheet(sheetIndex);
            sheet.setName(sheetName);
        }
        else
        {
            sheet = workbook.createSheet(sheetName, sheetIndex);
        }
        return sheet;
    }
    
    /**
     * 生成工作表表名
     * 
     * @param sheetIndex
     * @return
     * @see [類、類#方法、類#成員]
     */
    private String generateSheetName(int sheetIndex)
    {
        String sheetName = "";
        if (sheetIndex < workbook.getNumberOfSheets())
        {
            sheetName = workbook.getSheet(sheetIndex).getName();
        }
        else
        {
            sheetName = "sheet" + sheetIndex;
        }
        return sheetName;
    }
    
    /**
     * 將單行數據寫入到Excel緩沖區
     * 
     * @param rowContent 要寫入到Excel的數據,數組的每個元素對應一個單元格內容
     * @param rowIndex 寫入到Excel的行索引
     * @param sheetIndex 要寫入到Excel的工作表索引
     * @see [類、類#方法、類#成員]
     */
    public void writeRow(String[] rowContent, int rowIndex, int sheetIndex)
    {
        String sheetName = generateSheetName(sheetIndex);
        writeRow(rowContent, rowIndex, sheetName, sheetIndex);
    }
    
    /**
     * 將單行數據寫入到Excel緩沖區
     * 
     * @param rowContent 要寫入到Excel的數據,數組的每個元素對應一個單元格內容
     * @param rowIndex 寫入到Excel的行索引
     * @param sheetName 要寫入到Excel的工作表名
     * @param sheetIndex 要寫入到Excel的工作表索引
     * @see [類、類#方法、類#成員]
     */
    public void writeRow(String[] rowContent, int rowIndex, String sheetName, int sheetIndex)
    {
        // 得到工作表
        WritableSheet sheet = getWritableSheet(sheetName, sheetIndex);
        try
        {
            for (int i = 0; i < rowContent.length; i++)
            {
                if (rowContent[i] == null)
                {
                    jxl.write.Blank blank = new jxl.write.Blank(i, rowIndex);
                    sheet.addCell(blank);
                }
                else
                {
                    jxl.write.Label lable = new jxl.write.Label(i, rowIndex, rowContent[i]);
                    sheet.addCell(lable);
                }
            }
        }
        catch (WriteException e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * 寫入一個單元內容到Excel緩沖區
     * 
     * @param content 要寫入的單元格內容
     * @param rowIndex 寫入到Excel的行索引
     * @param colIndex 寫入到Excel的列索引
     * @param sheetIndex 要寫入到Excel的工作表索引
     */
    public void writeCell(String content, int rowIndex, int colIndex, int sheetIndex)
    {
        String sheetName = generateSheetName(sheetIndex);
        writeCell(content, rowIndex, colIndex, sheetName, sheetIndex);
        
    }
    
    /**
     * 寫入一個單元內容到Excel緩沖區
     * 
     * @param content 要寫入的單元格內容
     * @param rowIndex 寫入到Excel的行索引
     * @param colIndex 寫入到Excel的列索引
     * @param sheetName 要寫入到Excel的工作表名
     * @param sheetIndex 要寫入到Excel的工作表索引
     */
    public void writeCell(String content, int rowIndex, int colIndex, String sheetName, int sheetIndex)
    {
        // 得到工作表
        WritableSheet sheet = getWritableSheet(sheetName, sheetIndex);
        try
        {
            if (content == null)
            {
                jxl.write.Blank blank = new jxl.write.Blank(colIndex, rowIndex);
                sheet.addCell(blank);
            }
            else
            {
                jxl.write.Label lable = new jxl.write.Label(colIndex, rowIndex, content);
                sheet.addCell(lable);
            }
        }
        catch (WriteException e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * 將Excel緩沖區的數據刷新寫入到Excel文件中, <br/>
     * 在最后此方法必須被調用,否則數據不能真正寫入Excel文件中
     */
    public void flush()
    {
        try
        {
            if (workbook != null)
            {
                workbook.write();
                workbook.close();
            }
            if (book != null)
            {
                book.close();
            }
        }
        catch (WriteException | IOException e)
        {
            e.printStackTrace();
        }
    }
}
View Code

 

3.測試效果

(1).數據讀取測試

在讀取Excel表中有一個基礎方法,public Map<Integer, String[]> readData(int fromRowIndex, int rowNum, int fromColIndex, int colNum, int sheetIndex)。此方法的參數最多,控制能力最強,能夠靈活適應各種場景。其他方法大都是調用此方法,以實現定制化的一些讀取操作的。

 下面對排班信息進行讀取:

Excel源數據

這是一個Excel文件中的一張排班工作表Sheet的局部內容,雖然不太規整,但應該不會影響我的正常進行讀取。

測試方法

調用工具類中的方法進行數據讀取,讀取attend.xls的第一張工作表(排班表)的從第3行起的8行數據

    @Test
    public void readRows(){
        JxlExcelReader excelReader = new JxlExcelReader(new File("d:/IOTest/attend.xls"));
        // 讀取attend.xls的第一張工作表(排班表)的從第3行起的8行數據
        Map<Integer, String[]> datas = excelReader.readData(2, 8, 0);
        Set<Integer> rowIndexs = datas.keySet();
        for (int rowIndex : rowIndexs)
        {
            String[] rowData = datas.get(rowIndex);
            System.out.println(Arrays.toString(rowData));
        }
    }

 

 控制台輸出

信息讀取並打印出來了, excel部分單元格無值,所以打印結果部分輸出為空。

 

 

(2).數據寫入測試

     1)一般數據的寫入

在向Excel表中寫入數據的工具類中也有一個基礎方法 ,public void write(Map<Integer, String[]> contents, String sheetName, int sheetIndex)   。其他方法都是調用此方法得以實現的,如

  public void write(Map<Integer, String[]> contents, int sheetIndex)  是先獲得工作表的名字,將此名字作為sheetName參數。

public void write(Map<Integer, String[]> contents, int sheetIndex)
    {
        String sheetName = generateSheetName(sheetIndex);
        write(contents, sheetName, sheetIndex);
    }

   測試方法

@Test
    public void writeRows(){
        JxlExcelReader excelReader = new JxlExcelReader(new File("d:/IOTest/attend.xls"));
        // 讀取attend.xls的第一張工作表(排班表)的從第3行起的8行數據
        Map<Integer, String[]> datas = excelReader.readData(2, 8, 0);
        //將數據寫入writer-result.xls文件中
        JxlExcelWriter excelWriter=new JxlExcelWriter(new File("d:/IOTest/writer-result.xls"));
        excelWriter.write(datas, 0);
        
    }

 Excel文件寫入結果

文件不能打開,提示文件格式錯誤、文件遭到損壞。這到底是什么原因?是因為我們只將數據寫到內存緩沖區,並沒有將數據刷新到磁盤文件中需要調用方法flush() ,這里需要特別注意。

 修改后的代碼

 @Test
    public void writerRows(){
        JxlExcelReader excelReader = new JxlExcelReader(new File("d:/IOTest/attend.xls"));
        // 讀取attend.xls的第一張工作表(排班表)的從第3行起的8行數據
        Map<Integer, String[]> datas = excelReader.readData(2, 8, 0);
        //將數據寫入writer-result.xls文件中
        JxlExcelWriter excelWriter=new JxlExcelWriter(new File("d:/IOTest/writer-result.xls"));
        excelWriter.write(datas, 0);
    //此方法flush()一定得調用,否則無法真正寫入數據
        excelWriter.flush();
        
    } 

 

 寫入到excel中的數據

   

   2)數據分批(多次)寫入

可能同學會問,為什么最后非得調用flush方法,干嘛不將flush里面的代碼寫在write()方法中,畢竟使用者很可能忘記了調用flush方法的。這樣不多此一舉嗎,增加了讓人出錯的機率?其實這是一沒辦法的辦法,一種妥協吧,在時需要分批多次地寫入數據,此時只能用這條思路實現,否則除第一次調用write()方法寫入的數據外不能再次寫入新數據到excel表中。 比如,我要做一個解析考勤的小系統,對原始考勤信息進行分類匯總

這是將匯總內容向Excle表中寫入的部分代碼

 public void deptAttend()
    {
        
        Set<Entry<String, List<Employee>>> entrys = attendGroupByDept.entrySet();
        
        Iterator<Entry<String, List<Employee>>> itor = entrys.iterator();
        int sheetIndex = 1;
        JxlExcelWriter excelWriter = new JxlExcelWriter(excelFile);
        
        while (itor.hasNext())
        {
            Entry<String, List<Employee>> entry = itor.next();
            List<Employee> emps = entry.getValue();
            //每次循環寫入到同一個Excel文件的不同工作表sheet
            dataWriteToSheet(emps, sheetIndex, excelWriter);
            sheetIndex++;
        }
         //數據添加完成后,再調用flush方法
        excelWriter.flush();
        
    }

 private void dataWriteToSheet(List<Employee> emps, int sheetIndex, JxlExcelWriter excelWriter)
    {
      // .........省略部分代碼
        //寫入數據到指定索引的一個工作表
        excelWriter.write(contents, "部門" + deptNo + "的考勤", sheetIndex);
        
    }

 

  原始Excel數據

  
 按部門匯總后的Excel數據

3)向已有數據的工作表中追加寫入新數據

 測試代碼

 public static void main(String[] args)
    {
        JxlExcelWriter excelWriter = new JxlExcelWriter(new File("d:/IOTest/stu1.xls"));
        String[] rowContent = new String[] {null,"009", "小何", "2018-12-01", "13451234", "2017", "廣元", "網絡案例"};
        excelWriter.writeRow(rowContent, 11,0);
        excelWriter.flush();
    }

 Excel文件數據追加前

 

 Excel文件數據追加后

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM