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

如何使用shiftColumns方法删除列

郁高韵
2023-03-14

我想用Apache POI 5.0.0删除Excel(XLSX)中的一列。我想使用ShiftColumns方法,这样会自动调整受影响的公式。

void shiftColumns(int startColumn, int endColumn, int n)

https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/sheet.html

文档中说,如果要向左移动(覆盖左侧的列),应该使用负数。

String path = "pathOfTheExcelFile";
File file = new File(path);
    
Workbook wb = null;

try (FileInputStream inputStream = new FileInputStream(file)) {

    wb = WorkbookFactory.create(inputStream); // read workbook

} catch (IOException e) {
    e.printStackTrace();
}
    
if(wb == null)
        return;
    
Sheet sheet = wb.getSheetAt(0); // read first sheet
    
// deleting / overriding 2nd column
sheet.shiftColumns(2, 5, -1); // shifting from 3rd to last column to the left
    
try (OutputStream fileOut = new FileOutputStream(path)) {
    wb.write(fileOut); // writing the result in the Excel file (ERROR)
}
catch (Exception e) {
    e.printStackTrace();
}
finally {
    try {
        if (wb != null)
            wb.close();
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}

java.lang.IndexOutOfBoundsException
    at org.apache.xmlbeans.impl.store.Xobj.removeElement(Xobj.java:2099)
    at org.apache.xmlbeans.impl.store.Xobj.remove_element(Xobj.java:2130)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl.removeC(CTRowImpl.java:173)
    at org.apache.poi.xssf.usermodel.XSSFRow.fixupCTCells(XSSFRow.java:612)
    at org.apache.poi.xssf.usermodel.XSSFRow.onDocumentWrite(XSSFRow.java:582)
    at org.apache.poi.xssf.usermodel.XSSFSheet.write(XSSFSheet.java:3625)
    at org.apache.poi.xssf.usermodel.XSSFSheet.commit(XSSFSheet.java:3570)
    at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:465)
    at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:470)
    at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:221)
    at test.App.main(App.java:38)

PIC2

PIC3

共有1个答案

关正雅
2023-03-14

是的,即使在最新版本Apache POI 5.1.0中,Sheet.ShiftColumns仍然存在问题。当负移位时,ShiftColumns不能正确移除单元格。这就是为什么写的时候出错的原因。

如果显式删除要超调的列的单元格,那么错误就消失了。因此,在向左移动第三列(索引2)之前,我们需要删除第二列(索引1)中的所有单元格。

但也有额外的问题。即使是上一个版本也不在移动公式的同时更新计算链。这就是这个Q/A的问题:当单元格有公式时,shiftColumn方法不起作用。

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.model.CalculationChain;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import java.lang.reflect.Method;

public class ExcelShiftColums {

 private static void removeCalcChain(XSSFWorkbook workbook) throws Exception {
  CalculationChain calcchain = workbook.getCalculationChain();
  Method removeRelation = POIXMLDocumentPart.class.getDeclaredMethod("removeRelation", POIXMLDocumentPart.class); 
  removeRelation.setAccessible(true); 
  removeRelation.invoke(workbook, calcchain);
 }


 private static void removeColumn(Sheet sheet, int column) {
  for (Row row : sheet) {
   Cell cell = row.getCell(column);
   if (cell != null) {
    row.removeCell(cell);
   }
  }
 }
 
 private static int getLastFilledColumn(Sheet sheet) {
  int result = 0;
  for (Row row : sheet) {
   if (row.getLastCellNum() > result) result = row.getLastCellNum();
  }
  return result;     
 }

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

  String inFilePath = "./ExcelExampleIn.xlsx"; String outFilePath = "./ExcelExampleOut.xlsx";

  //String inFilePath = "./ExcelExampleIn.xls"; String outFilePath = "./ExcelExampleOut.xls";

  
  try (Workbook workbook = WorkbookFactory.create(new FileInputStream(inFilePath));
       FileOutputStream out = new FileOutputStream(outFilePath ) ) {

   Sheet sheet = workbook.getSheetAt(0);
   
   int lastFilledColumn = getLastFilledColumn(sheet);

   removeColumn(sheet, 1);
   sheet.shiftColumns(2, lastFilledColumn, -1);
   
   if (workbook instanceof XSSFWorkbook) removeCalcChain((XSSFWorkbook)workbook);
  
   workbook.write(out);
  }
 }
}
 类似资料:
  • 我在spring data jpa中的自定义删除方法中遇到错误。基本上,有一个包包含物品,当删除该包时,应该删除其中的所有物品。 以下是实体: 和存储库: 当我调用BagRepository.deleteByUidAndName(uid, name)时,我从hibernate中得到一个与外键约束相关的异常。设置显示它在删除包之前不会尝试先删除项目。 然而,如果我调用然后一切正常。 我想知道自定义这

  • 1. 前言 在 SQL Delete 一节中,我们介绍了 SQL 的基本删除功能,今天我们将以分类和实战的角度来进一步学习 SQL 的删除。 删除是一个很危险的操作,试想一下如果开发人员不慎操作失误,误删了一些数据,在数据未备份的情况下,该数据无法恢复,造成了损失绝对是致命的。 道路千万条,安全第一条。因此为了保证数据的安全性,在真正的企业级应用中都会默认的采用逻辑删除(软删除)的方式来处理数据删

  • 本文向大家介绍如何重新实现JavaScript删除方法?,包括了如何重新实现JavaScript删除方法?的使用技巧和注意事项,需要的朋友参考一下 始终牢记有关delete的以下几点:delete是JavaScript中的关键字,因此不应更改,并且您不能在单个变量中使用delete对象,因为它仅用于删除对象的属性。 delete关键字用于从JavaScript对象中删除属性,如以下代码所示- 示例

  • 问题内容: 是否可以从加载中删除元素而不创建新元素?例如这样的事情: 问题答案: 通过告诉父节点删除子节点来删除该节点: 请参阅文档 和 文档 。

  • 问题内容: 我试图删除第三行 这是我根据rgettman,Leo,zibi的评论进行的编辑。谢谢。 但这会删除一行中的值,但不会删除该行 问题答案: 如果您使用的是XLS文件(不是XLSX),则应使用HSSFWorkbook。我刚刚测试了以下解决方案,并且一切正常: 甚至更好地使用Workbook工厂,该工厂会为您进行识别: 在下面,您可以找到执行行删除的功能,该功能可以在xls和xlsx中使用(

  • 是否可以从加载的中删除元素而不创建新元素?例如,类似这样的事情: