Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.apache.poi.xssf.usermodel.XSSFHyperlink;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import com.vaadin.addon.spreadsheet.ConditionalFormatter.ConditionalFormatterEvaluator;
import com.vaadin.addon.spreadsheet.Spreadsheet.CellDeletionHandler;
import com.vaadin.addon.spreadsheet.Spreadsheet.CellValueChangeEvent;
import com.vaadin.addon.spreadsheet.Spreadsheet.CellValueHandler;
Expand Down Expand Up @@ -223,7 +224,12 @@ private String getCachedFormulaCellValue(Cell formulaCell) {
return result;
}

protected CellData createCellDataForCell(Cell cell) {
/**
* @param cell
* @param conditionalFormatter evaluator from a batch run of conditional formatting checks
* @return a new CellData instance
*/
protected CellData createCellDataForCell(Cell cell, ConditionalFormatterEvaluator conditionalFormatter) {
CellData cellData = new CellData();
cellData.row = cell.getRowIndex() + 1;
cellData.col = cell.getColumnIndex() + 1;
Expand Down Expand Up @@ -333,9 +339,8 @@ && isGenerallCell(cell)) {

// conditional formatting might be applied even if there isn't a
// value (such as borders for the cell to the right)
Set<Integer> cellFormattingIndexes = spreadsheet
.getConditionalFormatter().getCellFormattingIndex(cell);
if (cellFormattingIndexes != null) {
Set<Integer> cellFormattingIndexes = conditionalFormatter.getCellFormattingIndex(cell);
if (cellFormattingIndexes != null && !cellFormattingIndexes.isEmpty()) {

for (Integer i : cellFormattingIndexes) {
cellData.cellStyle = cellData.cellStyle + " cf" + i;
Expand Down Expand Up @@ -1126,32 +1131,37 @@ protected ArrayList<CellData> loadCellDataForRowAndColumnRange(
@SuppressWarnings("unchecked")
final Collection<String> customComponentCells = (Collection<String>) (componentIDtoCellKeysMap == null ? Collections
.emptyList() : componentIDtoCellKeysMap.values());
for (int r = firstRow - 1; r < lastRow; r++) {
Row row = activeSheet.getRow(r);
if (row != null && row.getLastCellNum() != -1
&& row.getLastCellNum() >= firstColumn) {
for (int c = firstColumn - 1; c < lastColumn; c++) {
final String key = SpreadsheetUtil.toKey(c + 1, r + 1);
if (!customComponentCells.contains(key)
&& !sentCells.contains(key)
&& !sentFormulaCells.contains(key)) {
Cell cell = row.getCell(c);
if (cell != null) {
final CellData cd = createCellDataForCell(cell);
if (cd != null) {
CellType cellType = cell.getCellType();
if (cellType == CellType.FORMULA) {
sentFormulaCells.add(key);
} else {
sentCells.add(key);

// iterate in reverse row/column order (bottom right to top left) to match CSS order for border calculations,
// to avoid issues like #651 where cell values are not updated in the proper sequence.
spreadsheet.getConditionalFormatter().evaluateBatch(formatter -> {
for (int r = lastRow - 1; r >= firstRow -1; r--) {
Row row = activeSheet.getRow(r);
if (row != null && row.getLastCellNum() != -1
&& row.getLastCellNum() >= firstColumn) {
for (int c = lastColumn - 1; c >= firstColumn -1; c--) {
final String key = SpreadsheetUtil.toKey(c + 1, r + 1);
if (!customComponentCells.contains(key)
&& !sentCells.contains(key)
&& !sentFormulaCells.contains(key)) {
Cell cell = row.getCell(c);
if (cell != null) {
final CellData cd = createCellDataForCell(cell, formatter);
if (cd != null) {
CellType cellType = cell.getCellType();
if (cellType == CellType.FORMULA) {
sentFormulaCells.add(key);
} else {
sentCells.add(key);
}
cellData.add(cd);
}
}
cellData.add(cd);
}
}
}
}
}
}
});
return cellData;
}

Expand Down Expand Up @@ -1182,42 +1192,48 @@ protected void updateMarkedCellValues() {
// update all cached formula cell values on client side, because they
// might have changed. also make sure all marked cells are updated
Iterator<Row> rows = sheet.rowIterator();
while (rows.hasNext()) {
final Row r = rows.next();
final Iterator<Cell> cells = r.cellIterator();
while (cells.hasNext()) {
final Cell cell = cells.next();
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();
final String key = SpreadsheetUtil.toKey(columnIndex + 1,
rowIndex + 1);
CellData cd = createCellDataForCell(cell);
// update formula cells
if (cell.getCellType() == CellType.FORMULA) {
if (cd != null) {
if (sentFormulaCells.contains(key)
|| markedCells.contains(key)) {
// iterate in reverse row/column order (bottom right to top left) to match CSS order for border calculations,
// to avoid issues like #651 where cell values are not updated in the proper sequence.
spreadsheet.getConditionalFormatter().evaluateBatch(formatter -> {
for (int ri = sheet.getLastRowNum(); ri >= 0; ri--) {
final Row r = sheet.getRow(ri);
if (r == null) continue;
for (int ci = r.getLastCellNum() - 1; ci >= 0; ci--) {
final Cell cell = r.getCell(ci);
if (cell == null) continue;
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();
final String key = SpreadsheetUtil.toKey(columnIndex + 1,
rowIndex + 1);
CellData cd = createCellDataForCell(cell, formatter);
// update formula cells
if (cell.getCellType() == CellType.FORMULA) {
if (cd != null) {
if (sentFormulaCells.contains(key)
|| markedCells.contains(key)) {
sentFormulaCells.add(key);
updatedCellData.add(cd);
}
} else if (sentFormulaCells.contains(key)) {
// in case the formula cell value has changed to null or
// empty; this case is probably quite rare, formula cell
// pointing to a cell that was removed or had its value
// cleared ???
sentFormulaCells.add(key);
cd = new CellData();
cd.col = columnIndex + 1;
cd.row = rowIndex + 1;
cd.cellStyle = "" + cell.getCellStyle().getIndex();
updatedCellData.add(cd);
}
} else if (sentFormulaCells.contains(key)) {
// in case the formula cell value has changed to null or
// empty; this case is probably quite rare, formula cell
// pointing to a cell that was removed or had its value
// cleared ???
sentFormulaCells.add(key);
cd = new CellData();
cd.col = columnIndex + 1;
cd.row = rowIndex + 1;
cd.cellStyle = "" + cell.getCellStyle().getIndex();
} else if (markedCells.contains(key)) {
sentCells.add(key);
updatedCellData.add(cd);
}
} else if (markedCells.contains(key)) {
sentCells.add(key);
updatedCellData.add(cd);
}
}
}
});

if (!changedFormulaCells.isEmpty()) {
fireFormulaValueChangeEvent(changedFormulaCells);
changedFormulaCells = new HashSet<CellReference>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

import org.apache.poi.ss.usermodel.BorderFormatting;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Color;
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
import org.apache.poi.ss.usermodel.DifferentialStyleProvider;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder.BorderSide;

/**
Expand Down Expand Up @@ -70,6 +72,17 @@ String getBorderColorCSS(BorderSide borderSide, String attribute,
String getBorderColorCSS(BorderSide borderSide, String attribute,
BorderFormatting format);

/**
* Returns CSS border definitions for the given attribute and color
*
* @param attr
* border CSS attribute
* @param colorInstance
* POI color
* @return CSS color string
*/
String getBorderColorCSS(String attr, Color colorInstance);

/**
* Writes the default background and foreground colors as CSS styles from
* the given cell style to the given string buffer.
Expand Down Expand Up @@ -101,6 +114,16 @@ String getBorderColorCSS(BorderSide borderSide, String attribute,
public String getBackgroundColorCSS(ConditionalFormattingRule rule);

/**
* Create a CSS color string for the background in the given style.
*
* @param styleProvider
* conditional format rule, table style, etc.
* @return valid color string with semicolon or <code>null</code> if no
* color matches.
*/
public String getBackgroundColorCSS(DifferentialStyleProvider styleProvider);

/**
* Create a CSS color string for the font in the given rule.
*
* @param rule
Expand All @@ -109,4 +132,14 @@ String getBorderColorCSS(BorderSide borderSide, String attribute,
* color matches.
*/
public String getFontColorCSS(ConditionalFormattingRule rule);

/**
* Create a CSS color string for the font in the given style provider.
*
* @param styleProvider
* conditional format rule, table style, etc.
* @return valid color string with semicolon or <code>null</code> if no
* color matches.
*/
public String getFontColorCSS(DifferentialStyleProvider styleProvider);
}
Loading