[英]How to use Array Spilling with Apache POI 5.1.0
使用Apache POI生成excel文件,是否可以防止Excel在公式中添加隱式交集運算符(@)?
例如,使用以下代碼,我想要做的是使用Excel Array Spilling behavior將列內的所有值從 A 復制到 K。 但是,當使用 Excel Desktop(版本 16.54)打開文件時,它會自動在公式中添加 @ 運算符。
在工作簿工作sheet
內部,在單元格 A1 中,而不是=IF(otherSheet!A:K=""; ""; otherSheet!A:K)
,我得到=@IF(@otherSheet!A:K=""; ""; otherSheet!A:K)
沒有相同的結果,因為我只從anotherSheet
獲取 A1 內的值。
import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.io.FileOutputStream
import java.nio.file._
object Main {
def main(args: Array[String]): Unit = {
val workbook = new XSSFWorkbook()
val sheet = workbook.createSheet("sheet")
val row = sheet.createRow(0)
val cell = row.createCell(0, CellType.FORMULA)
// Filling dummy data to another sheet
val otherSheet = workbook.createSheet("otherSheet")
val otherRow = otherSheet.createRow(0)
for (i <- 0 to 10) {
otherRow.createCell(i, CellType.STRING).setCellValue("Something")
}
// Copying values
val otherSheetContent = f"otherSheet!A:K"
cell.setCellFormula(f"""IF($otherSheetContent="", "", $otherSheetContent)""")
println(cell.getCellFormula) // IF(otherSheet!A:K="", "", otherSheet!A:K)
// Saving file
val file = Paths.get("workbook.xlsx")
workbook.write(new FileOutputStream(file.toFile))
}
}
您不能在 Apache POI 5.1.0 中使用動態數組公式和溢出數組行為。 溢出數組行為是在 Excel 365 版中引入的。它在以前的版本中不可用。 Apache POI 基於 Excel 2007 發布的Office Open XML 。因此使用 Apache POI 生成的 Excel 文件是 Excel 2007 文件。
為什么添加@
? 這在隱式交集運算符的“我們何時將 @ 添加到舊公式中?”一節中講述:@ :
一般來說,如果函數是在舊版本的 Excel 中編寫的,則返回多單元格區域或數組的函數將以 @ 為前綴。 ... 一個常見的例外是如果它們被包裝在一個接受數組或范圍的函數中(例如 SUM() 或 AVERAGE())。
所以添加了@
是因為IF
不希望它的任何參數中有一個數組。
使用 Apache POI 唯一可以實現的是設置舊數組公式。 見示例:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
class CreateExcelArrayFormula {
static void setArrayToFormula(XSSFCell cell, String ref) {
if (cell.getCTCell().getF() != null) {
cell.getCTCell().getF().setT(org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType.ARRAY);
cell.getCTCell().getF().setRef(ref);
}
}
public static void main(String[] args) throws Exception {
try (
Workbook workbook = new XSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {
Sheet sheet = workbook.createSheet();
Row row;
Cell cell;
// Filling dummy data to another sheet
Sheet otherSheet = workbook.createSheet("otherSheet");
for (int r = 0; r < 5; r++) {
row = otherSheet.createRow(r);
for (int c = 0; c < 11; c++) {
row.createCell(c).setCellValue("OS-R" + (r+1) + "C" + (c+1));
}
}
row = sheet.createRow(0);
cell = row.createCell(0);
cell.setCellFormula("IF(otherSheet!A1:K5=\"\", \"\", otherSheet!A1:K5)");
if (cell instanceof XSSFCell) {
setArrayToFormula((XSSFCell)cell, "A1:K5");
}
workbook.write(fileout);
}
}
}
但是您是否應該使用遺留數組公式的溢出數組行為來做這樣的事情? 不,你不應該,在我看來。 如果您使用公式=IF(otherSheet!A:K="", "", otherSheet!A:K)
使用溢出數組行為,則生成的文件將非常大。 這是因為完整的列引用A:K
跨越 1,048,576 行。 遺留數組也是如此。 永遠不應該使用具有完整列引用的數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.