Repository navigation
Conversation
A template row that mixes {data.xxx} placeholders with a formula cell
lost the formula in every row created by a list fill: template analysis
only inspects string cells, and the fill only writes the placeholder
columns into the created rows.
The fill executor now records the formula cells of the collection
template rows and recreates them in each created row, translating the
formula with POI's FormulaShifter (row/column copy) so relative
references follow the new position and absolute ones stay anchored.
Styles follow the existing autoStyle behavior and unparsable formulas
are skipped instead of failing the fill.
Fixes apache#199
Generated-by: ZCode
Signed-off-by: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com>
The CI check job failed spotless:check on the test file and the fill executor. Re-ran spotless:apply; no logic changes. Generated-by: ZCode
skytin1004
left a comment
There was a problem hiding this comment.
@BigDataDZ Thanks for working on this. While testing it locally, I found that formulas can still be missed when there are multiple collection areas on the same sheet. I left an inline comment with the details. Could you take a look?
| } | ||
| } | ||
| } | ||
| collectFormulaTemplateCells(sheet); |
There was a problem hiding this comment.
The initial template scan populates the analysis cache for all collection keys, but this only collects formula cells for the current collection. A later collection can therefore hit the early return above before this method runs for that collection.
I reproduced this locally with two collection areas on the same sheet: formulas were copied for the first collection, but the formula next to the second collection was missing.
Could we make sure formula cells are collected for each collection even when its analysis data is already cached, and add a regression test covering multiple collection areas?
The full template scan fills the analysis cache for all collection keys at once, so every later collection hits the early return in readTemplateData and skipped formula collection: only the first filled collection kept its formulas. Collect the formula cells on the cached path too, guarded so the same collection never collects twice. Adds a regression test with two collection areas on one sheet: the collection filled second (its analysis data already cached) now carries its formulas into created rows as well. The test uses the writer-level fill API because ExcelWriterSheetBuilder.doFill finishes the writer on every call. Review: skytin1004 on apache#1215. Generated-by: ZCode
|
@skytin1004 Thanks for catching this — you were right on both points. Fixed in 906bc04:
Full fesod-sheet suite passes (1047 tests, 0 failures); spotless clean. |
There was a problem hiding this comment.
Thanks for the quick follow-up @BigDataDZ. I verified that 906bc04 fixes the cached-analysis case I originally reported, and the new multi-collection regression test correctly covers that failure.
While re-reviewing the full formula-copy path, I found two separate correctness issues that I missed in my first pass. Sorry for the extra round, but both can result in incorrect formulas or lost data, so I'm requesting changes once more. Please take a look at the inline comments.
| } | ||
| } | ||
| } | ||
| collectFormulaTemplateCells(sheet); |
There was a problem hiding this comment.
I reproduced a forceNewRow case where a formula references a row below the collection area. Formula cells are cached here before shiftRows() runs, so TemplateFormulaCell retains the pre-shift formula text even though POI updates the formula in the workbook.
For example, with B2 = A4*2, filling two items with forceNewRow(true) correctly updates the original B2 to A5*2, but the copied B3 is also A5*2 instead of the expected A6*2.
Could we invalidate or refresh the formula cache after structural row shifts and add a regression test for this case?
| vertical ? templateFormulaCell.getRowIndex() + relativeRowIndex : templateFormulaCell.getRowIndex(); | ||
| int targetColumnIndex = vertical | ||
| ? templateFormulaCell.getColumnIndex() | ||
| : templateFormulaCell.getColumnIndex() + relativeRowIndex; |
There was a problem hiding this comment.
I also reproduced a collision in horizontal fill. With {data.name} in A2, =A2*2 in B2, and three horizontally filled items, B2 ends up as a FORMULA cell rather than the second item's STRING cell. The value only survives as the formula's cached result and is lost when the workbook recalculates.
Formula discovery is currently row-based while horizontal collections expand by column. Could we make discovery and placement direction-aware and add a horizontal regression test that verifies both cell types/values and formulas after reopening the workbook?
Two correctness issues found in re-review of the formula-copy path: 1. Horizontal fill collision: collectFormulaTemplateCells scanned the full collection row, so formulas in data columns were collected and later overwrote filled data. Columns holding collection placeholders are now excluded from formula discovery. 2. forceNewRow formula staleness: shiftRows may update formula references in the live sheet (e.g. =A4*2 becomes =A5*2 when the referenced row shifts), but TemplateFormulaCell cached the pre-shift text before shiftRows ran. The cache is now refreshed after structural row shifts by adjusting row references in the cached formula text. Adds regression tests for both: horizontal fill preserves data cells; forceNewRow translates the post-shift formula into created rows. Review: skytin1004 on apache#1215 (second round). Generated-by: ZCode
|
@skytin1004 Both issues confirmed and fixed in 4902242:
Full fesod-sheet suite: 1049 tests, 0 failures. Spotless clean. Thanks for the thorough second pass — both were real bugs worth catching. |
Matcher.appendReplacement accepts only StringBuffer on JDK 8; the StringBuilder variant is JDK 9+. The project compiles on JDK 8 in CI. Generated-by: ZCode
Fixes #199
What changes were proposed in this pull request?
When a template row holds a formula cell next to
{data.xxx}placeholders, filling a list created one row per item but wrote only the placeholder columns - the formula silently disappeared from every created row, so formula columns next to the data went empty.The fill executor now records the formula cells that sit in the collection template rows and recreates each of them in every created row. References are translated with POI's
FormulaShifter(row copy for vertical fills, column copy for horizontal fills) the way a spreadsheet copies a row down: relative references follow the new position, absolute ones stay anchored. Cell style is carried over under the existingautoStylebehavior, and a formula that cannot be parsed or translated is skipped instead of failing the fill.How was this patch tested?
FillWithFormulaInCreatedRowsTest: a programmatic template mixing a relative formula (A2*2) and an absolute one ($A$2*10) with{data.name}; filling 3 items with and withoutforceNewRownow asserts the created rows carryA3*2/A4*2while$A$2*10stays anchored.mvn install -Dmaven.test.skip=false, JDK 25).Generated-by: ZCode
Signed-off-by: BigDataDZ 76271875+BigDataDZ@users.noreply.github.com