converter.go 3.1 KB
package converter

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/linmadan/egglib-go/utils/excel"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"strings"
	"unicode/utf8"
)

type (
	CSVReader struct {
		Data *excel.ExcelImport
	}
)

func (cr *CSVReader) ToMap(reader io.Reader) ([]map[string]string, error) {
	var err error
	if reader, err = cr.PrepareCheck(reader); err != nil {
		return nil, err
	}

	r := csv.NewReader(reader)
	rows := make([]map[string]string, 0)
	var header = make([]string, 0)
	var headerMap = make(map[string]string)
	var index int = 0
	for i := range cr.Data.DataFields {
		item := cr.Data.DataFields[i]
		headerMap[item.CnName] = item.EnName
	}

	for {
		index++

		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, err
		}
		if index <= cr.Data.RowBegin-1 {
			continue
		}

		if len(header) == 0 {
			header = record
		} else {
			dict := map[string]string{}
			for i := range header {
				if column, ok := headerMap[header[i]]; ok {
					dict[column] = record[i]
				}
			}
			rows = append(rows, dict)
		}

	}
	return rows, nil
}

func (cr *CSVReader) PrepareCheck(reader io.Reader) (io.Reader, error) {
	return GBKToUtf8(reader)
}

func GBKToUtf8(readIn io.Reader) (io.Reader, error) {
	var (
		err      error
		fileByte []byte
	)
	fileByte, err = io.ReadAll(readIn)
	if err != nil {
		return nil, err
	}

	if utf8.Valid(fileByte) {
		return bytes.NewReader(fileByte), nil
	} else {
		utf8Reader := transform.NewReader(bytes.NewReader(fileByte), simplifiedchinese.GBK.NewDecoder())
		return utf8Reader, nil
	}
}

func OpenImportFileFromIoReader(ex *excel.ExcelImport, reader io.Reader, ext string) ([]map[string]string, error) {
	var tmp []map[string]string
	var err error
	if ext == "csv" || ext == ".csv" {
		csvReader := &CSVReader{ex}
		tmp, err = csvReader.ToMap(reader)
	} else {
		tmp, err = ex.OpenExcelFromIoReader(reader)
	}
	if err != nil {
		return nil, err
	}
	var response []map[string]string
	for i := range tmp {
		if fieldValueAllEmpty(tmp[i]) {
			continue
		}
		response = append(response, tmp[i])
	}
	return response, nil
}

func fieldValueAllEmpty(param map[string]string) bool {
	isAllEmpty := true
	for _, v := range param {
		value := strings.TrimSpace(v)
		if len(value) > 0 {
			isAllEmpty = false
		}
	}
	return isAllEmpty
}

// TODO: export csv
func MakeToCsv(sourData excel.ExcelMaker, w io.Writer) error {
	_, err := w.Write([]byte("\xEF\xBB\xBF")) //写入UTF-8 BOM
	if err != nil {
		return err
	}
	csvWriter := csv.NewWriter(w)
	fields := sourData.DataFieldList()
	firstRow := []string{}
	for i := range fields {
		firstRow = append(firstRow, fields[i].CnName)
	}
	title := sourData.TableTitle()
	if len(title) > 0 {
		csvWriter.Write(title)
	}
	csvWriter.Write(firstRow)
	dataLenght := sourData.DataListLen()
	for i := 0; i < dataLenght; i++ {
		rowData := []string{}
		for ii := range fields {
			cellValue := sourData.CellValue(i, fields[ii].EnName)
			str := ""
			if cellValue != nil {
				str = fmt.Sprintf("%v", cellValue)
			}
			rowData = append(rowData, str)
		}
		csvWriter.Write(rowData)
	}
	csvWriter.Flush()
	return csvWriter.Error()
}