150 lines
3.8 KiB
Go
150 lines
3.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/xuri/excelize/v2"
|
|
)
|
|
|
|
func templateColumns(raw string) ([]string, map[string]string, error) {
|
|
labels := map[string]string{}
|
|
decoder := json.NewDecoder(strings.NewReader(raw))
|
|
token, err := decoder.Token()
|
|
if err != nil || token != json.Delim('{') {
|
|
return nil, nil, err
|
|
}
|
|
keys := make([]string, 0)
|
|
for decoder.More() {
|
|
keyToken, tokenErr := decoder.Token()
|
|
if tokenErr != nil {
|
|
return nil, nil, tokenErr
|
|
}
|
|
key := keyToken.(string)
|
|
var label string
|
|
if tokenErr = decoder.Decode(&label); tokenErr != nil {
|
|
return nil, nil, tokenErr
|
|
}
|
|
keys = append(keys, key)
|
|
labels[key] = label
|
|
}
|
|
if _, err = decoder.Token(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return keys, labels, nil
|
|
}
|
|
func (s *ExportService) Export(ctx context.Context, tid string, params map[string]string) ([]byte, string, error) {
|
|
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
rows, _, err := s.uc.QueryExport(ctx, template, params)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
keys, labels, err := templateColumns(template.TemplateInfo)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
file := excelize.NewFile()
|
|
sheet := file.GetSheetName(0)
|
|
for column, key := range keys {
|
|
cell, _ := excelize.CoordinatesToCellName(column+1, 1)
|
|
_ = file.SetCellValue(sheet, cell, labels[key])
|
|
}
|
|
for rowIndex, row := range rows {
|
|
for column, key := range keys {
|
|
cell, _ := excelize.CoordinatesToCellName(column+1, rowIndex+2)
|
|
_ = file.SetCellValue(sheet, cell, row[key])
|
|
}
|
|
}
|
|
buffer, err := file.WriteToBuffer()
|
|
_ = file.Close()
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
return buffer.Bytes(), template.Name + ".xlsx", nil
|
|
}
|
|
func (s *ExportService) ExportBlankTemplate(ctx context.Context, tid string) ([]byte, string, error) {
|
|
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
keys, labels, err := templateColumns(template.TemplateInfo)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
file := excelize.NewFile()
|
|
sheet := file.GetSheetName(0)
|
|
for column, key := range keys {
|
|
cell, _ := excelize.CoordinatesToCellName(column+1, 1)
|
|
_ = file.SetCellValue(sheet, cell, labels[key])
|
|
}
|
|
buffer, err := file.WriteToBuffer()
|
|
_ = file.Close()
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
return buffer.Bytes(), template.Name + "_template.xlsx", nil
|
|
}
|
|
func (s *ExportService) Preview(ctx context.Context, tid string, params map[string]string) (string, error) {
|
|
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return s.uc.PreviewExport(ctx, template, params)
|
|
}
|
|
func (s *ExportService) Import(ctx context.Context, tid string, reader io.Reader) error {
|
|
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
file, err := excelize.OpenReader(reader)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
sheets := file.GetSheetList()
|
|
if len(sheets) == 0 {
|
|
return errors.New("工作簿没有工作表")
|
|
}
|
|
rows, err := file.GetRows(sheets[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(rows) < 2 {
|
|
return errors.New("Excel data is not enough.\nIt should contain title row and data")
|
|
}
|
|
keys, labels, err := templateColumns(template.TemplateInfo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
reverse := map[string]string{}
|
|
for _, key := range keys {
|
|
reverse[labels[key]] = key
|
|
}
|
|
headers := rows[0]
|
|
items := make([]map[string]any, 0, len(rows)-1)
|
|
for _, row := range rows[1:] {
|
|
item := map[string]any{}
|
|
for column, value := range row {
|
|
if column >= len(headers) {
|
|
continue
|
|
}
|
|
key := reverse[headers[column]]
|
|
if key != "" {
|
|
item[key] = value
|
|
}
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
if err = s.uc.ImportExportRows(ctx, template, items); err != nil {
|
|
return fmt.Errorf("导入失败: %w", err)
|
|
}
|
|
return nil
|
|
}
|