fix: the CSV round trip keeps values that start with an apostrophe before a formula character (WR-21)

escapeCell left '=x as it was and unescapeCell then dropped its
apostrophe on import. A value of apostrophes followed by a formula
character now gets one more apostrophe on export, and the import drops
exactly one, so unescapeCell is the inverse of escapeCell.
This commit is contained in:
2026-10-27 15:39:23 +01:00
parent 882d4ee05f
commit ed2d919aee
3 changed files with 18 additions and 7 deletions

View File

@@ -38,19 +38,27 @@ func formulaStart(s string) bool {
return false
}
// escapable reports whether s is a formula cell behind any number of
// apostrophes: the cells escapeCell prefixes.
func escapable(s string) bool {
return formulaStart(strings.TrimLeft(s, "'"))
}
// escapeCell prefixes a formula cell with an apostrophe (CSV formula
// injection, T-32-24).
// injection, T-32-24). A value that already starts with apostrophes before
// a formula character gets one more, so unescapeCell is its exact inverse
// and '=x survives a round trip (WR-21).
func escapeCell(s string) string {
if formulaStart(s) {
if escapable(s) {
return "'" + s
}
return s
}
// unescapeCell drops the apostrophe escapeCell added, so an exported file
// imports unchanged.
// unescapeCell drops the one apostrophe escapeCell added, so an exported
// file imports unchanged.
func unescapeCell(s string) string {
if strings.HasPrefix(s, "'") && formulaStart(s[1:]) {
if strings.HasPrefix(s, "'") && escapable(s[1:]) {
return s[1:]
}
return s