All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jxls.transform.poi.PoiCellData Maven / Gradle / Ivy

package org.jxls.transform.poi;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Map;

import org.apache.poi.ss.formula.FormulaParseException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.jxls.common.CellRef;
import org.jxls.common.Context;
import org.jxls.common.JxlsException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;

/**
 * Cell data wrapper for POI cell
 * 
 * @author Leonid Vysochyn
 */
public class PoiCellData extends org.jxls.common.CellData {
    private PoiRowData poiRowData;
    private RichTextString richTextString;
    private CellStyle cellStyle;
    private Hyperlink hyperlink;
    private Comment comment;
    private String commentAuthor;
    private Cell cell;

    public PoiCellData(CellRef cellRef) {
        super(cellRef);
    }

    public PoiCellData(CellRef cellRef, Cell cell) {
        super(cellRef);
        this.cell = cell;
    }

    public static PoiCellData createCellData(PoiRowData poiRowData, CellRef cellRef, Cell cell) {
        PoiCellData cellData = new PoiCellData(cellRef, cell);
        cellData.poiRowData = poiRowData;
        cellData.readCell(cell);
        cellData.updateFormulaValue();
        return cellData;
    }

    public void readCell(Cell cell) {
        readCellGeneralInfo(cell);
        readCellContents(cell);
        readCellStyle(cell);
    }

    private void readCellGeneralInfo(Cell cell) {
        hyperlink = cell.getHyperlink();
        try {
            comment = cell.getCellComment();
        } catch (Exception e) {
            throw new JxlsException("Failed to read cell comment at " + new CellReference(cell).formatAsString(), e);
        }
        if (comment != null) {
            commentAuthor = comment.getAuthor();
        }
        if (comment != null && comment.getString() != null && comment.getString().getString() != null) {
            String commentString = comment.getString().getString();
            String[] commentLines = commentString.split("\\n");
            for (String commentLine : commentLines) {
                if (isJxlsParamsComment(commentLine)) {
                    processJxlsParams(commentLine);
                    comment = null;
                    return;
                }
            }
            setCellComment(commentString);
        }
    }

    public CellStyle getCellStyle() {
        return cellStyle;
    }

    public void setCellStyle(CellStyle cellStyle) {
        this.cellStyle = cellStyle;
    }

    private void readCellContents(Cell cell) {
        switch (cell.getCellType()) {
            case STRING:
                richTextString = cell.getRichStringCellValue();
                cellValue = richTextString.getString();
                cellType = CellType.STRING;
                break;
            case BOOLEAN:
                cellValue = Boolean.valueOf(cell.getBooleanCellValue());
                cellType = CellType.BOOLEAN;
                break;
            case NUMERIC:
                readNumericCellContents(cell);
                break;
            case FORMULA:
                formula = cell.getCellFormula();
                cellValue = formula;
                cellType = CellType.FORMULA;
                break;
            case ERROR:
                cellValue = Byte.valueOf(cell.getErrorCellValue());
                cellType = CellType.ERROR;
                break;
            case BLANK:
            case _NONE:
                cellValue = null;
                cellType = CellType.BLANK;
                break;
        }
        evaluationResult = cellValue;
    }

    private void readNumericCellContents(Cell cell) {
        if (DateUtil.isCellDateFormatted(cell)) {
            cellValue = cell.getDateCellValue();
            cellType = CellType.DATE;
        } else {
            cellValue = Double.valueOf(cell.getNumericCellValue());
            cellType = CellType.NUMBER;
        }
    }

    private void readCellStyle(Cell cell) {
        cellStyle = cell.getCellStyle();
    }

    public void writeToCell(Cell cell, Context context, PoiTransformer transformer) {
        evaluate(context);
        if (evaluationResult instanceof WritableCellValue e) {
            cell.setCellStyle(cellStyle);
            e.writeToCell(cell, context);
        } else {
            updateCellGeneralInfo(cell);
            updateCellContents(cell);
            CellStyle targetCellStyle = cellStyle;
            if (context.isIgnoreSourceCellStyle()) {
                CellStyle dataFormatCellStyle = findCellStyle(evaluationResult, context.getCellStyleMap(), transformer);
                if (dataFormatCellStyle != null) {
                    targetCellStyle = dataFormatCellStyle;
                }
            }
            updateCellStyle(cell, targetCellStyle);
            poiRowData.getPoiSheetData().updateConditionalFormatting(this, cell);
        }
    }

    private CellStyle findCellStyle(Object evaluationResult, Map cellStyleMap, PoiTransformer transformer) {
        if (evaluationResult == null || cellStyleMap == null) {
            return null;
        }
        String cellName = cellStyleMap.get(evaluationResult.getClass().getSimpleName());
        if (cellName == null) {
            return null;
        }
        Sheet sheet = cell.getSheet();
        CellRef cellRef = new CellRef(cellName);
        if (cellRef.getSheetName() == null) {
            cellRef.setSheetName(sheet.getSheetName());
        }
        return transformer.getCellStyle(cellRef);
    }

    private void updateCellGeneralInfo(Cell cell) {
        if (hyperlink != null) {
            cell.setHyperlink(hyperlink);
        }
        if (comment != null && !PoiUtil.isJxComment(getCellComment())) {
            PoiUtil.setCellComment(cell, getCellComment(), commentAuthor, null);
        }
    }

    private void updateCellContents(Cell cell) {
        switch (targetCellType) {
            case STRING:
                updateStringCellContents(cell);
                break;
            case BOOLEAN:
                Boolean tf = (Boolean) evaluationResult;
                cell.setCellValue(tf.booleanValue());
                break;
            case DATE:
                cell.setCellValue((Date) evaluationResult);
                break;
            case LOCAL_DATE:
                cell.setCellValue((LocalDate) evaluationResult);
                break;
            case LOCAL_TIME:
                cell.setCellValue(((LocalTime) evaluationResult).atDate(LocalDate.now()));
                break;
            case LOCAL_DATETIME:
                cell.setCellValue((LocalDateTime) evaluationResult);
                break;
            case ZONED_DATETIME:
                cell.setCellValue(((ZonedDateTime) evaluationResult).toLocalDateTime());
                break;
            case INSTANT:
                cell.setCellValue(((Instant) evaluationResult).atZone(ZoneId.systemDefault()).toLocalDateTime());
                break;
            case NUMBER:
                cell.setCellValue(((Number) evaluationResult).doubleValue());
                break;
            case FORMULA:
                updateFormulaCellContents(cell);
                break;
            case ERROR:
                Byte b = (Byte) evaluationResult;
                cell.setCellErrorValue(b.byteValue());
                break;
            case BLANK:
                cell.setBlank();
                break;
        }
    }

    private void updateStringCellContents(Cell cell) {
        if (evaluationResult instanceof byte[]) {
            return;
        }
        String result = evaluationResult != null ? evaluationResult.toString() : "";
        if (cellValue != null && cellValue.equals(result)) {
            cell.setCellValue(richTextString);
        } else {
            cell.setCellValue(result);
        }
    }

    private void updateFormulaCellContents(Cell cell) {
        try {
            if (formulaContainsJointedCellRef((String) evaluationResult)) {
                cell.setCellValue((String) evaluationResult);
            } else {
                cell.setCellFormula((String) evaluationResult);
                clearCellValue(cell); // This call is especially important for streaming.
            }
        } catch (FormulaParseException e) {
            try {
                String formulaString = evaluationResult.toString();
                getTransformer().getLogger().warn(e, "Failed to set cell formula " + formulaString + " for cell " + this.toString());
                // Not required as setCellValue will set the cellType to STRING
                // cell.setCellType(org.apache.poi.ss.usermodel.CellType.STRING);
                cell.setCellValue(formulaString);
            } catch (Exception ex) {
                getTransformer().getLogger().error(ex, "Failed to convert formula to string for cell " + this.toString());
            }
        }
    }

    // protected so any user can change this piece of code
    protected void clearCellValue(org.apache.poi.ss.usermodel.Cell poiCell) {
        if (poiCell instanceof XSSFCell xcell) {
            CTCell cell = xcell.getCTCell(); // POI internal access, but there's no other way
            // Now do the XSSFCell.setFormula code that was done before POI commit https://github.com/apache/poi/commit/1253a29
            // After setting the formula in attribute f we clear the value attribute v if set. This causes a recalculation
            // and prevents wrong formula results.
            if (cell.isSetV()) {
                cell.unsetV();
            }
        }
    }

    private void updateCellStyle(Cell cell, CellStyle cellStyle) {
        cell.setCellStyle(cellStyle);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy