From 09ef5fddf9335f8a2e14b5eb197509ba80324e1f Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Thu, 12 Oct 2023 12:01:53 +0800 Subject: [PATCH] :art: Database template columns support calculations https://github.com/siyuan-note/siyuan/issues/9408 --- kernel/av/table.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/kernel/av/table.go b/kernel/av/table.go index a829dec2a7a..abdae0d17c8 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -19,6 +19,7 @@ package av import ( "math" "sort" + "strconv" "strings" ) @@ -714,6 +715,87 @@ func (table *Table) calcColTemplate(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.Template && "" != row.Cells[colIndex].Value.Template.Content { + val, _ := strconv.ParseFloat(row.Cells[colIndex].Value.Template.Content, 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.Template && "" != row.Cells[colIndex].Value.Template.Content { + val, _ := strconv.ParseFloat(row.Cells[colIndex].Value.Template.Content, 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.Template && "" != row.Cells[colIndex].Value.Template.Content { + val, _ := strconv.ParseFloat(row.Cells[colIndex].Value.Template.Content, 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.Template && "" != row.Cells[colIndex].Value.Template.Content { + val, _ := strconv.ParseFloat(row.Cells[colIndex].Value.Template.Content, 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.Template && "" != row.Cells[colIndex].Value.Template.Content { + val, _ := strconv.ParseFloat(row.Cells[colIndex].Value.Template.Content, 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.Template && "" != row.Cells[colIndex].Value.Template.Content { + val, _ := strconv.ParseFloat(row.Cells[colIndex].Value.Template.Content, 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)} + } } }