mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 02:37:24 +08:00
add excelutils func (#15727)
This commit is contained in:
@@ -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: "柱状图",
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user