|
|
@@ -7,7 +7,7 @@
|
|
|
// 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.
|
|
|
+// library needs Go version 1.15 or later.
|
|
|
|
|
|
package excelize
|
|
|
|
|
|
@@ -17,6 +17,7 @@ import (
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"math"
|
|
|
+ "math/cmplx"
|
|
|
"math/rand"
|
|
|
"net/url"
|
|
|
"reflect"
|
|
|
@@ -292,6 +293,15 @@ var tokenPriority = map[string]int{
|
|
|
// HLOOKUP
|
|
|
// IF
|
|
|
// IFERROR
|
|
|
+// IMABS
|
|
|
+// IMCOS
|
|
|
+// IMCOSH
|
|
|
+// IMCOT
|
|
|
+// IMCSC
|
|
|
+// IMCSCH
|
|
|
+// IMEXP
|
|
|
+// IMLN
|
|
|
+// IMLOG10
|
|
|
// INT
|
|
|
// ISBLANK
|
|
|
// ISERR
|
|
|
@@ -1475,8 +1485,38 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
|
|
|
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
|
|
|
}
|
|
|
}
|
|
|
- r := strings.NewReplacer("(", "", ")", "", "0+", "", "+0i", "", "0+0i", "0", "i", suffix)
|
|
|
- return newStringFormulaArg(r.Replace(fmt.Sprint(complex(real.Number, i.Number))))
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(complex(real.Number, i.Number)), suffix))
|
|
|
+}
|
|
|
+
|
|
|
+// cmplx2str replace complex number string characters.
|
|
|
+func cmplx2str(c, suffix string) string {
|
|
|
+ if c == "(0+0i)" || c == "(0-0i)" {
|
|
|
+ return "0"
|
|
|
+ }
|
|
|
+ c = strings.TrimPrefix(c, "(")
|
|
|
+ c = strings.TrimPrefix(c, "+0+")
|
|
|
+ c = strings.TrimPrefix(c, "-0+")
|
|
|
+ c = strings.TrimSuffix(c, ")")
|
|
|
+ c = strings.TrimPrefix(c, "0+")
|
|
|
+ if strings.HasPrefix(c, "0-") {
|
|
|
+ c = "-" + strings.TrimPrefix(c, "0-")
|
|
|
+ }
|
|
|
+ c = strings.TrimPrefix(c, "0+")
|
|
|
+ c = strings.TrimSuffix(c, "+0i")
|
|
|
+ c = strings.TrimSuffix(c, "-0i")
|
|
|
+ c = strings.NewReplacer("+1i", "i", "-1i", "-i").Replace(c)
|
|
|
+ c = strings.Replace(c, "i", suffix, -1)
|
|
|
+ return c
|
|
|
+}
|
|
|
+
|
|
|
+// str2cmplx convert complex number string characters.
|
|
|
+func str2cmplx(c string) string {
|
|
|
+ c = strings.Replace(c, "j", "i", -1)
|
|
|
+ if c == "i" {
|
|
|
+ c = "1i"
|
|
|
+ }
|
|
|
+ c = strings.NewReplacer("+i", "+1i", "-i", "-1i").Replace(c)
|
|
|
+ return c
|
|
|
}
|
|
|
|
|
|
// DEC2BIN function converts a decimal number into a Binary (Base 2) number.
|
|
|
@@ -1651,6 +1691,166 @@ func (fn *formulaFuncs) hex2dec(number string) formulaArg {
|
|
|
return newNumberFormulaArg(decimal)
|
|
|
}
|
|
|
|
|
|
+// IMABS function returns the absolute value (the modulus) of a complex
|
|
|
+// number. The syntax of the function is:
|
|
|
+//
|
|
|
+// IMABS(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMABS requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ return newNumberFormulaArg(cmplx.Abs(inumber))
|
|
|
+}
|
|
|
+
|
|
|
+// IMCOS function returns the cosine of a supplied complex number. The syntax
|
|
|
+// of the function is:
|
|
|
+//
|
|
|
+// IMCOS(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMCOS requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cos(inumber)), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMCOSH function returns the hyperbolic cosine of a supplied complex number. The syntax
|
|
|
+// of the function is:
|
|
|
+//
|
|
|
+// IMCOSH(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMCOSH(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMCOSH requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cosh(inumber)), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMCOT function returns the cotangent of a supplied complex number. The syntax
|
|
|
+// of the function is:
|
|
|
+//
|
|
|
+// IMCOT(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMCOT(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMCOT requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cot(inumber)), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMCSC function returns the cosecant of a supplied complex number. The syntax
|
|
|
+// of the function is:
|
|
|
+//
|
|
|
+// IMCSC(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMCSC requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ num := 1 / cmplx.Sin(inumber)
|
|
|
+ if cmplx.IsInf(num) {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMCSCH function returns the hyperbolic cosecant of a supplied complex
|
|
|
+// number. The syntax of the function is:
|
|
|
+//
|
|
|
+// IMCSCH(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMCSCH requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ num := 1 / cmplx.Sinh(inumber)
|
|
|
+ if cmplx.IsInf(num) {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMEXP function returns the exponential of a supplied complex number. The
|
|
|
+// syntax of the function is:
|
|
|
+//
|
|
|
+// IMEXP(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMEXP(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMEXP requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Exp(inumber)), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMLN function returns the natural logarithm of a supplied complex number.
|
|
|
+// The syntax of the function is:
|
|
|
+//
|
|
|
+// IMLN(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMLN requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ num := cmplx.Log(inumber)
|
|
|
+ if cmplx.IsInf(num) {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
|
|
|
+}
|
|
|
+
|
|
|
+// IMLOG10 function returns the common (base 10) logarithm of a supplied
|
|
|
+// complex number. The syntax of the function is:
|
|
|
+//
|
|
|
+// IMLOG10(inumber)
|
|
|
+//
|
|
|
+func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
|
|
|
+ if argsList.Len() != 1 {
|
|
|
+ return newErrorFormulaArg(formulaErrorVALUE, "IMLOG10 requires 1 argument")
|
|
|
+ }
|
|
|
+ inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128)
|
|
|
+ if err != nil {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, err.Error())
|
|
|
+ }
|
|
|
+ num := cmplx.Log10(inumber)
|
|
|
+ if cmplx.IsInf(num) {
|
|
|
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
|
|
|
+ }
|
|
|
+ return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i"))
|
|
|
+}
|
|
|
+
|
|
|
// OCT2BIN function converts an Octal (Base 8) number into a Binary (Base 2)
|
|
|
// number. The syntax of the function is:
|
|
|
//
|