Skip to content

Commit

Permalink
This fix #1665, supports getting formula string cell value
Browse files Browse the repository at this point in the history
- Improve compatibility for absolute path drawing part
- Fix incorrect table ID generated in the workbook which contains single table cells
- Fix missing relationship parts in the content types in some cases
- Upgrade number format parser to fix missing literal tokens in some cases
- Update built-in zh-cn and zh-tw language number format
- Ref #65, init new formula function: TEXT
- Remove duplicate style-related variables
- Update the unit tests
  • Loading branch information
xuri committed Sep 20, 2023
1 parent 744236b commit 9c079e5
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 163 deletions.
23 changes: 23 additions & 0 deletions calc.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@ type formulaFuncs struct {
// TBILLPRICE
// TBILLYIELD
// TDIST
// TEXT
// TEXTJOIN
// TIME
// TIMEVALUE
Expand Down Expand Up @@ -14035,6 +14036,28 @@ func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg {
return newStringFormulaArg(pre + targetText.Value() + post)
}

// TEXT function converts a supplied numeric value into text, in a
// user-specified format. The syntax of the function is:
//
// TEXT(value,format_text)
func (fn *formulaFuncs) TEXT(argsList *list.List) formulaArg {
if argsList.Len() != 2 {
return newErrorFormulaArg(formulaErrorVALUE, "TEXT requires 2 arguments")
}
value, fmtText := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
if value.Type == ArgError {
return value
}
if fmtText.Type == ArgError {
return fmtText
}
cellType := CellTypeNumber
if num := value.ToNumber(); num.Type != ArgNumber {
cellType = CellTypeSharedString
}
return newStringFormulaArg(format(value.Value(), fmtText.Value(), false, cellType, nil))
}

// TEXTJOIN function joins together a series of supplied text strings into one
// combined text string. The user can specify a delimiter to add between the
// individual text items, if required. The syntax of the function is:
Expand Down
13 changes: 13 additions & 0 deletions calc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,15 @@ func TestCalcCellValue(t *testing.T) {
"=SUBSTITUTE(\"abab\",\"x\",\"X\",2)": "abab",
"=SUBSTITUTE(\"John is 5 years old\",\"John\",\"Jack\")": "Jack is 5 years old",
"=SUBSTITUTE(\"John is 5 years old\",\"5\",\"6\")": "John is 6 years old",
// TEXT
"=TEXT(\"07/07/2015\",\"mm/dd/yyyy\")": "07/07/2015",
"=TEXT(42192,\"mm/dd/yyyy\")": "07/07/2015",
"=TEXT(42192,\"mmm dd yyyy\")": "Jul 07 2015",
"=TEXT(0.75,\"hh:mm\")": "18:00",
"=TEXT(36.363636,\"0.00\")": "36.36",
"=TEXT(567.9,\"$#,##0.00\")": "$567.90",
"=TEXT(-5,\"+ $#,##0.00;- $#,##0.00;$0.00\")": "- $5.00",
"=TEXT(5,\"+ $#,##0.00;- $#,##0.00;$0.00\")": "+ $5.00",
// TEXTJOIN
"=TEXTJOIN(\"-\",TRUE,1,2,3,4)": "1-2-3-4",
"=TEXTJOIN(A4,TRUE,A1:B2)": "1040205",
Expand Down Expand Up @@ -3866,6 +3875,10 @@ func TestCalcCellValue(t *testing.T) {
"=SUBSTITUTE()": {"#VALUE!", "SUBSTITUTE requires 3 or 4 arguments"},
"=SUBSTITUTE(\"\",\"\",\"\",\"\")": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
"=SUBSTITUTE(\"\",\"\",\"\",0)": {"#VALUE!", "instance_num should be > 0"},
// TEXT
"=TEXT()": {"#VALUE!", "TEXT requires 2 arguments"},
"=TEXT(NA(),\"\")": {"#N/A", "#N/A"},
"=TEXT(0,NA())": {"#N/A", "#N/A"},
// TEXTJOIN
"=TEXTJOIN()": {"#VALUE!", "TEXTJOIN requires at least 3 arguments"},
"=TEXTJOIN(\"\",\"\",1)": {"#VALUE!", "#VALUE!"},
Expand Down
2 changes: 2 additions & 0 deletions cell.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,8 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
}
}
return f.formattedValue(c, raw, CellTypeSharedString)
case "str":
return c.V, nil
case "inlineStr":
if c.IS != nil {
return f.formattedValue(&xlsxC{S: c.S, V: c.IS.String()}, raw, CellTypeInlineString)
Expand Down
13 changes: 8 additions & 5 deletions drawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ import (
func (f *File) prepareDrawing(ws *xlsxWorksheet, drawingID int, sheet, drawingXML string) (int, string) {
sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
if ws.Drawing != nil {
// The worksheet already has a picture or chart relationships, use the relationships drawing ../drawings/drawing%d.xml.
sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID)
// The worksheet already has a picture or chart relationships, use the
// relationships drawing ../drawings/drawing%d.xml or /xl/drawings/drawing%d.xml.
sheetRelationshipsDrawingXML = strings.ReplaceAll(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "/xl/drawings/", "../drawings/")
drawingID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingXML, "../drawings/drawing"), ".xml"))
drawingXML = strings.ReplaceAll(sheetRelationshipsDrawingXML, "..", "xl")
} else {
Expand Down Expand Up @@ -1247,9 +1248,11 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int, error) {
)
_, ok = f.Drawings.Load(path)
if !ok {
content := xlsxWsDr{}
content.A = NameSpaceDrawingML.Value
content.Xdr = NameSpaceDrawingMLSpreadSheet.Value
content := xlsxWsDr{
NS: NameSpaceDrawingMLSpreadSheet.Value,
Xdr: NameSpaceDrawingMLSpreadSheet.Value,
A: NameSpaceDrawingML.Value,
}
if _, ok = f.Pkg.Load(path); ok { // Append Model
decodeWsDr := decodeWsDr{}
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(path)))).
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ require (
github.com/richardlehane/msoleps v1.0.3 // indirect
github.com/stretchr/testify v1.8.0
github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca
github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a
golang.org/x/crypto v0.12.0
github.com/xuri/nfp v0.0.0-20230918160701-e5a3f5b24785
golang.org/x/crypto v0.13.0
golang.org/x/image v0.11.0
golang.org/x/net v0.14.0
golang.org/x/text v0.12.0
golang.org/x/net v0.15.0
golang.org/x/text v0.13.0
)
19 changes: 10 additions & 9 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca h1:uvPMDVyP7PXMMioYdyPH+0O+Ta/UO1WFfNYMO3Wz0eg=
github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a h1:Mw2VNrNNNjDtw68VsEj2+st+oCSn4Uz7vZw6TbhcV1o=
github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xuri/nfp v0.0.0-20230918160701-e5a3f5b24785 h1:FG9hcK7lhf3w/Y2NRUKy/mopsH0Oy6P1rib1KWXAie0=
github.com/xuri/nfp v0.0.0-20230918160701-e5a3f5b24785/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
Expand All @@ -33,8 +33,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -45,19 +45,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
Expand Down
20 changes: 10 additions & 10 deletions numfmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,16 @@ var (
31: "yyyy\"\"m\"\"d\"\"",
32: "hh\"\"mm\"\"",
33: "hh\"\"mm\"\"ss\"\"",
34: "上午/下午 hh\"\"mm\"\"",
35: "上午/下午 hh\"\"mm\"\"ss\"\"",
34: "上午/下午hh\"\"mm\"\"",
35: "上午/下午hh\"\"mm\"\"ss\"\"",
36: "[$-404]e/m/d",
50: "[$-404]e/m/d",
51: "[$-404]e\"\"m\"\"d\"\"",
52: "上午/下午 hh\"\"mm\"\"",
53: "上午/下午 hh\"\"mm\"\"ss\"\"",
52: "上午/下午hh\"\"mm\"\"",
53: "上午/下午hh\"\"mm\"\"ss\"\"",
54: "[$-404]e\"\"m\"\"d\"\"",
55: "上午/下午 hh\"\"mm\"\"",
56: "上午/下午 hh\"\"mm\"\"ss\"\"",
55: "上午/下午hh\"\"mm\"\"",
56: "上午/下午hh\"\"mm\"\"ss\"\"",
57: "[$-404]e/m/d",
58: "[$-404]e\"\"m\"\"d\"\"",
},
Expand All @@ -129,16 +129,16 @@ var (
31: "yyyy\"\"m\"\"d\"\"",
32: "h\"\"mm\"\"",
33: "h\"\"mm\"\"ss\"\"",
34: "上午/下午 h\"\"mm\"\"",
35: "上午/下午 h\"\"mm\"\"ss\"\"",
34: "上午/下午h\"\"mm\"\"",
35: "上午/下午h\"\"mm\"\"ss\"\"",
36: "yyyy\"\"m\"\"",
50: "yyyy\"\"m\"\"",
51: "m\"\"d\"\"",
52: "yyyy\"\"m\"\"",
53: "m\"\"d\"\"",
54: "m\"\"d\"\"",
55: "上午/下午 h\"\"mm\"\"",
56: "上午/下午 h\"\"mm\"\"ss\"\"",
55: "上午/下午h\"\"mm\"\"",
56: "上午/下午h\"\"mm\"\"ss\"\"",
57: "yyyy\"\"m\"\"",
58: "m\"\"d\"\"",
},
Expand Down
1 change: 1 addition & 0 deletions numfmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func TestNumFmt(t *testing.T) {
{"43528", "[$-111]MM/DD/YYYY", "43528"},
{"43528", "[$US-409]MM/DD/YYYY", "US03/04/2019"},
{"43543.586539351854", "AM/PM h h:mm", "PM 14 2:04"},
{"45186", "DD.MM.YYYY", "17.09.2023"},
{"text", "AM/PM h h:mm", "text"},
{"43466.189571759256", "[$-404]aaa;@", "週二"},
{"43466.189571759256", "[$-404]aaaa;@", "星期二"},
Expand Down
2 changes: 1 addition & 1 deletion slicer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import (
// Caption specifies the caption of the slicer, this setting is optional.
//
// Macro used for set macro for the slicer, the workbook extension should be
// XLSM or XLTM
// XLSM or XLTM.
//
// Width specifies the width of the slicer, this setting is optional.
//
Expand Down
Loading

0 comments on commit 9c079e5

Please sign in to comment.