Skip to content

[Bug] A cell read into a ReadCellData field loses its row and column index #1131

Description

@CodeMan-cmd

Search before asking

  • I searched in the issues and found nothing similar.

Fesod version

2.1.0-incubating (main branch, commit 4e3f3aa)

JDK version

Temurin 1.8.0_472

Operating system

Windows 10 (amd64)

Steps To Reproduce

Read a file into a model with a ReadCellData field, or read with readDefaultReturn(ReadDefaultReturnEnum.READ_CELL_DATA).

Model:

public class CellDataReadData {
    @DateTimeFormat("yyyy年MM月dd日")
    private ReadCellData<String> date;

    private ReadCellData<Integer> integer1;
    private Integer integer2;
    private ReadCellData<?> formulaValue;
}

Code:

FesodSheet.write(file, CellDataWriteData.class).sheet().doWrite(data);

CollectingReadListener<CellDataReadData> listener = new CollectingReadListener<>();
FesodSheet.read(file, CellDataReadData.class, listener).sheet().doRead();
CellDataReadData row = listener.getFirstRow();

row.getDate().getRowIndex();     // null, the cell is A2, so row 1
row.getDate().getColumnIndex();  // null, the cell is A2, so column 0

Reproduced on xlsx, xls and csv, so it does not depend on the file format.

Current Behavior

Every ReadCellData that reaches a listener has getRowIndex() == null and getColumnIndex() == null, for a model field and for READ_CELL_DATA alike. WriteCellData on the write side does carry them.

Parsers do set the coordinates on the cell data: CellTagHandler (lines 150-151) for xlsx, FormulaRecordHandler and BoolErrRecordHandler for xls, CsvExcelReadExecutor (lines 237-239) for csv.

They are lost in ConverterUtils.convertToJavaObject: when the target type is CellData or ReadCellData it calls cellData.clone() (line 161) and ReadCellData.clone() copies the value, the number, the boolean, the data format and the formula, but not rowIndex/columnIndex. The method even receives rowIndex and columnIndex as arguments (lines 151-152) at the moment it drops them.

Measured before the fix, xlsx / xls / csv:

date(row=null,col=null) integer1(row=null,col=null) formula(row=null,col=null)

So a listener cannot tell which cell a value came from, which is the main reason to read a cell as ReadCellData instead of as a plain value.

Expected Behavior

A cloned cell describes the same cell, so it keeps the coordinates:

date(row=1,col=0) integer1(row=1,col=1) formula(row=1,col=3)

After the change the values above are read back on xlsx, xls and csv.

Anything else?

The fix copies rowIndex and columnIndex in ReadCellData.clone().

Tests: a round trip assertion in CellDataDataTest (3 formats) and a unit test ReadCellDataTest.cloneKeepsCoordinates. Without the fix 4 of the 5 new assertions fail, with it all of them pass.

PR follows.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions