8000 new feature: name a cell range and few minor fixes by dorssar · Pull Request #150 · dhatim/fastexcel · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

new feature: name a cell range and few minor fixes #150

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

Merged
merged 14 commits into from
Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ or shade every Nth row (e.g. every 5th):
```java
ws.range(0, 0, 10, 10).style().shadeRows(Color.GRAY2, 5).set();
```
Name a cell range (name of a cell range can only include letters, numbers and underscore):
```java
ws.range(0, 0, 0, 10).setName("header");
```

### Formulas

Expand Down
10 changes: 10 additions & 0 deletions fastexcel-writer/src/main/java/org/dhatim/fastexcel/Range.java
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ public ListDataValidation validateWithList(Range listRange) {
return listDataValidation;
}

/**
* 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 set of styles used by the cells in this range.
*
Expand Down
51 changes: 42 additions & 9 deletions fastexcel-writer/src/main/java/org/dhatim/fastexcel/Workbook.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Map;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
Expand Down Expand Up @@ -204,21 +205,53 @@ private void writeWorkbookFile() throws IOException {
* (if there are any repeating rows or cols in the sheet at all) **/

for (Worksheet ws : worksheets) {
int worksheetIndex = getIndex(ws) - 1;
String defineName = Stream.of(ws.getRepeatingCols(),ws.getRepeatingRows())
.filter(Objects::nonNull)
.map(r -> ws.getName() + "!" + r.toString())
.map(r -> "'" + ws.getName() + "'!" + r.toString())
.collect(Collectors.joining(","));
10000
w.append("<definedNames>");
Copy link
Collaborator

Choose a reason for hiding this comment

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

If defineName and namesRanges are empty then will never be closed.

Copy link
Contributor Author
@dorssar dorssar Feb 10, 2021

Choose a reason for hiding this comment

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

I think you overlooked (it's being closed on line 254 either way).

Copy link
Collaborator

Choose a reason for hiding this comment

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

So if both defineName and namedRanges are not empty, then it will be closed twice?

Copy link
Contributor Author
@dorssar dorssar Feb 10, 2021

Choose a reason for hiding this comment

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

It will be opened and then closed only once, but there are conditional <definedName> tags inside of this <definedNames> tag.

Copy link
Contributor Author
@dorssar dorssar Feb 10, 2021

Choose a reason for hiding this comment

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

If they are empty - we'll have <definedNames></definedNames>, otherwise if any of them are non-empty we will have

<definedNames>
    <definedName>....sth...</definedName>
    <definedName>....sth2...</definedName>
</definedNames>

Copy link
Collaborator

Choose a reason for hidin EDBE g this comment

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

Oh. I see it now. I misstook line 221 as </definedNames>. Nevertheless I would be good to cover this part of code in a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, will try to do that. Where should I put this test?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can put it in a new class in src/test/java

Copy link
Contributor Author
@dorssar dorssar Mar 8, 2021

Choose a reason for hiding this comment

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

Can I put it into PoiCompatibilityTest.java ? I guess all of the existing similar tests are there ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

Please include a test that verifies (for example using Apache POI) that a worksheet with a named range is valid.

Done!

if (!defineName.isEmpty()) {
w.append("<definedNames>");
w.append("<definedName function=\"false\" " +
"hidden=\"false\" " +
"localSheetId=\"0\" " +
"name=\"_xlnm.Print_Titles\" " +
"vbProcedure=\"false\">");
w.append(defineName);
w.append("</definedName>");
w.append("</definedNames>");
"hidden=\"false\" localSheetId=\"" +
worksheetIndex + "\" name=\"_xlnm.Print_Titles\" " +
"vbProcedure=\"false\">")
.append(defineName)
.append("</definedName>");
}
/** define specifically named ranges **/
for (Map.Entry<String, Range> nr : ws.getNamedRanges().entrySet()) {
1E0A String rangeName = nr.getKey();
Range range = nr.getValue();
w.append("<definedName function=\"false\" " +
"hidden=\"false\" localSheetId=\"" +
worksheetIndex + "\" name=\"")
.append(rangeName)
.append("\" vbProcedure=\"false\">&apos;")
.append(ws.getName())
.append("&apos;")
.append("!")
.append("$" + Range.colToString(range.getLeft()) + "$" + (1 + range.getTop()))
.append(":")
.append("$" + Range.colToString(range.getRight()) + "$" + (1 + range.getBottom()))
.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\">")
.append("&apos;")
.append(ws.getName())
.append("&apos;")
.append("!")
.append("$" + Range.colToString(af.getLeft()) + "$" + (1 + af.getTop()))
.append(":")
.append("$" + Range.colToString(af.getRight()) + "$" + (1 + af.getBottom()))
.append("</definedName>");
}
w.append("</definedNames>");
}
w.append("</workbook>");
});
Expand Down
38 changes: 38 additions & 0 deletions fastexcel-writer/src/main/java/org/dhatim/fastexcel/Worksheet.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ public class Worksheet {
* Range of row where will be inserted auto filter
*/
private Range autoFilterRange = null;
/**
* List of named ranges.
*/
private Map<String, Range> namedRanges = new LinkedHashMap();

/**
* The set of protection options that are applied on the sheet.
Expand Down Expand Up @@ -248,6 +252,16 @@ public RepeatRowRange getRepeatingRows(){
return repeatingRows;
}

/**
* Get cell range that autofilter is applied to.
*
* @return Range of cells that autofilter is set to
* (null if autofilter is not set).
*/
public Range getAutoFilterRange(){
return autoFilterRange;
}

/**
* Get repeating cols defined for the print setup.
*
Expand All @@ -258,6 +272,16 @@ public RepeatColRange getRepeatingCols(){
return repeatingCols;
}

/**
* Get a list of named ranges.
*
* @return Map containing named range entries
* where keys are the names and values are cell ranges.
*/
public Map<String, Range> getNamedRanges() {
return namedRanges;
}

/**
* Get parent workbook.
*
Expand Down Expand Up @@ -1209,4 +1233,18 @@ public void header(String text, Position position) {
this.header.put(position, "&amp;" + position.getPos() +
prepareForXml(text));
}

/**
* Add the given range to this sheet's
* list of named ranges under the provided name.
* It will be visible when this sheet is open in the
* cell range dropdown menu under the specified name.
*
* @param range Range of cells that needs to be named.
* @param name String representing the given cell range's name.
*
*/
public void addNamedRange(Range range, String name) {
this.namedRanges.put(name, range);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -630,4 +630,31 @@ private static boolean isWorkSheetDisplayingGridLines(byte[] data) throws IOExce
return xws.isDisplayGridlines();
}

@Test
void hasValidNamedRange() throws Exception {

byte[] data = writeWorkbook(wb -> {
Worksheet ws = wb.newWorksheet("Worksheet 1");
ws.value(0, 1, "column 1");
ws.value(0, 2, "column 2");
ws.value(0, 3, "column 3");
ws.value(1, 1, "value 1");
ws.value(1, 2, "value 2");
ws.value(1, 3, "value 3");
ws.range(0, 0, 1, 3).setName("col names");
});

// Check generated workbook with Apache POI
XSSFWorkbook xwb = new XSSFWorkbook(new ByteArrayInputStream(data));
XSSFSheet xws = xwb.getSheetAt(0);
// Fetch the XSSF Name object
XSSFName name = xwb.getName("col names");
String formula = name.getRefersToFormula();

assertTrue(name != null);
assertTrue(name.getNameName().equals("col names"));
assertTrue(formula.equals("'Worksheet 1'!$A$1:$D$2"));
}


}
0