已验证 提交 688808b2 编写于 作者: xurime's avatar xurime

This closes #1819, formula calculation engine support array formulas

- Improve the defined name and table name validation rules
- Rename internal variable names to avoid the same with Go 1.21's built-in min and max functions
- Simplify data type conversion in internal code
- Update GitHub Actions workflow configuration, test on Go 1.22.x, and disable Go module cache
- Update dependencies module
上级 02b84a90
......@@ -5,7 +5,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.18.x, 1.19.x, 1.20.x, '>=1.21.1']
go-version: [1.18.x, 1.19.x, 1.20.x, '>=1.21.1', 1.22.x]
os: [ubuntu-latest, macos-latest, windows-latest]
targetplatform: [x86, x64]
......@@ -17,6 +17,7 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: false
- name: Checkout code
uses: actions/checkout@v4
......
......@@ -281,6 +281,10 @@ func (fa formulaArg) Value() (value string) {
return fmt.Sprintf("%g", fa.Number)
case ArgString:
return fa.String
case ArgMatrix:
if args := fa.ToList(); len(args) > 0 {
return args[0].Value()
}
case ArgError:
return fa.Error
}
......@@ -299,6 +303,10 @@ func (fa formulaArg) ToNumber() formulaArg {
}
case ArgNumber:
n = fa.Number
case ArgMatrix:
if args := fa.ToList(); len(args) > 0 {
return args[0].ToNumber()
}
}
return newNumberFormulaArg(n)
}
......@@ -920,9 +928,14 @@ func newEmptyFormulaArg() formulaArg {
//
// TODO: handle subtypes: Nothing, Text, Logical, Error, Concatenation, Intersection, Union
func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.Token) (formulaArg, error) {
var err error
opdStack, optStack, opfStack, opfdStack, opftStack, argsStack := NewStack(), NewStack(), NewStack(), NewStack(), NewStack(), NewStack()
var inArray, inArrayRow bool
var (
err error
inArray, inArrayRow bool
formulaArray [][]formulaArg
formulaArrayRow []formulaArg
opdStack, optStack, opfStack = NewStack(), NewStack(), NewStack()
opfdStack, opftStack, argsStack = NewStack(), NewStack(), NewStack()
)
for i := 0; i < len(tokens); i++ {
token := tokens[i]
......@@ -936,11 +949,11 @@ func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.T
// function start
if isFunctionStartToken(token) {
if token.TValue == "ARRAY" {
inArray = true
inArray, formulaArray = true, [][]formulaArg{}
continue
}
if token.TValue == "ARRAYROW" {
inArrayRow = true
inArrayRow, formulaArrayRow = true, []formulaArg{}
continue
}
opfStack.Push(token)
......@@ -1021,14 +1034,16 @@ func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.T
}
if inArrayRow && isOperand(token) {
formulaArrayRow = append(formulaArrayRow, opfdStack.Pop().(formulaArg))
continue
}
if inArrayRow && isFunctionStopToken(token) {
formulaArray = append(formulaArray, formulaArrayRow)
inArrayRow = false
continue
}
if inArray && isFunctionStopToken(token) {
argsStack.Peek().(*list.List).PushBack(opfdStack.Pop())
argsStack.Peek().(*list.List).PushBack(newMatrixFormulaArg(formulaArray))
inArray = false
continue
}
......@@ -1825,13 +1840,13 @@ func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) formulaArg {
if n.Type != ArgNumber {
return n
}
max, x1 := 100, x.Number*0.5
maxVal, x1 := 100, x.Number*0.5
x2 := x1 * x1
x1 = math.Pow(x1, n.Number)
n1, n2, n3, n4, add := fact(n.Number), 1.0, 0.0, n.Number, false
result := x1 / n1
t := result * 0.9
for result != t && max != 0 {
for result != t && maxVal != 0 {
x1 *= x2
n3++
n1 *= n3
......@@ -1844,7 +1859,7 @@ func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) formulaArg {
} else {
result -= r
}
max--
maxVal--
add = !add
}
return newNumberFormulaArg(result)
......@@ -2151,8 +2166,8 @@ func (fn *formulaFuncs) bitwise(name string, argsList *list.List) formulaArg {
if num1.Type != ArgNumber || num2.Type != ArgNumber {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
max := math.Pow(2, 48) - 1
if num1.Number < 0 || num1.Number > max || num2.Number < 0 || num2.Number > max {
maxVal := math.Pow(2, 48) - 1
if num1.Number < 0 || num1.Number > maxVal || num2.Number < 0 || num2.Number > maxVal {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
bitwiseFuncMap := map[string]func(a, b int) int{
......@@ -6958,9 +6973,9 @@ func (fn *formulaFuncs) BETAdotINV(argsList *list.List) formulaArg {
// incompleteGamma is an implementation of the incomplete gamma function.
func incompleteGamma(a, x float64) float64 {
max := 32
maxVal := 32
summer := 0.0
for n := 0; n <= max; n++ {
for n := 0; n <= maxVal; n++ {
divisor := a
for i := 1; i <= n; i++ {
divisor *= a + float64(i)
......@@ -7079,7 +7094,7 @@ func (fn *formulaFuncs) BINOMdotDISTdotRANGE(argsList *list.List) formulaArg {
// binominv implement inverse of the binomial distribution calculation.
func binominv(n, p, alpha float64) float64 {
q, i, sum, max := 1-p, 0.0, 0.0, 0.0
q, i, sum, maxVal := 1-p, 0.0, 0.0, 0.0
n = math.Floor(n)
if q > p {
factor := math.Pow(q, n)
......@@ -7091,8 +7106,8 @@ func binominv(n, p, alpha float64) float64 {
return i
}
factor := math.Pow(p, n)
sum, max = 1-factor, n
for i = 0; i < max && sum >= alpha; i++ {
sum, maxVal = 1-factor, n
for i = 0; i < maxVal && sum >= alpha; i++ {
factor *= (n - i) / (i + 1) * q / p
sum -= factor
}
......@@ -8078,10 +8093,13 @@ func (fn *formulaFuncs) FORECASTdotLINEAR(argsList *list.List) formulaArg {
return fn.pearsonProduct("FORECAST.LINEAR", 3, argsList)
}
// maritxToSortedColumnList convert matrix formula arguments to a ascending
// matrixToSortedColumnList convert matrix formula arguments to a ascending
// order list by column.
func maritxToSortedColumnList(arg formulaArg) formulaArg {
mtx, cols := []formulaArg{}, len(arg.Matrix[0])
func matrixToSortedColumnList(arg formulaArg) formulaArg {
var (
mtx []formulaArg
cols = len(arg.Matrix[0])
)
for colIdx := 0; colIdx < cols; colIdx++ {
for _, row := range arg.Matrix {
cell := row[colIdx]
......@@ -8120,14 +8138,14 @@ func (fn *formulaFuncs) FREQUENCY(argsList *list.List) formulaArg {
c [][]formulaArg
i, j int
)
if dataMtx = maritxToSortedColumnList(data); dataMtx.Type != ArgList {
if dataMtx = matrixToSortedColumnList(data); dataMtx.Type != ArgList {
return dataMtx
}
if binsMtx = maritxToSortedColumnList(bins); binsMtx.Type != ArgList {
if binsMtx = matrixToSortedColumnList(bins); binsMtx.Type != ArgList {
return binsMtx
}
for row := 0; row < len(binsMtx.List)+1; row++ {
rows := []formulaArg{}
var rows []formulaArg
for col := 0; col < 1; col++ {
rows = append(rows, newNumberFormulaArg(0))
}
......@@ -8349,8 +8367,8 @@ func (fn *formulaFuncs) GEOMEAN(argsList *list.List) formulaArg {
return product
}
count := fn.COUNT(argsList)
min := fn.MIN(argsList)
if product.Number > 0 && min.Number > 0 {
minVal := fn.MIN(argsList)
if product.Number > 0 && minVal.Number > 0 {
return newNumberFormulaArg(math.Pow(product.Number, 1/count.Number))
}
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
......@@ -9055,7 +9073,7 @@ func (fn *formulaFuncs) HARMEAN(argsList *list.List) formulaArg {
if argsList.Len() < 1 {
return newErrorFormulaArg(formulaErrorVALUE, "HARMEAN requires at least 1 argument")
}
if min := fn.MIN(argsList); min.Number < 0 {
if minVal := fn.MIN(argsList); minVal.Number < 0 {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
number, val, cnt := 0.0, 0.0, 0.0
......@@ -10002,7 +10020,7 @@ func (fn *formulaFuncs) MAX(argsList *list.List) formulaArg {
if argsList.Len() == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "MAX requires at least 1 argument")
}
return fn.max(false, argsList)
return fn.maxValue(false, argsList)
}
// MAXA function returns the largest value from a supplied set of numeric
......@@ -10015,7 +10033,7 @@ func (fn *formulaFuncs) MAXA(argsList *list.List) formulaArg {
if argsList.Len() == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "MAXA requires at least 1 argument")
}
return fn.max(true, argsList)
return fn.maxValue(true, argsList)
}
// MAXIFS function returns the maximum value from a subset of values that are
......@@ -10031,36 +10049,36 @@ func (fn *formulaFuncs) MAXIFS(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
var args []formulaArg
max, maxRange := -math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
maxVal, maxRange := -math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
args = append(args, arg.Value.(formulaArg))
}
for _, ref := range formulaIfsMatch(args) {
if num := maxRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber && max < num.Number {
max = num.Number
if num := maxRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber && maxVal < num.Number {
maxVal = num.Number
}
}
if max == -math.MaxFloat64 {
max = 0
if maxVal == -math.MaxFloat64 {
maxVal = 0
}
return newNumberFormulaArg(max)
return newNumberFormulaArg(maxVal)
}
// calcListMatrixMax is part of the implementation max.
func calcListMatrixMax(maxa bool, max float64, arg formulaArg) float64 {
func calcListMatrixMax(maxa bool, maxVal float64, arg formulaArg) float64 {
for _, cell := range arg.ToList() {
if cell.Type == ArgNumber && cell.Number > max {
if cell.Type == ArgNumber && cell.Number > maxVal {
if maxa && cell.Boolean || !cell.Boolean {
max = cell.Number
maxVal = cell.Number
}
}
}
return max
return maxVal
}
// max is an implementation of the formula functions MAX and MAXA.
func (fn *formulaFuncs) max(maxa bool, argsList *list.List) formulaArg {
max := -math.MaxFloat64
// maxValue is an implementation of the formula functions MAX and MAXA.
func (fn *formulaFuncs) maxValue(maxa bool, argsList *list.List) formulaArg {
maxVal := -math.MaxFloat64
for token := argsList.Front(); token != nil; token = token.Next() {
arg := token.Value.(formulaArg)
switch arg.Type {
......@@ -10069,29 +10087,29 @@ func (fn *formulaFuncs) max(maxa bool, argsList *list.List) formulaArg {
continue
} else {
num := arg.ToBool()
if num.Type == ArgNumber && num.Number > max {
max = num.Number
if num.Type == ArgNumber && num.Number > maxVal {
maxVal = num.Number
continue
}
}
num := arg.ToNumber()
if num.Type != ArgError && num.Number > max {
max = num.Number
if num.Type != ArgError && num.Number > maxVal {
maxVal = num.Number
}
case ArgNumber:
if arg.Number > max {
max = arg.Number
if arg.Number > maxVal {
maxVal = arg.Number
}
case ArgList, ArgMatrix:
max = calcListMatrixMax(maxa, max, arg)
maxVal = calcListMatrixMax(maxa, maxVal, arg)
case ArgError:
return arg
}
}
if max == -math.MaxFloat64 {
max = 0
if maxVal == -math.MaxFloat64 {
maxVal = 0
}
return newNumberFormulaArg(max)
return newNumberFormulaArg(maxVal)
}
// MEDIAN function returns the statistical median (the middle value) of a list
......@@ -10145,7 +10163,7 @@ func (fn *formulaFuncs) MIN(argsList *list.List) formulaArg {
if argsList.Len() == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "MIN requires at least 1 argument")
}
return fn.min(false, argsList)
return fn.minValue(false, argsList)
}
// MINA function returns the smallest value from a supplied set of numeric
......@@ -10158,7 +10176,7 @@ func (fn *formulaFuncs) MINA(argsList *list.List) formulaArg {
if argsList.Len() == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "MINA requires at least 1 argument")
}
return fn.min(true, argsList)
return fn.minValue(true, argsList)
}
// MINIFS function returns the minimum value from a subset of values that are
......@@ -10174,36 +10192,36 @@ func (fn *formulaFuncs) MINIFS(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
}
var args []formulaArg
min, minRange := math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
minVal, minRange := math.MaxFloat64, argsList.Front().Value.(formulaArg).Matrix
for arg := argsList.Front().Next(); arg != nil; arg = arg.Next() {
args = append(args, arg.Value.(formulaArg))
}
for _, ref := range formulaIfsMatch(args) {
if num := minRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber && min > num.Number {
min = num.Number
if num := minRange[ref.Row][ref.Col].ToNumber(); num.Type == ArgNumber && minVal > num.Number {
minVal = num.Number
}
}
if min == math.MaxFloat64 {
min = 0
if minVal == math.MaxFloat64 {
minVal = 0
}
return newNumberFormulaArg(min)
return newNumberFormulaArg(minVal)
}
// calcListMatrixMin is part of the implementation min.
func calcListMatrixMin(mina bool, min float64, arg formulaArg) float64 {
func calcListMatrixMin(mina bool, minVal float64, arg formulaArg) float64 {
for _, cell := range arg.ToList() {
if cell.Type == ArgNumber && cell.Number < min {
if cell.Type == ArgNumber && cell.Number < minVal {
if mina && cell.Boolean || !cell.Boolean {
min = cell.Number
minVal = cell.Number
}
}
}
return min
return minVal
}
// min is an implementation of the formula functions MIN and MINA.
func (fn *formulaFuncs) min(mina bool, argsList *list.List) formulaArg {
min := math.MaxFloat64
// minValue is an implementation of the formula functions MIN and MINA.
func (fn *formulaFuncs) minValue(mina bool, argsList *list.List) formulaArg {
minVal := math.MaxFloat64
for token := argsList.Front(); token != nil; token = token.Next() {
arg := token.Value.(formulaArg)
switch arg.Type {
......@@ -10212,29 +10230,29 @@ func (fn *formulaFuncs) min(mina bool, argsList *list.List) formulaArg {
continue
} else {
num := arg.ToBool()
if num.Type == ArgNumber && num.Number < min {
min = num.Number
if num.Type == ArgNumber && num.Number < minVal {
minVal = num.Number
continue
}
}
num := arg.ToNumber()
if num.Type != ArgError && num.Number < min {
min = num.Number
if num.Type != ArgError && num.Number < minVal {
minVal = num.Number
}
case ArgNumber:
if arg.Number < min {
min = arg.Number
if arg.Number < minVal {
minVal = arg.Number
}
case ArgList, ArgMatrix:
min = calcListMatrixMin(mina, min, arg)
minVal = calcListMatrixMin(mina, minVal, arg)
case ArgError:
return arg
}
}
if min == math.MaxFloat64 {
min = 0
if minVal == math.MaxFloat64 {
minVal = 0
}
return newNumberFormulaArg(min)
return newNumberFormulaArg(minVal)
}
// pearsonProduct is an implementation of the formula functions FORECAST,
......@@ -13554,7 +13572,7 @@ func (fn *formulaFuncs) code(name string, argsList *list.List) formulaArg {
//
// CONCAT(text1,[text2],...)
func (fn *formulaFuncs) CONCAT(argsList *list.List) formulaArg {
return fn.concat("CONCAT", argsList)
return fn.concat(argsList)
}
// CONCATENATE function joins together a series of supplied text strings into
......@@ -13562,12 +13580,12 @@ func (fn *formulaFuncs) CONCAT(argsList *list.List) formulaArg {
//
// CONCATENATE(text1,[text2],...)
func (fn *formulaFuncs) CONCATENATE(argsList *list.List) formulaArg {
return fn.concat("CONCATENATE", argsList)
return fn.concat(argsList)
}
// concat is an implementation of the formula functions CONCAT and
// CONCATENATE.
func (fn *formulaFuncs) concat(name string, argsList *list.List) formulaArg {
func (fn *formulaFuncs) concat(argsList *list.List) formulaArg {
var buf bytes.Buffer
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
for _, cell := range arg.Value.(formulaArg).ToList() {
......@@ -13831,16 +13849,16 @@ func (fn *formulaFuncs) LENB(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "LENB requires 1 string argument")
}
bytes := 0
result := 0
for _, r := range argsList.Front().Value.(formulaArg).Value() {
b := utf8.RuneLen(r)
if b == 1 {
bytes++
result++
} else if b > 1 {
bytes += 2
result += 2
}
}
return newNumberFormulaArg(float64(bytes))
return newNumberFormulaArg(float64(result))
}
// LOWER converts all characters in a supplied text string to lower case. The
......@@ -14774,7 +14792,7 @@ func (fn *formulaFuncs) COLUMN(argsList *list.List) formulaArg {
// calcColsRowsMinMax calculation min and max value for given formula arguments
// sequence of the formula functions COLUMNS and ROWS.
func calcColsRowsMinMax(cols bool, argsList *list.List) (min, max int) {
func calcColsRowsMinMax(cols bool, argsList *list.List) (minVal, maxVal int) {
getVal := func(cols bool, cell cellRef) int {
if cols {
return cell.Col
......@@ -14784,22 +14802,22 @@ func calcColsRowsMinMax(cols bool, argsList *list.List) (min, max int) {
if argsList.Front().Value.(formulaArg).cellRanges != nil && argsList.Front().Value.(formulaArg).cellRanges.Len() > 0 {
crs := argsList.Front().Value.(formulaArg).cellRanges
for cr := crs.Front(); cr != nil; cr = cr.Next() {
if min == 0 {
min = getVal(cols, cr.Value.(cellRange).From)
if minVal == 0 {
minVal = getVal(cols, cr.Value.(cellRange).From)
}
if max < getVal(cols, cr.Value.(cellRange).To) {
max = getVal(cols, cr.Value.(cellRange).To)
if maxVal < getVal(cols, cr.Value.(cellRange).To) {
maxVal = getVal(cols, cr.Value.(cellRange).To)
}
}
}
if argsList.Front().Value.(formulaArg).cellRefs != nil && argsList.Front().Value.(formulaArg).cellRefs.Len() > 0 {
cr := argsList.Front().Value.(formulaArg).cellRefs
for refs := cr.Front(); refs != nil; refs = refs.Next() {
if min == 0 {
min = getVal(cols, refs.Value.(cellRef))
if minVal == 0 {
minVal = getVal(cols, refs.Value.(cellRef))
}
if max < getVal(cols, refs.Value.(cellRef)) {
max = getVal(cols, refs.Value.(cellRef))
if maxVal < getVal(cols, refs.Value.(cellRef)) {
maxVal = getVal(cols, refs.Value.(cellRef))
}
}
}
......@@ -14814,13 +14832,13 @@ func (fn *formulaFuncs) COLUMNS(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "COLUMNS requires 1 argument")
}
min, max := calcColsRowsMinMax(true, argsList)
if max == MaxColumns {
minVal, maxVal := calcColsRowsMinMax(true, argsList)
if maxVal == MaxColumns {
return newNumberFormulaArg(float64(MaxColumns))
}
result := max - min + 1
if max == min {
if min == 0 {
result := maxVal - minVal + 1
if maxVal == minVal {
if minVal == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "invalid reference")
}
return newNumberFormulaArg(float64(1))
......@@ -15555,13 +15573,13 @@ func (fn *formulaFuncs) ROWS(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "ROWS requires 1 argument")
}
min, max := calcColsRowsMinMax(false, argsList)
if max == TotalRows {
minVal, maxVal := calcColsRowsMinMax(false, argsList)
if maxVal == TotalRows {
return newNumberFormulaArg(TotalRows)
}
result := max - min + 1
if max == min {
if min == 0 {
result := maxVal - minVal + 1
if maxVal == minVal {
if minVal == 0 {
return newErrorFormulaArg(formulaErrorVALUE, "invalid reference")
}
return newNumberFormulaArg(float64(1))
......
......@@ -354,20 +354,20 @@ func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
}
// parseColRange parse and convert column range with column name to the column number.
func (f *File) parseColRange(columns string) (min, max int, err error) {
func (f *File) parseColRange(columns string) (minVal, maxVal int, err error) {
colsTab := strings.Split(columns, ":")
min, err = ColumnNameToNumber(colsTab[0])
minVal, err = ColumnNameToNumber(colsTab[0])
if err != nil {
return
}
max = min
maxVal = minVal
if len(colsTab) == 2 {
if max, err = ColumnNameToNumber(colsTab[1]); err != nil {
if maxVal, err = ColumnNameToNumber(colsTab[1]); err != nil {
return
}
}
if max < min {
min, max = max, min
if maxVal < minVal {
minVal, maxVal = maxVal, minVal
}
return
}
......
......@@ -68,22 +68,22 @@ func TestTimeFromExcelTime(t *testing.T) {
})
}
for hour := 0; hour < 24; hour++ {
for min := 0; min < 60; min++ {
for minVal := 0; minVal < 60; minVal++ {
for sec := 0; sec < 60; sec++ {
date := time.Date(2021, time.December, 30, hour, min, sec, 0, time.UTC)
date := time.Date(2021, time.December, 30, hour, minVal, sec, 0, time.UTC)
// Test use 1900 date system
excel1900Time, err := timeToExcelTime(date, false)
assert.NoError(t, err)
date1900Out := timeFromExcelTime(excel1900Time, false)
assert.EqualValues(t, hour, date1900Out.Hour())
assert.EqualValues(t, min, date1900Out.Minute())
assert.EqualValues(t, minVal, date1900Out.Minute())
assert.EqualValues(t, sec, date1900Out.Second())
// Test use 1904 date system
excel1904Time, err := timeToExcelTime(date, true)
assert.NoError(t, err)
date1904Out := timeFromExcelTime(excel1904Time, true)
assert.EqualValues(t, hour, date1904Out.Hour())
assert.EqualValues(t, min, date1904Out.Minute())
assert.EqualValues(t, minVal, date1904Out.Minute())
assert.EqualValues(t, sec, date1904Out.Second())
}
}
......
......@@ -980,21 +980,21 @@ func (f *File) drawChartSeriesDLbls(i int, opts *Chart) *cDLbls {
// drawPlotAreaCatAx provides a function to draw the c:catAx element.
func (f *File) drawPlotAreaCatAx(opts *Chart) []*cAxs {
max := &attrValFloat{Val: opts.XAxis.Maximum}
min := &attrValFloat{Val: opts.XAxis.Minimum}
maxVal := &attrValFloat{Val: opts.XAxis.Maximum}
minVal := &attrValFloat{Val: opts.XAxis.Minimum}
if opts.XAxis.Maximum == nil {
max = nil
maxVal = nil
}
if opts.XAxis.Minimum == nil {
min = nil
minVal = nil
}
axs := []*cAxs{
{
AxID: &attrValInt{Val: intPtr(100000000)},
Scaling: &cScaling{
Orientation: &attrValString{Val: stringPtr(orientation[opts.XAxis.ReverseOrder])},
Max: max,
Min: min,
Max: maxVal,
Min: minVal,
},
Delete: &attrValBool{Val: boolPtr(opts.XAxis.None)},
AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])},
......@@ -1030,8 +1030,8 @@ func (f *File) drawPlotAreaCatAx(opts *Chart) []*cAxs {
AxID: &attrValInt{Val: intPtr(opts.XAxis.axID)},
Scaling: &cScaling{
Orientation: &attrValString{Val: stringPtr(orientation[opts.XAxis.ReverseOrder])},
Max: max,
Min: min,
Max: maxVal,
Min: minVal,
},
Delete: &attrValBool{Val: boolPtr(true)},
AxPos: &attrValString{Val: stringPtr("b")},
......@@ -1052,13 +1052,13 @@ func (f *File) drawPlotAreaCatAx(opts *Chart) []*cAxs {
// drawPlotAreaValAx provides a function to draw the c:valAx element.
func (f *File) drawPlotAreaValAx(opts *Chart) []*cAxs {
max := &attrValFloat{Val: opts.YAxis.Maximum}
min := &attrValFloat{Val: opts.YAxis.Minimum}
maxVal := &attrValFloat{Val: opts.YAxis.Maximum}
minVal := &attrValFloat{Val: opts.YAxis.Minimum}
if opts.YAxis.Maximum == nil {
max = nil
maxVal = nil
}
if opts.YAxis.Minimum == nil {
min = nil
minVal = nil
}
var logBase *attrValFloat
if opts.YAxis.LogBase >= 2 && opts.YAxis.LogBase <= 1000 {
......@@ -1070,8 +1070,8 @@ func (f *File) drawPlotAreaValAx(opts *Chart) []*cAxs {
Scaling: &cScaling{
LogBase: logBase,
Orientation: &attrValString{Val: stringPtr(orientation[opts.YAxis.ReverseOrder])},
Max: max,
Min: min,
Max: maxVal,
Min: minVal,
},
Delete: &attrValBool{Val: boolPtr(opts.YAxis.None)},
AxPos: &attrValString{Val: stringPtr(valAxPos[opts.YAxis.ReverseOrder])},
......@@ -1109,8 +1109,8 @@ func (f *File) drawPlotAreaValAx(opts *Chart) []*cAxs {
AxID: &attrValInt{Val: intPtr(opts.YAxis.axID)},
Scaling: &cScaling{
Orientation: &attrValString{Val: stringPtr(orientation[opts.YAxis.ReverseOrder])},
Max: max,
Min: min,
Max: maxVal,
Min: minVal,
},
Delete: &attrValBool{Val: boolPtr(false)},
AxPos: &attrValString{Val: stringPtr("r")},
......@@ -1129,21 +1129,21 @@ func (f *File) drawPlotAreaValAx(opts *Chart) []*cAxs {
// drawPlotAreaSerAx provides a function to draw the c:serAx element.
func (f *File) drawPlotAreaSerAx(opts *Chart) []*cAxs {
max := &attrValFloat{Val: opts.YAxis.Maximum}
min := &attrValFloat{Val: opts.YAxis.Minimum}
maxVal := &attrValFloat{Val: opts.YAxis.Maximum}
minVal := &attrValFloat{Val: opts.YAxis.Minimum}
if opts.YAxis.Maximum == nil {
max = nil
maxVal = nil
}
if opts.YAxis.Minimum == nil {
min = nil
minVal = nil
}
return []*cAxs{
{
AxID: &attrValInt{Val: intPtr(100000005)},
Scaling: &cScaling{
Orientation: &attrValString{Val: stringPtr(orientation[opts.YAxis.ReverseOrder])},
Max: max,
Min: min,
Max: maxVal,
Min: minVal,
},
Delete: &attrValBool{Val: boolPtr(opts.YAxis.None)},
AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])},
......
......@@ -334,9 +334,9 @@ func (ws *xlsxWorksheet) checkSheet() {
// with r="0" attribute.
func (ws *xlsxWorksheet) checkSheetRows() (int, []xlsxRow) {
var (
row, max int
r0 []xlsxRow
maxRowNum = func(num int, c []xlsxC) int {
row, maxVal int
r0 []xlsxRow
maxRowNum = func(num int, c []xlsxC) int {
for _, cell := range c {
if _, n, err := CellNameToCoordinates(cell.R); err == nil && n > num {
num = n
......@@ -351,8 +351,8 @@ func (ws *xlsxWorksheet) checkSheetRows() (int, []xlsxRow) {
continue
}
if i == 0 && *r.R == 0 {
if num := maxRowNum(row, r.C); num > max {
max = num
if num := maxRowNum(row, r.C); num > maxVal {
maxVal = num
}
r0 = append(r0, r)
continue
......@@ -361,8 +361,8 @@ func (ws *xlsxWorksheet) checkSheetRows() (int, []xlsxRow) {
row = *r.R
}
}
if max > row {
row = max
if maxVal > row {
row = maxVal
}
return row, r0
}
......
......@@ -8,9 +8,9 @@ require (
github.com/stretchr/testify v1.8.4
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05
golang.org/x/crypto v0.18.0
golang.org/x/crypto v0.19.0
golang.org/x/image v0.14.0
golang.org/x/net v0.20.0
golang.org/x/net v0.21.0
golang.org/x/text v0.14.0
)
......
......@@ -65,21 +65,21 @@ func RGBToHSL(r, g, b uint8) (h, s, l float64) {
fR := float64(r) / 255
fG := float64(g) / 255
fB := float64(b) / 255
max := math.Max(math.Max(fR, fG), fB)
min := math.Min(math.Min(fR, fG), fB)
l = (max + min) / 2
if max == min {
maxVal := math.Max(math.Max(fR, fG), fB)
minVal := math.Min(math.Min(fR, fG), fB)
l = (maxVal + minVal) / 2
if maxVal == minVal {
// Achromatic.
h, s = 0, 0
} else {
// Chromatic.
d := max - min
d := maxVal - minVal
if l > 0.5 {
s = d / (2.0 - max - min)
s = d / (2.0 - maxVal - minVal)
} else {
s = d / (max + min)
s = d / (maxVal + minVal)
}
switch max {
switch maxVal {
case fR:
h = (fG - fB) / d
if fG < fB {
......
此差异已折叠。
......@@ -63,7 +63,7 @@ func (f *File) GetRows(sheet string, opts ...Options) ([][]string, error) {
return nil, err
}
rows, _ := f.Rows(sheet)
results, cur, max := make([][]string, 0, 64), 0, 0
results, cur, maxVal := make([][]string, 0, 64), 0, 0
for rows.Next() {
cur++
row, err := rows.Columns(opts...)
......@@ -72,10 +72,10 @@ func (f *File) GetRows(sheet string, opts ...Options) ([][]string, error) {
}
results = append(results, row)
if len(row) > 0 {
max = cur
maxVal = cur
}
}
return results[:max], rows.Close()
return results[:maxVal], rows.Close()
}
// Rows defines an iterator to a sheet.
......
......@@ -439,24 +439,24 @@ func (sw *StreamWriter) SetRow(cell string, values []interface{}, opts ...RowOpt
// the width column B:C as 20:
//
// err := sw.SetColWidth(2, 3, 20)
func (sw *StreamWriter) SetColWidth(min, max int, width float64) error {
func (sw *StreamWriter) SetColWidth(minVal, maxVal int, width float64) error {
if sw.sheetWritten {
return ErrStreamSetColWidth
}
if min < MinColumns || min > MaxColumns || max < MinColumns || max > MaxColumns {
if minVal < MinColumns || minVal > MaxColumns || maxVal < MinColumns || maxVal > MaxColumns {
return ErrColumnNumber
}
if width > MaxColumnWidth {
return ErrColumnWidth
}
if min > max {
min, max = max, min
if minVal > maxVal {
minVal, maxVal = maxVal, minVal
}
sw.cols.WriteString(`<col min="`)
sw.cols.WriteString(strconv.Itoa(min))
sw.cols.WriteString(strconv.Itoa(minVal))
sw.cols.WriteString(`" max="`)
sw.cols.WriteString(strconv.Itoa(max))
sw.cols.WriteString(strconv.Itoa(maxVal))
sw.cols.WriteString(`" width="`)
sw.cols.WriteString(strconv.FormatFloat(width, 'f', -1, 64))
sw.cols.WriteString(`" customWidth="1"/>`)
......
......@@ -19,7 +19,6 @@ import (
"regexp"
"strconv"
"strings"
"unicode"
"unicode/utf8"
)
......@@ -316,14 +315,22 @@ func checkDefinedName(name string) error {
if utf8.RuneCountInString(name) > MaxFieldLength {
return ErrNameLength
}
for i, c := range name {
if string(c) == "_" {
continue
inCodeRange := func(code int, tbl []int) bool {
for i := 0; i < len(tbl); i += 2 {
if tbl[i] <= code && code <= tbl[i+1] {
return true
}
}
if unicode.IsLetter(c) {
continue
return false
}
for i, c := range name {
if i == 0 {
if inCodeRange(int(c), supportedDefinedNameAtStartCharCodeRange) {
continue
}
return newInvalidNameError(name)
}
if i > 0 && (unicode.IsDigit(c) || c == '.') {
if inCodeRange(int(c), supportedDefinedNameAfterStartCharCodeRange) {
continue
}
return newInvalidNameError(name)
......
......@@ -302,6 +302,163 @@ var IndexedColorMapping = []string{
"000000", "FFFFFF",
}
// supportedDefinedNameAtStartCharCodeRange list the valid first character of a
// defined name ASCII letters.
var supportedDefinedNameAtStartCharCodeRange = []int{
65, 90, 92, 92, 95, 95, 97, 122, 161, 161, 164, 164,
167, 168, 170, 170, 173, 173, 175, 186, 188, 696, 699, 705,
711, 711, 713, 715, 717, 717, 720, 721, 728, 731, 733, 733,
736, 740, 750, 750, 880, 883, 886, 887, 890, 893, 902, 902,
904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1315,
1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1610,
1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788,
1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026,
2036, 2037, 2042, 2042, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401,
2417, 2418, 2427, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480,
2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611,
2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701,
2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749,
2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864,
2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972,
2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084,
3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161,
3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257,
3261, 3261, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368,
3370, 3385, 3389, 3389, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505,
3507, 3515, 3517, 3517, 3520, 3526, 3585, 3642, 3648, 3662, 3713, 3714,
3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763,
3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911,
3913, 3948, 3976, 3979, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189,
4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293,
4304, 4346, 4348, 4348, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4680,
4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749,
4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822,
4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
5743, 5750, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905,
5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103,
6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6400, 6428, 6480, 6509,
6512, 6516, 6528, 6569, 6593, 6599, 6656, 6678, 6917, 6963, 6981, 6987,
7043, 7072, 7086, 7087, 7168, 7203, 7245, 7247, 7258, 7293, 7424, 7615,
7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025,
8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126,
8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180,
8182, 8188, 8208, 8208, 8211, 8214, 8216, 8216, 8220, 8221, 8224, 8225,
8229, 8231, 8240, 8240, 8242, 8243, 8245, 8245, 8251, 8251, 8305, 8305,
8308, 8308, 8319, 8319, 8321, 8324, 8336, 8340, 8450, 8451, 8453, 8453,
8455, 8455, 8457, 8467, 8469, 8470, 8473, 8477, 8481, 8482, 8484, 8484,
8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
8526, 8526, 8531, 8532, 8539, 8542, 8544, 8584, 8592, 8601, 8658, 8658,
8660, 8660, 8704, 8704, 8706, 8707, 8711, 8712, 8715, 8715, 8719, 8719,
8721, 8721, 8725, 8725, 8730, 8730, 8733, 8736, 8739, 8739, 8741, 8741,
8743, 8748, 8750, 8750, 8756, 8759, 8764, 8765, 8776, 8776, 8780, 8780,
8786, 8786, 8800, 8801, 8804, 8807, 8810, 8811, 8814, 8815, 8834, 8835,
8838, 8839, 8853, 8853, 8857, 8857, 8869, 8869, 8895, 8895, 8978, 8978,
9312, 9397, 9424, 9449, 9472, 9547, 9552, 9588, 9601, 9615, 9618, 9621,
9632, 9633, 9635, 9641, 9650, 9651, 9654, 9655, 9660, 9661, 9664, 9665,
9670, 9672, 9675, 9675, 9678, 9681, 9698, 9701, 9711, 9711, 9733, 9734,
9737, 9737, 9742, 9743, 9756, 9756, 9758, 9758, 9792, 9792, 9794, 9794,
9824, 9825, 9827, 9829, 9831, 9834, 9836, 9837, 9839, 9839, 11264, 11310,
11312, 11358, 11360, 11375, 11377, 11389, 11392, 11492, 11520, 11557, 11568, 11621,
11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710,
11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 12288, 12291, 12293, 12311,
12317, 12319, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12443, 12447,
12449, 12543, 12549, 12589, 12593, 12686, 12704, 12727, 12784, 12828, 12832, 12841,
12849, 12850, 12857, 12857, 12896, 12923, 12927, 12927, 12963, 12968, 13059, 13059,
13069, 13069, 13076, 13076, 13080, 13080, 13090, 13091, 13094, 13095, 13099, 13099,
13110, 13110, 13115, 13115, 13129, 13130, 13133, 13133, 13137, 13137, 13143, 13143,
13179, 13182, 13184, 13188, 13192, 13258, 13261, 13267, 13269, 13270, 13272, 13272,
13275, 13277, 13312, 19893, 19968, 40899, 40960, 42124, 42240, 42508, 42512, 42527,
42538, 42539, 42560, 42591, 42594, 42606, 42624, 42647, 42786, 42887, 42891, 42892,
43003, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187,
43274, 43301, 43312, 43334, 43520, 43560, 43584, 43586, 43588, 43595, 44032, 55203,
57344, 63560, 63744, 64045, 64048, 64106, 64112, 64217, 64256, 64262, 64275, 64279,
64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321,
64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
65072, 65073, 65075, 65092, 65097, 65106, 65108, 65111, 65113, 65126, 65128, 65131,
65136, 65140, 65142, 65276, 65281, 65374, 65377, 65470, 65474, 65479, 65482, 65487,
65490, 65495, 65498, 65500, 65504, 65510,
}
// supportedDefinedNameAfterStartCharCodeRange list the valid after first
// character of a defined name ASCII letters.
var supportedDefinedNameAfterStartCharCodeRange = []int{
46, 46, 48, 57, 63, 63, 65, 90, 92, 92, 95, 95,
97, 122, 161, 161, 164, 164, 167, 168, 170, 170, 173, 173,
175, 186, 188, 887, 890, 893, 900, 902, 904, 906, 908, 908,
910, 929, 931, 1315, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469,
1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522,
1536, 1539, 1542, 1544, 1547, 1547, 1550, 1562, 1567, 1567, 1569, 1630,
1632, 1641, 1646, 1747, 1749, 1791, 1807, 1866, 1869, 1969, 1984, 2038,
2042, 2042, 2305, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415,
2417, 2418, 2427, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472,
2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510,
2519, 2519, 2524, 2525, 2527, 2531, 2534, 2554, 2561, 2563, 2565, 2570,
2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617,
2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652,
2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728,
2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765,
2768, 2768, 2784, 2787, 2790, 2799, 2801, 2801, 2817, 2819, 2821, 2828,
2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884,
2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2929,
2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972,
2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016,
3018, 3021, 3024, 3024, 3031, 3031, 3046, 3066, 3073, 3075, 3077, 3084,
3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144,
3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3192, 3199,
3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257,
3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299,
3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368,
3370, 3385, 3389, 3396, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3427,
3430, 3445, 3449, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515,
3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551,
3570, 3571, 3585, 3642, 3647, 3662, 3664, 3673, 3713, 3714, 3716, 3716,
3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747,
3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780,
3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3843, 3859, 3897,
3902, 3911, 3913, 3948, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028,
4030, 4044, 4046, 4047, 4096, 4169, 4176, 4249, 4254, 4293, 4304, 4346,
4348, 4348, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4680, 4682, 4685,
4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784,
4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
4882, 4885, 4888, 4954, 4959, 4960, 4969, 4988, 4992, 5017, 5024, 5108,
5121, 5740, 5743, 5750, 5760, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003,
6016, 6099, 6103, 6103, 6107, 6109, 6112, 6121, 6128, 6137, 6155, 6158,
6160, 6169, 6176, 6263, 6272, 6314, 6400, 6428, 6432, 6443, 6448, 6459,
6464, 6464, 6470, 6509, 6512, 6516, 6528, 6569, 6576, 6601, 6608, 6617,
6624, 6683, 6912, 6987, 6992, 7001, 7009, 7036, 7040, 7082, 7086, 7097,
7168, 7223, 7232, 7241, 7245, 7293, 7424, 7654, 7678, 7957, 7960, 7965,
7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029,
8031, 8061, 8064, 8116, 8118, 8132, 8134, 8147, 8150, 8155, 8157, 8175,
8178, 8180, 8182, 8190, 8192, 8208, 8211, 8214, 8216, 8216, 8220, 8221,
8224, 8225, 8229, 8240, 8242, 8243, 8245, 8245, 8251, 8251, 8260, 8260,
8274, 8274, 8287, 8292, 8298, 8305, 8308, 8316, 8319, 8332, 8336, 8340,
8352, 8373, 8400, 8432, 8448, 8527, 8531, 8584, 8592, 9000, 9003, 9191,
9216, 9254, 9280, 9290, 9312, 9885, 9888, 9916, 9920, 9923, 9985, 9988,
9990, 9993, 9996, 10023, 10025, 10059, 10061, 10061, 10063, 10066, 10070, 10070,
10072, 10078, 10081, 10087, 10102, 10132, 10136, 10159, 10161, 10174, 10176, 10180,
10183, 10186, 10188, 10188, 10192, 10213, 10224, 10626, 10649, 10711, 10716, 10747,
10750, 11084, 11088, 11092, 11264, 11310, 11312, 11358, 11360, 11375, 11377, 11389,
11392, 11498, 11517, 11517, 11520, 11557, 11568, 11621, 11631, 11631, 11648, 11670,
11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 11904, 11929, 11931, 12019,
12032, 12245, 12272, 12283, 12288, 12311, 12317, 12335, 12337, 12348, 12350, 12351,
12353, 12438, 12441, 12447, 12449, 12543, 12549, 12589, 12593, 12686, 12688, 12727,
12736, 12771, 12784, 12830, 12832, 12867, 12880, 13054, 13056, 19893, 19904, 40899,
40960, 42124, 42128, 42182, 42240, 42508, 42512, 42539, 42560, 42591, 42594, 42610,
42620, 42621, 42623, 42647, 42752, 42892, 43003, 43051, 43072, 43123, 43136, 43204,
43216, 43225, 43264, 43310, 43312, 43347, 43520, 43574, 43584, 43597, 43600, 43609,
44032, 55203, 55296, 64045, 64048, 64106, 64112, 64217, 64256, 64262, 64275, 64279,
64285, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
64467, 64829, 64848, 64911, 64914, 64967, 65008, 65021, 65024, 65039, 65056, 65062,
65072, 65073, 65075, 65092, 65097, 65106, 65108, 65111, 65113, 65126, 65128, 65131,
65136, 65140, 65142, 65276, 65279, 65279, 65281, 65374, 65377, 65470, 65474, 65479,
65482, 65487, 65490, 65495, 65498, 65500, 65504, 65510, 65512, 65518, 65529, 65533,
}
// supportedImageTypes defined supported image types.
var supportedImageTypes = map[string]string{
".bmp": ".bmp", ".emf": ".emf", ".emz": ".emz", ".gif": ".gif",
......@@ -332,7 +489,7 @@ var supportedDrawingUnderlineTypes = []string{
var supportedPositioning = []string{"absolute", "oneCell", "twoCell"}
// builtInDefinedNames defined built-in defined names are built with a _xlnm prefix.
var builtInDefinedNames = []string{"_xlnm.Print_Area", "_xlnm.Print_Titles", "_xlnm._FilterDatabase"}
var builtInDefinedNames = []string{"_xlnm.Print_Area", "_xlnm.Print_Titles", "_xlnm.Criteria", "_xlnm._FilterDatabase", "_xlnm.Extract", "_xlnm.Consolidate_Area", "_xlnm.Database", "_xlnm.Sheet_Title"}
const templateDocpropsApp = `<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><TotalTime>0</TotalTime><Application>Go Excelize</Application></Properties>`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册