簡體   English   中英

將條件格式應用於僅特定於該行的整行

[英]Apply Conditional Formatting to Entire Row Specific Only to That Row

我正在嘗試創建具有基於不同值的多個不同規則的條件格式,這些規則僅適用於值匹配的行。這是我迄今為止針對某些上下文的代碼。

XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("new sheet");

// Create a row and put some cells in it. Rows are 0 based.
XSSFRow row1 = sheet.createRow(0);

// Create a cell
row1.createCell(0).setCellValue("Lot Type");
row1.createCell(1).setCellValue("Lot Size");
row1.createCell(2).setCellValue("Square Footage");
row1.createCell(3).setCellValue("Heating/Cooling");
row1.createCell(4).setCellValue("Extras");

XSSFRow row2 = sheet.createRow(1);
row2.createCell(0).setCellValue("Residential");
row2.createCell(1).setCellValue("8000");
row2.createCell(2).setCellValue("1200");
row2.createCell(3).setCellValue("Yes");
row2.createCell(4).setCellValue("None");

XSSFRow row3 = sheet.createRow(1);
row3.createCell(0).setCellValue("Industrial");
row3.createCell(1).setCellValue("12000");
row3.createCell(2).setCellValue("8000");
row3.createCell(3).setCellValue("");
row3.createCell(4).setCellValue("");

// Set conditional rules
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();

ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule("$A2 = " + "\"" + "Residential" + "\"");
PatternFormatting fill = rule.createPatternFormatting();
fill.setFillBackgroundColor(IndexedColors.YELLOW.index);
fill.setFillPattern(PatternFormatting.SOLID_FOREGROUND);

CellRangeAddress[] regions = new CellRangeAddress[]{CellRangeAddress.valueOf("C2"), CellRangeAddress.valueOf("E2")};

ConditionalFormattingRule[] cfRules = new ConditionalFormattingRule[]{rule};

sheetCF.addConditionalFormatting(regions,cfRules);

// Write the output to a file
return wb;

所以這有效,但前提是第 2 行 A 列輸入了值“住宅”。 我想要發生的是,“地塊類型”將有一個包含不同選項(“住宅”、“工業”、“農業”等)的下拉列表,並且每個“地塊類型”都有不同的“必填”字段,並且我不知道用戶將為每一行選擇什么。

就行和可能的下拉選項而言,可能的選項很大。 目前,生成了 10000 行,每行都有 40 多個下拉選項。 這不是特別必要的信息,但它的意思是簡單地循環 i < 10000 並增加行索引; “A#”、“C#”等,然后每個索引循環遍歷我所有的下拉選項規則,這不是一個可行的解決方案。

如果這是唯一的選擇,那就這樣吧,但我希望有一種方法可以使用 Excel 方程或條件格式做一些事情,我可以將不同的“批次類型”連接到它們所需的列,並帶有編號索引行在方程本身內動態使用。 這意味着我可以只在可能的行上設置一次條件格式,而不必經歷一些巨大的雙循環。

類似於以下內容,我嘗試過但沒有成功:

ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule("$A$ = " + "\"" + "Residential" + "\"");
PatternFormatting fill = rule.createPatternFormatting();
fill.setFillBackgroundColor(IndexedColors.YELLOW.index);
fill.setFillPattern(PatternFormatting.SOLID_FOREGROUND);

CellRangeAddress[] regions = new CellRangeAddress[]{CellRangeAddress.valueOf("C$"), CellRangeAddress.valueOf("E$")};

我將如何設想這在文字中起作用的是,無論行索引具有輸入到 A 單元格中的值“住宅”,它都會導致相應的行,並且只有該行的 C 和 E 單元格被突出顯示

提前感謝您的幫助!

Excel 並不擅長將用戶指向需要填寫的單元格。只要始終需要填寫相同的列,數據驗證或條件格式都可以提供。 但是,如果強制列本身是有條件的,那么這會很快導致數千種不同的數據驗證或條件格式規則。 正如你已經提到的,這是不可行的。

但是您問的問題是關於自動調整到不同行的條件公式規則。 這是可能的。

條件公式規則以及默認公式尊重單元格引用中的$標記,以區分固定單元格引用和可變單元格引用。 因此,如果將公式規則=($A2="Residential")應用於范圍A2:E1000 ,則對第 2 行的行引用將在其他行中進行調整,因為它是可變的,而不是由$固定的。 所以它在第 2 行檢查=($A2="Residential") ,在第 3 行檢查 = =($A3="Residential") ,在第 4 行檢查=($A4="Residential") ,依此類推。

但當然,條件格式會應用於給定范圍A2:E1000中的所有列。 因此,如果規則連續匹配,則所有列A:E都會被格式化。 這就是問題所在。 如果只突出顯示所需的列,則必須有多個不同的單元格范圍應用條件格式。 這導致您提到的數千種可能性。

我能想到的一種解決方案是每個標識符(在您的情況下為批次類型)具有不同的公式規則,對於每個標識符所需的列可能具有不同的規則。 只要違反了其中一條規則,就會突出顯示整行。 這將是可以解決的,具有與不同標識符一樣多的條件格式規則,所有這些規則都應用於整個數據范圍。

完整示例:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;

import java.io.FileOutputStream;

public class ConditionalFormattingRulesAndRanges {

 public static void main(String[] args) throws Exception {
     
  Object[][] data = new Object[][] {
   new Object[] {"Lot Type", "Lot Size", "Square Footage", "Heating/Cooling", "Extras"},
   new Object[] {"Residential", 8000, 1200, "Yes", "None"},
   new Object[] {"Industrial", 12000, 8000, "", ""},
   new Object[] {"Agriculture", 4000, 900, "No", "Much"},
   new Object[] {"Industrial", 10000, "", "Yes", ""},
   new Object[] {"Residential", 8500, 1000, "", "None"},
   new Object[] {"Agriculture", 9000, "", "", ""}
  };
  int dataRowCount = data.length;
  int columnCount = data[0].length;
  
  String[] identifiers = new String[] {"Residential", "Industrial", "Agriculture"};
  String[] requiredColumnsRules = new String[] {"OR($C2=\"\",$D2=\"\",$E2=\"\")", "OR($C2=\"\",$D2=\"\")", "$C2=\"\""};
  int identifiersCount = identifiers.length;
 
  Workbook workbook = new XSSFWorkbook(); String filePath ="./ConditionalFormattingRulesAndRanges.xlsx";
  int lastRow = workbook.getSpreadsheetVersion().getLastRowIndex();

  Sheet sheet = workbook.createSheet();
  
  int r = 0;
  for (Object[] rowData : data) {
   Row row = sheet.createRow(r);
   int c = 0;
   for (Object cellValue : rowData) {
    Cell cell = row.createCell(c);
    if (cellValue instanceof Number) {
     cell.setCellValue(((Number)cellValue).doubleValue());   
    } else {
     cell.setCellValue(String.valueOf(cellValue));
    }
    c++;
   }
   r++;   
  }
  for (int i = 0; i < columnCount; i++) {
   sheet.autoSizeColumn(i);   
  }
  sheet.createFreezePane(1,1,1,1);

  DataValidationHelper dvHelper = sheet.getDataValidationHelper();
  DataValidationConstraint dvConstraint = dvHelper.createExplicitListConstraint(identifiers) ;
  CellRangeAddressList addressList = new CellRangeAddressList(1, lastRow, 0, 0);
  DataValidation validation = dvHelper.createValidation(dvConstraint, addressList);
  validation.createPromptBox("Hint", "If the line is highlighted in yellow, mandatory fields are not filled out.");
  if (workbook instanceof XSSFWorkbook) validation.setShowPromptBox(true);
  sheet.addValidationData(validation);


  SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
  ConditionalFormattingRule[] cfRules = new ConditionalFormattingRule[identifiersCount];
  
  for (int i = 0; i < identifiersCount; i++) {
   String identifier = identifiers[i];
   String requiredColumnsRule = requiredColumnsRules[i];
      
   String formulaRule = "AND($A2 = " + "\"" + identifier + "\"," + requiredColumnsRule + ")"; // rule will be applied from row 2 on; Row reference is not fixed, so it will be adjusted
  
   ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule(formulaRule);
   PatternFormatting patternFmt = rule.createPatternFormatting();
   patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index);
  
   cfRules[i] = rule;
  }
  
  CellRangeAddress[] dataRange = new CellRangeAddress[]{CellRangeAddress.valueOf("A2:E" + lastRow)}; // rules applied to the whole possible data range  
  sheetCF.addConditionalFormatting(dataRange, cfRules);

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

 }
}

另一種解決方案是為每個必填列設置一個條件格式規則。 該規則必須為每個公式定義該列是強制性列的標識符。 這需要為每個必填列設置一個完整的條件格式。

完整的例子:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;

import java.io.FileOutputStream;

public class ConditionalFormattingRulesAndRanges2 {

 public static void main(String[] args) throws Exception {
     
  Object[][] data = new Object[][] {
   new Object[] {"Lot Type", "Lot Size", "Square Footage", "Heating/Cooling", "Extras"},
   new Object[] {"Residential", 8000, 1200, "Yes", "None"},
   new Object[] {"Industrial", 12000, 8000, "", ""},
   new Object[] {"Agriculture", 4000, 900, "No", "Much"},
   new Object[] {"Industrial", 10000, "", "Yes", ""},
   new Object[] {"Residential", 8500, 1000, "", "None"},
   new Object[] {"Agriculture", 9000, "", "", ""}
  };
  int dataRowCount = data.length;
  int columnCount = data[0].length;
  
  String[] identifiers = new String[] {"Residential", "Industrial", "Agriculture"};
  String[] rules = new String[] { // rule will be applied from row 2 on; Row reference is not fixed, so it will be adjusted
   "AND($C2=\"\",OR($A2=\"Residential\",$A2=\"Industrial\",$A2=\"Agriculture\"))", // column C needs to be filled for all identifiers
   "AND($D2=\"\",OR($A2=\"Residential\",$A2=\"Industrial\"))", // column D needs to be filled for Residential and Industrial only 
   "AND($E2=\"\",OR($A2=\"Residential\"))" // column E needs to be filled for Residential only   
  };
  int rulesCount = rules.length; 
  
  Workbook workbook = new XSSFWorkbook(); String filePath ="./ConditionalFormattingRulesAndRanges.xlsx";
  int lastRow = workbook.getSpreadsheetVersion().getLastRowIndex();
  
  CellRangeAddress[][] rulesAppliedTo = new CellRangeAddress[][] {
   new CellRangeAddress[]{CellRangeAddress.valueOf("C2:C" + lastRow)},   
   new CellRangeAddress[]{CellRangeAddress.valueOf("D2:D" + lastRow)},   
   new CellRangeAddress[]{CellRangeAddress.valueOf("E2:E" + lastRow)}
  };
 
  Sheet sheet = workbook.createSheet();
  
  int r = 0;
  for (Object[] rowData : data) {
   Row row = sheet.createRow(r);
   int c = 0;
   for (Object cellValue : rowData) {
    Cell cell = row.createCell(c);
    if (cellValue instanceof Number) {
     cell.setCellValue(((Number)cellValue).doubleValue());   
    } else {
     cell.setCellValue(String.valueOf(cellValue));
    }
    c++;
   }
   r++;   
  }
  for (int i = 0; i < columnCount; i++) {
   sheet.autoSizeColumn(i);   
  }
  sheet.createFreezePane(1,1,1,1);

  DataValidationHelper dvHelper = sheet.getDataValidationHelper();
  DataValidationConstraint dvConstraint = dvHelper.createExplicitListConstraint(identifiers) ;
  CellRangeAddressList addressList = new CellRangeAddressList(1, lastRow, 0, 0);
  DataValidation validation = dvHelper.createValidation(dvConstraint, addressList);
  validation.createPromptBox("Hint", "If a cell is highlighted in yellow, then this is a mandatory.");
  if (workbook instanceof XSSFWorkbook) validation.setShowPromptBox(true);
  sheet.addValidationData(validation);

  SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
  for (int i = 0; i < rulesCount; i++) {
   String formulaRule = rules[i];
  
   ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule(formulaRule);
   PatternFormatting patternFmt = rule.createPatternFormatting();
   patternFmt.setFillBackgroundColor(IndexedColors.YELLOW.index);
  
   ConditionalFormattingRule[] cfRules = new ConditionalFormattingRule[]{rule};   
   CellRangeAddress[] appliedTo = rulesAppliedTo[i]; 
   sheetCF.addConditionalFormatting(appliedTo, cfRules);
  }

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

 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM