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

Feature optimize merge function #236

Merged
merged 3 commits into from
Dec 20, 2022
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
44 changes: 29 additions & 15 deletions fastexcel-writer/src/main/java/org/dhatim/fastexcel/Worksheet.java
Original file line number Diff line number Diff line change
Expand Up @@ -688,18 +688,6 @@ public Range range(int top, int left, int bottom, int right) {
return new Range(this, top, left, bottom, right);
}

/**
* Check if the given cell is within merged ranges.
*
* @param r Zero-based row number.
* @param c Zero-based column number.
* @return {@code true} if the cell is within merged ranges, {@code false}
* otherwise.
*/
private boolean isCellInMergedRanges(int r, int c) {
return mergedRanges.stream().anyMatch(range -> range.contains(r, c));
}

/**
* Write column definitions of this worksheet as an XML element.
*
Expand All @@ -708,6 +696,29 @@ private boolean isCellInMergedRanges(int r, int c) {
* @throws IOException If an I/O error occurs.
*/
private void writeCols(Writer w, int nbCols) throws IOException {
// Get merged range bitMatrix
int maxRows = (mergedRanges.stream().filter(Objects::nonNull).map(Range::getBottom).reduce(0, Math::max)) + 1;
int maxCols = (mergedRanges.stream().filter(Objects::nonNull).map(Range::getRight).reduce(0, Math::max)) + 1;
if (rows.size() > maxRows) {
maxRows = rows.size();
}
if (nbCols > maxCols) {
maxCols = nbCols;
}
int rowSize = (maxCols + 31) / 32;
int[] bits = new int[rowSize * maxRows];
mergedRanges.forEach(r -> {
int top = r.getTop();
int left = r.getLeft();
int right = r.getRight();
int bottom = r.getBottom();
for (int y = top; y < bottom; y++) {
int offset = y * rowSize;
for (int x = left; x < right; x++) {
bits[offset + (x / 32)] |= 1 << (x & 0x1f);
}
}
});
// Adjust column widths
boolean started = false;
for (int c = 0; c < nbCols; ++c) {
Expand All @@ -718,8 +729,10 @@ private void writeCols(Writer w, int nbCols) throws IOException {
maxWidth = colWidths.get(c);
} else {
for (int r = 0; r < rows.size(); ++r) {
int offset = r * rowSize + (c / 32);
boolean isCellInMergedRanges = ((bits[offset] >>> (c & 0x1f)) & 1) != 0;
// Exclude merged cells from computation && hidden rows
Object o = hiddenRows.contains(r) || isCellInMergedRanges(r, c) ? null : value(r, c);
Object o = hiddenRows.contains(r) || isCellInMergedRanges ? null : value(r, c);
if (o != null && !(o instanceof Formula)) {
int length = o.toString().length();
maxWidth = Math.max(maxWidth, (int) ((length * 7 + 10) / 7.0 * 256) / 256.0);
Expand All @@ -739,6 +752,7 @@ private void writeCols(Writer w, int nbCols) throws IOException {
}
}


/**
* Write a column as an XML element.
*
Expand Down Expand Up @@ -1265,10 +1279,10 @@ public void header(String text, Position position) {
* 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.function.Consumer;
import java.util.stream.IntStream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -196,6 +195,25 @@ void mergedRanges() throws Exception {
});
}

@Test
void testForGithubIssue185() throws Exception {
long start = System.currentTimeMillis();
writeWorkbook(wb -> {
Worksheet ws = wb.newWorksheet("Worksheet 1");
for (int i = 0; i < 10000; i++) {
if ((i + 1) % 100 == 0) {
ws.range(i, 0, i, 19).merge();
continue;
}
for (int j = 0; j < 20; j++) {
ws.value(i, j, "*****");
}
}
});
long end = System.currentTimeMillis();
System.out.println("cost:" + (end - start) + "ms");
}

@Test
void shouldBeAbleToNullifyCell() throws IOException {
writeWorkbook(wb ->{
Expand Down