python-google-sheets 1.0.1__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google_sheets/api_request.py +45 -10
- google_sheets/google_sheets.py +52 -40
- google_sheets/spreadsheet_requests/__init__.py +4 -0
- google_sheets/spreadsheet_requests/dimension.py +8 -0
- google_sheets/spreadsheet_requests/general_models.py +12 -0
- {python_google_sheets-1.0.1.dist-info → python_google_sheets-1.2.0.dist-info}/METADATA +66 -22
- {python_google_sheets-1.0.1.dist-info → python_google_sheets-1.2.0.dist-info}/RECORD +10 -10
- {python_google_sheets-1.0.1.dist-info → python_google_sheets-1.2.0.dist-info}/WHEEL +0 -0
- {python_google_sheets-1.0.1.dist-info → python_google_sheets-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {python_google_sheets-1.0.1.dist-info → python_google_sheets-1.2.0.dist-info}/top_level.txt +0 -0
google_sheets/api_request.py
CHANGED
|
@@ -29,6 +29,7 @@ from .spreadsheet_requests import (
|
|
|
29
29
|
|
|
30
30
|
# dimension
|
|
31
31
|
InsertDimension,
|
|
32
|
+
DeleteDimension,
|
|
32
33
|
UpdateDimensionProperties,
|
|
33
34
|
AddDimensionGroup,
|
|
34
35
|
DeleteDimensionGroup,
|
|
@@ -111,10 +112,10 @@ class ApiRequest:
|
|
|
111
112
|
|
|
112
113
|
@staticmethod
|
|
113
114
|
def add_boolean_format_rule(
|
|
114
|
-
*,
|
|
115
115
|
sheet_id: int,
|
|
116
116
|
ranges: list[str],
|
|
117
117
|
condition_type: ConditionType,
|
|
118
|
+
*,
|
|
118
119
|
condition_values: list[ConditionValue] = None,
|
|
119
120
|
cell_format: CellFormat,
|
|
120
121
|
) -> dict:
|
|
@@ -142,8 +143,8 @@ class ApiRequest:
|
|
|
142
143
|
|
|
143
144
|
@staticmethod
|
|
144
145
|
def add(
|
|
145
|
-
*,
|
|
146
146
|
sheet_id: int,
|
|
147
|
+
*,
|
|
147
148
|
ranges: list[str],
|
|
148
149
|
interpolation_points: tuple[IPTypeAndValue, IPTypeAndValue] | tuple[IPTypeAndValue, IPTypeAndValue, IPTypeAndValue],
|
|
149
150
|
interpolation_point_colors: tuple[ColorStyle, ColorStyle] | tuple[ColorStyle, ColorStyle, ColorStyle],
|
|
@@ -209,10 +210,11 @@ class ApiRequest:
|
|
|
209
210
|
RED_YELLOW_GREEN_PERCENT = 'RED_YELLOW_GREEN_PERCENT'
|
|
210
211
|
|
|
211
212
|
@staticmethod
|
|
212
|
-
def add_preset(
|
|
213
|
+
def add_preset(sheet_id: int, ranges: list[str], preset: Preset) -> dict:
|
|
213
214
|
grid_ranges = [GridRange(sheet_id=sheet_id, **ApiRequest._split_excel_range(range_, return_as_dict=True)) for range_ in ranges]
|
|
214
215
|
AGP = ApiRequest.GradientRule.Preset
|
|
215
216
|
|
|
217
|
+
# Two interpolation points presets
|
|
216
218
|
if preset in (AGP.WHITE_GREEN, AGP.WHITE_YELLOW, AGP.WHITE_RED, AGP.GREEN_WHITE, AGP.YELLOW_WHITE, AGP.RED_WHITE):
|
|
217
219
|
if preset == AGP.WHITE_YELLOW:
|
|
218
220
|
minpoint_color_style, maxpoint_color_style = Color_.Basic.WHITE, Color_.ConditionalFormatting.YELLOW
|
|
@@ -241,7 +243,7 @@ class ApiRequest:
|
|
|
241
243
|
)
|
|
242
244
|
)).dict()
|
|
243
245
|
|
|
244
|
-
else: #
|
|
246
|
+
else: # Three interpolation points presets
|
|
245
247
|
if preset in (AGP.RED_WHITE_GREEN_PERCENTILE, AGP.RED_WHITE_GREEN_PERCENT):
|
|
246
248
|
minpoint_cs, midpoint_cs, maxpoint_cs = Color_.ConditionalFormatting.RED, Color_.Basic.WHITE, Color_.ConditionalFormatting.GREEN
|
|
247
249
|
midpoint_type = InterpolationPointType.PERCENTILE if preset == AGP.RED_WHITE_GREEN_PERCENTILE else InterpolationPointType.PERCENT
|
|
@@ -275,11 +277,11 @@ class ApiRequest:
|
|
|
275
277
|
)).dict()
|
|
276
278
|
|
|
277
279
|
@staticmethod
|
|
278
|
-
def delete_conditional_format_rule(
|
|
280
|
+
def delete_conditional_format_rule(sheet_id: int, *, index: int) -> dict:
|
|
279
281
|
return DeleteConditionalFormatRule(sheet_id=sheet_id, index=index).dict()
|
|
280
282
|
|
|
281
283
|
@staticmethod
|
|
282
|
-
def update_conditional_format_rule(
|
|
284
|
+
def update_conditional_format_rule(sheet_id: int, *, index: int, rule: ConditionalFormatRule) -> dict:
|
|
283
285
|
return UpdateConditionalFormatRule(sheet_id=sheet_id, index=index, rule=rule).dict()
|
|
284
286
|
|
|
285
287
|
@staticmethod
|
|
@@ -340,6 +342,7 @@ class ApiRequest:
|
|
|
340
342
|
@staticmethod
|
|
341
343
|
def unmerge_cells(
|
|
342
344
|
sheet_id: int,
|
|
345
|
+
*,
|
|
343
346
|
range_: str = None,
|
|
344
347
|
start_row: int = None,
|
|
345
348
|
end_row: int = None,
|
|
@@ -376,7 +379,7 @@ class ApiRequest:
|
|
|
376
379
|
).dict()
|
|
377
380
|
|
|
378
381
|
@staticmethod
|
|
379
|
-
def insert_rows(sheet_id: int, start_index: int, end_index: int = None, inherit_from_before: bool = True) -> dict:
|
|
382
|
+
def insert_rows(sheet_id: int, start_index: int, end_index: int = None, *, inherit_from_before: bool = True) -> dict:
|
|
380
383
|
"""
|
|
381
384
|
Indexes are zero-based and inclusive [start_index, end_index]. If end_index is not specified, then a single
|
|
382
385
|
row will be inserted at start_index.
|
|
@@ -393,7 +396,7 @@ class ApiRequest:
|
|
|
393
396
|
).dict()
|
|
394
397
|
|
|
395
398
|
@staticmethod
|
|
396
|
-
def insert_columns(sheet_id: int, start_index: int, end_index: int = None, inherit_from_before: bool = True) -> dict:
|
|
399
|
+
def insert_columns(sheet_id: int, start_index: int, end_index: int = None, *, inherit_from_before: bool = True) -> dict:
|
|
397
400
|
"""
|
|
398
401
|
Indexes are zero-based and inclusive [start_index, end_index]. If end_index is not specified, then a single
|
|
399
402
|
column will be inserted at start_index.
|
|
@@ -409,6 +412,38 @@ class ApiRequest:
|
|
|
409
412
|
inherit_from_before=inherit_from_before
|
|
410
413
|
).dict()
|
|
411
414
|
|
|
415
|
+
@staticmethod
|
|
416
|
+
def delete_rows(sheet_id: int, start_index: int, end_index: int = None):
|
|
417
|
+
"""
|
|
418
|
+
Indexes are zero-based and inclusive [start_index, end_index]. If end_index is not specified, then a single
|
|
419
|
+
row at start_index will be deleted.
|
|
420
|
+
"""
|
|
421
|
+
end_index = end_index or start_index
|
|
422
|
+
return DeleteDimension(
|
|
423
|
+
range=DimensionRange(
|
|
424
|
+
sheet_id=sheet_id,
|
|
425
|
+
dimension=Dimension.ROWS,
|
|
426
|
+
start_index=start_index,
|
|
427
|
+
end_index=end_index + 1
|
|
428
|
+
)
|
|
429
|
+
).dict()
|
|
430
|
+
|
|
431
|
+
@staticmethod
|
|
432
|
+
def delete_columns(sheet_id: int, start_index: int, end_index: int = None):
|
|
433
|
+
"""
|
|
434
|
+
Indexes are zero-based and inclusive [start_index, end_index]. If end_index is not specified, then a single
|
|
435
|
+
column at start_index will be deleted.
|
|
436
|
+
"""
|
|
437
|
+
end_index = end_index or start_index
|
|
438
|
+
return DeleteDimension(
|
|
439
|
+
range=DimensionRange(
|
|
440
|
+
sheet_id=sheet_id,
|
|
441
|
+
dimension=Dimension.COLUMNS,
|
|
442
|
+
start_index=start_index,
|
|
443
|
+
end_index=end_index + 1
|
|
444
|
+
)
|
|
445
|
+
).dict()
|
|
446
|
+
|
|
412
447
|
@staticmethod
|
|
413
448
|
def clear_columns(sheet_id: int, rows_count: int, start_index: int, end_index: int = None) -> dict:
|
|
414
449
|
"""
|
|
@@ -516,8 +551,8 @@ class ApiRequest:
|
|
|
516
551
|
|
|
517
552
|
@staticmethod
|
|
518
553
|
def add_sheet(
|
|
519
|
-
*,
|
|
520
554
|
sheet_id: int = None,
|
|
555
|
+
*,
|
|
521
556
|
title: str = None,
|
|
522
557
|
index: int = None,
|
|
523
558
|
hidden: bool = None,
|
|
@@ -542,7 +577,7 @@ class ApiRequest:
|
|
|
542
577
|
)).dict()
|
|
543
578
|
|
|
544
579
|
@staticmethod
|
|
545
|
-
def _split_excel_range(range_: str, return_as_dict: bool = False) -> tuple[int, int, int, int] | dict[str, int]:
|
|
580
|
+
def _split_excel_range(range_: str, *, return_as_dict: bool = False) -> tuple[int, int, int, int] | dict[str, int]:
|
|
546
581
|
if ':' in range_:
|
|
547
582
|
match = re.match(r'([A-Z]+)(\d+):([A-Z]+)(\d+)$', range_)
|
|
548
583
|
if not match:
|
google_sheets/google_sheets.py
CHANGED
|
@@ -4,7 +4,7 @@ from google.oauth2.service_account import Credentials
|
|
|
4
4
|
from googleapiclient.discovery import build
|
|
5
5
|
from googleapiclient.errors import HttpError
|
|
6
6
|
|
|
7
|
-
from .spreadsheet_requests import Spreadsheet, SheetProperties,
|
|
7
|
+
from .spreadsheet_requests import Spreadsheet, SheetProperties, RangeData, Dimension, ValueRenderOption, DateTimeRenderOption
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from googleapiclient.discovery import Resource # noqa
|
|
@@ -85,7 +85,7 @@ class GoogleSheets:
|
|
|
85
85
|
return spreadsheet_id, f'https://docs.google.com/spreadsheets/d/{spreadsheet_id}'
|
|
86
86
|
|
|
87
87
|
@staticmethod
|
|
88
|
-
def update_spreadsheet(spreadsheet_id: str, api_requests: list[dict], service: 'Resource') -> None:
|
|
88
|
+
def update_spreadsheet(spreadsheet_id: str, api_requests: list[dict], *, service: 'Resource') -> None:
|
|
89
89
|
"""
|
|
90
90
|
Updates Google Sheet with the specified API requests.
|
|
91
91
|
|
|
@@ -100,7 +100,7 @@ class GoogleSheets:
|
|
|
100
100
|
raise e
|
|
101
101
|
|
|
102
102
|
@staticmethod
|
|
103
|
-
def copy_sheet(source_spreadsheet_id: str, source_sheet_id: str, destination_spreadsheet_id: str, service: 'Resource') -> SheetProperties:
|
|
103
|
+
def copy_sheet(source_spreadsheet_id: str, source_sheet_id: str, destination_spreadsheet_id: str, *, service: 'Resource') -> SheetProperties:
|
|
104
104
|
request = service.spreadsheets().sheets().copyTo(
|
|
105
105
|
spreadsheetId=source_spreadsheet_id,
|
|
106
106
|
sheetId=source_sheet_id,
|
|
@@ -118,63 +118,75 @@ class GoogleSheets:
|
|
|
118
118
|
@staticmethod
|
|
119
119
|
def get_spreadsheet_range_values(
|
|
120
120
|
spreadsheet_id: str,
|
|
121
|
-
sheets: list[str | int],
|
|
122
|
-
ranges: list[list[str]],
|
|
121
|
+
sheets: list[str | int] | str | int,
|
|
122
|
+
ranges: list[list[str]] | list[str] | str,
|
|
123
|
+
*,
|
|
124
|
+
by_columns: bool = False,
|
|
123
125
|
service: 'Resource'
|
|
124
|
-
) -> list[list[
|
|
126
|
+
) -> list[list[RangeData]] | None:
|
|
125
127
|
"""
|
|
126
128
|
Reads values from the specified ranges of the table.
|
|
127
129
|
IMPORTANT: If the last cells in the range are empty, they will be omitted. If all cells are empty, an empty
|
|
128
130
|
list will be returned for that range. However, leading empty cells are preserved and will appear in
|
|
129
|
-
the result
|
|
131
|
+
the result.
|
|
130
132
|
|
|
131
133
|
Args:
|
|
132
|
-
spreadsheet_id (str): ID of the table
|
|
133
|
-
sheets (list[str | int]): Name or ID of the
|
|
134
|
-
ranges (list[list[str]]):
|
|
135
|
-
|
|
134
|
+
spreadsheet_id (str): ID of the table.
|
|
135
|
+
sheets (list[str | int] | str | int): Name or ID of the sheet(s).
|
|
136
|
+
ranges (list[list[str]] | list[str] | str): Single range or list of ranges from each sheet in A1 notation.
|
|
137
|
+
by_columns (bool, optional): If True, returns data organized by columns instead of rows. Defaults to False.
|
|
138
|
+
service (googleapiclient.discovery.Resource): Google Sheets service object.
|
|
136
139
|
|
|
137
140
|
Returns:
|
|
138
|
-
list[list[
|
|
139
|
-
corresponds to an element in the list. If the range is a single row or a single column, a list of values
|
|
140
|
-
is returned Otherwise, a list of lists of values is returned.
|
|
141
|
+
list[list[RangeData]] | None: For each range of each sheet, returns a matrix of values (RangeData - list[list[SimpleType]]). Returns None if an error occurs.
|
|
141
142
|
"""
|
|
142
|
-
assert
|
|
143
|
+
assert \
|
|
144
|
+
( # sheets: list[str | int], ranges: list[list[str]]
|
|
145
|
+
isinstance(sheets, list) and not isinstance(sheets[0], list) and
|
|
146
|
+
isinstance(ranges, list) and isinstance(ranges[0], list) and not isinstance(ranges[0][0], list) and
|
|
147
|
+
len(sheets) == len(ranges)
|
|
148
|
+
) or ( # sheets: str | int, ranges: list[str] | str
|
|
149
|
+
(isinstance(sheets, str) or isinstance(sheets, int)) and
|
|
150
|
+
(isinstance(ranges, list) and not isinstance(ranges[0], list) or isinstance(ranges, str))
|
|
151
|
+
), 'sheets and ranges must be either list[str | int] and list[list[str]] respectively and same size, or str | int and list[str] | str respectively'
|
|
152
|
+
|
|
153
|
+
# Normalize sheets and ranges to list[str | int] and list[list[str]] respectively
|
|
154
|
+
if isinstance(ranges, str):
|
|
155
|
+
ranges = [ranges]
|
|
156
|
+
if isinstance(sheets, str) or isinstance(sheets, int):
|
|
157
|
+
sheets = [sheets]
|
|
158
|
+
ranges = [ranges]
|
|
143
159
|
|
|
144
160
|
ranges_processed = []
|
|
161
|
+
ss = None
|
|
145
162
|
if any(isinstance(sheet, int) for sheet in sheets):
|
|
146
163
|
ss = GoogleSheets.get_spreadsheet(spreadsheet_id, service)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
for sheet_id_or_name, sheet_ranges in zip(sheets, ranges):
|
|
165
|
+
if isinstance(sheet_id_or_name, int):
|
|
166
|
+
try:
|
|
167
|
+
sheet_name = next(sht.properties.title for sht in ss.sheets if sht.properties.sheet_id == sheet_id_or_name)
|
|
168
|
+
except StopIteration:
|
|
169
|
+
return None
|
|
170
|
+
else:
|
|
171
|
+
sheet_name = sheet_id_or_name
|
|
172
|
+
ranges_processed.extend([f'{sheet_name}!{range_}' for range_ in sheet_ranges])
|
|
154
173
|
|
|
155
174
|
try:
|
|
156
175
|
response = service.spreadsheets().values().batchGet(
|
|
157
176
|
spreadsheetId=spreadsheet_id,
|
|
158
177
|
ranges=ranges_processed,
|
|
159
|
-
|
|
160
|
-
|
|
178
|
+
majorDimension=Dimension.COLUMNS if by_columns else Dimension.ROWS,
|
|
179
|
+
valueRenderOption=ValueRenderOption.UNFORMATTED_VALUE,
|
|
180
|
+
dateTimeRenderOption=DateTimeRenderOption.FORMATTED_STRING
|
|
161
181
|
).execute(num_retries=5)
|
|
162
|
-
except HttpError
|
|
163
|
-
|
|
182
|
+
except HttpError:
|
|
183
|
+
return None
|
|
164
184
|
else:
|
|
165
185
|
result = []
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if len(values) == 1: # If range is a single row
|
|
173
|
-
result.append(values[0])
|
|
174
|
-
else:
|
|
175
|
-
if max([len(row) for row in values]) <= 1: # If range is a single column
|
|
176
|
-
result.append([(row[0] if row else '') for row in values])
|
|
177
|
-
else:
|
|
178
|
-
result.append(values)
|
|
179
|
-
|
|
186
|
+
value_ranges = iter(response.get('valueRanges', []))
|
|
187
|
+
for sheet_no in range(len(ranges)):
|
|
188
|
+
sheet_ranges = []
|
|
189
|
+
for range_no in range(len(ranges[sheet_no])):
|
|
190
|
+
sheet_ranges.append(next(value_ranges).get('values', []))
|
|
191
|
+
result.append(sheet_ranges)
|
|
180
192
|
return result
|
|
@@ -24,6 +24,7 @@ from .merge_cells import (
|
|
|
24
24
|
)
|
|
25
25
|
from .dimension import (
|
|
26
26
|
InsertDimension,
|
|
27
|
+
DeleteDimension,
|
|
27
28
|
UpdateDimensionProperties,
|
|
28
29
|
AddDimensionGroup,
|
|
29
30
|
DeleteDimensionGroup,
|
|
@@ -58,9 +59,12 @@ from .spreadsheet import (
|
|
|
58
59
|
)
|
|
59
60
|
|
|
60
61
|
from .general_models import (
|
|
62
|
+
ValueRenderOption,
|
|
63
|
+
DateTimeRenderOption,
|
|
61
64
|
Color,
|
|
62
65
|
ColorStyle,
|
|
63
66
|
GridRange,
|
|
64
67
|
FieldMask,
|
|
65
68
|
SimpleType,
|
|
69
|
+
RangeData,
|
|
66
70
|
)
|
|
@@ -51,6 +51,14 @@ class InsertDimension(BaseModel):
|
|
|
51
51
|
return {class_name: json.loads(super().json(*args, **kwargs, by_alias=True, exclude_none=True))}
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
class DeleteDimension(BaseModel):
|
|
55
|
+
range: DimensionRange
|
|
56
|
+
|
|
57
|
+
def dict(self, *args, **kwargs):
|
|
58
|
+
class_name = self.__class__.__name__[0].lower() + self.__class__.__name__[1:]
|
|
59
|
+
return {class_name: json.loads(super().json(*args, **kwargs, by_alias=True, exclude_none=True))}
|
|
60
|
+
|
|
61
|
+
|
|
54
62
|
class UpdateDimensionProperties(BaseModel):
|
|
55
63
|
range: DimensionRange
|
|
56
64
|
properties: DimensionProperties
|
|
@@ -4,6 +4,18 @@ from pydantic import BaseModel, Field, model_validator
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
SimpleType = str | int | float | bool
|
|
7
|
+
RangeData = list[list[SimpleType]]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ValueRenderOption(StrEnum):
|
|
11
|
+
FORMATTED_VALUE = 'FORMATTED_VALUE' # Calculated & formatted according to the cell's formatting. DEFAULT value.
|
|
12
|
+
UNFORMATTED_VALUE = 'UNFORMATTED_VALUE' # Calculated, not formatted (e.g. 123.45 instead of $123.45).
|
|
13
|
+
FORMULA = 'FORMULA' # The formula as entered in the cell, e.g. '=SUM(A1:B1)'. If the cell contains a formula, this field will start with an '=' sign.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DateTimeRenderOption(StrEnum):
|
|
17
|
+
SERIAL_NUMBER = 'SERIAL_NUMBER' # A number, where 1 corresponds to December 30, 1899. DEFAULT value.
|
|
18
|
+
FORMATTED_STRING = 'FORMATTED_STRING' # A string, formatted according to the cell's formatting.
|
|
7
19
|
|
|
8
20
|
|
|
9
21
|
class ThemeColorType(StrEnum):
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-google-sheets
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: A lightweight and efficient Python wrapper for the Google Sheets API v4
|
|
5
5
|
Author-email: Timofey Egorov <timegorr@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Timofey28/python-google-sheets
|
|
8
|
+
Project-URL: Issues, https://github.com/Timofey28/python-google-sheets/issues
|
|
9
|
+
Keywords: spreadsheets,google-spreadsheets,google-sheets,api,wrapper,python,pydantic
|
|
7
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
8
15
|
Classifier: Operating System :: OS Independent
|
|
9
16
|
Requires-Python: >=3.11
|
|
10
17
|
Description-Content-Type: text/markdown
|
|
@@ -81,7 +88,7 @@ spreadsheet_id, url = GoogleSheets.create_spreadsheet(
|
|
|
81
88
|
)
|
|
82
89
|
```
|
|
83
90
|
|
|
84
|
-
### `update_spreadsheet(spreadsheet_id: str, api_requests: list[dict], service: 'Resource') -> None`
|
|
91
|
+
### `update_spreadsheet(spreadsheet_id: str, api_requests: list[dict], *, service: 'Resource') -> None`
|
|
85
92
|
Execute a `batchUpdate` with one or more request objects.
|
|
86
93
|
|
|
87
94
|
```python
|
|
@@ -93,7 +100,7 @@ requests = [
|
|
|
93
100
|
GoogleSheets.update_spreadsheet(spreadsheet_id, requests, service)
|
|
94
101
|
```
|
|
95
102
|
|
|
96
|
-
### `copy_sheet(source_spreadsheet_id: str, source_sheet_id: str, destination_spreadsheet_id: str, service: 'Resource') -> SheetProperties`
|
|
103
|
+
### `copy_sheet(source_spreadsheet_id: str, source_sheet_id: str, destination_spreadsheet_id: str, *, service: 'Resource') -> SheetProperties`
|
|
97
104
|
Copy a sheet from one spreadsheet into another.
|
|
98
105
|
|
|
99
106
|
```python
|
|
@@ -113,19 +120,39 @@ spreadsheet = GoogleSheets.get_spreadsheet(spreadsheet_id, service)
|
|
|
113
120
|
print([sheet.properties.title for sheet in spreadsheet.sheets])
|
|
114
121
|
```
|
|
115
122
|
|
|
116
|
-
### `get_spreadsheet_range_values(spreadsheet_id: str, sheets: list[str | int], ranges: list[list[str]], service: 'Resource') -> list[list[
|
|
117
|
-
|
|
123
|
+
### `get_spreadsheet_range_values(spreadsheet_id: str, sheets: list[str | int] | str | int, ranges: list[list[str]] | list[str] | str, *, by_columns: bool = False, service: 'Resource') -> list[list[RangeData]] | None:`
|
|
124
|
+
Reads values from multiple ranges across multiple sheets. Returns a matrix of values (RangeData - list[list[SimpleType]]) for each range of each sheet. Returns None if an error occurs.
|
|
125
|
+
|
|
126
|
+
Code from this example returns one range from sheet with id `1601337967` and three ranges from sheet `Summary` (assuming that these sheets exist in the spreadsheet). You can mix and match sheet names and ids as needed.
|
|
118
127
|
|
|
119
128
|
```python
|
|
120
129
|
values = GoogleSheets.get_spreadsheet_range_values(
|
|
121
|
-
spreadsheet_id=
|
|
122
|
-
sheets=[
|
|
123
|
-
ranges=[['A2:
|
|
124
|
-
service=service
|
|
130
|
+
spreadsheet_id=SPREADSHEET_ID,
|
|
131
|
+
sheets=[1601337967, 'Summary'],
|
|
132
|
+
ranges=[['A2:C100'], ['A1:E10', 'F1:F10', 'H1']],
|
|
133
|
+
service=service
|
|
125
134
|
)
|
|
126
|
-
print(values)
|
|
127
135
|
```
|
|
128
136
|
|
|
137
|
+
Next two examples return the same data (assuming that sheet `Sheet1` exists and has id `0`). With `by_columns=True` the values are grouped by columns instead of rows.
|
|
138
|
+
```python
|
|
139
|
+
values = GoogleSheets.get_spreadsheet_range_values(
|
|
140
|
+
SPREADSHEET_ID,
|
|
141
|
+
sheets='Sheet1',
|
|
142
|
+
ranges=['A1:E5'],
|
|
143
|
+
by_columns=True,
|
|
144
|
+
service=service
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
```python
|
|
148
|
+
values = GoogleSheets.get_spreadsheet_range_values(
|
|
149
|
+
SPREADSHEET_ID,
|
|
150
|
+
sheets=0,
|
|
151
|
+
ranges='A1:E5',
|
|
152
|
+
by_columns=True,
|
|
153
|
+
service=service
|
|
154
|
+
)
|
|
155
|
+
```
|
|
129
156
|
---
|
|
130
157
|
|
|
131
158
|
## `ApiRequest` methods for `batchUpdate`
|
|
@@ -151,9 +178,10 @@ req = ApiRequest.update_cells(
|
|
|
151
178
|
)
|
|
152
179
|
```
|
|
153
180
|
|
|
181
|
+
---
|
|
154
182
|
### Conditional formatting
|
|
155
183
|
|
|
156
|
-
### `add_boolean_format_rule(
|
|
184
|
+
### `add_boolean_format_rule(sheet_id: int, ranges: list[str], condition_type: ConditionType, *, condition_values: list[ConditionValue] = None, cell_format: CellFormat) -> dict`
|
|
157
185
|
Add a rule (for example, highlight values greater than `100`).
|
|
158
186
|
|
|
159
187
|
```python
|
|
@@ -171,7 +199,7 @@ req = ApiRequest.add_boolean_format_rule(
|
|
|
171
199
|
)
|
|
172
200
|
```
|
|
173
201
|
|
|
174
|
-
### `GradientRule.add(
|
|
202
|
+
### `GradientRule.add(sheet_id: int, *, ranges: list[str], interpolation_points: tuple[IPTypeAndValue, IPTypeAndValue] | tuple[IPTypeAndValue, IPTypeAndValue, IPTypeAndValue], interpolation_point_colors: tuple[ColorStyle, ColorStyle] | tuple[ColorStyle, ColorStyle, ColorStyle]) -> dict`
|
|
175
203
|
Add a custom color scale with 2 or 3 interpolation points.
|
|
176
204
|
|
|
177
205
|
```python
|
|
@@ -193,7 +221,7 @@ req = ApiRequest.GradientRule.add(
|
|
|
193
221
|
)
|
|
194
222
|
```
|
|
195
223
|
|
|
196
|
-
### `GradientRule.add_preset(
|
|
224
|
+
### `GradientRule.add_preset(sheet_id: int, ranges: list[str], preset: Preset) -> dict`
|
|
197
225
|
Add a gradient rule from a built-in preset.
|
|
198
226
|
|
|
199
227
|
```python
|
|
@@ -204,14 +232,14 @@ req = ApiRequest.GradientRule.add_preset(
|
|
|
204
232
|
)
|
|
205
233
|
```
|
|
206
234
|
|
|
207
|
-
### `delete_conditional_format_rule(
|
|
235
|
+
### `delete_conditional_format_rule(sheet_id: int, *, index: int) -> dict`
|
|
208
236
|
Delete a conditional format rule by index.
|
|
209
237
|
|
|
210
238
|
```python
|
|
211
239
|
req = ApiRequest.delete_conditional_format_rule(sheet_id=0, index=0)
|
|
212
240
|
```
|
|
213
241
|
|
|
214
|
-
### `update_conditional_format_rule(
|
|
242
|
+
### `update_conditional_format_rule(sheet_id: int, *, index: int, rule: ConditionalFormatRule) -> dict`
|
|
215
243
|
Replace an existing conditional format rule by index.
|
|
216
244
|
|
|
217
245
|
```python
|
|
@@ -299,7 +327,7 @@ Delete a sheet.
|
|
|
299
327
|
req = ApiRequest.delete_sheet(sheet_id=3)
|
|
300
328
|
```
|
|
301
329
|
|
|
302
|
-
### `add_sheet(
|
|
330
|
+
### `add_sheet(sheet_id: int = None, *, title: str = None, index: int = None, hidden: bool = None, row_count: int = None, column_count: int = None, frozen_row_count: int = None, frozen_column_count: int = None, hide_grid_lines: bool = None) -> dict`
|
|
303
331
|
Create a new sheet with optional properties.
|
|
304
332
|
|
|
305
333
|
```python
|
|
@@ -311,6 +339,7 @@ req = ApiRequest.add_sheet(
|
|
|
311
339
|
)
|
|
312
340
|
```
|
|
313
341
|
|
|
342
|
+
---
|
|
314
343
|
### Merge and freeze
|
|
315
344
|
|
|
316
345
|
### `merge_cells(sheet_id: int, range_: str, merge_type: MergeType = MergeType.MERGE_ALL) -> dict`
|
|
@@ -320,7 +349,7 @@ Merge cells in a range.
|
|
|
320
349
|
req = ApiRequest.merge_cells(sheet_id=0, range_='A1:C1')
|
|
321
350
|
```
|
|
322
351
|
|
|
323
|
-
### `unmerge_cells(sheet_id: int, range_: str = None, start_row: int = None, end_row: int = None, start_column: int | str = None, end_column: int | str = None) -> dict`
|
|
352
|
+
### `unmerge_cells(sheet_id: int, *, range_: str = None, start_row: int = None, end_row: int = None, start_column: int | str = None, end_column: int | str = None) -> dict`
|
|
324
353
|
Unmerge cells in a range (or by explicit indexes).
|
|
325
354
|
|
|
326
355
|
```python
|
|
@@ -334,24 +363,39 @@ Freeze top rows and/or left columns.
|
|
|
334
363
|
req = ApiRequest.freeze(sheet_id=0, rows=1, columns=1)
|
|
335
364
|
```
|
|
336
365
|
|
|
366
|
+
---
|
|
337
367
|
### Rows and columns
|
|
338
368
|
|
|
339
|
-
### `insert_rows(sheet_id: int, start_index: int, end_index: int = None, inherit_from_before: bool = True) -> dict`
|
|
340
|
-
Insert one or more rows (zero-based
|
|
369
|
+
### `insert_rows(sheet_id: int, start_index: int, end_index: int = None, *, inherit_from_before: bool = True) -> dict`
|
|
370
|
+
Insert one or more rows (Indexes are zero-based and inclusive [start_index, end_index]).
|
|
341
371
|
|
|
342
372
|
```python
|
|
343
373
|
req = ApiRequest.insert_rows(sheet_id=0, start_index=5, end_index=9)
|
|
344
374
|
```
|
|
345
375
|
|
|
346
|
-
### `insert_columns(sheet_id: int, start_index: int, end_index: int = None, inherit_from_before: bool = True) -> dict`
|
|
347
|
-
Insert columns (zero-based
|
|
376
|
+
### `insert_columns(sheet_id: int, start_index: int, end_index: int = None, *, inherit_from_before: bool = True) -> dict`
|
|
377
|
+
Insert columns (Indexes are zero-based and inclusive [start_index, end_index]).
|
|
348
378
|
|
|
349
379
|
```python
|
|
350
380
|
req = ApiRequest.insert_columns(sheet_id=0, start_index=2, end_index=3)
|
|
351
381
|
```
|
|
352
382
|
|
|
383
|
+
### `delete_rows(sheet_id: int, start_index: int, end_index: int = None) -> dict`
|
|
384
|
+
Delete one or more rows (Indexes are zero-based and inclusive [start_index, end_index]).
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
req = ApiRequest.delete_rows(sheet_id=0, start_index=5, end_index=9)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### `delete_columns(sheet_id: int, start_index: int, end_index: int = None) -> dict`
|
|
391
|
+
Delete columns (Indexes are zero-based and inclusive [start_index, end_index]).
|
|
392
|
+
|
|
393
|
+
```python
|
|
394
|
+
req = ApiRequest.delete_columns(sheet_id=0, start_index=2, end_index=3)
|
|
395
|
+
```
|
|
396
|
+
|
|
353
397
|
### `clear_columns(sheet_id: int, rows_count: int, start_index: int, end_index: int = None) -> dict`
|
|
354
|
-
Clear values and formatting in one or more columns.
|
|
398
|
+
Clear values and formatting in one or more columns (Indexes are zero-based and inclusive [start_index, end_index]).
|
|
355
399
|
|
|
356
400
|
```python
|
|
357
401
|
req = ApiRequest.clear_columns(sheet_id=0, rows_count=500, start_index=4, end_index=5)
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
google_sheets/__init__.py,sha256=ZhBNb6oS2tyliSe89Vc0Kw0DSxLMArl3GIMQNf1qsKo,850
|
|
2
|
-
google_sheets/api_request.py,sha256=
|
|
3
|
-
google_sheets/google_sheets.py,sha256=
|
|
2
|
+
google_sheets/api_request.py,sha256=MJ14qQ8j4LVXxXGl80nhzep4WN76gcyLoZC8QSvy6DE,26470
|
|
3
|
+
google_sheets/google_sheets.py,sha256=uJBdCoFNFSFl-zQIhKm9JT7y3IL8tjvwUXdUNysNpMw,8886
|
|
4
4
|
google_sheets/styles.py,sha256=9n-4W8EW8F62JxPCL99uctNVv3j703wO2UqoAGWoylo,13418
|
|
5
5
|
google_sheets/utils.py,sha256=hmqVC75t2Q4lTztKKxerWar7B_HQnrmO2EGhbesdkNU,1695
|
|
6
|
-
google_sheets/spreadsheet_requests/__init__.py,sha256=
|
|
6
|
+
google_sheets/spreadsheet_requests/__init__.py,sha256=ygiBT-2Rg67DEULY24NcAjFfSUR9IrCedLQz47LjXcs,1398
|
|
7
7
|
google_sheets/spreadsheet_requests/conditional_format_rule.py,sha256=wCN37BBWnoitXifcl9ni0KlPKxuKEwIVOnt7Z2n6DcE,6775
|
|
8
|
-
google_sheets/spreadsheet_requests/dimension.py,sha256=
|
|
9
|
-
google_sheets/spreadsheet_requests/general_models.py,sha256=
|
|
8
|
+
google_sheets/spreadsheet_requests/dimension.py,sha256=CLKyPsEvoQXGCYky_FLU3CBOlAr8qkLVZaKDzng703g,2952
|
|
9
|
+
google_sheets/spreadsheet_requests/general_models.py,sha256=1hq157SuycJ_9bC84lfLajRiL8vkLPMwGc-b-wOBON0,3484
|
|
10
10
|
google_sheets/spreadsheet_requests/merge_cells.py,sha256=Y7ChGjmb07jCCG1aP2Ws126cq2AXfhF4rwqskvrTv0w,1023
|
|
11
11
|
google_sheets/spreadsheet_requests/spreadsheet.py,sha256=lUMhrIpo_YOiPEbzgwONeSx4GDaeSn928R83qHcj7F8,3706
|
|
12
12
|
google_sheets/spreadsheet_requests/update_cells.py,sha256=cOLcDKp4pgj6xgzoWOJXCO8IlmK_htweX-6WzNka9TM,9159
|
|
13
13
|
google_sheets/spreadsheet_requests/update_sheet_properties.py,sha256=Gvmrc2SV3UCBF40mJCsAQaOKppA_C53dp8LYrRaisfM,1830
|
|
14
|
-
python_google_sheets-1.0.
|
|
15
|
-
python_google_sheets-1.0.
|
|
16
|
-
python_google_sheets-1.0.
|
|
17
|
-
python_google_sheets-1.0.
|
|
18
|
-
python_google_sheets-1.0.
|
|
14
|
+
python_google_sheets-1.2.0.dist-info/licenses/LICENSE,sha256=2PFWLbALHdUFzFd2QtLQvu7Ku4M6IO53Ns6b892nVvg,1090
|
|
15
|
+
python_google_sheets-1.2.0.dist-info/METADATA,sha256=eu_uK-kaX_Ygb-wZ3g52w87RYcoiWbR3X4EL9IyOIyo,17740
|
|
16
|
+
python_google_sheets-1.2.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
17
|
+
python_google_sheets-1.2.0.dist-info/top_level.txt,sha256=AEiUl4h4VXrqsRO0AiL9C7ArYqmDhVuz--b035K3r34,14
|
|
18
|
+
python_google_sheets-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
{python_google_sheets-1.0.1.dist-info → python_google_sheets-1.2.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|