-
Notifications
You must be signed in to change notification settings - Fork 1
/
sheetsvc.go
114 lines (97 loc) · 2.98 KB
/
sheetsvc.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
package xls2sheets
import (
"context"
"fmt"
"log"
"net/http"
"strings"
"google.golang.org/api/sheets/v4"
)
// sheetSvc is a type that has a number of wrappers around subset of sheets
// Service functions.
type sheetSvc struct {
svc *sheets.Service
spreadsheetID string
}
func newSheetSvc(client *http.Client, spreadsheetID string) (*sheetSvc, error) {
svc, err := sheets.New(client)
if err != nil {
return nil, err
}
return &sheetSvc{svc: svc, spreadsheetID: spreadsheetID}, nil
}
// get returns a range of values from spreadsheet.
func (s *sheetSvc) get(Range string) (*sheets.ValueRange, error) {
return s.svc.Spreadsheets.Values.Get(s.spreadsheetID, Range).Do()
}
// clear clears range within the target spreadsheet.
func (s *sheetSvc) clear(Range string) (*sheets.ClearValuesResponse, error) {
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/clear
rb := &sheets.ClearValuesRequest{}
return s.svc.Spreadsheets.Values.Clear(s.spreadsheetID, Range, rb).Do()
}
// addSheet adds a sheet.
func (s *sheetSvc) addSheet(address string) error {
titleRange := strings.SplitN(address, "!", 2)
if titleRange[0] == "" {
return fmt.Errorf("invalid address: %q", address)
}
requests := []*sheets.Request{
{AddSheet: &sheets.AddSheetRequest{
Properties: &sheets.SheetProperties{Title: titleRange[0]},
}},
}
rb := &sheets.BatchUpdateSpreadsheetRequest{Requests: requests}
_, err := s.svc.Spreadsheets.BatchUpdate(s.spreadsheetID, rb).Do()
if err != nil {
return err
}
return nil
}
func (s *sheetSvc) update(data *sheets.ValueRange) (*sheets.BatchUpdateValuesResponse, error) {
const valueInputOption = userEntered // proper formatting of resulting values
// Reference: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/batchUpdate
rb := &sheets.BatchUpdateValuesRequest{
ValueInputOption: valueInputOption,
Data: []*sheets.ValueRange{data},
}
resp, err := s.svc.Spreadsheets.Values.
BatchUpdate(s.spreadsheetID, rb).
Context(context.TODO()).
Do()
if err != nil {
return nil, err
}
return resp, nil
}
func (s *sheetSvc) validate(sheets []string, create bool) (*sheets.Spreadsheet, error) {
// getting information about the spreadsheet
log.Printf(" * retrieving information about the spreadsheet")
spreadsheet, err := s.svc.Spreadsheets.Get(s.spreadsheetID).Do()
if err != nil {
return nil, err
}
log.Printf(" * validating target configuration")
// need to ensure that all provided addresses are referencing valid
// sheets
for _, address := range sheets {
valid := false
for _, existing := range spreadsheet.Sheets {
if strings.HasPrefix(address, existing.Properties.Title) {
valid = true
break
}
}
if valid {
continue
}
if !valid && create {
if err := s.addSheet(address); err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("address %q referencing nonexisting sheet - create it and restart", address)
}
}
return spreadsheet, nil
}