add excelutils func (#15727)

This commit is contained in:
gouqi11
2023-01-07 20:55:14 +08:00
committed by GitHub
parent c9b46c5f74
commit 031503735a
2 changed files with 152 additions and 19 deletions
+37
View File
@@ -0,0 +1,37 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package excelutils // import "yunion.io/x/onecloud/pkg/util/excelutils"
type ExcelChartType string
const (
CHART_TYPE_LINE ExcelChartType = "line" // 折线图
CHART_TYPE_PIE ExcelChartType = "pie" // 饼图
CHART_TYPE_RADAR ExcelChartType = "radar" // 雷达图
CHART_TYPE_SCATTER ExcelChartType = "scatter" // 散点图
CHART_TYPE_COL ExcelChartType = "col" // 柱状图
)
const (
DEFAULT_SHEET = "Sheet1"
)
var ChartMap = map[ExcelChartType]string{
CHART_TYPE_LINE: "折线图",
CHART_TYPE_PIE: "饼图",
CHART_TYPE_RADAR: "雷达图",
CHART_TYPE_SCATTER: "散点图",
CHART_TYPE_COL: "柱状图",
}
+115 -19
View File
@@ -19,17 +19,13 @@ import (
"fmt"
"io"
"os"
"strconv"
"strings"
"github.com/360EntSecGroup-Skylar/excelize"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
const (
DEFAULT_SHEET = "Sheet1"
"yunion.io/x/pkg/errors"
)
func decimalBaseMaxWidth(decNum int, base int) int {
@@ -77,16 +73,23 @@ func decimal2Alphabet(decNum int) string {
return buf.String()
}
func exportHeader(xlsx *excelize.File, texts []string, rowIndex int) {
func exportHeader(xlsx *excelize.File, texts []string, rowIndex int, sheet string) {
if len(sheet) == 0 {
sheet = DEFAULT_SHEET
}
for i := 0; i < len(texts); i += 1 {
cell := fmt.Sprintf("%s%d", decimal2Alphabet(i), rowIndex)
xlsx.SetCellValue(DEFAULT_SHEET, cell, texts[i])
xlsx.SetCellValue(sheet, cell, texts[i])
}
}
func exportRow(xlsx *excelize.File, data jsonutils.JSONObject, keys []string, rowIndex int) {
func exportRow(xlsx *excelize.File, data jsonutils.JSONObject, keys []string, rowIndex int, sheet string) {
if len(sheet) == 0 {
sheet = DEFAULT_SHEET
}
for i := 0; i < len(keys); i += 1 {
var valStr string
cell := fmt.Sprintf("%s%d", decimal2Alphabet(i), rowIndex)
// var valStr string
var val jsonutils.JSONObject
if strings.Contains(keys[i], ".") {
val, _ = data.GetIgnoreCases(strings.Split(keys[i], ".")...)
@@ -97,33 +100,126 @@ func exportRow(xlsx *excelize.File, data jsonutils.JSONObject, keys []string, ro
// hack, make floating point number prettier
if fval, ok := val.(*jsonutils.JSONFloat); ok {
f, _ := fval.Float()
valStr = stringutils2.PrettyFloat(f, 2)
fvalResult, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", f), 64)
xlsx.SetCellValue(sheet, cell, fvalResult)
} else if ival, ok := val.(*jsonutils.JSONInt); ok {
i, _ := ival.Int()
xlsx.SetCellValue(sheet, cell, i)
} else if bval, ok := val.(*jsonutils.JSONBool); ok {
b, _ := bval.Bool()
xlsx.SetCellValue(sheet, cell, b)
} else {
valStr, _ = val.GetString()
s, _ := val.GetString()
xlsx.SetCellValue(sheet, cell, s)
}
}
cell := fmt.Sprintf("%s%d", decimal2Alphabet(i), rowIndex)
xlsx.SetCellValue(DEFAULT_SHEET, cell, valStr)
}
}
func Export(data []jsonutils.JSONObject, keys []string, texts []string, writer io.Writer) error {
xlsx := excelize.NewFile()
exportHeader(xlsx, texts, 1)
exportHeader(xlsx, texts, 1, "")
for i := 0; i < len(data); i += 1 {
exportRow(xlsx, data[i], keys, i+2)
exportRow(xlsx, data[i], keys, i+2, "")
}
return xlsx.Write(writer)
}
// key:data中对应的key,text:头
func ExportFile(data []jsonutils.JSONObject, keys []string, texts []string, filename string) error {
writer, err := os.Create(filename)
if err != nil {
return err
}
defer writer.Close()
return Export(data, keys, texts, writer)
}
func ExportWriter(data []jsonutils.JSONObject, keys []string, texts []string, writer io.Writer) *excelize.File {
xlsx := excelize.NewFile()
exportHeader(xlsx, texts, 1, "")
for i := 0; i < len(data); i += 1 {
exportRow(xlsx, data[i], keys, i+2, "")
}
return xlsx
}
type SExcelChartSeries struct {
Name string
Categories string
Values string
}
type SExcelChartTitle struct {
Name string
}
type SExcelChartFormat struct {
XScale float64 `json:"x_scale"`
YScale float64 `json:"y_scale"`
XOffset float64 `json:"x_offset"`
YOffset float64 `json:"y_offset"`
PrintObj bool `json:"print_obj"`
LockAspectRatio bool `json:"lock_aspect_ratio"`
Locked bool `json:"locked"`
}
type SExcelChartParams struct {
Type ExcelChartType
Series []SExcelChartSeries
Title SExcelChartTitle
Format SExcelChartFormat
}
func AddNewSheet(data []jsonutils.JSONObject, keys []string, texts []string, sheet string, f *excelize.File) *excelize.File {
// 新建sheet
f.NewSheet(sheet)
exportHeader(f, texts, 1, sheet)
for i := 0; i < len(data); i += 1 {
exportRow(f, data[i], keys, i+2, sheet)
}
return f
}
func AddChartWithSheet(key, sheet string, chartType ExcelChartType, f *excelize.File) (*excelize.File, error) {
// 获取对应sheet中的所有header
keys := f.GetRows(sheet)
if len(keys) == 0 {
return nil, errors.Errorf("empty sheet")
}
// 获取header对应的坐标
keyIndex := 'A'
for k, v := range keys[0] {
if v == key {
keyIndex = keyIndex + rune(k)
}
}
// 图表请求
params := SExcelChartParams{
Type: chartType,
Series: []SExcelChartSeries{
{
Name: fmt.Sprintf("'%s'!$%s$1", sheet, string(keyIndex)),
Categories: fmt.Sprintf("'%s'!$A$2:$A$%d", sheet, len(keys)),
Values: fmt.Sprintf("'%s'!$%s$2:$%s$%d", sheet, string(keyIndex), string(keyIndex), len(keys))},
},
Title: SExcelChartTitle{Name: fmt.Sprintf("%s - %s", key, ChartMap[chartType])},
Format: SExcelChartFormat{
XScale: 2.7,
YScale: 2.9,
PrintObj: true,
},
}
paramObj := jsonutils.Marshal(params)
err := f.AddChart(sheet, "A1", paramObj.PrettyString())
if err != nil {
return nil, err
}
return f, nil
}
func CheckChartType(chartType string) bool {
_, isExist := ChartMap[ExcelChartType(chartType)]
return isExist
}