-
Notifications
You must be signed in to change notification settings - Fork 6
/
importer.go
127 lines (119 loc) · 4.52 KB
/
importer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package importer
import (
"path/filepath"
"github.com/pkg/errors"
"github.com/tableauio/tableau/format"
"github.com/tableauio/tableau/internal/fs"
"github.com/tableauio/tableau/internal/importer/book"
"github.com/tableauio/tableau/log"
"github.com/tableauio/tableau/proto/tableaupb"
)
type Importer interface {
// Filename returns the parsed filename of the original inputed filename.
// - Excel: same as the inputed filename.
// - CSV: recognizes pattern: "<BookName>#<SheetName>.csv", and returns Glob name "<BookName>#*.csv".
// - XML: same as the inputed filename.
Filename() string
// Bookname returns the book name after parsing the original inputed filename.
// - Excel: the base filename without file extension.
// - CSV: recognizes pattern: "<BookName>#<SheetName>.csv", and returns "<BookName>".
// - XML: the base filename without file extension.
BookName() string
// Metabook returns the metadata of the book.
Metabook() *tableaupb.Metabook
// GetSheets returns all sheets in order of the book.
GetSheets() []*book.Sheet
// GetSheet returns a Sheet of the specified sheet name.
GetSheet(name string) *book.Sheet
}
// New creates a new importer.
func New(filename string, setters ...Option) (Importer, error) {
opts := parseOptions(setters...)
fmt := format.Ext2Format(filepath.Ext(filename))
switch fmt {
case format.Excel:
return NewExcelImporter(filename, opts.Sheets, opts.Parser, opts.Mode, opts.Cloned)
case format.CSV:
return NewCSVImporter(filename, opts.Sheets, opts.Parser)
case format.XML:
return NewXMLImporter(filename, opts.Sheets, opts.Parser, opts.Mode)
default:
return nil, errors.Errorf("unsupported format: %v", fmt)
}
}
// GetMergerImporters return all related importers.
// 1. support Glob pattern, refer https://pkg.go.dev/path/filepath#Glob
// 2. exclude self
// 3. special process for CSV filename pattern: "<BookName>#<SheetName>.csv"
func GetMergerImporters(primaryBookPath, sheetName string, bookNameGlobs []string) ([]Importer, error) {
bookPaths, err := resolveBookPaths(primaryBookPath, sheetName, bookNameGlobs)
if err != nil {
return nil, errors.WithMessagef(err, "failed to resolve workbook paths")
}
var importers []Importer
for fpath := range bookPaths {
log.Infof("%18s: %s", "merge workbook", fpath)
importer, err := New(fpath, Sheets([]string{sheetName}), Cloned())
if err != nil {
return nil, errors.WithMessagef(err, "failed to create importer: %s", fpath)
}
importers = append(importers, importer)
}
return importers, nil
}
// GetScatterImporters return all related importers.
// 1. support Glob pattern, refer https://pkg.go.dev/path/filepath#Glob
// 2. exclude self
// 3. special process for CSV filename pattern: "<BookName>#<SheetName>.csv"
func GetScatterImporters(primaryBookPath, sheetName string, bookNameGlobs []string) ([]Importer, error) {
bookPaths, err := resolveBookPaths(primaryBookPath, sheetName, bookNameGlobs)
if err != nil {
return nil, errors.WithMessagef(err, "failed to resolve workbook paths")
}
var importers []Importer
for fpath := range bookPaths {
log.Infof("%18s: %s", "scatter workbook", fpath)
importer, err := New(fpath, Sheets([]string{sheetName}), Cloned())
if err != nil {
return nil, errors.WithMessagef(err, "failed to create importer: %s", fpath)
}
importers = append(importers, importer)
}
return importers, nil
}
// resolveBookPaths resolve and return all related workbook paths.
// 1. support Glob pattern, refer https://pkg.go.dev/path/filepath#Glob
// 2. exclude self
// 3. special process for CSV filename pattern: "<BookName>#<SheetName>.csv"
func resolveBookPaths(primaryBookPath, sheetName string, bookNameGlobs []string) (map[string]bool, error) {
bookPaths := map[string]bool{}
if len(bookNameGlobs) == 0 {
return bookPaths, nil
}
fmt := format.Ext2Format(filepath.Ext(primaryBookPath))
curDir := filepath.Dir(primaryBookPath)
for _, nameGlob := range bookNameGlobs {
pattern := filepath.Join(curDir, nameGlob)
matches, err := filepath.Glob(pattern)
if err != nil {
return nil, errors.WithMessagef(err, "failed to glob pattern: %s", pattern)
}
for _, match := range matches {
path := match
if fmt == format.CSV {
// special process for CSV filename pattern: "<BookName>#<SheetName>.csv"
path, err = fs.ParseCSVBooknamePatternFrom(match)
if err != nil {
return nil, err
}
}
if fs.IsSamePath(path, primaryBookPath) {
// exclude self
continue
}
slashPath := fs.GetCleanSlashPath(path)
bookPaths[slashPath] = true
}
}
return bookPaths, nil
}