From 0a02c8257dd37ef32f1f9097fbe7aa1a1dad5051 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 16 Jul 2023 22:03:39 +0800 Subject: [PATCH] :art: Attribute View columns calculate https://github.com/siyuan-note/siyuan/issues/8699 --- app/src/protyle/render/av/cell.ts | 26 +++---- app/src/types/index.d.ts | 2 +- kernel/av/av.go | 65 ++++++++++++++++- kernel/av/table.go | 111 +++++++++++------------------- 4 files changed, 119 insertions(+), 85 deletions(-) diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 7848190de..d66885e1f 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -11,43 +11,43 @@ export const getCalcValue = (column: IAVColumn) => { let value = ""; switch (column.calc.operator) { case "Count all": - value = `${resultCalc.content}${window.siyuan.languages.calcResultCountAll}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultCountAll}`; break; case "Count values": - value = `${resultCalc.content}${window.siyuan.languages.calcResultCountValues}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultCountValues}`; break; case "Count unique values": - value = `${resultCalc.content}${window.siyuan.languages.calcResultCountUniqueValues}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultCountUniqueValues}`; break; case "Count empty": - value = `${resultCalc.content}${window.siyuan.languages.calcResultCountEmpty}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultCountEmpty}`; break; case "Count not empty": - value = `${resultCalc.content}${window.siyuan.languages.calcResultCountNotEmpty}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultCountNotEmpty}`; break; case "Percent empty": - value = `${resultCalc.content}${window.siyuan.languages.calcResultPercentEmpty}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultPercentEmpty}`; break; case "Percent not empty": - value = `${resultCalc.content}${window.siyuan.languages.calcResultPercentNotEmpty}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultPercentNotEmpty}`; break; case "Sum": - value = `${resultCalc.content}${window.siyuan.languages.calcResultSum}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultSum}`; break; case "Average": - value = `${resultCalc.content}${window.siyuan.languages.calcResultAverage}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultAverage}`; break; case "Median": - value = `${resultCalc.content}${window.siyuan.languages.calcResultMedian}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultMedian}`; break; case "Min": - value = `${resultCalc.content}${window.siyuan.languages.calcResultMin}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultMin}`; break; case "Max": - value = `${resultCalc.content}${window.siyuan.languages.calcResultMax}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultMax}`; break; case "Range": - value = `${resultCalc.content}${window.siyuan.languages.calcResultRange}`; + value = `${resultCalc.formattedContent}${window.siyuan.languages.calcResultRange}`; break; } return value; diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts index 74a7c6e4c..356aed17b 100644 --- a/app/src/types/index.d.ts +++ b/app/src/types/index.d.ts @@ -919,7 +919,7 @@ interface IAVCell { interface IAVCellValue { type: TAVCol, text?: { content: string }, - number?: { content?: number, isNotEmpty: boolean }, + number?: { content?: number, isNotEmpty: boolean, format?: string, formattedContent?: string }, mSelect?: { content: string, color: string }[] block?: { content: string, id: string } date?: { content: string, content2?: string } diff --git a/kernel/av/av.go b/kernel/av/av.go index e48f33692..91b551fb6 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -19,8 +19,11 @@ package av import ( "errors" + "fmt" + "math" "os" "path/filepath" + "strconv" "github.com/88250/gulu" "github.com/88250/lute/ast" @@ -112,8 +115,66 @@ type ValueText struct { } type ValueNumber struct { - Content float64 `json:"content"` - IsNotEmpty bool `json:"isNotEmpty"` + Content float64 `json:"content"` + IsNotEmpty bool `json:"isNotEmpty"` + Format NumberFormat `json:"format"` + FormattedContent string `json:"formattedContent"` +} + +type NumberFormat string + +const ( + NumberFormatNone NumberFormat = "" + NumberFormatPercent NumberFormat = "percent" +) + +func NewValueNumber(content float64) *ValueNumber { + return &ValueNumber{ + Content: content, + IsNotEmpty: true, + Format: NumberFormatNone, + FormattedContent: fmt.Sprintf("%f", content), + } +} + +func NewFormattedValueNumber(content float64, format NumberFormat) (ret *ValueNumber) { + ret = &ValueNumber{ + Content: content, + IsNotEmpty: true, + Format: format, + FormattedContent: fmt.Sprintf("%f", content), + } + switch format { + case NumberFormatNone: + ret.FormattedContent = strconv.FormatFloat(content, 'f', -1, 64) + case NumberFormatPercent: + ret.FormattedContent = strconv.FormatFloat(content*100, 'f', -1, 64) + "%" + } + return +} + +func (number *ValueNumber) FormatNumber() { + switch number.Format { + case NumberFormatNone: + number.FormattedContent = strconv.FormatFloat(number.Content, 'f', -1, 64) + case NumberFormatPercent: + number.FormattedContent = strconv.FormatFloat(number.Content*100, 'f', -1, 64) + "%" + } +} + +// RoundUp rounds like 12.3416 -> 12.35 +func RoundUp(val float64, precision int) float64 { + return math.Ceil(val*(math.Pow10(precision))) / math.Pow10(precision) +} + +// RoundDown rounds like 12.3496 -> 12.34 +func RoundDown(val float64, precision int) float64 { + return math.Floor(val*(math.Pow10(precision))) / math.Pow10(precision) +} + +// Round rounds to nearest like 12.3456 -> 12.35 +func Round(val float64, precision int) float64 { + return math.Round(val*(math.Pow10(precision))) / math.Pow10(precision) } type ValueDate struct { diff --git a/kernel/av/table.go b/kernel/av/table.go index 4290add29..dd2ec5022 100644 --- a/kernel/av/table.go +++ b/kernel/av/table.go @@ -381,7 +381,7 @@ func (table *Table) CalcCols() { func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -389,7 +389,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countValues += len(row.Cells[colIndex].Value.MSelect) } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countValues), NumberFormatNone)} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -403,7 +403,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUniqueValues), NumberFormatNone)} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -411,7 +411,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty), NumberFormatNone)} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -419,7 +419,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty), NumberFormatNone)} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -428,8 +428,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -439,8 +438,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } } } @@ -448,7 +446,7 @@ func (table *Table) calcColMSelect(col *TableColumn, colIndex int) { func (table *Table) calcColSelect(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -456,7 +454,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countValues), NumberFormatNone)} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -466,7 +464,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countUniqueValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUniqueValues), NumberFormatNone)} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -474,7 +472,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty), NumberFormatNone)} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -482,7 +480,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty), NumberFormatNone)} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -491,8 +489,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: false}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -502,8 +499,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } } } @@ -511,7 +507,7 @@ func (table *Table) calcColSelect(col *TableColumn, colIndex int) { func (table *Table) calcColDate(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -519,7 +515,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countValues), NumberFormatNone)} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[int64]bool{} @@ -531,7 +527,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUniqueValues), NumberFormatNone)} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -539,7 +535,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty), NumberFormatNone)} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -547,7 +543,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty), NumberFormatNone)} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -556,8 +552,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -567,8 +562,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorEarliest: earliest := int64(0) @@ -616,7 +610,7 @@ func (table *Table) calcColDate(col *TableColumn, colIndex int) { func (table *Table) calcColNumber(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -624,7 +618,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countValues), NumberFormatNone)} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[float64]bool{} @@ -636,7 +630,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUniqueValues), NumberFormatNone)} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -644,7 +638,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty), NumberFormatNone)} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -652,7 +646,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty), NumberFormatNone)} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -661,8 +655,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -672,8 +665,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorSum: sum := 0.0 @@ -756,7 +748,7 @@ func (table *Table) calcColNumber(col *TableColumn, colIndex int) { func (table *Table) calcColText(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -764,7 +756,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countValues), NumberFormatNone)} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -776,7 +768,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUniqueValues), NumberFormatNone)} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -784,7 +776,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty), NumberFormatNone)} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -792,7 +784,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty), NumberFormatNone)} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -801,8 +793,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -812,8 +803,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } } } @@ -821,7 +811,7 @@ func (table *Table) calcColText(col *TableColumn, colIndex int) { func (table *Table) calcColBlock(col *TableColumn, colIndex int) { switch col.Calc.Operator { case CalcOperatorCountAll: - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(len(table.Rows)), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(len(table.Rows)), NumberFormatNone)} case CalcOperatorCountValues: countValues := 0 for _, row := range table.Rows { @@ -829,7 +819,7 @@ func (table *Table) calcColBlock(col *TableColumn, colIndex int) { countValues++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countValues), NumberFormatNone)} case CalcOperatorCountUniqueValues: countUniqueValues := 0 uniqueValues := map[string]bool{} @@ -841,7 +831,7 @@ func (table *Table) calcColBlock(col *TableColumn, colIndex int) { } } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countUniqueValues), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countUniqueValues), NumberFormatNone)} case CalcOperatorCountEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -849,7 +839,7 @@ func (table *Table) calcColBlock(col *TableColumn, colIndex int) { countEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty), NumberFormatNone)} case CalcOperatorCountNotEmpty: countNotEmpty := 0 for _, row := range table.Rows { @@ -857,7 +847,7 @@ func (table *Table) calcColBlock(col *TableColumn, colIndex int) { countNotEmpty++ } } - col.Calc.Result = &Value{Number: &ValueNumber{Content: float64(countNotEmpty), IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty), NumberFormatNone)} case CalcOperatorPercentEmpty: countEmpty := 0 for _, row := range table.Rows { @@ -866,8 +856,7 @@ func (table *Table) calcColBlock(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } case CalcOperatorPercentNotEmpty: countNotEmpty := 0 @@ -877,23 +866,7 @@ func (table *Table) calcColBlock(col *TableColumn, colIndex int) { } } if 0 < len(table.Rows) { - content := RoundUp(float64(countNotEmpty)/float64(len(table.Rows))*100, 2) - col.Calc.Result = &Value{Number: &ValueNumber{Content: content, IsNotEmpty: true}} + col.Calc.Result = &Value{Number: NewFormattedValueNumber(float64(countNotEmpty)/float64(len(table.Rows)), NumberFormatPercent)} } } } - -// RoundUp rounds like 12.3416 -> 12.35 -func RoundUp(val float64, precision int) float64 { - return math.Ceil(val*(math.Pow10(precision))) / math.Pow10(precision) -} - -// RoundDown rounds like 12.3496 -> 12.34 -func RoundDown(val float64, precision int) float64 { - return math.Floor(val*(math.Pow10(precision))) / math.Pow10(precision) -} - -// Round rounds to nearest like 12.3456 -> 12.35 -func Round(val float64, precision int) float64 { - return math.Round(val*(math.Pow10(precision))) / math.Pow10(precision) -}