Merge pull request #15353 from swordqiu/hotfix/qj-excel-output-pretty-float

fix: make excel output floating number pretty
This commit is contained in:
Zexi Li
2022-11-12 18:39:54 +08:00
committed by GitHub
3 changed files with 127 additions and 1 deletions
+9 -1
View File
@@ -24,6 +24,8 @@ import (
"github.com/360EntSecGroup-Skylar/excelize"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
const (
@@ -92,7 +94,13 @@ func exportRow(xlsx *excelize.File, data jsonutils.JSONObject, keys []string, ro
val, _ = data.GetIgnoreCases(keys[i])
}
if val != nil {
valStr, _ = val.GetString()
// hack, make floating point number prettier
if fval, ok := val.(*jsonutils.JSONFloat); ok {
f, _ := fval.Float()
valStr = stringutils2.PrettyFloat(f, 2)
} else {
valStr, _ = val.GetString()
}
}
cell := fmt.Sprintf("%s%d", decimal2Alphabet(i), rowIndex)
xlsx.SetCellValue(DEFAULT_SHEET, cell, valStr)
+47
View File
@@ -19,6 +19,7 @@ import (
"encoding/hex"
"fmt"
"math/rand"
"strconv"
"strings"
"time"
)
@@ -187,3 +188,49 @@ func FilterEmpty(input []string) []string {
}
return ret
}
func PrettyFloat(f float64, precision int) string {
fstr := strconv.FormatFloat(f, 'f', -1, 64)
dotPos := strings.Index(fstr, ".")
if dotPos < 0 {
return fstr
}
neg := false
if fstr[0] == '-' {
neg = true
fstr = fstr[1:]
dotPos -= 1
}
numPart, _ := strconv.ParseInt(fstr[:dotPos], 10, 64)
prePartStr := fstr[dotPos+1:]
if numPart == 0 {
nonZeroPos := 0
for prePartStr[nonZeroPos] == '0' {
nonZeroPos += 1
}
precision += nonZeroPos
}
if precision < len(prePartStr) {
prePart, _ := strconv.ParseInt(prePartStr[:precision], 10, 64)
if prePartStr[precision] > '4' {
// rounding up
prePart += 1
}
prePartStr = fmt.Sprintf(fmt.Sprintf("%%.%dd", precision), prePart)
if len(prePartStr) > precision {
prePartStr = prePartStr[1:]
numPart += 1
}
}
for len(prePartStr) > 0 && prePartStr[len(prePartStr)-1] == '0' {
prePartStr = prePartStr[0 : len(prePartStr)-1]
}
ret := strconv.FormatInt(numPart, 10)
if len(prePartStr) > 0 {
ret += "." + prePartStr
}
if neg {
ret = "-" + ret
}
return ret
}
+71
View File
@@ -16,6 +16,7 @@ package stringutils2
import (
"reflect"
"strconv"
"testing"
)
@@ -211,3 +212,73 @@ func TestFilterEmpty(t *testing.T) {
}
}
}
func TestPrettyFloat(t *testing.T) {
cases := []struct {
in float64
prec int
want string
}{
{
in: 3.1415926,
prec: 2,
want: "3.14",
},
{
in: 3.1415926,
prec: 3,
want: "3.142",
},
{
in: 3.89999999,
prec: 2,
want: "3.9",
},
{
in: 3.88999999,
prec: 2,
want: "3.89",
},
{
in: 3.99999999,
prec: 2,
want: "4",
},
{
in: 0.000020000001,
prec: 2,
want: "0.00002",
},
{
in: 0.000021000001,
prec: 2,
want: "0.000021",
},
{
in: 0.000021100001,
prec: 2,
want: "0.000021",
},
{
in: -3.15,
prec: 1,
want: "-3.2",
},
{
in: 3.5,
prec: 0,
want: "4",
},
{
in: 0.999999999999,
prec: 2,
want: "1",
},
}
for _, c := range cases {
got := PrettyFloat(c.in, c.prec)
if got != c.want {
t.Errorf("%s precision %d want %s got %s", strconv.FormatFloat(c.in, 'f', -1, 64), c.prec, c.want, got)
}
}
}