Skip to content

Commit 703b737

Browse files
committed
This closes #1861, fix missing parentheses in the adjusted formula
- Allow adjust cell reference with max rows/columns - Fix incorrect data validation escape result - Update out date reference link in the documentation - Update unit tests
1 parent 5975d87 commit 703b737

File tree

3 files changed

+44
-31
lines changed

3 files changed

+44
-31
lines changed

adjust.go

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,17 @@ func (f *File) adjustSingleRowFormulas(sheet, sheetN string, r *xlsxRow, num, of
239239
// adjustCellRef provides a function to adjust cell reference.
240240
func (f *File) adjustCellRef(cellRef string, dir adjustDirection, num, offset int) (string, error) {
241241
var SQRef []string
242+
applyOffset := func(coordinates []int, idx1, idx2, maxVal int) []int {
243+
if coordinates[idx1] >= num {
244+
coordinates[idx1] += offset
245+
}
246+
if coordinates[idx2] >= num {
247+
if coordinates[idx2] += offset; coordinates[idx2] > maxVal {
248+
coordinates[idx2] = maxVal
249+
}
250+
}
251+
return coordinates
252+
}
242253
for _, ref := range strings.Split(cellRef, " ") {
243254
if !strings.Contains(ref, ":") {
244255
ref += ":" + ref
@@ -251,22 +262,12 @@ func (f *File) adjustCellRef(cellRef string, dir adjustDirection, num, offset in
251262
if offset < 0 && coordinates[0] == coordinates[2] {
252263
continue
253264
}
254-
if coordinates[0] >= num {
255-
coordinates[0] += offset
256-
}
257-
if coordinates[2] >= num {
258-
coordinates[2] += offset
259-
}
265+
coordinates = applyOffset(coordinates, 0, 2, MaxColumns)
260266
} else {
261267
if offset < 0 && coordinates[1] == coordinates[3] {
262268
continue
263269
}
264-
if coordinates[1] >= num {
265-
coordinates[1] += offset
266-
}
267-
if coordinates[3] >= num {
268-
coordinates[3] += offset
269-
}
270+
coordinates = applyOffset(coordinates, 1, 3, TotalRows)
270271
}
271272
if ref, err = coordinatesToRangeRef(coordinates); err != nil {
272273
return "", err
@@ -446,12 +447,8 @@ func (f *File) adjustFormulaRef(sheet, sheetN, formula string, keepRelative bool
446447
val += operand
447448
continue
448449
}
449-
if isFunctionStartToken(token) {
450-
val += token.TValue + string(efp.ParenOpen)
451-
continue
452-
}
453-
if isFunctionStopToken(token) {
454-
val += token.TValue + string(efp.ParenClose)
450+
if paren := transformParenthesesToken(token); paren != "" {
451+
val += transformParenthesesToken(token)
455452
continue
456453
}
457454
if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText {
@@ -463,6 +460,18 @@ func (f *File) adjustFormulaRef(sheet, sheetN, formula string, keepRelative bool
463460
return val, nil
464461
}
465462

463+
// transformParenthesesToken returns formula part with parentheses by given
464+
// token.
465+
func transformParenthesesToken(token efp.Token) string {
466+
if isFunctionStartToken(token) || isBeginParenthesesToken(token) {
467+
return token.TValue + string(efp.ParenOpen)
468+
}
469+
if isFunctionStopToken(token) || isEndParenthesesToken(token) {
470+
return token.TValue + string(efp.ParenClose)
471+
}
472+
return ""
473+
}
474+
466475
// adjustRangeSheetName returns replaced range reference by given source and
467476
// target sheet name.
468477
func adjustRangeSheetName(rng, source, target string) string {
@@ -551,12 +560,8 @@ func transformArrayFormula(tokens []efp.Token, afs []arrayFormulaOperandToken) s
551560
if skip {
552561
continue
553562
}
554-
if isFunctionStartToken(token) {
555-
val += token.TValue + string(efp.ParenOpen)
556-
continue
557-
}
558-
if isFunctionStopToken(token) {
559-
val += token.TValue + string(efp.ParenClose)
563+
if paren := transformParenthesesToken(token); paren != "" {
564+
val += transformParenthesesToken(token)
560565
continue
561566
}
562567
if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText {
@@ -985,14 +990,14 @@ func (f *File) adjustDataValidations(ws *xlsxWorksheet, sheet string, dir adjust
985990
worksheet.DataValidations.DataValidation[i].Sqref = ref
986991
}
987992
if worksheet.DataValidations.DataValidation[i].Formula1 != nil {
988-
formula := unescapeDataValidationFormula(worksheet.DataValidations.DataValidation[i].Formula1.Content)
993+
formula := formulaUnescaper.Replace(worksheet.DataValidations.DataValidation[i].Formula1.Content)
989994
if formula, err = f.adjustFormulaRef(sheet, sheetN, formula, false, dir, num, offset); err != nil {
990995
return err
991996
}
992997
worksheet.DataValidations.DataValidation[i].Formula1 = &xlsxInnerXML{Content: formulaEscaper.Replace(formula)}
993998
}
994999
if worksheet.DataValidations.DataValidation[i].Formula2 != nil {
995-
formula := unescapeDataValidationFormula(worksheet.DataValidations.DataValidation[i].Formula2.Content)
1000+
formula := formulaUnescaper.Replace(worksheet.DataValidations.DataValidation[i].Formula2.Content)
9961001
if formula, err = f.adjustFormulaRef(sheet, sheetN, formula, false, dir, num, offset); err != nil {
9971002
return err
9981003
}

adjust_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,14 @@ func TestAdjustCols(t *testing.T) {
463463

464464
assert.NoError(t, f.InsertCols("Sheet1", "A", 2))
465465
assert.Nil(t, ws.(*xlsxWorksheet).Cols)
466+
467+
f = NewFile()
468+
assert.NoError(t, f.SetCellFormula("Sheet1", "A2", "(1-0.5)/2"))
469+
assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
470+
formula, err := f.GetCellFormula("Sheet1", "B2")
471+
assert.NoError(t, err)
472+
assert.Equal(t, "(1-0.5)/2", formula)
473+
assert.NoError(t, f.Close())
466474
}
467475

468476
func TestAdjustColDimensions(t *testing.T) {
@@ -1061,13 +1069,13 @@ func TestAdjustDataValidations(t *testing.T) {
10611069

10621070
// Test adjust data validation with multiple cell range
10631071
dv = NewDataValidation(true)
1064-
dv.Sqref = "G1:G3 H1:H3"
1072+
dv.Sqref = "G1:G3 H1:H3 A3:A1048576"
10651073
assert.NoError(t, dv.SetDropList([]string{"1", "2", "3"}))
10661074
assert.NoError(t, f.AddDataValidation("Sheet1", dv))
10671075
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
10681076
dvs, err = f.GetDataValidations("Sheet1")
10691077
assert.NoError(t, err)
1070-
assert.Equal(t, "G1:G4 H1:H4", dvs[3].Sqref)
1078+
assert.Equal(t, "G1:G4 H1:H4 A4:A1048576", dvs[3].Sqref)
10711079

10721080
dv = NewDataValidation(true)
10731081
dv.Sqref = "C5:D6"

excelize.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,14 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int {
453453
// UpdateLinkedValue fix linked values within a spreadsheet are not updating in
454454
// Office Excel application. This function will be remove value tag when met a
455455
// cell have a linked value. Reference
456-
// https://social.technet.microsoft.com/Forums/office/en-US/e16bae1f-6a2c-4325-8013-e989a3479066/excel-2010-linked-cells-not-updating
456+
// https://learn.microsoft.com/en-us/archive/msdn-technet-forums/e16bae1f-6a2c-4325-8013-e989a3479066
457457
//
458458
// Notice: after opening generated workbook, Excel will update the linked value
459459
// and generate a new value and will prompt to save the file or not.
460460
//
461461
// For example:
462462
//
463-
// <row r="19" spans="2:2">
463+
// <row r="19">
464464
// <c r="B19">
465465
// <f>SUM(Sheet2!D2,Sheet2!D11)</f>
466466
// <v>100</v>
@@ -469,7 +469,7 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int {
469469
//
470470
// to
471471
//
472-
// <row r="19" spans="2:2">
472+
// <row r="19">
473473
// <c r="B19">
474474
// <f>SUM(Sheet2!D2,Sheet2!D11)</f>
475475
// </c>

0 commit comments

Comments
 (0)