@@ -194,24 +194,85 @@ class RetableExcelSupport<T : RetableColumns>(
194194 private fun String.isUrl (): Boolean =
195195 take(7 ) == " http://" || take(8 ) == " https://"
196196
197+ /* *
198+ * Sets up Excel data validation (dropdown lists) for all [StringRetableColumn]s that define allowed values.
199+ *
200+ * Tries the standard inline approach first ([setupStdValueConstraints]). If it fails due to the
201+ * Excel 255-character formula limit, falls back to a hidden sheet-based approach
202+ * ([setupHiddenSheetBasedValueConstraints]).
203+ */
197204 private fun XSSFSheet.setupValueConstraints (columns : T ) {
198- columns.list()
205+ val constrainedColumns = columns.list()
199206 .filterIsInstance<StringRetableColumn >()
200207 .filter { it.allowedValues.orEmpty().isNotEmpty() }
201- .forEach { column ->
202- val allowedValues = column.allowedValues.orEmpty()
203- val constraint = dataValidationHelper.createExplicitListConstraint(allowedValues.toTypedArray())
204- val cellRange = CellRangeAddressList (
205- if (options.firstRecordAsHeader) 1 else 0 ,
206- workbook.spreadsheetVersion.lastRowIndex,
207- column.index - 1 ,
208- column.index - 1
209- )
210- val validation = dataValidationHelper.createValidation(constraint, cellRange)
211- validation.showPromptBox = true
212- validation.suppressDropDownArrow = false
213- addValidationData(validation)
208+
209+ if (constrainedColumns.isNotEmpty()) {
210+ try {
211+ setupStdValueConstraints(constrainedColumns)
212+ } catch (_: IllegalArgumentException ) {
213+ // excel formula 255-character limit potentially exceeded,
214+ // fallback to hidden sheet-based value constraints
215+ setupHiddenSheetBasedValueConstraints(constrainedColumns)
214216 }
217+ }
218+ }
219+
220+ private fun XSSFSheet.setupStdValueConstraints (constrainedColumns : List <StringRetableColumn >) {
221+ constrainedColumns.forEach { column ->
222+ val columnIndex = column.index - 1
223+
224+ val allowedValues = column.allowedValues.orEmpty()
225+ val constraint = dataValidationHelper.createExplicitListConstraint(allowedValues.toTypedArray())
226+ val cellRange = CellRangeAddressList (
227+ if (options.firstRecordAsHeader) 1 else 0 ,
228+ workbook.spreadsheetVersion.lastRowIndex,
229+ columnIndex,
230+ columnIndex
231+ )
232+ val validation = dataValidationHelper.createValidation(constraint, cellRange)
233+ validation.showPromptBox = true
234+ validation.suppressDropDownArrow = false
235+ addValidationData(validation)
236+ }
237+ }
238+
239+ private fun XSSFSheet.setupHiddenSheetBasedValueConstraints (constrainedColumns : List <StringRetableColumn >) {
240+ val constraintSheetName = " _constraints_${this .sheetName} "
241+ val constraintSheet = workbook.createSheet(constraintSheetName)
242+ val constraintSheetIndex = workbook.getSheetIndex(constraintSheet)
243+ workbook.setSheetHidden(constraintSheetIndex, true )
244+
245+ constrainedColumns.forEach { column ->
246+ val columnIndex = column.index - 1
247+
248+ val allowedValues = column.allowedValues.orEmpty()
249+ allowedValues.forEachIndexed { rowIndex, value ->
250+ val row = constraintSheet.getRow(rowIndex)
251+ ? : constraintSheet.createRow(rowIndex)
252+ row.createCell(columnIndex).setCellValue(value)
253+ }
254+
255+ val rangeName = " ${constraintSheetName} _${columnIndex} "
256+ val lastRow = allowedValues.size
257+ val colLetter = (' A' + columnIndex)
258+ val formulaRef = " '$constraintSheetName '!\$ ${colLetter} \$ 1:\$ ${colLetter} \$ $lastRow "
259+
260+ val name = workbook.createName()
261+ name.nameName = rangeName
262+ name.refersToFormula = formulaRef
263+
264+ val constraint = dataValidationHelper.createFormulaListConstraint(rangeName)
265+ val cellRange = CellRangeAddressList (
266+ if (options.firstRecordAsHeader) 1 else 0 ,
267+ workbook.spreadsheetVersion.lastRowIndex,
268+ columnIndex,
269+ columnIndex
270+ )
271+ val validation = dataValidationHelper.createValidation(constraint, cellRange)
272+ validation.showPromptBox = true
273+ validation.suppressDropDownArrow = false
274+ addValidationData(validation)
275+ }
215276 }
216277}
217278
0 commit comments