diff --git a/kernel/av/table.go b/kernel/av/table.go index 9d7ef8f99..b66aa5c66 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -1628,5 +1628,98 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) { if 0 < len(table.Rows) { col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } + case CalcOperatorSum: + sum := 0.0 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { + for _, content := range row.Cells[colIndex].Value.Rollup.Contents { + val, _ := strconv.ParseFloat(content.String(), 64) + sum += val + } + } + } + col.Calc.Result = &Value{Number: NewFormattedValueNumber(sum, col.NumberFormat)} + case CalcOperatorAverage: + sum := 0.0 + count := 0 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { + for _, content := range row.Cells[colIndex].Value.Rollup.Contents { + val, _ := strconv.ParseFloat(content.String(), 64) + sum += val + count++ + } + } + } + if 0 != count { + col.Calc.Result = &Value{Number: NewFormattedValueNumber(sum/float64(count), col.NumberFormat)} + } + case CalcOperatorMedian: + values := []float64{} + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { + for _, content := range row.Cells[colIndex].Value.Rollup.Contents { + val, _ := strconv.ParseFloat(content.String(), 64) + values = append(values, val) + } + } + } + sort.Float64s(values) + if len(values) > 0 { + if len(values)%2 == 0 { + col.Calc.Result = &Value{Number: NewFormattedValueNumber((values[len(values)/2-1]+values[len(values)/2])/2, col.NumberFormat)} + } else { + col.Calc.Result = &Value{Number: NewFormattedValueNumber(values[len(values)/2], col.NumberFormat)} + } + } + case CalcOperatorMin: + minVal := math.MaxFloat64 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { + for _, content := range row.Cells[colIndex].Value.Rollup.Contents { + val, _ := strconv.ParseFloat(content.String(), 64) + if val < minVal { + minVal = val + } + } + } + } + if math.MaxFloat64 != minVal { + col.Calc.Result = &Value{Number: NewFormattedValueNumber(minVal, col.NumberFormat)} + } + case CalcOperatorMax: + maxVal := -math.MaxFloat64 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { + for _, content := range row.Cells[colIndex].Value.Rollup.Contents { + val, _ := strconv.ParseFloat(content.String(), 64) + if val > maxVal { + maxVal = val + } + } + } + } + if -math.MaxFloat64 != maxVal { + col.Calc.Result = &Value{Number: NewFormattedValueNumber(maxVal, col.NumberFormat)} + } + case CalcOperatorRange: + minVal := math.MaxFloat64 + maxVal := -math.MaxFloat64 + for _, row := range table.Rows { + if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { + for _, content := range row.Cells[colIndex].Value.Rollup.Contents { + val, _ := strconv.ParseFloat(content.String(), 64) + if val < minVal { + minVal = val + } + if val > maxVal { + maxVal = val + } + } + } + } + if math.MaxFloat64 != minVal && -math.MaxFloat64 != maxVal { + col.Calc.Result = &Value{Number: NewFormattedValueNumber(maxVal-minVal, col.NumberFormat)} + } } }