xlsx

作者: 次序 | 来源:发表于2020-07-19 11:23 被阅读0次
package main

import (
    "encoding/json"
    "log"
    "os"
    "path"
    "path/filepath"
    "sync"

    "github.com/tealeg/xlsx"
)

///////////////////////////////////////////////////////
var conf Conf

type Conf struct {
    SrcDir string `json:"src"`
    DstDir string `json:"dst"`
    SrcG   int    `json:"srcg"`
    DstG   int    `json:"dstg"`
}

///////////////////////////////////////////////////////
func Walk(p string) []string {
    l := []string{}
    if err := filepath.Walk(p, func(p string, f os.FileInfo, err error) error {
        if f != nil && !f.IsDir() && path.Ext(p) == ".xlsx" {
            l = append(l, f.Name())
        }
        return nil
    }); err != nil {
        panic(err)
    }
    return l
}

///////////////////////////////////////////////////////

type DictInfo struct {
    Src   string
    Dst   string
    Dict  map[string][]*xlsx.Cell
    Excel *xlsx.File
}

var (
    makeG  = 1
    makeC  = make(chan *DictInfo, 1000)
    makeWG = sync.WaitGroup{}

    mergeG  = 1
    mergeC  = make(chan *DictInfo, 1000)
    mergeWG = sync.WaitGroup{}

    saveG  = 1
    saveC  = make(chan *DictInfo, 1000)
    saveWG = sync.WaitGroup{}

    defaultStyle = xlsx.NewStyle()
)

func Merge(f string) {
    log.Println("merge file:", f)

    info := &DictInfo{
        Src:  conf.SrcDir + f,
        Dst:  conf.DstDir + f,
        Dict: make(map[string][]*xlsx.Cell, 32),
    }

    makeC <- info
}

func MakeDict() {
    makeWG.Add(1)
    go func() {
        defer func() {
            makeWG.Done()
        }()
        for info := range makeC {
            excel, err := xlsx.OpenFile(info.Src)
            if err != nil {
                panic(err)
            }

            for _, sheet := range excel.Sheets {
                for _, row := range sheet.Rows {
                    if len(row.Cells) > 1 {
                        v := []*xlsx.Cell{}
                        for _, c := range row.Cells[1:] {
                            if c.String() != "" {
                                v = append(v, c)
                            }
                        }
                        info.Dict[row.Cells[0].String()] = v
                        //info.Dict[row.Cells[0].String()] = row.Cells[1:]
                    }
                }
            }
            mergeC <- info
        }
    }()
}

func MergeDict() {
    mergeWG.Add(1)
    go func() {
        defer mergeWG.Done()
        for info := range mergeC {
            excel, err := xlsx.OpenFile(info.Dst)
            if err != nil {
                panic(err)
            }

            change := false

            for _, sheet := range excel.Sheets {
                for _, row := range sheet.Rows {
                    if cells, ok := info.Dict[row.Cells[0].String()]; ok {
                        // just copy new cell
                        for i := 0; i < len(cells); i++ {
                            if len(row.Cells)-1 > i && row.Cells[i+1].String() == "" {
                                *row.Cells[i+1] = *cells[i]
                                change = true
                            } else if len(row.Cells)-1 <= i {
                                cell := row.AddCell()
                                *cell = *cells[i]
                                change = true
                            }
                        }
                    }
                }
            }

            if change {
                info.Excel = excel
                saveC <- info
            }
        }
    }()
}

func SaveDict() {
    saveWG.Add(1)
    go func() {
        defer saveWG.Done()
        for info := range saveC {
            // clear style
            for _, sheet := range info.Excel.Sheets {
                for _, row := range sheet.Rows {
                    for _, cell := range row.Cells {
                        cell.SetStyle(defaultStyle)
                    }
                }
                for _, col := range sheet.Cols {
                    col.SetStyle(defaultStyle)
                }
            }
            x := &xlsx.File{
                Sheet:  info.Excel.Sheet,
                Sheets: info.Excel.Sheets,
            }
            x.Save(info.Dst)
        }
    }()
}

func init() {
    f, err := os.Open("./conf.json")
    if err != nil {
        panic(err)
    }
    err = json.NewDecoder(f).Decode(&conf)
    if err != nil {
        panic(err)
    }
}

func main() {
    for i := 0; i < makeG; i++ {
        MakeDict()
    }
    for i := 0; i < mergeG; i++ {
        MergeDict()
    }
    for i := 0; i < saveG; i++ {
        SaveDict()
    }

    lf := Walk(conf.SrcDir)
    for _, f := range lf {
        Merge(f)
    }

    close(makeC)
    makeWG.Wait()
    close(mergeC)
    mergeWG.Wait()
    close(saveC)
    saveWG.Wait()
}

相关文章

网友评论

      本文标题:xlsx

      本文链接:https://www.haomeiwen.com/subject/xaylkktx.html