我想使用 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
檔案說,如果你想左移(覆寫左側的列),你應該使用負數。
我在以下 Excel 檔案中嘗試了以下示例:
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();
}
}
我想更改的 Excel 檔案:

執行代碼后,我在線收到此錯誤wb.write(fileOut);:
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)
僅供參考,我使用 Java 11 和這些庫:
圖書館
執行后,我的檔案有0KB。
我在將作業簿保存在 Excel 檔案中的同時除錯到 Apache POI 庫中。這就是問題開始的地方。也許它可以幫助你:
圖片1
圖片2
圖3
uj5u.com熱心網友回復:
是的,即使在最新版本的 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);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/349788.html
標籤:爪哇 擅长 apache-poi
上一篇:將陣列粘貼到范圍上的索引符號
下一篇:vba回圈不檢查重復的零件號
