Skip to content

Commit f8f699a

Browse files
committed
Go 1.15 and later required, qax-os#65 fn: IMABS, IMCOS, IMCOSH, IMCOT, IMCSC, IMCSCH, IMEXP, IMLN and IMLOG10
1 parent 89c262f commit f8f699a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+328
-61
lines changed

.travis.yml

-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ install:
44
- go get -d -t -v ./... && go build -v ./...
55

66
go:
7-
- 1.11.x
8-
- 1.12.x
9-
- 1.13.x
10-
- 1.14.x
117
- 1.15.x
128
- 1.16.x
139

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
## Introduction
1515

16-
Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLSX / XLSM / XLTM files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.10 or later. The full API docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc) and [docs reference](https://xuri.me/excelize/).
16+
Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLSX / XLSM / XLTM files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.15 or later. The full API docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc) and [docs reference](https://xuri.me/excelize/).
1717

1818
## Basic Usage
1919

README_zh.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
## 简介
1515

16-
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.10 或更高版本,完整的 API 使用文档请访问 [go.dev](https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc) 或查看 [参考文档](https://xuri.me/excelize/)
16+
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本,完整的 API 使用文档请访问 [go.dev](https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc) 或查看 [参考文档](https://xuri.me/excelize/)
1717

1818
## 快速上手
1919

adjust.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
88
// complex components by high compatibility, and provided streaming API for
99
// generating or reading data from a worksheet with huge amounts of data. This
10-
// library needs Go version 1.10 or later.
10+
// library needs Go version 1.15 or later.
1111

1212
package excelize
1313

calc.go

+203-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
88
// complex components by high compatibility, and provided streaming API for
99
// generating or reading data from a worksheet with huge amounts of data. This
10-
// library needs Go version 1.10 or later.
10+
// library needs Go version 1.15 or later.
1111

1212
package excelize
1313

@@ -17,6 +17,7 @@ import (
1717
"errors"
1818
"fmt"
1919
"math"
20+
"math/cmplx"
2021
"math/rand"
2122
"net/url"
2223
"reflect"
@@ -292,6 +293,15 @@ var tokenPriority = map[string]int{
292293
// HLOOKUP
293294
// IF
294295
// IFERROR
296+
// IMABS
297+
// IMCOS
298+
// IMCOSH
299+
// IMCOT
300+
// IMCSC
301+
// IMCSCH
302+
// IMEXP
303+
// IMLN
304+
// IMLOG10
295305
// INT
296306
// ISBLANK
297307
// ISERR
@@ -1475,8 +1485,38 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
14751485
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
14761486
}
14771487
}
1478-
r := strings.NewReplacer("(", "", ")", "", "0+", "", "+0i", "", "0+0i", "0", "i", suffix)
1479-
return newStringFormulaArg(r.Replace(fmt.Sprint(complex(real.Number, i.Number))))
1488+
return newStringFormulaArg(cmplx2str(fmt.Sprint(complex(real.Number, i.Number)), suffix))
1489+
}
1490+
1491+
// cmplx2str replace complex number string characters.
1492+
func cmplx2str(c, suffix string) string {
1493+
if c == "(0+0i)" || c == "(0-0i)" {
1494+
return "0"
1495+
}
1496+
c = strings.TrimPrefix(c, "(")
1497+
c = strings.TrimPrefix(c, "+0+")
1498+
c = strings.TrimPrefix(c, "-0+")
1499+
c = strings.TrimSuffix(c, ")")
1500+
c = strings.TrimPrefix(c, "0+")
1501+
if strings.HasPrefix(c, "0-") {
1502+
c = "-" + strings.TrimPrefix(c, "0-")
1503+
}
1504+
c = strings.TrimPrefix(c, "0+")
1505+
c = strings.TrimSuffix(c, "+0i")
1506+
c = strings.TrimSuffix(c, "-0i")
1507+
c = strings.NewReplacer("+1i", "i", "-1i", "-i").Replace(c)
1508+
c = strings.Replace(c, "i", suffix, -1)
1509+
return c
1510+
}
1511+
1512+
// str2cmplx convert complex number string characters.
1513+
func str2cmplx(c string) string {
1514+
c = strings.Replace(c, "j", "i", -1)
1515+
if c == "i" {
1516+
c = "1i"
1517+
}
1518+
c = strings.NewReplacer("+i", "+1i", "-i", "-1i").Replace(c)
1519+
return c
14801520
}
14811521

14821522
// DEC2BIN function converts a decimal number into a Binary (Base 2) number.
@@ -1651,6 +1691,166 @@ func (fn *formulaFuncs) hex2dec(number string) formulaArg {
16511691
return newNumberFormulaArg(decimal)
16521692
}
16531693

1694+
// IMABS function returns the absolute value (the modulus) of a complex
1695+
// number. The syntax of the function is:
1696+
//
1697+
// IMABS(inumber)
1698+
//
1699+
func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg {
1700+
if argsList.Len() != 1 {
1701+
return newErrorFormulaArg(formulaErrorVALUE, "IMABS requires 1 argument")
1702+
}
1703+
inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128)
1704+
if err != nil {
1705+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1706+
}
1707+
return newNumberFormulaArg(cmplx.Abs(inumber))
1708+
}
1709+
1710+
// IMCOS function returns the cosine of a supplied complex number. The syntax
1711+
// of the function is:
1712+
//
1713+
// IMCOS(inumber)
1714+
//
1715+
func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg {
1716+
if argsList.Len() != 1 {
1717+
return newErrorFormulaArg(formulaErrorVALUE, "IMCOS requires 1 argument")
1718+
}
1719+
inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128)
1720+
if err != nil {
1721+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1722+
}
1723+
return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cos(inumber)), "i"))
1724+
}
1725+
1726+
// IMCOSH function returns the hyperbolic cosine of a supplied complex number. The syntax
1727+
// of the function is:
1728+
//
1729+
// IMCOSH(inumber)
1730+
//
1731+
func (fn *formulaFuncs) IMCOSH(argsList *list.List) formulaArg {
1732+
if argsList.Len() != 1 {
1733+
return newErrorFormulaArg(formulaErrorVALUE, "IMCOSH requires 1 argument")
1734+
}
1735+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1736+
if err != nil {
1737+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1738+
}
1739+
return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cosh(inumber)), "i"))
1740+
}
1741+
1742+
// IMCOT function returns the cotangent of a supplied complex number. The syntax
1743+
// of the function is:
1744+
//
1745+
// IMCOT(inumber)
1746+
//
1747+
func (fn *formulaFuncs) IMCOT(argsList *list.List) formulaArg {
1748+
if argsList.Len() != 1 {
1749+
return newErrorFormulaArg(formulaErrorVALUE, "IMCOT requires 1 argument")
1750+
}
1751+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1752+
if err != nil {
1753+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1754+
}
1755+
return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cot(inumber)), "i"))
1756+
}
1757+
1758+
// IMCSC function returns the cosecant of a supplied complex number. The syntax
1759+
// of the function is:
1760+
//
1761+
// IMCSC(inumber)
1762+
//
1763+
func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg {
1764+
if argsList.Len() != 1 {
1765+
return newErrorFormulaArg(formulaErrorVALUE, "IMCSC requires 1 argument")
1766+
}
1767+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1768+
if err != nil {
1769+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1770+
}
1771+
num := 1 / cmplx.Sin(inumber)
1772+
if cmplx.IsInf(num) {
1773+
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
1774+
}
1775+
return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
1776+
}
1777+
1778+
// IMCSCH function returns the hyperbolic cosecant of a supplied complex
1779+
// number. The syntax of the function is:
1780+
//
1781+
// IMCSCH(inumber)
1782+
//
1783+
func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
1784+
if argsList.Len() != 1 {
1785+
return newErrorFormulaArg(formulaErrorVALUE, "IMCSCH requires 1 argument")
1786+
}
1787+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1788+
if err != nil {
1789+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1790+
}
1791+
num := 1 / cmplx.Sinh(inumber)
1792+
if cmplx.IsInf(num) {
1793+
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
1794+
}
1795+
return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
1796+
}
1797+
1798+
// IMEXP function returns the exponential of a supplied complex number. The
1799+
// syntax of the function is:
1800+
//
1801+
// IMEXP(inumber)
1802+
//
1803+
func (fn *formulaFuncs) IMEXP(argsList *list.List) formulaArg {
1804+
if argsList.Len() != 1 {
1805+
return newErrorFormulaArg(formulaErrorVALUE, "IMEXP requires 1 argument")
1806+
}
1807+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1808+
if err != nil {
1809+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1810+
}
1811+
return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Exp(inumber)), "i"))
1812+
}
1813+
1814+
// IMLN function returns the natural logarithm of a supplied complex number.
1815+
// The syntax of the function is:
1816+
//
1817+
// IMLN(inumber)
1818+
//
1819+
func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg {
1820+
if argsList.Len() != 1 {
1821+
return newErrorFormulaArg(formulaErrorVALUE, "IMLN requires 1 argument")
1822+
}
1823+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1824+
if err != nil {
1825+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1826+
}
1827+
num := cmplx.Log(inumber)
1828+
if cmplx.IsInf(num) {
1829+
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
1830+
}
1831+
return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
1832+
}
1833+
1834+
// IMLOG10 function returns the common (base 10) logarithm of a supplied
1835+
// complex number. The syntax of the function is:
1836+
//
1837+
// IMLOG10(inumber)
1838+
//
1839+
func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
1840+
if argsList.Len() != 1 {
1841+
return newErrorFormulaArg(formulaErrorVALUE, "IMLOG10 requires 1 argument")
1842+
}
1843+
inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
1844+
if err != nil {
1845+
return newErrorFormulaArg(formulaErrorNUM, err.Error())
1846+
}
1847+
num := cmplx.Log10(inumber)
1848+
if cmplx.IsInf(num) {
1849+
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
1850+
}
1851+
return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
1852+
}
1853+
16541854
// OCT2BIN function converts an Octal (Base 8) number into a Binary (Base 2)
16551855
// number. The syntax of the function is:
16561856
//

calc_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ func TestCalcCellValue(t *testing.T) {
9090
"=COMPLEX(10,-5,\"i\")": "10-5i",
9191
"=COMPLEX(0,5)": "5i",
9292
"=COMPLEX(3,0)": "3",
93+
"=COMPLEX(0,-2)": "-2i",
94+
"=COMPLEX(0,0)": "0",
95+
"=COMPLEX(0,-1,\"j\")": "-j",
9396
// DEC2BIN
9497
"=DEC2BIN(2)": "10",
9598
"=DEC2BIN(3)": "11",
@@ -127,6 +130,43 @@ func TestCalcCellValue(t *testing.T) {
127130
"=HEX2OCT(\"8\",10)": "0000000010",
128131
"=HEX2OCT(\"FFFFFFFFF8\")": "7777777770",
129132
"=HEX2OCT(\"1F3\")": "763",
133+
// IMABS
134+
"=IMABS(\"2j\")": "2",
135+
"=IMABS(\"-1+2i\")": "2.23606797749979",
136+
"=IMABS(COMPLEX(-1,2,\"j\"))": "2.23606797749979",
137+
// IMCOS
138+
"=IMCOS(0)": "1",
139+
"=IMCOS(0.5)": "0.877582561890373",
140+
"=IMCOS(\"3+0.5i\")": "-1.1163412445261518-0.0735369737112366i",
141+
// IMCOSH
142+
"=IMCOSH(0.5)": "1.127625965206381",
143+
"=IMCOSH(\"3+0.5i\")": "8.835204606500994+4.802825082743033i",
144+
"=IMCOSH(\"2-i\")": "2.0327230070196656-3.0518977991518i",
145+
"=IMCOSH(COMPLEX(1,-1))": "0.8337300251311491-0.9888977057628651i",
146+
// IMCOT
147+
"=IMCOT(0.5)": "1.830487721712452",
148+
"=IMCOT(\"3+0.5i\")": "-0.4793455787473728-2.016092521506228i",
149+
"=IMCOT(\"2-i\")": "-0.171383612909185+0.8213297974938518i",
150+
"=IMCOT(COMPLEX(1,-1))": "0.21762156185440268+0.868014142895925i",
151+
// IMCSC
152+
"=IMCSC(\"j\")": "-0.8509181282393216i",
153+
// IMCSCH
154+
"=IMCSCH(COMPLEX(1,-1))": "0.30393100162842646+0.6215180171704284i",
155+
// IMEXP
156+
"=IMEXP(0)": "1",
157+
"=IMEXP(0.5)": "1.648721270700128",
158+
"=IMEXP(\"1-2i\")": "-1.1312043837568135-2.4717266720048183i",
159+
"=IMEXP(COMPLEX(1,-1))": "1.4686939399158851-2.2873552871788423i",
160+
// IMLN
161+
"=IMLN(0.5)": "-0.693147180559945",
162+
"=IMLN(\"3+0.5i\")": "1.1123117757621668+0.16514867741462683i",
163+
"=IMLN(\"2-i\")": "0.8047189562170503-0.4636476090008061i",
164+
"=IMLN(COMPLEX(1,-1))": "0.3465735902799727-0.7853981633974483i",
165+
// IMLOG10
166+
"=IMLOG10(0.5)": "-0.301029995663981",
167+
"=IMLOG10(\"3+0.5i\")": "0.48307086636951624+0.07172315929479262i",
168+
"=IMLOG10(\"2-i\")": "0.34948500216800943-0.20135959813668655i",
169+
"=IMLOG10(COMPLEX(1,-1))": "0.1505149978319906-0.3410940884604603i",
130170
// OCT2BIN
131171
"=OCT2BIN(\"5\")": "101",
132172
"=OCT2BIN(\"0000000001\")": "1",
@@ -1135,6 +1175,37 @@ func TestCalcCellValue(t *testing.T) {
11351175
"=HEX2OCT(1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
11361176
"=HEX2OCT(-513,10)": "strconv.ParseInt: parsing \"-\": invalid syntax",
11371177
"=HEX2OCT(1,-1)": "#NUM!",
1178+
// IMABS
1179+
"=IMABS()": "IMABS requires 1 argument",
1180+
"=IMABS(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1181+
// IMCOS
1182+
"=IMCOS()": "IMCOS requires 1 argument",
1183+
"=IMCOS(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1184+
// IMCOSH
1185+
"=IMCOSH()": "IMCOSH requires 1 argument",
1186+
"=IMCOSH(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1187+
// IMCOT
1188+
"=IMCOT()": "IMCOT requires 1 argument",
1189+
"=IMCOT(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1190+
// IMCSC
1191+
"=IMCSC()": "IMCSC requires 1 argument",
1192+
"=IMCSC(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1193+
"=IMCSC(0)": "#NUM!",
1194+
// IMCSCH
1195+
"=IMCSCH()": "IMCSCH requires 1 argument",
1196+
"=IMCSCH(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1197+
"=IMCSCH(0)": "#NUM!",
1198+
// IMEXP
1199+
"=IMEXP()": "IMEXP requires 1 argument",
1200+
"=IMEXP(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1201+
// IMLN
1202+
"=IMLN()": "IMLN requires 1 argument",
1203+
"=IMLN(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1204+
"=IMLN(0)": "#NUM!",
1205+
// IMLOG10
1206+
"=IMLOG10()": "IMLOG10 requires 1 argument",
1207+
"=IMLOG10(\"\")": "strconv.ParseComplex: parsing \"\": invalid syntax",
1208+
"=IMLOG10(0)": "#NUM!",
11381209
// OCT2BIN
11391210
"=OCT2BIN()": "OCT2BIN requires at least 1 argument",
11401211
"=OCT2BIN(1,1,1)": "OCT2BIN allows at most 2 arguments",

calcchain.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
88
// complex components by high compatibility, and provided streaming API for
99
// generating or reading data from a worksheet with huge amounts of data. This
10-
// library needs Go version 1.10 or later.
10+
// library needs Go version 1.15 or later.
1111

1212
package excelize
1313

cell.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
88
// complex components by high compatibility, and provided streaming API for
99
// generating or reading data from a worksheet with huge amounts of data. This
10-
// library needs Go version 1.10 or later.
10+
// library needs Go version 1.15 or later.
1111

1212
package excelize
1313

chart.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
88
// complex components by high compatibility, and provided streaming API for
99
// generating or reading data from a worksheet with huge amounts of data. This
10-
// library needs Go version 1.10 or later.
10+
// library needs Go version 1.15 or later.
1111

1212
package excelize
1313

0 commit comments

Comments
 (0)