当使用 SXSSFWorkbook 创建 excel 并使用 XSSFWorkbook 修改

场景:
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

请提出解决方案。


POPMUISE
浏览 983回答 1
1回答

千巷猫影

默认情况下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:所有单元格中都有内联字符串。XSSFTest.xlsx看起来像这样:现在所有内联字符串都已正确更新。LibreOfficeVersion: 6.0.7.3Build ID: 1:6.0.7-0ubuntu0.18.04.5
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java