google_drive 2.1.12 → 3.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +2 -2
- data/lib/google_drive/acl.rb +8 -8
- data/lib/google_drive/api_client_fetcher.rb +23 -17
- data/lib/google_drive/collection.rb +6 -6
- data/lib/google_drive/file.rb +16 -16
- data/lib/google_drive/session.rb +36 -25
- data/lib/google_drive/spreadsheet.rb +41 -24
- data/lib/google_drive/worksheet.rb +331 -161
- metadata +28 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8579ea758131c51c083928052abf518b1f327b9b9666e798c17007801f0c1476
|
4
|
+
data.tar.gz: c04c47fe2d0337bb2e471227ad66e90b857b33784f01f8d60d7406f63fcad92b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d52bac1e4e05bd2dee4503a67a4c9da7eaeee700dfa9bca2f668bc88c04df065b5a7c209a4808d98a63610cb27318df3bef859e6e016ba4fbe1029782440aa58
|
7
|
+
data.tar.gz: 24facac6a6116210ea76b82f139fcd5c93e5624fbdb889f2fb89de65c98a6eb11ae31fb0c892cb221a5b689e2fc5271bb6636ad1215559e2689a8ef9b5edbf85
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ This is a Ruby library to read/write files/spreadsheets in Google Drive/Docs.
|
|
5
5
|
NOTE: This is NOT a library to create Google Drive App.
|
6
6
|
|
7
7
|
|
8
|
-
* [Migration from ver.
|
8
|
+
* [Migration from ver. 2.x.x or before](#migration)
|
9
9
|
* [How to install](#install)
|
10
10
|
* [How to use](#use)
|
11
11
|
* [API documentation](http://www.rubydoc.info/gems/google_drive)
|
@@ -16,7 +16,7 @@ NOTE: This is NOT a library to create Google Drive App.
|
|
16
16
|
* [Author](#author)
|
17
17
|
|
18
18
|
|
19
|
-
## <a name="migration">Migration from ver.
|
19
|
+
## <a name="migration">Migration from ver. 2.x.x or before</a>
|
20
20
|
|
21
21
|
There are some incompatible API changes. See
|
22
22
|
[MIGRATING.md](https://github.com/gimite/google-drive-ruby/blob/master/MIGRATING.md).
|
data/lib/google_drive/acl.rb
CHANGED
@@ -21,8 +21,8 @@ module GoogleDrive
|
|
21
21
|
def initialize(session, file)
|
22
22
|
@session = session
|
23
23
|
@file = file
|
24
|
-
api_permissions = @session.
|
25
|
-
@file.id, fields: '*',
|
24
|
+
api_permissions = @session.drive_service.list_permissions(
|
25
|
+
@file.id, fields: '*', supports_all_drives: true
|
26
26
|
)
|
27
27
|
@entries =
|
28
28
|
api_permissions.permissions.map { |perm| AclEntry.new(perm, self) }
|
@@ -70,10 +70,10 @@ module GoogleDrive
|
|
70
70
|
def push(params_or_entry, options = {})
|
71
71
|
entry = params_or_entry.is_a?(AclEntry) ?
|
72
72
|
params_or_entry : AclEntry.new(params_or_entry)
|
73
|
-
api_permission = @session.
|
73
|
+
api_permission = @session.drive_service.create_permission(
|
74
74
|
@file.id,
|
75
75
|
entry.params,
|
76
|
-
{ fields: '*',
|
76
|
+
**{ fields: '*', supports_all_drives: true }.merge(options)
|
77
77
|
)
|
78
78
|
new_entry = AclEntry.new(api_permission, self)
|
79
79
|
@entries.push(new_entry)
|
@@ -85,20 +85,20 @@ module GoogleDrive
|
|
85
85
|
# e.g.
|
86
86
|
# spreadsheet.acl.delete(spreadsheet.acl[1])
|
87
87
|
def delete(entry)
|
88
|
-
@session.
|
89
|
-
@file.id, entry.id,
|
88
|
+
@session.drive_service.delete_permission(
|
89
|
+
@file.id, entry.id, supports_all_drives: true
|
90
90
|
)
|
91
91
|
@entries.delete(entry)
|
92
92
|
end
|
93
93
|
|
94
94
|
# @api private
|
95
95
|
def update_role(entry)
|
96
|
-
api_permission = @session.
|
96
|
+
api_permission = @session.drive_service.update_permission(
|
97
97
|
@file.id,
|
98
98
|
entry.id,
|
99
99
|
{ role: entry.role },
|
100
100
|
fields: '*',
|
101
|
-
|
101
|
+
supports_all_drives: true
|
102
102
|
)
|
103
103
|
entry.api_permission = api_permission
|
104
104
|
entry
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require 'net/https'
|
5
5
|
require 'uri'
|
6
6
|
require 'google/apis/drive_v3'
|
7
|
+
require 'google/apis/sheets_v4'
|
7
8
|
Net::HTTP.version_1_2
|
8
9
|
|
9
10
|
module GoogleDrive
|
@@ -19,30 +20,35 @@ module GoogleDrive
|
|
19
20
|
|
20
21
|
def initialize(authorization, client_options, request_options)
|
21
22
|
@drive = Google::Apis::DriveV3::DriveService.new
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
@sheets = Google::Apis::SheetsV4::SheetsService.new
|
24
|
+
|
25
|
+
[@drive, @sheets].each do |service|
|
26
|
+
service.authorization = authorization
|
27
|
+
|
28
|
+
# Make the timeout virtually infinite because some of the operations
|
29
|
+
# (e.g., uploading a large file) can take very long.
|
30
|
+
# This value is the maximal allowed timeout in seconds on JRuby.
|
31
|
+
t = (2**31 - 1) / 1000
|
32
|
+
service.client_options.open_timeout_sec = t
|
33
|
+
service.client_options.read_timeout_sec = t
|
34
|
+
service.client_options.send_timeout_sec = t
|
35
|
+
|
36
|
+
if client_options
|
37
|
+
service.client_options.members.each do |name|
|
38
|
+
if !client_options[name].nil?
|
39
|
+
service.client_options[name] = client_options[name]
|
40
|
+
end
|
36
41
|
end
|
37
42
|
end
|
38
|
-
end
|
39
43
|
|
40
|
-
|
41
|
-
|
44
|
+
if request_options
|
45
|
+
service.request_options = service.request_options.merge(request_options)
|
46
|
+
end
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
50
|
attr_reader(:drive)
|
51
|
+
attr_reader(:sheets)
|
46
52
|
|
47
53
|
def request_raw(method, url, data, extra_header, _auth)
|
48
54
|
options = @drive.request_options.merge(header: extra_header)
|
@@ -19,16 +19,16 @@ module GoogleDrive
|
|
19
19
|
|
20
20
|
# Adds the given GoogleDrive::File to the folder.
|
21
21
|
def add(file)
|
22
|
-
@session.
|
23
|
-
file.id, add_parents: id, fields: '',
|
22
|
+
@session.drive_service.update_file(
|
23
|
+
file.id, add_parents: id, fields: '', supports_all_drives: true
|
24
24
|
)
|
25
25
|
nil
|
26
26
|
end
|
27
27
|
|
28
28
|
# Removes the given GoogleDrive::File from the folder.
|
29
29
|
def remove(file)
|
30
|
-
@session.
|
31
|
-
file.id, remove_parents: id, fields: '',
|
30
|
+
@session.drive_service.update_file(
|
31
|
+
file.id, remove_parents: id, fields: '', supports_all_drives: true
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
@@ -61,8 +61,8 @@ module GoogleDrive
|
|
61
61
|
parents: [id]
|
62
62
|
}.merge(file_properties)
|
63
63
|
|
64
|
-
file = @session.
|
65
|
-
file_metadata, fields: '*',
|
64
|
+
file = @session.drive_service.create_file(
|
65
|
+
file_metadata, fields: '*', supports_all_drives: true
|
66
66
|
)
|
67
67
|
|
68
68
|
@session.wrap_api_file(file)
|
data/lib/google_drive/file.rb
CHANGED
@@ -38,8 +38,8 @@ module GoogleDrive
|
|
38
38
|
|
39
39
|
# Reloads file metadata such as title and acl.
|
40
40
|
def reload_metadata
|
41
|
-
@api_file = @session.
|
42
|
-
id, fields: '*',
|
41
|
+
@api_file = @session.drive_service.get_file(
|
42
|
+
id, fields: '*', supports_all_drives: true
|
43
43
|
)
|
44
44
|
@acl = Acl.new(@session, self) if @acl
|
45
45
|
end
|
@@ -94,9 +94,9 @@ module GoogleDrive
|
|
94
94
|
#
|
95
95
|
# To export the file in other formats, use export_as_file.
|
96
96
|
def download_to_file(path, params = {})
|
97
|
-
@session.
|
97
|
+
@session.drive_service.get_file(
|
98
98
|
id,
|
99
|
-
{ download_dest: path,
|
99
|
+
{ download_dest: path, supports_all_drives: true }.merge(params)
|
100
100
|
)
|
101
101
|
end
|
102
102
|
|
@@ -113,9 +113,9 @@ module GoogleDrive
|
|
113
113
|
#
|
114
114
|
# To export the file in other formats, use export_to_io.
|
115
115
|
def download_to_io(io, params = {})
|
116
|
-
@session.
|
116
|
+
@session.drive_service.get_file(
|
117
117
|
id,
|
118
|
-
{ download_dest: io,
|
118
|
+
**{ download_dest: io, supports_all_drives: true }.merge(params)
|
119
119
|
)
|
120
120
|
end
|
121
121
|
|
@@ -184,8 +184,8 @@ module GoogleDrive
|
|
184
184
|
|
185
185
|
# Reads content from +io+ and updates the file with the content.
|
186
186
|
def update_from_io(io, params = {})
|
187
|
-
params = { upload_source: io,
|
188
|
-
@session.
|
187
|
+
params = { upload_source: io, supports_all_drives: true }.merge(params)
|
188
|
+
@session.drive_service.update_file(id, nil, **params)
|
189
189
|
nil
|
190
190
|
end
|
191
191
|
|
@@ -193,10 +193,10 @@ module GoogleDrive
|
|
193
193
|
# If +permanent+ is +true+, deletes the file permanently.
|
194
194
|
def delete(permanent = false)
|
195
195
|
if permanent
|
196
|
-
@session.
|
196
|
+
@session.drive_service.delete_file(id, supports_all_drives: true)
|
197
197
|
else
|
198
|
-
@session.
|
199
|
-
id, { trashed: true },
|
198
|
+
@session.drive_service.update_file(
|
199
|
+
id, { trashed: true }, supports_all_drives: true
|
200
200
|
)
|
201
201
|
end
|
202
202
|
nil
|
@@ -204,8 +204,8 @@ module GoogleDrive
|
|
204
204
|
|
205
205
|
# Renames title of the file.
|
206
206
|
def rename(title)
|
207
|
-
@session.
|
208
|
-
id, { name: title },
|
207
|
+
@session.drive_service.update_file(
|
208
|
+
id, { name: title }, supports_all_drives: true
|
209
209
|
)
|
210
210
|
nil
|
211
211
|
end
|
@@ -214,8 +214,8 @@ module GoogleDrive
|
|
214
214
|
|
215
215
|
# Creates copy of this file with the given title.
|
216
216
|
def copy(title, file_properties = {})
|
217
|
-
api_file = @session.
|
218
|
-
id, { name: title }.merge(file_properties), fields: '*',
|
217
|
+
api_file = @session.drive_service.copy_file(
|
218
|
+
id, { name: title }.merge(file_properties), fields: '*', supports_all_drives: true
|
219
219
|
)
|
220
220
|
@session.wrap_api_file(api_file)
|
221
221
|
end
|
@@ -259,7 +259,7 @@ module GoogleDrive
|
|
259
259
|
|
260
260
|
def export_to_dest(dest, format)
|
261
261
|
mime_type = EXT_TO_CONTENT_TYPE['.' + format] || format
|
262
|
-
@session.
|
262
|
+
@session.drive_service.export_file(id, mime_type, download_dest: dest)
|
263
263
|
nil
|
264
264
|
end
|
265
265
|
end
|
data/lib/google_drive/session.rb
CHANGED
@@ -141,15 +141,13 @@ module GoogleDrive
|
|
141
141
|
config.client_id = options[:client_id]
|
142
142
|
config.client_secret = options[:client_secret]
|
143
143
|
end
|
144
|
-
if !config.client_id
|
145
|
-
config.client_id =
|
146
|
-
'452925651630-egr1f18o96acjjvphpbbd1qlsevkho1d.' \
|
147
|
-
'apps.googleusercontent.com'
|
148
|
-
config.client_secret = '1U3-Krii5x1oLPrwD5zgn-ry'
|
149
|
-
elsif !config.client_id || !config.client_secret
|
144
|
+
if !config.client_id || !config.client_secret
|
150
145
|
raise(
|
151
146
|
ArgumentError,
|
152
|
-
'client_id
|
147
|
+
'client_id or client_secret is missing in the config. Follow ' \
|
148
|
+
'https://github.com/gimite/google-drive-ruby/blob/master/doc/authorization.md ' \
|
149
|
+
'to provide a valid config. google_drive library no longer provides ' \
|
150
|
+
'the default credential due to a limitation of Google API.'
|
153
151
|
)
|
154
152
|
end
|
155
153
|
|
@@ -219,10 +217,17 @@ module GoogleDrive
|
|
219
217
|
attr_accessor :on_auth_fail
|
220
218
|
|
221
219
|
# Returns an instance of Google::Apis::DriveV3::DriveService.
|
222
|
-
def
|
220
|
+
def drive_service
|
223
221
|
@fetcher.drive
|
224
222
|
end
|
225
223
|
|
224
|
+
alias drive drive_service
|
225
|
+
|
226
|
+
# Returns an instance of Google::Apis::SheetsV4::SheetsService.
|
227
|
+
def sheets_service
|
228
|
+
@fetcher.sheets
|
229
|
+
end
|
230
|
+
|
226
231
|
# Returns list of files for the user as array of GoogleDrive::File or its
|
227
232
|
# subclass. You can specify parameters documented at
|
228
233
|
# https://developers.google.com/drive/v3/web/search-parameters
|
@@ -247,8 +252,8 @@ module GoogleDrive
|
|
247
252
|
def files(params = {}, &block)
|
248
253
|
params = convert_params(params)
|
249
254
|
execute_paged!(
|
250
|
-
method:
|
251
|
-
parameters: { fields: '*',
|
255
|
+
method: drive_service.method(:list_files),
|
256
|
+
parameters: { fields: '*', supports_all_drives: true, include_items_from_all_drives: true }.merge(params),
|
252
257
|
items_method_name: :files,
|
253
258
|
converter: proc { |af| wrap_api_file(af) },
|
254
259
|
&block
|
@@ -280,7 +285,7 @@ module GoogleDrive
|
|
280
285
|
# Returns an instance of GoogleDrive::File or its subclass
|
281
286
|
# (GoogleDrive::Spreadsheet, GoogleDrive::Collection).
|
282
287
|
def file_by_id(id)
|
283
|
-
api_file =
|
288
|
+
api_file = drive_service.get_file(id, fields: '*', supports_all_drives: true)
|
284
289
|
wrap_api_file(api_file)
|
285
290
|
end
|
286
291
|
|
@@ -379,13 +384,12 @@ module GoogleDrive
|
|
379
384
|
# "1smypkyAz4STrKO4Zkos5Z4UPUJKvvgIza32LnlQ7OGw/od7/private/full")
|
380
385
|
def worksheet_by_url(url)
|
381
386
|
case url
|
382
|
-
when %r{^https?://spreadsheets.google.com/feeds/worksheets
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
"#{Regexp.last_match(2)}#{Regexp.last_match(3)}"
|
387
|
+
when %r{^https?://spreadsheets.google.com/feeds/worksheets/(.*)/.*/full/(.*)$}
|
388
|
+
spreadsheet_id = Regexp.last_match(1)
|
389
|
+
worksheet_feed_id = Regexp.last_match(2)
|
390
|
+
when %r{^https?://spreadsheets.google.com/feeds/cells/(.*)/(.*)/private/full(\?.*)?$}
|
391
|
+
spreadsheet_id = Regexp.last_match(1)
|
392
|
+
worksheet_feed_id = Regexp.last_match(2)
|
389
393
|
else
|
390
394
|
raise(
|
391
395
|
GoogleDrive::Error,
|
@@ -394,8 +398,15 @@ module GoogleDrive
|
|
394
398
|
)
|
395
399
|
end
|
396
400
|
|
397
|
-
|
398
|
-
|
401
|
+
spreadsheet = spreadsheet_by_key(spreadsheet_id)
|
402
|
+
worksheet = spreadsheet.worksheets.find{ |ws| ws.worksheet_feed_id == worksheet_feed_id }
|
403
|
+
unless worksheet
|
404
|
+
raise(
|
405
|
+
GoogleDrive::Error,
|
406
|
+
"Worksheet not found for the given URL: #{url}"
|
407
|
+
)
|
408
|
+
end
|
409
|
+
worksheet
|
399
410
|
end
|
400
411
|
|
401
412
|
# Returns the root folder.
|
@@ -496,8 +507,8 @@ module GoogleDrive
|
|
496
507
|
name: title,
|
497
508
|
}.merge(file_properties)
|
498
509
|
|
499
|
-
file =
|
500
|
-
file_metadata, fields: '*',
|
510
|
+
file = drive_service.create_file(
|
511
|
+
file_metadata, fields: '*', supports_all_drives: true
|
501
512
|
)
|
502
513
|
|
503
514
|
wrap_api_file(file)
|
@@ -587,7 +598,7 @@ module GoogleDrive
|
|
587
598
|
end
|
588
599
|
|
589
600
|
elsif opts[:parameters] && opts[:parameters].key?(:page_token)
|
590
|
-
response = opts[:method].call(opts[:parameters])
|
601
|
+
response = opts[:method].call(**opts[:parameters])
|
591
602
|
items = response.__send__(opts[:items_method_name]).map do |item|
|
592
603
|
opts[:converter] ? opts[:converter].call(item) : item
|
593
604
|
end
|
@@ -643,7 +654,7 @@ module GoogleDrive
|
|
643
654
|
upload_source: source,
|
644
655
|
content_type: 'application/octet-stream',
|
645
656
|
fields: '*',
|
646
|
-
|
657
|
+
supports_all_drives: true
|
647
658
|
}
|
648
659
|
for k, v in params
|
649
660
|
unless %i[convert convert_mime_type parents].include?(k)
|
@@ -661,7 +672,7 @@ module GoogleDrive
|
|
661
672
|
end
|
662
673
|
file_metadata[:parents] = params[:parents] if params[:parents]
|
663
674
|
|
664
|
-
file =
|
675
|
+
file = drive_service.create_file(file_metadata, **api_params)
|
665
676
|
wrap_api_file(file)
|
666
677
|
end
|
667
678
|
|
@@ -16,6 +16,10 @@ module GoogleDrive
|
|
16
16
|
# create_spreadsheet in GoogleDrive::Session to get GoogleDrive::Spreadsheet
|
17
17
|
# object.
|
18
18
|
class Spreadsheet < GoogleDrive::File
|
19
|
+
|
20
|
+
# TODO: Bump up the major version before switching the existing methods to
|
21
|
+
# v4 API because it requires to turn on a new API in the API console.
|
22
|
+
|
19
23
|
include(Util)
|
20
24
|
|
21
25
|
SUPPORTED_EXPORT_FORMAT = Set.new(%w[xlsx csv pdf])
|
@@ -45,16 +49,8 @@ module GoogleDrive
|
|
45
49
|
|
46
50
|
# Returns worksheets of the spreadsheet as array of GoogleDrive::Worksheet.
|
47
51
|
def worksheets
|
48
|
-
|
49
|
-
|
50
|
-
raise(GoogleDrive::Error,
|
51
|
-
format(
|
52
|
-
"%s doesn't look like a worksheets feed URL because its root " \
|
53
|
-
'is not <feed>.',
|
54
|
-
worksheets_feed_url
|
55
|
-
))
|
56
|
-
end
|
57
|
-
doc.css('entry').map { |e| Worksheet.new(@session, self, e) }.freeze
|
52
|
+
api_spreadsheet = @session.sheets_service.get_spreadsheet(id, fields: 'sheets.properties')
|
53
|
+
api_spreadsheet.sheets.map{ |s| Worksheet.new(@session, self, s.properties) }
|
58
54
|
end
|
59
55
|
|
60
56
|
# Returns a GoogleDrive::Worksheet with the given title in the spreadsheet.
|
@@ -68,24 +64,32 @@ module GoogleDrive
|
|
68
64
|
# Returns a GoogleDrive::Worksheet with the given gid.
|
69
65
|
#
|
70
66
|
# Returns nil if not found.
|
71
|
-
def
|
72
|
-
|
73
|
-
worksheets.find { |ws| ws.
|
67
|
+
def worksheet_by_sheet_id(sheet_id)
|
68
|
+
sheet_id = sheet_id.to_i
|
69
|
+
worksheets.find { |ws| ws.sheet_id == sheet_id }
|
74
70
|
end
|
75
71
|
|
72
|
+
alias worksheet_by_gid worksheet_by_sheet_id
|
73
|
+
|
76
74
|
# Adds a new worksheet to the spreadsheet. Returns added
|
77
75
|
# GoogleDrive::Worksheet.
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
76
|
+
#
|
77
|
+
# When +index+ is specified, the worksheet is inserted at the given
|
78
|
+
# +index+.
|
79
|
+
def add_worksheet(title, max_rows = 100, max_cols = 20, index: nil)
|
80
|
+
(response,) = batch_update([{
|
81
|
+
add_sheet: {
|
82
|
+
properties: {
|
83
|
+
title: title,
|
84
|
+
index: index,
|
85
|
+
grid_properties: {
|
86
|
+
row_count: max_rows,
|
87
|
+
column_count: max_cols,
|
88
|
+
},
|
89
|
+
},
|
90
|
+
},
|
91
|
+
}])
|
92
|
+
Worksheet.new(@session, self, response.add_sheet.properties)
|
89
93
|
end
|
90
94
|
|
91
95
|
# Not available for GoogleDrive::Spreadsheet. Use export_as_file instead.
|
@@ -114,5 +118,18 @@ module GoogleDrive
|
|
114
118
|
'Use export_to_io instead.'
|
115
119
|
)
|
116
120
|
end
|
121
|
+
|
122
|
+
# Performs batch update of the spreadsheet.
|
123
|
+
#
|
124
|
+
# +requests+ is an Array of Google::Apis::SheetsV4::Request or its Hash
|
125
|
+
# equivalent. Returns an Array of Google::Apis::SheetsV4::Response.
|
126
|
+
def batch_update(requests)
|
127
|
+
batch_request =
|
128
|
+
Google::Apis::SheetsV4::BatchUpdateSpreadsheetRequest.new(
|
129
|
+
requests: requests)
|
130
|
+
batch_response =
|
131
|
+
@session.sheets_service.batch_update_spreadsheet(id, batch_request)
|
132
|
+
batch_response.replies
|
133
|
+
end
|
117
134
|
end
|
118
135
|
end
|
@@ -16,51 +16,104 @@ module GoogleDrive
|
|
16
16
|
class Worksheet
|
17
17
|
include(Util)
|
18
18
|
|
19
|
+
# A few default color instances that match the colors from the Google Sheets web UI.
|
20
|
+
#
|
21
|
+
# TODO: Add more colors from
|
22
|
+
# https://github.com/denilsonsa/gimp-palettes/blob/master/palettes/Google-Drive.gpl
|
23
|
+
module Colors
|
24
|
+
RED = Google::Apis::SheetsV4::Color.new(red: 1.0)
|
25
|
+
DARK_RED_1 = Google::Apis::SheetsV4::Color.new(red: 0.8)
|
26
|
+
RED_BERRY = Google::Apis::SheetsV4::Color.new(red: 0.596)
|
27
|
+
DARK_RED_BERRY_1 = Google::Apis::SheetsV4::Color.new(red: 0.659, green: 0.11)
|
28
|
+
ORANGE = Google::Apis::SheetsV4::Color.new(red: 1.0, green: 0.6)
|
29
|
+
DARK_ORANGE_1 = Google::Apis::SheetsV4::Color.new(red: 0.9, green: 0.569, blue: 0.22)
|
30
|
+
YELLOW = Google::Apis::SheetsV4::Color.new(red: 1.0, green: 1.0)
|
31
|
+
DARK_YELLOW_1 = Google::Apis::SheetsV4::Color.new(red: 0.945, green: 0.76, blue: 0.196)
|
32
|
+
GREEN = Google::Apis::SheetsV4::Color.new(green: 1.0)
|
33
|
+
DARK_GREEN_1 = Google::Apis::SheetsV4::Color.new(red: 0.416, green: 0.659, blue: 0.31)
|
34
|
+
CYAN = Google::Apis::SheetsV4::Color.new(green: 1.0, blue: 1.0)
|
35
|
+
DARK_CYAN_1 = Google::Apis::SheetsV4::Color.new(red: 0.27, green: 0.506, blue: 0.557)
|
36
|
+
CORNFLOWER_BLUE = Google::Apis::SheetsV4::Color.new(red: 0.29, green: 0.525, blue: 0.91)
|
37
|
+
DARK_CORNFLOWER_BLUE_1 = Google::Apis::SheetsV4::Color.new(red: 0.235, green: 0.47, blue: 0.847)
|
38
|
+
BLUE = Google::Apis::SheetsV4::Color.new(blue: 1.0)
|
39
|
+
DARK_BLUE_1 = Google::Apis::SheetsV4::Color.new(red: 0.239, green: 0.522, blue: 0.776)
|
40
|
+
PURPLE = Google::Apis::SheetsV4::Color.new(red: 0.6, blue: 1.0)
|
41
|
+
DARK_PURPLE_1 = Google::Apis::SheetsV4::Color.new(red: 0.404, green: 0.306, blue: 0.655)
|
42
|
+
MAGENTA = Google::Apis::SheetsV4::Color.new(red: 1.0, blue: 1.0)
|
43
|
+
DARK_MAGENTA_1 = Google::Apis::SheetsV4::Color.new(red: 0.651, green: 0.302, blue: 0.475)
|
44
|
+
WHITE = Google::Apis::SheetsV4::Color.new(red: 1.0, green: 1.0, blue: 1.0)
|
45
|
+
BLACK = Google::Apis::SheetsV4::Color.new(red: 0.0, green: 0.0, blue: 0.0)
|
46
|
+
GRAY = Google::Apis::SheetsV4::Color.new(red: 0.8, green: 0.8, blue: 0.8)
|
47
|
+
DARK_GRAY_1 = Google::Apis::SheetsV4::Color.new(red: 0.714, green: 0.714, blue: 0.714)
|
48
|
+
end
|
49
|
+
|
19
50
|
# @api private
|
20
51
|
# A regexp which matches an invalid character in XML 1.0:
|
21
52
|
# https://en.wikipedia.org/wiki/Valid_characters_in_XML#XML_1.0
|
22
|
-
|
53
|
+
XML_INVALID_CHAR_REGEXP =
|
23
54
|
/[^\u0009\u000a\u000d\u0020-\ud7ff\ue000-\ufffd\u{10000}-\u{10ffff}]/
|
24
55
|
|
25
56
|
# @api private
|
26
|
-
def initialize(session, spreadsheet,
|
57
|
+
def initialize(session, spreadsheet, properties)
|
27
58
|
@session = session
|
28
59
|
@spreadsheet = spreadsheet
|
29
|
-
|
30
|
-
|
60
|
+
set_properties(properties)
|
31
61
|
@cells = nil
|
32
62
|
@input_values = nil
|
33
63
|
@numeric_values = nil
|
34
64
|
@modified = Set.new
|
35
65
|
@list = nil
|
66
|
+
@v4_requests = []
|
36
67
|
end
|
37
68
|
|
38
69
|
# Nokogiri::XML::Element object of the <entry> element in a worksheets feed.
|
39
|
-
|
70
|
+
#
|
71
|
+
# DEPRECATED: This method is deprecated, and now requires additional
|
72
|
+
# network fetch. Consider using properties instead.
|
73
|
+
def worksheet_feed_entry
|
74
|
+
@worksheet_feed_entry ||= @session.request(:get, worksheet_feed_url).root
|
75
|
+
end
|
76
|
+
|
77
|
+
# Google::Apis::SheetsV4::SheetProperties object for this worksheet.
|
78
|
+
attr_reader :properties
|
40
79
|
|
41
80
|
# Title of the worksheet (shown as tab label in Web interface).
|
42
|
-
attr_reader
|
81
|
+
attr_reader :title
|
82
|
+
|
83
|
+
# Index of the worksheet (affects tab order in web interface).
|
84
|
+
attr_reader :index
|
85
|
+
|
86
|
+
# GoogleDrive::Spreadsheet which this worksheet belongs to.
|
87
|
+
attr_reader :spreadsheet
|
43
88
|
|
44
89
|
# Time object which represents the time the worksheet was last updated.
|
45
|
-
|
90
|
+
#
|
91
|
+
# DEPRECATED: From google_drive 3.0.0, it returns the time the
|
92
|
+
# *spreadsheet* was last updated, instead of the worksheet. This is because
|
93
|
+
# it looks the information is not available in Sheets v4 API.
|
94
|
+
def updated
|
95
|
+
spreadsheet.modified_time.to_time
|
96
|
+
end
|
46
97
|
|
47
98
|
# URL of cell-based feed of the worksheet.
|
99
|
+
#
|
100
|
+
# DEPRECATED: This method is deprecated, and now requires additional
|
101
|
+
# network fetch.
|
48
102
|
def cells_feed_url
|
49
|
-
|
103
|
+
worksheet_feed_entry.css(
|
50
104
|
"link[rel='http://schemas.google.com/spreadsheets/2006#cellsfeed']"
|
51
105
|
)[0]['href']
|
52
106
|
end
|
53
107
|
|
54
108
|
# URL of worksheet feed URL of the worksheet.
|
55
109
|
def worksheet_feed_url
|
56
|
-
|
110
|
+
return '%s/%s' % [spreadsheet.worksheets_feed_url, worksheet_feed_id]
|
57
111
|
end
|
58
112
|
|
59
113
|
# URL to export the worksheet as CSV.
|
60
114
|
def csv_export_url
|
61
|
-
|
62
|
-
|
63
|
-
)[0]['href']
|
115
|
+
'https://docs.google.com/spreadsheets/d/%s/export?gid=%s&format=csv' %
|
116
|
+
[spreadsheet.id, gid]
|
64
117
|
end
|
65
118
|
|
66
119
|
# Exports the worksheet as String in CSV format.
|
@@ -74,10 +127,14 @@ module GoogleDrive
|
|
74
127
|
open(path, 'wb') { |f| f.write(data) }
|
75
128
|
end
|
76
129
|
|
77
|
-
#
|
130
|
+
# ID of the worksheet.
|
131
|
+
def sheet_id
|
132
|
+
@properties.sheet_id
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns sheet_id.to_s.
|
78
136
|
def gid
|
79
|
-
|
80
|
-
CGI.parse(URI.parse(csv_export_url).query)['gid'].last
|
137
|
+
sheet_id.to_s
|
81
138
|
end
|
82
139
|
|
83
140
|
# URL to view/edit the worksheet in a Web browser.
|
@@ -85,18 +142,22 @@ module GoogleDrive
|
|
85
142
|
format("%s\#gid=%s", spreadsheet.human_url, gid)
|
86
143
|
end
|
87
144
|
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
145
|
+
# Copy worksheet to specified spreadsheet.
|
146
|
+
# This method can take either instance of GoogleDrive::Spreadsheet or its id.
|
147
|
+
def copy_to(spreadsheet_or_id)
|
148
|
+
destination_spreadsheet_id =
|
149
|
+
spreadsheet_or_id.respond_to?(:id) ?
|
150
|
+
spreadsheet_or_id.id : spreadsheet_or_id
|
151
|
+
request = Google::Apis::SheetsV4::CopySheetToAnotherSpreadsheetRequest.new(
|
152
|
+
destination_spreadsheet_id: destination_spreadsheet_id,
|
153
|
+
)
|
154
|
+
@session.sheets_service.copy_spreadsheet(spreadsheet.id, sheet_id, request)
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
# Copy worksheet to owner spreadsheet.
|
159
|
+
def duplicate
|
160
|
+
copy_to(spreadsheet)
|
100
161
|
end
|
101
162
|
|
102
163
|
# Returns content of the cell as String. Arguments must be either
|
@@ -240,6 +301,13 @@ module GoogleDrive
|
|
240
301
|
@meta_modified = true
|
241
302
|
end
|
242
303
|
|
304
|
+
# Updates index of the worksheet.
|
305
|
+
# Note that update is not sent to the server until you call save().
|
306
|
+
def index=(index)
|
307
|
+
@index = index
|
308
|
+
@meta_modified = true
|
309
|
+
end
|
310
|
+
|
243
311
|
# @api private
|
244
312
|
def cells
|
245
313
|
reload_cells unless @cells
|
@@ -314,8 +382,19 @@ module GoogleDrive
|
|
314
382
|
# Note that changes you made by []= etc. is discarded if you haven't called
|
315
383
|
# save().
|
316
384
|
def reload
|
317
|
-
|
318
|
-
|
385
|
+
api_spreadsheet =
|
386
|
+
@session.sheets_service.get_spreadsheet(
|
387
|
+
spreadsheet.id,
|
388
|
+
ranges: "'%s'" % @title,
|
389
|
+
fields:
|
390
|
+
'sheets(properties,data.rowData.values' \
|
391
|
+
'(formattedValue,userEnteredValue,effectiveValue))'
|
392
|
+
)
|
393
|
+
api_sheet = api_spreadsheet.sheets[0]
|
394
|
+
set_properties(api_sheet.properties)
|
395
|
+
update_cells_from_api_sheet(api_sheet)
|
396
|
+
@v4_requests = []
|
397
|
+
@worksheet_feed_entry = nil
|
319
398
|
true
|
320
399
|
end
|
321
400
|
|
@@ -324,122 +403,59 @@ module GoogleDrive
|
|
324
403
|
sent = false
|
325
404
|
|
326
405
|
if @meta_modified
|
406
|
+
add_request({
|
407
|
+
update_sheet_properties: {
|
408
|
+
properties: {
|
409
|
+
sheet_id: sheet_id,
|
410
|
+
title: title,
|
411
|
+
index: index,
|
412
|
+
grid_properties: {row_count: max_rows, column_count: max_cols},
|
413
|
+
},
|
414
|
+
fields: '*',
|
415
|
+
},
|
416
|
+
})
|
417
|
+
end
|
327
418
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
|
332
|
-
<title>#{h(title)}</title>
|
333
|
-
<gs:rowCount>#{h(max_rows)}</gs:rowCount>
|
334
|
-
<gs:colCount>#{h(max_cols)}</gs:colCount>
|
335
|
-
</entry>
|
336
|
-
EOS
|
337
|
-
|
338
|
-
result = @session.request(
|
339
|
-
:put,
|
340
|
-
edit_url,
|
341
|
-
data: xml,
|
342
|
-
header: {
|
343
|
-
'Content-Type' => 'application/atom+xml;charset=utf-8',
|
344
|
-
'If-Match' => '*'
|
345
|
-
}
|
346
|
-
)
|
347
|
-
set_worksheet_feed_entry(result.root)
|
348
|
-
|
419
|
+
if !@v4_requests.empty?
|
420
|
+
self.spreadsheet.batch_update(@v4_requests)
|
421
|
+
@v4_requests = []
|
349
422
|
sent = true
|
350
423
|
end
|
351
424
|
|
352
|
-
|
353
|
-
# Gets id and edit URL for each cell.
|
354
|
-
# Note that return-empty=true is required to get those info for empty cells.
|
355
|
-
cell_entries = {}
|
356
|
-
rows = @modified.map { |r, _c| r }
|
357
|
-
cols = @modified.map { |_r, c| c }
|
358
|
-
url = concat_url(
|
359
|
-
cells_feed_url,
|
360
|
-
"?return-empty=true&min-row=#{rows.min}&max-row=#{rows.max}" \
|
361
|
-
"&min-col=#{cols.min}&max-col=#{cols.max}"
|
362
|
-
)
|
363
|
-
doc = @session.request(:get, url)
|
425
|
+
@remote_title = @title
|
364
426
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
427
|
+
unless @modified.empty?
|
428
|
+
min_modified_row = 1.0 / 0.0
|
429
|
+
max_modified_row = 0
|
430
|
+
min_modified_col = 1.0 / 0.0
|
431
|
+
max_modified_col = 0
|
432
|
+
@modified.each do |r, c|
|
433
|
+
min_modified_row = r if r < min_modified_row
|
434
|
+
max_modified_row = r if r > max_modified_row
|
435
|
+
min_modified_col = c if c < min_modified_col
|
436
|
+
max_modified_col = c if c > max_modified_col
|
369
437
|
end
|
370
438
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
raise(
|
384
|
-
GoogleDrive::Error,
|
385
|
-
format(
|
386
|
-
"The user doesn't have write permission to the spreadsheet: %p",
|
387
|
-
spreadsheet
|
388
|
-
)
|
389
|
-
)
|
439
|
+
# Uses update_spreadsheet_value instead batch_update_spreadsheet with
|
440
|
+
# update_cells. batch_update_spreadsheet has benefit that the request
|
441
|
+
# can be batched with other requests. But it has drawback that the
|
442
|
+
# type of the value (string_value, number_value, etc.) must be
|
443
|
+
# explicitly specified in user_entered_value. Since I don't know exact
|
444
|
+
# logic to determine the type from text, I chose to use
|
445
|
+
# update_spreadsheet_value here.
|
446
|
+
range = "'%s'!R%dC%d:R%dC%d" %
|
447
|
+
[@title, min_modified_row, min_modified_col, max_modified_row, max_modified_col]
|
448
|
+
values = (min_modified_row..max_modified_row).map do |r|
|
449
|
+
(min_modified_col..max_modified_col).map do |c|
|
450
|
+
@modified.include?([r, c]) ? (@cells[[r, c]] || '') : nil
|
390
451
|
end
|
391
|
-
edit_url = edit_link['href']
|
392
|
-
xml << <<-EOS
|
393
|
-
<entry>
|
394
|
-
<batch:id>#{h(row)},#{h(col)}</batch:id>
|
395
|
-
<batch:operation type="update"/>
|
396
|
-
<id>#{h(id)}</id>
|
397
|
-
<link
|
398
|
-
rel="edit"
|
399
|
-
type="application/atom+xml"
|
400
|
-
href="#{h(edit_url)}"/>
|
401
|
-
<gs:cell
|
402
|
-
row="#{h(row)}"
|
403
|
-
col="#{h(col)}"
|
404
|
-
inputValue="#{h(value)}"/>
|
405
|
-
</entry>
|
406
|
-
EOS
|
407
|
-
end
|
408
|
-
xml << <<-"EOS"
|
409
|
-
</feed>
|
410
|
-
EOS
|
411
|
-
|
412
|
-
batch_url = concat_url(cells_feed_url, '/batch')
|
413
|
-
result = @session.request(
|
414
|
-
:post,
|
415
|
-
batch_url,
|
416
|
-
data: xml,
|
417
|
-
header: {
|
418
|
-
'Content-Type' => 'application/atom+xml;charset=utf-8',
|
419
|
-
'If-Match' => '*'
|
420
|
-
}
|
421
|
-
)
|
422
|
-
result.css('entry').each do |entry|
|
423
|
-
interrupted = entry.css('batch|interrupted')[0]
|
424
|
-
if interrupted
|
425
|
-
raise(
|
426
|
-
GoogleDrive::Error,
|
427
|
-
format('Update has failed: %s', interrupted['reason'])
|
428
|
-
)
|
429
|
-
end
|
430
|
-
next if entry.css('batch|status').first['code'] =~ /^2/
|
431
|
-
raise(
|
432
|
-
GoogleDrive::Error,
|
433
|
-
format(
|
434
|
-
'Updating cell %s has failed: %s',
|
435
|
-
entry.css('id').text, entry.css('batch|status')[0]['reason']
|
436
|
-
)
|
437
|
-
)
|
438
452
|
end
|
453
|
+
value_range = Google::Apis::SheetsV4::ValueRange.new(values: values)
|
454
|
+
@session.sheets_service.update_spreadsheet_value(
|
455
|
+
spreadsheet.id, range, value_range, value_input_option: 'USER_ENTERED')
|
439
456
|
|
440
457
|
@modified.clear
|
441
458
|
sent = true
|
442
|
-
|
443
459
|
end
|
444
460
|
|
445
461
|
sent
|
@@ -454,17 +470,20 @@ module GoogleDrive
|
|
454
470
|
# Deletes this worksheet. Deletion takes effect right away without calling
|
455
471
|
# save().
|
456
472
|
def delete
|
457
|
-
|
458
|
-
|
459
|
-
|
473
|
+
spreadsheet.batch_update([{
|
474
|
+
delete_sheet: Google::Apis::SheetsV4::DeleteSheetRequest.new(sheet_id: sheet_id),
|
475
|
+
}])
|
460
476
|
end
|
461
477
|
|
462
|
-
# Returns true if you have changes made by []= which haven't been saved.
|
478
|
+
# Returns true if you have changes made by []= etc. which haven't been saved.
|
463
479
|
def dirty?
|
464
|
-
!@modified.empty?
|
480
|
+
!@modified.empty? || !@v4_requests.empty?
|
465
481
|
end
|
466
482
|
|
467
483
|
# List feed URL of the worksheet.
|
484
|
+
#
|
485
|
+
# DEPRECATED: This method is deprecated, and now requires additional
|
486
|
+
# network fetch.
|
468
487
|
def list_feed_url
|
469
488
|
@worksheet_feed_entry.css(
|
470
489
|
"link[rel='http://schemas.google.com/spreadsheets/2006#listfeed']"
|
@@ -517,7 +536,7 @@ module GoogleDrive
|
|
517
536
|
end
|
518
537
|
|
519
538
|
def inspect
|
520
|
-
fields = {
|
539
|
+
fields = { spreadsheet_id: spreadsheet.id, gid: gid }
|
521
540
|
fields[:title] = @title if @title
|
522
541
|
format(
|
523
542
|
"\#<%p %s>",
|
@@ -526,39 +545,170 @@ module GoogleDrive
|
|
526
545
|
)
|
527
546
|
end
|
528
547
|
|
529
|
-
|
548
|
+
# Merges a range of cells together. "MERGE_COLUMNS" is another option for merge_type
|
549
|
+
def merge_cells(top_row, left_col, num_rows, num_cols, merge_type: 'MERGE_ALL')
|
550
|
+
range = v4_range_object(top_row, left_col, num_rows, num_cols)
|
551
|
+
add_request({
|
552
|
+
merge_cells:
|
553
|
+
Google::Apis::SheetsV4::MergeCellsRequest.new(
|
554
|
+
range: range, merge_type: merge_type),
|
555
|
+
})
|
556
|
+
end
|
557
|
+
|
558
|
+
# Changes the formatting of a range of cells to match the given number format.
|
559
|
+
# For example to change A1 to a percentage with 1 decimal point:
|
560
|
+
# worksheet.set_number_format(1, 1, 1, 1, "##.#%")
|
561
|
+
# Google API reference: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#numberformat
|
562
|
+
def set_number_format(top_row, left_col, num_rows, num_cols, pattern, type: "NUMBER")
|
563
|
+
number_format = Google::Apis::SheetsV4::NumberFormat.new(type: type, pattern: pattern)
|
564
|
+
format = Google::Apis::SheetsV4::CellFormat.new(number_format: number_format)
|
565
|
+
fields = 'userEnteredFormat(numberFormat)'
|
566
|
+
format_cells(top_row, left_col, num_rows, num_cols, format, fields)
|
567
|
+
end
|
568
|
+
|
569
|
+
# Changes text alignment of a range of cells.
|
570
|
+
# Horizontal alignment can be "LEFT", "CENTER", or "RIGHT".
|
571
|
+
# Vertical alignment can be "TOP", "MIDDLE", or "BOTTOM".
|
572
|
+
# Google API reference: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#HorizontalAlign
|
573
|
+
def set_text_alignment(
|
574
|
+
top_row, left_col, num_rows, num_cols,
|
575
|
+
horizontal: nil, vertical: nil)
|
576
|
+
return if horizontal.nil? && vertical.nil?
|
577
|
+
|
578
|
+
format = Google::Apis::SheetsV4::CellFormat.new(
|
579
|
+
horizontal_alignment: horizontal, vertical_alignment: vertical)
|
580
|
+
subfields =
|
581
|
+
(horizontal.nil? ? [] : ['horizontalAlignment']) +
|
582
|
+
(vertical.nil? ? [] : ['verticalAlignment'])
|
583
|
+
|
584
|
+
fields = 'userEnteredFormat(%s)' % subfields.join(',')
|
585
|
+
format_cells(top_row, left_col, num_rows, num_cols, format, fields)
|
586
|
+
end
|
587
|
+
|
588
|
+
# Changes the background color on a range of cells. e.g.:
|
589
|
+
# worksheet.set_background_color(1, 1, 1, 1, GoogleDrive::Worksheet::Colors::DARK_YELLOW_1)
|
590
|
+
#
|
591
|
+
# background_color is an instance of Google::Apis::SheetsV4::Color.
|
592
|
+
def set_background_color(top_row, left_col, num_rows, num_cols, background_color)
|
593
|
+
format = Google::Apis::SheetsV4::CellFormat.new(background_color: background_color)
|
594
|
+
fields = 'userEnteredFormat(backgroundColor)'
|
595
|
+
format_cells(top_row, left_col, num_rows, num_cols, format, fields)
|
596
|
+
end
|
597
|
+
|
598
|
+
# Change the text formatting on a range of cells. e.g., To set cell
|
599
|
+
# A1 to have red text that is bold and italic:
|
600
|
+
# worksheet.set_text_format(
|
601
|
+
# 1, 1, 1, 1,
|
602
|
+
# bold: true,
|
603
|
+
# italic: true,
|
604
|
+
# foreground_color: GoogleDrive::Worksheet::Colors::RED_BERRY)
|
605
|
+
#
|
606
|
+
# foreground_color is an instance of Google::Apis::SheetsV4::Color.
|
607
|
+
# Google API reference:
|
608
|
+
# https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#textformat
|
609
|
+
def set_text_format(top_row, left_col, num_rows, num_cols, bold: false,
|
610
|
+
italic: false, strikethrough: false, font_size: nil,
|
611
|
+
font_family: nil, foreground_color: nil)
|
612
|
+
text_format = Google::Apis::SheetsV4::TextFormat.new(
|
613
|
+
bold: bold,
|
614
|
+
italic: italic,
|
615
|
+
strikethrough: strikethrough,
|
616
|
+
font_size: font_size,
|
617
|
+
font_family: font_family,
|
618
|
+
foreground_color: foreground_color
|
619
|
+
)
|
530
620
|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
621
|
+
format = Google::Apis::SheetsV4::CellFormat.new(text_format: text_format)
|
622
|
+
fields = 'userEnteredFormat(textFormat)'
|
623
|
+
format_cells(top_row, left_col, num_rows, num_cols, format, fields)
|
624
|
+
end
|
625
|
+
|
626
|
+
# Update the border styles for a range of cells.
|
627
|
+
# borders is a Hash of Google::Apis::SheetsV4::Border keyed with the
|
628
|
+
# following symbols: :top, :bottom, :left, :right, :innerHorizontal, :innerVertical
|
629
|
+
# e.g., To set a black double-line on the bottom of A1:
|
630
|
+
# update_borders(
|
631
|
+
# 1, 1, 1, 1,
|
632
|
+
# {bottom: Google::Apis::SheetsV4::Border.new(
|
633
|
+
# style: "DOUBLE", color: GoogleDrive::Worksheet::Colors::BLACK)})
|
634
|
+
def update_borders(top_row, left_col, num_rows, num_cols, borders)
|
635
|
+
request = Google::Apis::SheetsV4::UpdateBordersRequest.new(borders)
|
636
|
+
request.range = v4_range_object(top_row, left_col, num_rows, num_cols)
|
637
|
+
add_request({update_borders: request})
|
638
|
+
end
|
639
|
+
|
640
|
+
# Add an instance of Google::Apis::SheetsV4::Request (or its Hash
|
641
|
+
# equivalent) which will be applied on the next call to the save method.
|
642
|
+
def add_request(request)
|
643
|
+
@v4_requests.push(request)
|
537
644
|
end
|
538
645
|
|
539
|
-
|
540
|
-
|
541
|
-
|
646
|
+
# @api private
|
647
|
+
def worksheet_feed_id
|
648
|
+
gid_int = sheet_id
|
649
|
+
xor_val = gid_int > 31578 ? 474 : 31578
|
650
|
+
letter = gid_int > 31578 ? 'o' : ''
|
651
|
+
letter + (gid_int ^ xor_val).to_s(36)
|
652
|
+
end
|
653
|
+
|
654
|
+
private
|
655
|
+
|
656
|
+
def format_cells(top_row, left_col, num_rows, num_cols, format, fields)
|
657
|
+
add_request({
|
658
|
+
repeat_cell:
|
659
|
+
Google::Apis::SheetsV4::RepeatCellRequest.new(
|
660
|
+
range: v4_range_object(top_row, left_col, num_rows, num_cols),
|
661
|
+
cell: Google::Apis::SheetsV4::CellData.new(user_entered_format: format),
|
662
|
+
fields: fields
|
663
|
+
),
|
664
|
+
})
|
665
|
+
end
|
666
|
+
|
667
|
+
def set_properties(properties)
|
668
|
+
@properties = properties
|
669
|
+
@title = @remote_title = properties.title
|
670
|
+
@index = properties.index
|
671
|
+
if properties.grid_properties.nil?
|
672
|
+
@max_rows = @max_cols = 0
|
673
|
+
else
|
674
|
+
@max_rows = properties.grid_properties.row_count
|
675
|
+
@max_cols = properties.grid_properties.column_count
|
676
|
+
end
|
677
|
+
@meta_modified = false
|
542
678
|
end
|
543
679
|
|
544
680
|
def reload_cells
|
545
|
-
|
681
|
+
response =
|
682
|
+
@session.sheets_service.get_spreadsheet(
|
683
|
+
spreadsheet.id,
|
684
|
+
ranges: "'%s'" % @remote_title,
|
685
|
+
fields: 'sheets.data.rowData.values(formattedValue,userEnteredValue,effectiveValue)'
|
686
|
+
)
|
687
|
+
update_cells_from_api_sheet(response.sheets[0])
|
688
|
+
end
|
546
689
|
|
547
|
-
|
548
|
-
|
690
|
+
def update_cells_from_api_sheet(api_sheet)
|
691
|
+
rows_data = api_sheet.data[0].row_data || []
|
549
692
|
|
693
|
+
@num_rows = rows_data.size
|
694
|
+
@num_cols = 0
|
550
695
|
@cells = {}
|
551
696
|
@input_values = {}
|
552
697
|
@numeric_values = {}
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
698
|
+
|
699
|
+
rows_data.each_with_index do |row_data, r|
|
700
|
+
next if !row_data.values
|
701
|
+
@num_cols = row_data.values.size if row_data.values.size > @num_cols
|
702
|
+
row_data.values.each_with_index do |cell_data, c|
|
703
|
+
k = [r + 1, c + 1]
|
704
|
+
@cells[k] = cell_data.formatted_value || ''
|
705
|
+
@input_values[k] = extended_value_to_str(cell_data.user_entered_value)
|
706
|
+
@numeric_values[k] =
|
707
|
+
cell_data.effective_value && cell_data.effective_value.number_value ?
|
708
|
+
cell_data.effective_value.number_value.to_f : nil
|
709
|
+
end
|
561
710
|
end
|
711
|
+
|
562
712
|
@modified.clear
|
563
713
|
end
|
564
714
|
|
@@ -589,12 +739,32 @@ module GoogleDrive
|
|
589
739
|
end
|
590
740
|
|
591
741
|
def validate_cell_value(value)
|
592
|
-
if value =~
|
742
|
+
if value =~ XML_INVALID_CHAR_REGEXP
|
593
743
|
raise(
|
594
744
|
ArgumentError,
|
595
745
|
format('Contains invalid character %p for XML 1.0: %p', $&, value)
|
596
746
|
)
|
597
747
|
end
|
598
748
|
end
|
749
|
+
|
750
|
+
def v4_range_object(top_row, left_col, num_rows, num_cols)
|
751
|
+
Google::Apis::SheetsV4::GridRange.new(
|
752
|
+
sheet_id: sheet_id,
|
753
|
+
start_row_index: top_row - 1,
|
754
|
+
start_column_index: left_col - 1,
|
755
|
+
end_row_index: top_row + num_rows - 1,
|
756
|
+
end_column_index: left_col + num_cols - 1
|
757
|
+
)
|
758
|
+
end
|
759
|
+
|
760
|
+
def extended_value_to_str(extended_value)
|
761
|
+
return '' if !extended_value
|
762
|
+
value =
|
763
|
+
extended_value.number_value ||
|
764
|
+
extended_value.string_value ||
|
765
|
+
extended_value.bool_value ||
|
766
|
+
extended_value.formula_value
|
767
|
+
value.to_s
|
768
|
+
end
|
599
769
|
end
|
600
770
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google_drive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroshi Ichikawa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -31,25 +31,45 @@ dependencies:
|
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 2.0.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name: google-
|
34
|
+
name: google-apis-drive_v3
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.
|
39
|
+
version: 0.5.0
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 0.
|
42
|
+
version: 1.0.0
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 0.
|
49
|
+
version: 0.5.0
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.0.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: google-apis-sheets_v4
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.4.0
|
50
60
|
- - "<"
|
51
61
|
- !ruby/object:Gem::Version
|
52
|
-
version: 0.
|
62
|
+
version: 1.0.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.4.0
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.0.0
|
53
73
|
- !ruby/object:Gem::Dependency
|
54
74
|
name: googleauth
|
55
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,8 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
188
|
- !ruby/object:Gem::Version
|
169
189
|
version: '0'
|
170
190
|
requirements: []
|
171
|
-
|
172
|
-
rubygems_version: 2.6.14
|
191
|
+
rubygems_version: 3.2.3
|
173
192
|
signing_key:
|
174
193
|
specification_version: 4
|
175
194
|
summary: A library to read/write files/spreadsheets in Google Drive/Docs.
|