Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#453: Add new data validation: ListFormulaDataValidation. #454

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package org.dhatim.fastexcel;

import java.io.IOException;

/**
* A ListDataValidation defines a DataValidation for a worksheet of type = "list"
*/
public class ListFormulaDataValidation implements DataValidation {
private final static String TYPE = "list";
private final Range range;
private final Formula formula;

private boolean allowBlank = true;
private boolean showDropdown = true;
private DataValidationErrorStyle errorStyle = DataValidationErrorStyle.INFORMATION;
private boolean showErrorMessage = false;
private String errorTitle;
private String error;

/**
* Constructor
*
* @param range The Range this validation is applied to
* @param formula The Formula of this validation to retrieve the list
*/
ListFormulaDataValidation(Range range, Formula formula) {
this.range = range;
this.formula = formula;
}

/**
* whether blank cells should pass the validation
*
* @param allowBlank whether or not to allow blank values
* @return this ListDataValidation
*/
public ListFormulaDataValidation allowBlank(boolean allowBlank) {
this.allowBlank = allowBlank;
return this;
}

/**
* Whether Excel will show an in-cell dropdown list
* containing the validation list
*
* @param showDropdown whether or not to show the dropdown
* @return this ListDataValidation
*/
public ListFormulaDataValidation showDropdown(boolean showDropdown) {
this.showDropdown = showDropdown;
return this;
}

/**
* The style of error alert used for this data validation.
*
* @param errorStyle The DataValidationErrorStyle for this DataValidation
* @return this ListDataValidation
*/
public ListFormulaDataValidation errorStyle(DataValidationErrorStyle errorStyle) {
this.errorStyle = errorStyle;
return this;
}

/**
* Whether to display the error alert message when an invalid value has been entered.
*
* @param showErrorMessage whether to display the error message
* @return this ListDataValidation
*/
public ListFormulaDataValidation showErrorMessage(boolean showErrorMessage) {
this.showErrorMessage = showErrorMessage;
return this;
}

/**
* Title bar text of error alert.
*
* @param errorTitle The error title
* @return this ListDataValidation
*/
public ListFormulaDataValidation errorTitle(String errorTitle) {
this.errorTitle = errorTitle;
return this;
}

/**
* Message text of error alert.
*
* @param error The error message
* @return this ListDataValidation
*/
public ListFormulaDataValidation error(String error) {
this.error = error;
return this;
}

/**
* Write this dataValidation as an XML element.
*
* @param w Output writer.
* @throws IOException If an I/O error occurs.
*/
@Override
public void write(Writer w) throws IOException {
w
.append("<dataValidation sqref=\"")
.append(range.toString())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnessesary .toString()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I try to append the range without "toString", an error is return

.append("\" type=\"")
.append(TYPE)
.append("\" allowBlank=\"")
.append(String.valueOf(allowBlank))
.append("\" showDropDown=\"")
.append(String.valueOf(!showDropdown)) // for some reason, this is the inverse of what you'd expect
.append("\" errorStyle=\"")
.append(errorStyle.toString())
.append("\" showErrorMessage=\"")
.append(String.valueOf(showErrorMessage))
.append("\" errorTitle=\"")
.append(errorTitle)
.append("\" error=\"")
.append(error)
.append("\"><formula1>")
.append(formula.getExpression())
.append("</formula1></dataValidation>");
}
}
40 changes: 38 additions & 2 deletions fastexcel-writer/src/main/java/org/dhatim/fastexcel/Range.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public class Range implements Ref {
*/
private final int right;

/**
* Check about the Range visibility when a named range is added.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this comment confusing. Doesn't seem to turn on any "Check", but rather control the scope of this range (right?)

*/
private boolean globalVisibility = false;

/**
* Constructor. Note coordinates are reordered if necessary to make sure
* {@code top} &lt;= {@code bottom} and {@code left} &lt;= {@code right}.
Expand Down Expand Up @@ -201,7 +206,19 @@ public ListDataValidation validateWithList(Range listRange) {
return listDataValidation;
}

/**
/**
* Construct a new ListDataValidation
*
* @param formula The Formula to retrieve the validation list
* @return a new list data validation object
*/
public ListFormulaDataValidation validateWithListByFormula(String formula) {
ListFormulaDataValidation listDataValidation = new ListFormulaDataValidation(this, new Formula(formula));
worksheet.addValidation(listDataValidation);
return listDataValidation;
}

/**
* Construct a new ListDataValidation
*
* @param formula The custom validation formula
Expand All @@ -216,13 +233,32 @@ public CustomDataValidation validateWithFormula(String formula) {
/**
* Specifically define this range by assigning it a name.
* It will be visible in the cell range dropdown menu.
*
*
* @param name string representing the name of this cell range
*/
public void setName(String name) {
worksheet.addNamedRange(this, name);
}

/**
* Return the visibility of this range.
*
* @return {@code true} if the range is visible by all worksheet, {@code false} if it is visible only by the worksheet contains the range
*/
public boolean isGlobalVisibility() {
return globalVisibility;
}

/**
* Set the visibility of this range
*
* @param globalVisibility {@code true} to allow to see the range by all worksheet
*/
public Range setGlobalVisibility(boolean globalVisibility) {
this.globalVisibility = globalVisibility;
return this;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other setters return void. returning this here seems inconsistent

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand. I change it

}

/**
* Return the set of styles used by the cells in this range.
*
Expand Down
62 changes: 33 additions & 29 deletions fastexcel-writer/src/main/java/org/dhatim/fastexcel/Workbook.java
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,14 @@ private boolean hasComments() {
private void writeWorkbookFile() throws IOException {
writeFile("xl/workbook.xml", w -> {
w.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<workbook " +
"xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" " +
"xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">" +
"<workbookPr date1904=\"false\"/>" +
"<bookViews>" +
"<workbookView activeTab=\"" + activeTab + "\"/>" +
"</bookViews>" +
"<sheets>");
"<workbook " +
"xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" " +
"xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">" +
"<workbookPr date1904=\"false\"/>" +
"<bookViews>" +
"<workbookView activeTab=\"" + activeTab + "\"/>" +
"</bookViews>" +
"<sheets>");

for (Worksheet ws : worksheets) {
writeWorkbookSheet(w, ws);
Expand All @@ -312,12 +312,12 @@ private void writeWorkbookFile() throws IOException {
for (Worksheet ws : worksheets) {
int worksheetIndex = getIndex(ws) - 1;
List<Object> repeatingColsAndRows = Stream.of(ws.getRepeatingCols(), ws.getRepeatingRows())
.filter(Objects::nonNull)
.collect(Collectors.toList());
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (!repeatingColsAndRows.isEmpty()) {
w.append("<definedName function=\"false\" hidden=\"false\" localSheetId=\"")
.append(worksheetIndex)
.append("\" name=\"_xlnm.Print_Titles\" vbProcedure=\"false\">");
.append(worksheetIndex)
.append("\" name=\"_xlnm.Print_Titles\" vbProcedure=\"false\">");
for (int i = 0; i < repeatingColsAndRows.size(); ++i) {
if (i > 0) {
w.append(",");
Expand All @@ -330,26 +330,30 @@ private void writeWorkbookFile() throws IOException {
for (Map.Entry<String, Range> nr : ws.getNamedRanges().entrySet()) {
String rangeName = nr.getKey();
Range range = nr.getValue();
w.append("<definedName function=\"false\" " +
"hidden=\"false\" localSheetId=\"")
.append(worksheetIndex)
.append("\" name=\"")
.append(rangeName)
.append("\" vbProcedure=\"false\">'")
.appendEscaped(ws.getName())
.append("'!")
.append(range.toAbsoluteString())
.append("</definedName>");
w.append("<definedName function=\"false\" hidden=\"false\"");

if (range.isGlobalVisibility()) {
w.append(" localSheetId=\"")
.append(worksheetIndex).append("\"");
}

w.append(" name=\"")
.append(rangeName)
.append("\" vbProcedure=\"false\">'")
.appendEscaped(ws.getName())
.append("'!")
.append(range.toAbsoluteString())
.append("</definedName>");
}
Range af = ws.getAutoFilterRange();
if (af != null) {
w.append("<definedName function=\"false\" hidden=\"true\" localSheetId=\"")
.append(worksheetIndex)
.append("\" name=\"_xlnm._FilterDatabase\" vbProcedure=\"false\">'")
.appendEscaped(ws.getName())
.append("'!")
.append(af.toAbsoluteString())
.append("</definedName>");
.append(worksheetIndex)
.append("\" name=\"_xlnm._FilterDatabase\" vbProcedure=\"false\">'")
.appendEscaped(ws.getName())
.append("'!")
.append(af.toAbsoluteString())
.append("</definedName>");
}
}
w.append("</definedNames>");
Expand All @@ -366,7 +370,7 @@ private void writeWorkbookFile() throws IOException {
*/
private void writeWorkbookSheet(Writer w, Worksheet ws) throws IOException {
w.append("<sheet name=\"").appendEscaped(ws.getName()).append("\" r:id=\"rId").append(getIndex(ws) + 2)
.append("\" sheetId=\"").append(getIndex(ws));
.append("\" sheetId=\"").append(getIndex(ws));

if (ws.getVisibilityState() != null) {
w.append("\" state=\"").append(ws.getVisibilityState().getName());
Expand Down