使用 apache poi 对数千个单元格进行自定义数据验证

Custom Data Validation to thousands of cells using apache poi

我正在 Java 中创建一个 excel sheet,它有超过 10k 条记录。对于特定列,我想对该列中的所有单元格设置验证,它可以是“NEW_RULE-x”类型,其中 x >= 1 (NEW_RULE-1, NEW_RULE-2,. ..等)或“x”型(1,2,...等)

所以在 excel 中手动,我想出了将自定义验证应用于单元格(假设是 D3)的方法: "=OR(AND(LEFT(D3,9)="NEW_RULE-",MID(D3,10,1)>="1"),OR(AND(D3>=1,D3<=999999) ))”。 如果我想将它应用于 D4,则验证公式将包含 D4 而不是 D3。他们是对整个 D 列执行此操作的通用方法吗,这样我就不必在迭代记录时为 Java 代码中的每个单元格申请?下面是生成快速 excel sheet 并在 D3 单元格进行数据验证的代码。

        String filePath = "D\mysheet.xlsx";
        File file = new File(filePath);
        XSSFWorkbook workbook = new XSSFWorkbook();
        FileOutputStream fos;
        try {
            XSSFSheet sheet = workbook.createSheet();

            for (int i = 0; i <= 5; i++) {

                XSSFRow row = sheet.getRow(i);

                if(row == null)
                    row = sheet.createRow(i);

                XSSFCell cell=row.getCell(0);

                if(cell == null)
                    cell = row.createCell(0, XSSFCell.CELL_TYPE_STRING);

                cell.setCellValue("Keyword" +i);

                cell=row.getCell(1);

                if(cell == null)
                    cell = row.createCell(1, XSSFCell.CELL_TYPE_STRING);
                cell.setCellValue("PASS" +i);

                System.out.println("1");
            }
            XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
            XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper.createCustomConstraint(
                    "=OR(AND(LEFT(D3,9)=\"NEW_RULE-\",MID(D3,10,1)>=\"1\"),OR(AND(D3>=1,D3<=999999)))");

            //=OR(AND(LEFT(D3,9)="NEW_RULE-",MID(D3,10,1)>="1"),OR(AND(D3>=1,D3<=999999)))

            CellRangeAddressList addressList = new CellRangeAddressList(2,2,3,3);
            XSSFDataValidation dataValidation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, addressList);
            sheet.addValidationData(dataValidation);
            fos = new FileOutputStream(filePath);
            workbook.write(fos);
            fos.close();
        }finally{
        }

    }```

首先:通过apache poi设置公式字符串时,不要将等号=放在前面。等号不存储在 Excel 的存储中。它仅在 GUI.

中可见

当使用公式时,即使在条件格式和数据验证中,单元格引用也可以是相对的或绝对的。例如 A1 是相对引用,而 $A 是绝对引用。因此,由于您在公式中仅使用相对引用,因此引用将调整到 sheet 中的新单元格。例如,D1 单元格中的 LEFT(D1,9)="NEW_RULE-" 将是 D2 单元格中的 LEFT(D2,9)="NEW_RULE-"D3 单元格中的 LEFT(D3,9)="NEW_RULE-" 等等。

因此公式字符串 "OR(AND(LEFT($D1,9)=\"NEW_RULE-\",MID($D1,10,1)>=\"1\"),OR(AND($D1>=1,$D1<=999999)))" 可用于单元格 D1:D1000,并且对于绝对列 D.

中的当前相对行始终是正确的

完整示例:

import java.io.FileOutputStream;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddressList;

class CreateExcelDataValidation {

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

  //Workbook workbook = new HSSFWorkbook(); String filePath = "./mysheet.xls";
  Workbook workbook = new XSSFWorkbook(); String filePath = "./mysheet.xlsx";

  Sheet sheet = workbook.createSheet();
 
  for (int i = 0; i <= 5; i++) {
   Row row = sheet.getRow(i);
   if (row == null) row = sheet.createRow(i);
   Cell cell = row.getCell(0);
   if (cell == null) cell = row.createCell(0);
   cell.setCellValue("Keyword" +i);
   cell = row.getCell(1);
   if (cell == null) cell = row.createCell(1);
   cell.setCellValue("PASS" +i);
  } 
  
  DataValidationHelper dvHelper = sheet.getDataValidationHelper();
  DataValidationConstraint dvConstraint = dvHelper.createCustomConstraint("OR(AND(LEFT($D1,9)=\"NEW_RULE-\",MID($D1,10,1)>=\"1\"),OR(AND($D1>=1,$D1<=999999)))");
  CellRangeAddressList addressList = new CellRangeAddressList(0, 1000, 3, 3);
  DataValidation validation = dvHelper.createValidation(dvConstraint, addressList);
  if (workbook instanceof XSSFWorkbook) validation.setShowErrorBox(true);
  sheet.addValidationData(validation);

  FileOutputStream out = new FileOutputStream(filePath);
  workbook.write(out);
  workbook.close();
  out.close();

 }
}