当前位置: 首页 > 知识库问答 >
问题:

使用SXSSFWorkbook创建excel并使用XSSFWorkbook修改excel时,字符串单元格数据在excel编辑器中不可见

都沈浪
2023-03-14

场景:
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更新单元格值时,单元格的原始值和单元格的字符串值是不同的。

Apache POI版本:4.1.0

请提出解决方案。

共有1个答案

贲宏硕
2023-03-14

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 CompressStmpFiles,boolean useSharedStringsTable)。因此如果使用以下构造函数:

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

则不会使用内联字符串,以后使用XSSF进行更新也不会有问题。

如果SXSSFWorkbook使用的不是共享字符串表,而是内联字符串,则稍后使用XSSF更新单元格时会出现问题,因为使用内联字符串时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();

 }
}

xssftest.xlsx如下所示:

现在所有内联字符串都正确更新了。

LibreOffice
Version: 6.0.7.3
Build ID: 1:6.0.7-0ubuntu0.18.04.5
 类似资料:
  • 问题内容: 还有其他方法可以使用Apache POI库在Excel中合并单元格? 我正在尝试使用以下内容,但无法正常工作 问题答案: 您可以使用 该示例将从B2合并到E2。请记住,它是基于零的索引(例如POI版本3.12)。 有关详细信息,请参见《BusyDeveloper指南》。

  • 我试着用下面的方法,但它不起作用

  • 如何用SXSSF流式api编辑已有的大型excel文件 如何使用SXSSF写入现有文件? 我有一个现有的文件,我需要更新内容,更改一些内容的单元格颜色。 null 如何通过更改单元格颜色来更新结果文件? }

  • 我的C#. Net应用程序通过使用excel公式字符串加载和读取excel工作表单元格值。 例如,excel工作表位置和选项卡名称及其单元格行/列将作为公式字符串提供。 'D:\DataX[数据.Xls]EOD'$A5级 根据上述公式-C#应用程序加载数据。Xls,并打开EOD选项卡,应读取第5行A列值。 寻找在C#中完成的最佳方式。Net框架。

  • 问题内容: 如何在poi的帮助下在单元格中写下我的全部价值? 即如果值是1000.000,那么我怎么能写出完整的值而不会在“之后”截断000。与POI?表示我想要全部价值。 就我而言,只需要1000,但这对我来说不是正确的格式。 问题答案: 您必须设置要存储此数字的单元格的“格式”。示例代码: 来源:http : //poi.apache.org/spreadsheet/quick- guide.

  • 问题:我想在单元格内容的旁边或下面找到一个单元格的值,一个工作簿的文本值。 示例:在Sheet2中,我有两个随机单元格(假设它的索引未知,并且total不是定义的名称) 我想搜索值“200”站在总数旁边,并把它放在表2(一个活动单元格)。如果有多个单元格包含单词“total”,请列出所有单元格,如果可能,请将包含我正在寻找的单元格的工作表的名称放入。价值200张2 写入结果activeCell.v