Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/user-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,23 @@ Alternatively, use ``gspread.utils.to_records()`` for more control over headers:
# {'fruit': 'banana', 'alternate name': 'yellow stick', 'tastiness': 'quite'}


Getting All Values From Every Worksheet at Once
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Using ``get_all_worksheet_values()`` (fetches every worksheet in a single API call):

.. code:: python

all_values = spreadsheet.get_all_worksheet_values()
# {'Sheet1': [['a', 'b'], ['c', 'd']], 'Sheet 2': [['1', '2']]}

Optionally, pass ``skip_worksheet_titles`` to leave out worksheets you don't need:

.. code:: python

all_values = spreadsheet.get_all_worksheet_values(skip_worksheet_titles=["Sheet1"])


Loading Worksheet Data into a DataFrame
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
32 changes: 31 additions & 1 deletion gspread/spreadsheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from .exceptions import WorksheetNotFound
from .http_client import HTTPClient, ParamsType
from .urls import DRIVE_FILES_API_V3_URL, SPREADSHEET_DRIVE_URL
from .utils import ExportFormat, finditem
from .utils import ExportFormat, absolute_range_name, extract_title_from_range, finditem
from .worksheet import Worksheet


Expand Down Expand Up @@ -284,6 +284,36 @@ def get_worksheet_by_id(self, id: Union[str, int]) -> Worksheet:
except (StopIteration, KeyError):
raise WorksheetNotFound("id {} not found".format(worksheet_id_int))

def get_all_worksheet_values(
self,
skip_worksheet_titles: Optional[List[str]] = None,
params: Optional[ParamsType] = None,
) -> Dict:
"""Returns all values from all worksheets in a single API call.

:param list skip_worksheet_titles: (optional) A list of worksheet titles to skip.
:returns: A dict mapping worksheet title to its values.
:rtype: dict
"""
if skip_worksheet_titles is None:
skip_worksheet_titles = []

ranges = [
absolute_range_name(ws.title)
for ws in self.worksheets()
if ws.title not in skip_worksheet_titles
]

if not ranges:
return {}

response = self.values_batch_get(ranges, params=params)

return {
extract_title_from_range(vr["range"]): vr.get("values", [])
for vr in response.get("valueRanges", [])
}

def worksheets(self, exclude_hidden: bool = False) -> List[Worksheet]:
"""Returns a list of all :class:`worksheets <gspread.worksheet.Worksheet>`
in a spreadsheet.
Expand Down
21 changes: 19 additions & 2 deletions gspread/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
CELL_ADDR_RE = re.compile(r"([A-Za-z]+)([1-9]\d*)")
A1_ADDR_ROW_COL_RE = re.compile(r"([A-Za-z]+)?([1-9]\d*)?$")
A1_ADDR_FULL_RE = re.compile(r"[A-Za-z]+\d+:[A-Za-z]+\d+") # e.g. A1:B2 not A1:B
SHEET_TITLE_RE = re.compile(r"'((?:[^']|'')+)'!|([^!]+)!")

URL_KEY_V1_RE = re.compile(r"key=([^&#]+)")
URL_KEY_V2_RE = re.compile(r"/spreadsheets/d/([a-zA-Z0-9-_]+)")
Expand Down Expand Up @@ -365,7 +366,7 @@ def rowcol_to_a1(row: int, col: int) -> str:
column_label = ""

while div:
(div, mod) = divmod(div, 26)
div, mod = divmod(div, 26)
if mod == 0:
mod = 26
div -= 1
Expand Down Expand Up @@ -561,7 +562,7 @@ def column_letter_to_index(column: str) -> int:
gspread.exceptions.InvalidInputValue: invalid value: !@#$%^&, must be a column letter
"""
try:
(_, index) = _a1_to_rowcol_unbounded(column)
_, index = _a1_to_rowcol_unbounded(column)
except IncorrectCellLabel:
# make it coherent and raise the same exception in case of any error
# from user input value
Expand Down Expand Up @@ -622,6 +623,22 @@ def extract_id_from_url(url: str) -> str:
raise NoValidUrlKeyFound


def extract_title_from_range(range_string: str) -> str:
"""Extracts the worksheet title from a range string.

:param str range_string: A range string e.g. ``'Sheet Name'!A1:Z100`` or ``Sheet1!A1:Z100``
:returns: The worksheet title.
:rtype: str

:raises:
:class:`~gspread.exceptions.InvalidInputValue`: if the title cannot be extracted.
"""
match = SHEET_TITLE_RE.match(range_string)
if match:
return (match.group(1) or match.group(2)).replace("''", "'")
raise InvalidInputValue


def wid_to_gid(wid: str) -> str:
"""Calculate gid of a worksheet from its wid."""
widval = wid[1:] if len(wid) > 3 else wid
Expand Down
Loading
Loading