From a092f2d3240e015ea12c599444f3bc75e81fe5b5 Mon Sep 17 00:00:00 2001 From: jlangch Date: Tue, 3 Sep 2024 14:24:08 +0200 Subject: [PATCH] Added :excel cell text validation --- .../impl/util/excel/ExcelCellStyles.java | 4 +- .../venice/impl/util/excel/ExcelSheet.java | 45 +++++++++++++++ .../venice/util/excel/ExcelSheetFacade.java | 21 +++++++ .../com/github/jlangch/venice/excel.venice | 57 +++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelCellStyles.java b/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelCellStyles.java index c317b1745..2cbb0298f 100644 --- a/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelCellStyles.java +++ b/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelCellStyles.java @@ -219,8 +219,8 @@ private Map getStandardFormats() { cellDataFormats.put("boolean", null); cellDataFormats.put("integer", "#,###0"); cellDataFormats.put("float", "#,##0.00"); - cellDataFormats.put("date", "d.m.yyyy"); - cellDataFormats.put("datetime", "d.m.yyyy hh:mm:ss"); + cellDataFormats.put("date", "dd.MM.yyyy"); + cellDataFormats.put("datetime", "dd.MM.yyyy hh:mm:ss"); return cellDataFormats; } diff --git a/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelSheet.java b/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelSheet.java index 7ac79b529..8ae31f727 100644 --- a/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelSheet.java +++ b/src/main/java/com/github/jlangch/venice/impl/util/excel/ExcelSheet.java @@ -32,6 +32,8 @@ import java.util.List; import java.util.Map; +import org.apache.poi.hssf.usermodel.HSSFDataValidationHelper; +import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.Cell; @@ -41,6 +43,9 @@ import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.ConditionalFormattingRule; import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.FillPatternType; @@ -55,9 +60,12 @@ import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFColor; +import org.apache.poi.xssf.usermodel.XSSFDataValidationHelper; import org.apache.poi.xssf.usermodel.XSSFRichTextString; +import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import com.github.jlangch.venice.ExcelException; @@ -330,6 +338,43 @@ public void conditionalBackgroundColor( sheetCF.addConditionalFormatting(regions, rule); } + public void addTextDataValidation( + final List validValues, + final boolean emptyCellAllowed, + final String errTitle, + final String errText, + final int regionFirstRow, + final int regionLastRow, + final int regionFirstCol, + final int regionLastCol + ) { + final DataValidationHelper validationHelper = sheet instanceof XSSFSheet + ? new XSSFDataValidationHelper((XSSFSheet)sheet) + : new HSSFDataValidationHelper((HSSFSheet)sheet); + + // Create a constraint for the dropdown list + final DataValidationConstraint constraint = validationHelper.createExplicitListConstraint( + validValues.toArray(new String[0])); + + // Define the cell range for which this validation applies + final CellRangeAddressList addressList = new CellRangeAddressList( + regionFirstRow, regionLastRow, + regionFirstCol, regionLastCol); + + // Create the data validation object + final DataValidation dataValidation = validationHelper.createValidation(constraint, addressList); + dataValidation.setEmptyCellAllowed(emptyCellAllowed); + if (errTitle != null || errText != null) { + dataValidation.setShowErrorBox(true); + dataValidation.createErrorBox( + errTitle == null ? "" : errTitle, + errText == null ? "" : errText); + } + + // Add the data validation to the sheet + sheet.addValidationData(dataValidation); + } + public Object getValue(final int row, final int col) { final Cell cell = getCell(row, col); return getValue(cell); diff --git a/src/main/java/com/github/jlangch/venice/util/excel/ExcelSheetFacade.java b/src/main/java/com/github/jlangch/venice/util/excel/ExcelSheetFacade.java index fd336229a..5217cfc1e 100644 --- a/src/main/java/com/github/jlangch/venice/util/excel/ExcelSheetFacade.java +++ b/src/main/java/com/github/jlangch/venice/util/excel/ExcelSheetFacade.java @@ -168,6 +168,27 @@ public void conditionalBackgroundColor( sheet.conditionalBackgroundColor(condRule, condRegion, bgColorHtml); } + public void addTextDataValidation( + final List validValues, + final boolean emptyCellAllowed, + final String errTitle, + final String errText, + final int regionFirstRow1, + final int regionLastRow1, + final int regionFirstCol1, + final int regionLastCol1 + ) { + sheet.addTextDataValidation( + validValues, + emptyCellAllowed, + errTitle, + errText, + regionFirstRow1-1, + regionLastRow1-1, + regionFirstCol1-1, + regionLastCol1-1); + } + public ExcelSheetFacade noHeader() { this.noHeader = true; return this; diff --git a/src/main/resources/com/github/jlangch/venice/excel.venice b/src/main/resources/com/github/jlangch/venice/excel.venice index 418193d53..0a9fabc88 100644 --- a/src/main/resources/com/github/jlangch/venice/excel.venice +++ b/src/main/resources/com/github/jlangch/venice/excel.venice @@ -845,6 +845,63 @@ { :pre [(instance-of? :ExcelSheetFacade sheet)] } (. sheet :conditionalBackgroundColor rule region bg-color-html)) + + +(defn + ^{ :arglists '( + "(add-text-data-validation sheet + strings + empty-cell-allowed + err-title + err-text + region-first-row region-last-row, + region-first-col, region-last-col)") + :doc "Adds a text enumeration validation to a cell region in a sheet" + :examples '( + """ + (do + (load-module :excel) + (let [wbook (excel/create :xlsx) + sheet (excel/add-sheet wbook "Sheet 1")] + (excel/write-values sheet 1 1 "John" "Doe" "male" 28) + (excel/write-values sheet 2 1 "Sue" "Ford" "female" 26) + (excel/add-text-data-validation sheet + ["male" "female" "unknown"] + true ;; allow empty cell + "Invalid gender" + "Use one of: 'male', 'female', 'unknown'" + 1 2 3 3) + (excel/auto-size-columns sheet) + (excel/write->file wbook "sample.xlsx"))) + """ ) + :see-also '( + "excel/clear-row", "excel/delete-row", + "excel/copy-row", "excel/copy-row-to-end", + "excel/write-items", "excel/write-item", "excel/cell-formula", + "excel/auto-size-columns", "excel/auto-size-column", + "excel/row-height") } + + add-text-data-validation [sheet + strings empty-cell-allowed + err-title err-text + region-first-row region-last-row + region-first-col region-last-col] + + { :pre [(instance-of? :ExcelSheetFacade sheet) + (sequential? strings) + (every? string? strings) + (boolean? empty-cell-allowed) + (or (nil? err-title) (string? err-title)) + (or (nil? err-text) (string? err-text)) + (long? region-first-row) (pos? region-first-row) + (long? region-last-row) (pos? region-last-row) + (long? region-first-col) (pos? region-first-col) + (long? region-last-col) (pos? region-last-col)] } + + (. sheet :addTextDataValidation strings empty-cell-allowed + err-title err-text + region-first-row region-last-row + region-first-col region-last-col))