亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當使用 SXSSFWorkbook 創建 excel 并使用 XSSFWorkbook 修改

當使用 SXSSFWorkbook 創建 excel 并使用 XSSFWorkbook 修改

POPMUISE 2022-12-21 14:35:00
場景:1) 使用 SXSSFWorkbook 將一個 csv 文件轉換為 excel 文件。2) 如果再次從 CSV 文件讀取數據并使用 XSSFWorkbook 將數據寫入上面生成的 excel 文件,則字符串數據在 libre office 中不可見,但如果在在線 excel 查看器中打開 excel 文件(一些 excel觀眾提到文件已損壞,數據可以恢復)。使用 SXSSFWorkbook 創建單元格:Cell cell = row.createCell(1);cell.setCellValue("一些值");使用 XSSFWorkbook 更新單元格:Cell cell = row.getCell(1);cell.setCellValue("一些值");觀察結果:1) 當使用 XSSFCell 更新單元格值時,單元格的原始值和單元格的字符串值不同。2)如果excel文件是用SXSSFWorkbook生成的,用XSSFWorkbook打開的,那么內部維護的STCellType是STCellType.INLINE_STR,如果excel文件是用XSSFWorkbook生成的,那么內部維護的STCellType是STCellType.S(XSSFCell的CTCell中用的是STCellType)。Apache POI 版本:4.1.0請提出解決方案。
查看完整描述

1 回答

?
千巷貓影

TA貢獻1829條經驗 獲得超7個贊

默認情況下SXSSFWorkbook使用內聯字符串,而默認情況下XSSFWorkbook使用共享字符串表。并且XSSFCell.setCellValueImpl對于內聯字符串是不完整的。它確實:


...

if(_cell.getT() == STCellType.INLINE_STR) {

 //set the 'pre-evaluated result

 _cell.setV(str.getString());

}

...

所以對于內聯字符串,它總是設置v包含文本的元素。但是內聯字符串也可能包含包含文本的is元素t,甚至包含is不同富文本運行的元素。這不被視為使用XSSFCell.


但是可以構建SXSSFWorkbook ,因此它也使用共享字符串表。請參閱構造函數SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, boolean compressTmpFiles, boolean useSharedStringsTable)。因此,如果使用以下構造函數:


SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(), 2, true, true);

然后不使用內聯字符串,以后使用更新XSSF也不會有問題。


如果SXSSFWorkbook不是使用shared strings table而是使用inline strings,由于in using inline stringsXSSF的不完整,后面更新cells using時會出現問題。XSSFCell可能的解決方法是管理使用自己的代碼更新的內聯字符串。


例子:


import java.io.FileOutputStream;

import java.io.FileInputStream;


import org.apache.poi.ss.usermodel.WorkbookFactory;

import org.apache.poi.xssf.usermodel.*;

import org.apache.poi.xssf.streaming.*;


import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;


public class SXSSFTest {


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


  // first create SXSSFTest.xlsx using SXSSF ============================================


  String[][] data1 = new String[][]{

   new String[]{"A1", "B1", "C1"},

   new String[]{"A2", "B2", "C2"},

   new String[]{"A3", "B3", "C3"},

   new String[]{"A4", "B4", "C4"}

  };


  SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();

  //SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(), 2, true, true);


  SXSSFSheet sxssfSheet = sxssfWorkbook.createSheet();


  int r = 0;

  for (String[] rowValues : data1) {

   SXSSFRow row = sxssfSheet.createRow(r++);

   int c = 0;

   for (String value : rowValues) {

    SXSSFCell cell = row.createCell(c++);

    cell.setCellValue(value);

   }

  }


  FileOutputStream outputStream = new FileOutputStream("SXSSFTest.xlsx");

  sxssfWorkbook.write(outputStream);

  outputStream.close();

  sxssfWorkbook.dispose();

  sxssfWorkbook.close();


  // now reread the SXSSFTest.xlsx and update it using XSSF =============================


  String[][] data2 = new String[][]{

   new String[]{"A2 New", "B2 New", "C2 New"},

   new String[]{"A3 New", "B3 New", "C3 New"}

  };


  XSSFWorkbook xssfWorkbook = (XSSFWorkbook)WorkbookFactory.create(

                               new FileInputStream("SXSSFTest.xlsx"));


  XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);


  r = 1;

  for (String[] rowValues : data2) {

   XSSFRow row = xssfSheet.getRow(r++); if (row == null) row = xssfSheet.createRow(r++);

   int c = 0;

   for (String value : rowValues) {

    XSSFCell cell = row.getCell(c++); 

    if (cell != null) { // cell was already there

     if (cell.getCTCell().getT() == STCellType.INLINE_STR) { // cell has inline string in it

      if (cell.getCTCell().isSetIs()) { // inline string has is element

       cell.getCTCell().getIs().setT(value); // set t element in is element

      } else {

       cell.getCTCell().setV(value); // set v element of inline string

      }

     } else {

      cell.setCellValue(value); // set shared string cell value

     }

    } else {

     cell = row.createCell(c++);

     cell.setCellValue(value);

    }

   }

  }


  outputStream = new FileOutputStream("XSSFTest.xlsx");

  xssfWorkbook.write(outputStream);

  outputStream.close();   

  xssfWorkbook.close();


 }

}

在那之后SXSSFTest.xlsx我的看起來像這樣LibreOffice Calc:

http://img1.sycdn.imooc.com//63a2a96a0001b1cc06560276.jpg

所有單元格中都有內聯字符串。

XSSFTest.xlsx看起來像這樣:

http://img1.sycdn.imooc.com//63a2a9760001075706550273.jpg

現在所有內聯字符串都已正確更新。


LibreOffice

Version: 6.0.7.3

Build ID: 1:6.0.7-0ubuntu0.18.04.5


查看完整回答
反對 回復 2022-12-21
  • 1 回答
  • 0 關注
  • 1125 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號