package org.openlca.io.xls.results; import java.awt.Color; import java.math.RoundingMode; import java.util.Collections; import java.util.Date; import java.util.HashMap; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.openlca.core.database.EntityCache; import org.openlca.core.model.DQIndicator; import org.openlca.core.model.DQSystem; import org.openlca.core.model.Location; import org.openlca.core.model.descriptors.FlowDescriptor; import org.openlca.core.model.descriptors.ImpactCategoryDescriptor; import org.openlca.core.model.descriptors.ProcessDescriptor; import org.openlca.io.CategoryPair; import org.openlca.io.DisplayValues; import org.openlca.io.xls.Excel; import com.google.common.base.Strings; /** * A helper class for writing values of results to Excel files. */ public class CellWriter { private final EntityCache cache; private final HashMap<Long, String> flowUnits = new HashMap<>(); private final CellStyles styles; public CellWriter(EntityCache cache, Workbook wb) { this.cache = cache; this.styles = new CellStyles(wb); } /** * Writes the process information into the given row, starting in column col */ public void processCol(Sheet sheet, int row, int col, ProcessDescriptor process) { cell(sheet, row++, col, process.getRefId(), false); cell(sheet, row++, col, process.getName(), false); if (process.getLocation() == null) return; Location loc = cache.get(Location.class, process.getLocation()); String code = loc == null ? "" : loc.getCode(); cell(sheet, row++, col, code, false); } /** * Writes the impact category information into the given row, starting in * column col */ public void impactRow(Sheet sheet, int row, int col, ImpactCategoryDescriptor impact) { cell(sheet, row, col++, impact.getRefId(), false); cell(sheet, row, col++, impact.getName(), false); cell(sheet, row, col++, impact.getReferenceUnit(), false); } /** * Writes the given flow information into the given row, starting in column * col */ public void flowRow(Sheet sheet, int row, int col, FlowDescriptor flow) { flow(sheet, row, col, flow, true); } /** * Writes the given flow information into the given col, starting in row row */ public void flowCol(Sheet sheet, int row, int col, FlowDescriptor flow) { flow(sheet, row, col, flow, false); } private void flow(Sheet sheet, int row, int col, FlowDescriptor flow, boolean isRow) { cell(sheet, isRow ? row : row++, !isRow ? col : col++, flow.getRefId(), false); cell(sheet, isRow ? row : row++, !isRow ? col : col++, flow.getName(), false); CategoryPair flowCat = CategoryPair.create(flow, cache); cell(sheet, isRow ? row : row++, !isRow ? col : col++, flowCat.getCategory(), false); cell(sheet, isRow ? row : row++, !isRow ? col : col++, flowCat.getSubCategory(), false); cell(sheet, isRow ? row : row++, !isRow ? col : col++, flowUnit(flow), false); } public int dataQuality(Sheet sheet, int row, int col, double[] quality, RoundingMode rounding, int scores) { return dataQuality(sheet, row, col, quality, rounding, scores, false); } /** * Writes the given data quality information into the given row, starting * with column col */ private int dataQuality(Sheet sheet, int row, int col, double[] quality, RoundingMode rounding, int scores, boolean bold) { if (scores == 0 || quality == null) return col; for (int i = 0; i < quality.length; i++) { double value = quality[i]; if (value == 0d) continue; int score = (int) (rounding == RoundingMode.CEILING ? Math.ceil(value) : Math.round(value)); Color color = DQColors.get(score, scores); cell(sheet, row, col + i, Integer.toString(score), color, bold); } return col + quality.length; } /** * Writes the data quality indicators of the given system into the given * row, starting with column col. */ public int dataQualityHeader(Sheet sheet, int row, int col, DQSystem system) { Collections.sort(system.indicators); for (DQIndicator indicator : system.indicators) { String name = Integer.toString(indicator.position); if (!Strings.isNullOrEmpty(indicator.name)) { name = indicator.name.substring(0, 1); } cell(sheet, row, col++, name, true); } return col; } public int headerRow(Sheet sheet, int row, int col, String... vals) { if (vals == null) return col; for (Object val : vals) { cell(sheet, row, col++, val, true); } return col; } public int headerCol(Sheet sheet, int row, int col, String... vals) { if (vals == null) return row; for (Object val : vals) { cell(sheet, row++, col, val, true); } return row; } public void cell(Sheet sheet, int row, int col, Object val) { cell(sheet, row, col, val, false); } public void cell(Sheet sheet, int row, int col, Object val, boolean bold) { if (bold) { cell(sheet, row, col, val, styles.bold()); } else { cell(sheet, row, col, val, (CellStyle) null); } } private void cell(Sheet sheet, int row, int col, Object val, Color color, boolean bold) { if (bold) { cell(sheet, row, col, val, styles.bold(color)); } else { cell(sheet, row, col, val, styles.normal(color)); } } void wrappedCell(Sheet sheet, int row, int col, Object val, Color color, boolean bold) { Cell cell = null; if (bold) { cell = cell(sheet, row, col, val, styles.bold(color)); } else { cell = cell(sheet, row, col, val, styles.normal(color)); } cell.getCellStyle().setWrapText(true); } private Cell cell(Sheet sheet, int row, int col, Object val, CellStyle style) { Cell cell = null; if (val instanceof Number) { cell = Excel.cell(sheet, row, col, ((Number) val).doubleValue()); } else if (val instanceof Date) { cell = Excel.cell(sheet, row, col); cell.setCellValue((Date) val); style = styles.date(); } else { cell = Excel.cell(sheet, row, col, val == null ? "" : val.toString()); } cell.setCellStyle(style); return cell; } private String flowUnit(FlowDescriptor flow) { String unit = flowUnits.get(flow.getId()); if (unit != null) return unit; unit = DisplayValues.referenceUnit(flow, cache); flowUnits.put(flow.getId(), unit == null ? "" : unit); return unit; } }