{"id":13501635,"url":"https://github.com/nithinmurali/pygsheets","last_synced_at":"2025-05-14T03:07:02.817Z","repository":{"id":38628404,"uuid":"60546709","full_name":"nithinmurali/pygsheets","owner":"nithinmurali","description":"Google Sheets Python API v4","archived":false,"fork":false,"pushed_at":"2024-05-19T22:19:44.000Z","size":2542,"stargazers_count":1510,"open_issues_count":68,"forks_count":220,"subscribers_count":47,"default_branch":"staging","last_synced_at":"2024-10-29T12:01:00.238Z","etag":null,"topics":["google-sheets","google-sheets-api","google-sheets-api-v4","google-sheets-library","python","python-lib","spreadsheet"],"latest_commit_sha":null,"homepage":"https://pygsheets.readthedocs.io/en/latest","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nithinmurali.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-06T17:20:44.000Z","updated_at":"2024-10-25T16:07:46.000Z","dependencies_parsed_at":"2024-06-05T18:57:56.022Z","dependency_job_id":"6ba5ecc8-7372-4292-91f6-d90a206556e2","html_url":"https://github.com/nithinmurali/pygsheets","commit_stats":{"total_commits":861,"total_committers":91,"mean_commits":9.461538461538462,"dds":"0.45296167247386765","last_synced_commit":"ffaec54c693afe33f72a0c6bea1d955a7a02b0cb"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithinmurali%2Fpygsheets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithinmurali%2Fpygsheets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithinmurali%2Fpygsheets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nithinmurali%2Fpygsheets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nithinmurali","download_url":"https://codeload.github.com/nithinmurali/pygsheets/tar.gz/refs/heads/staging","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247962594,"owners_count":21024870,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-sheets","google-sheets-api","google-sheets-api-v4","google-sheets-library","python","python-lib","spreadsheet"],"created_at":"2024-07-31T22:01:44.431Z","updated_at":"2025-05-14T03:07:02.797Z","avatar_url":"https://github.com/nithinmurali.png","language":"Python","funding_links":["https://www.buymeacoffee.com/pygsheets"],"categories":["Python","Data Format \u0026 I/O","Database Clients"],"sub_categories":["For Python"],"readme":"# pygsheets - Google Spreadsheets Python API v4\n[![Build Status](https://travis-ci.org/nithinmurali/pygsheets.svg?branch=staging)](https://travis-ci.org/nithinmurali/pygsheets)  [![PyPI version](https://badge.fury.io/py/pygsheets.svg)](https://badge.fury.io/py/pygsheets)    [![Documentation Status](https://readthedocs.org/projects/pygsheets/badge/?version=latest)](http://pygsheets.readthedocs.io/en/latest/?badge=latest) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/nithinmurali/pygsheets)\n\nA simple, intuitive library for google sheets which gets your work done.\n \nFeatures:\n\n* Open, create, delete and share spreadsheets using _title_ or _key_\n* Intuitive models - spreadsheet, worksheet, cell, datarange\n* Control permissions of spreadsheets.\n* Set cell format, text format, color, write notes\n* Named and Protected Ranges Support\n* Work with range of cells easily with DataRange and Gridrange\n* Data validation support. checkboxes, drop-downs etc.\n* Conditional formatting support\n* get multiple ranges with get_values_batch and update wit update_values_batch\n\n## Updates\n* version [2.0.5](https://github.com/nithinmurali/pygsheets/releases/tag/2.0.5) released\n\n## Installation\n\n#### From PyPi (Stable)\n\n```sh\npip install pygsheets\n\n```\n\nIf you are installing from pypi please see the docs [here](https://pygsheets.readthedocs.io/en/stable/).\n\n\n#### From GitHub (Recommended)\n\n```sh\npip install https://github.com/nithinmurali/pygsheets/archive/staging.zip\n\n```\n\nIf you are installing from github please see the docs [here](https://pygsheets.readthedocs.io/en/staging/).\n\n## Basic Usage\n\nBasic features are shown here, for complete set of features see the full documentation [here](http://pygsheets.readthedocs.io/en/staging/).\n\n1. Obtain OAuth2 credentials from Google Developers Console for __google spreadsheet api__ and __drive api__ and save the file as `client_secret.json` in same directory as project. [read more here.](https://pygsheets.readthedocs.io/en/latest/authorization.html)\n\n2. Start using pygsheets: \n   \nSample scenario : you want to share a numpy array with your remote friend \n\n```python\nimport pygsheets\nimport numpy as np\n\ngc = pygsheets.authorize()\n\n# Open spreadsheet and then worksheet\nsh = gc.open('my new sheet')\nwks = sh.sheet1\n\n# Update a cell with value (just to let him know values is updated ;) )\nwks.update_value('A1', \"Hey yank this numpy array\")\nmy_nparray = np.random.randint(10, size=(3, 4))\n\n# update the sheet with array\nwks.update_values('A2', my_nparray.tolist())\n\n# share the sheet with your friend\nsh.share(\"myFriend@gmail.com\")\n\n```\n\nSample Scenario: you want to fill height values of students\n```python\n\n## import pygsheets and open the sheet as given above\n\nheader = wks.cell('A1')\nheader.value = 'Names'\nheader.text_format['bold'] = True # make the header bold\nheader.update()\n\n# or achive the same in oneliner\nwks.cell('B1').set_text_format('bold', True).value = 'heights'\n\n# set the names\nwks.update_values('A2:A5',[['name1'],['name2'],['name3'],['name4']])\n\n# set the heights\nheights = wks.range('B2:B5', returnas='range')  # get the range as DataRange object\nheights.name = \"heights\"  # name the range\nheights.update_values([[50],[60],[67],[66]]) # update the values\nwks.update_value('B6','=average(heights)') # set the avg value of heights using named range\n\n```\n\n## More Examples\n\n### Opening a Spreadsheet\n\n```python\n# You can open a spreadsheet by its title as it appears in Google Docs \nsh = gc.open(\"pygsheetTest\")\n\n# If you want to be specific, use a key\nsht1 = gc.open_by_key('1mwA-NmvjDqd3A65c8hsxOpqdfdggPR0fgfg5nXRKScZAuM')\n\n# open enable TeamDrive support\ngc.drive.enable_team_drive(\"Dqd3A65c8hsxOpqdfdggPR0fgfg\")\n\n# create a spreadsheet in a folder (by id)\nsht2 = gc.create(\"new sheet\", folder=\"\u003cyour_folder_id\u003e\")\n\n\n```\n\n### Operations on Spreadsheet [doc](http://pygsheets.readthedocs.io/en/latest/spreadsheet.html)\n\n\u003cdetails\u003e \u003csummary\u003eshow code\u003c/summary\u003e\n\n```python\n\nimport pygsheets\nc = pygsheets.authorize()\nsh = c.open('spreadsheet')\n\n# create a new sheet with 50 rows and 60 colums\nwks = sh.add_worksheet(\"new sheet\",rows=50,cols=60)\n\n# create a new sheet with 50 rows and 60 colums at the begin of worksheets\nwks = sh.add_worksheet(\"new sheet\",rows=50,cols=60,index=0)\n\n# or copy from another worksheet\nwks = sh.add_worksheet(\"new sheet\", src_worksheet='\u003cother worksheet instance\u003e')\n\n# delete this wroksheet\nsh.del_worksheet(wks)\n\n# unshare the sheet\nsh.remove_permissions(\"myNotSoFriend@gmail.com\")\n\n```\n\n\u003c/details\u003e\n\n### Selecting a Worksheet\n\n\u003cdetails\u003e \u003csummary\u003eshow code\u003c/summary\u003e\n\n```python\nimport pygsheets\nc = pygsheets.authorize()\nsh = c.open('spreadsheet')\n\n# Select worksheet by id, index, title.\nwks = sh.worksheet_by_title(\"my test sheet\")\n\n# By any property\nwks = sh.worksheet('index', 0)\n\n# Get a list of all worksheets\nwks_list = sh.worksheets()\n\n# Or just\nwks = sh[0]\n```\n\n\u003c/details\u003e\n\n### Operations on Worksheet [doc](http://pygsheets.readthedocs.io/en/latest/worksheet.html)\n\n\u003cdetails\u003e \u003csummary\u003eshow code\u003c/summary\u003e\n\n```python\n# Get values as 2d array('matrix') which can easily be converted to an numpy aray or as 'cell' list\nvalues_mat = wks.get_values(start=(1,1), end=(20,20), returnas='matrix')\n\n# Get values of - rows A1 to B10, column C, 1st row, 10th row\nwks.get_values_batch(['A1:B10', 'C', '1', (10, None)])\n\n# Get all values of sheet as 2d list of cells\ncell_matrix = wks.get_all_values(returnas='matrix')\n\n# update a range of values with a cell list or matrix\nwks.update_values(crange='A1:E10', values=values_mat)\n\n# update multiple ranges with bath update\nwks.update_values_batch(['A1:A2', 'B1:B2'], [[[1],[2]], [[3],[4]]])\n\n# Insert 2 rows after 20th row and fill with values\nwks.insert_rows(row=20, number=2, values=values_list)\n\n# resize by changing rows and colums\nwks.rows=30\n\n# use the worksheet as a csv\nfor row in wks:\n    print(row)\n\n# get values by indexes\n A1_value = wks[0][0]\n\n# clear all values\nwks.clear()\n\n# Search for a table in the worksheet and append a row to it\nwks.append_table(values=[1,2,3,4])\n\n# export a worksheet as csv\nwks.export(pygsheets.ExportType.CSV)\n\n# Find/Replace cells with string value\ncell_list = worksheet.find(\"query string\")\n\n# Find/Replace cells with regexp\nfilter_re = re.compile(r'(small|big) house')\ncell_list = worksheet.find(filter_re, searchByRegex=True)\ncell_list = worksheet.replace(filter_re, 'some house', searchByRegex=True)\n\n# Move a worksheet in the same spreadsheet (update index)\nwks.index = 2 # index start at 1 , not 0\n\n# Update title\nwks.title = \"NewTitle\"\n\n# Update hidden state\nwks.hidden = False\n\n# working with named ranges\nwks.create_named_range('A1', 'A10', 'prices')\nwks.get_named_range('prices')\nwks.get_named_ranges()  # will return a list of DataRange objects\nwks.delete_named_range('prices')\n\n# apply format\nwks.apply_format(['A1:B1', 'D:E'], [\"NUMBER\", \"TEXT\"])\n\n# Plot a chart/graph\nwks.add_chart(('A1', 'A6'), [('B1', 'B6')], 'Health Trend')\n\n# create drop-downs\nwks.set_data_validation(start='C4', end='E7', condition_type='NUMBER_BETWEEN', condition_values=[2,10], strict=True, showCustomUi=True, inputMessage=\"inut between 2 and 10\")\n\n# set a formula and extend it to more cells\ncell = wks.cell('C1')\ncell.value = '=A1+B1'\nwks.apply_format('C1:C10', cell, 'userEnteredValue.formulaValue')\n\n```\n\n\u003c/details\u003e\n\n#### Pandas integration\nIf you work with pandas, you can directly use the dataframes\n```python\n#set the values of a pandas dataframe to sheet\nwks.set_dataframe(df,(1,1))\n\n#you can also get the values of sheet as dataframe\ndf = wks.get_as_df()\n\n```\n\n\n### Cell Object [doc](http://pygsheets.readthedocs.io/en/latest/cell.html)\n\nEach cell has a __value__ and cordinates (__row__, __col__, __label__) properties.\n\nGetting cell objects\n\n\u003cdetails open\u003e \u003csummary\u003eshow code\u003c/summary\u003e\n\n```python\nc1 = Cell('A1',\"hello\")  # create a unlinked cell\nc1 = worksheet.cell('A1')  # creates a linked cell whose changes syncs instantanously\ncl.value  # Getting cell value\nc1.value_unformatted #Getting cell unformatted value\nc1.formula # Getting cell formula if any\nc1.note # any notes on the cell\nc1.address # address object with cell position\n\ncell_list = worksheet.range('A1:C7')  # get a range of cells \ncell_list = worksheet.col(5, returnas='cell')  # return all cells in 5th column(E)\n\n```\n\n\u003c/details\u003e\n\nMost of the functions has `returnas` param, if whose value is `cell` it will return a list of cell objects. Also you can use *label* or *(row,col)* tuple interchangbly as a cell adress\n\n### Cell Operations\n\nEach cell is directly linked with its cell in spreadsheet, hence changing the value of cell object will update the corresponding cell in spreadsheet unless you explictly unlink it\nAlso not that bu default only the value of cell is fetched, so if you are directly accessing any cell properties call `cell.fetch()` beforehand. \n\nDifferent ways of updating Cells\n\n\u003cdetails\u003e \u003csummary\u003eshow code\u003c/summary\u003e\n\n```python\n# using linked cells\nc1 = worksheet.cell('B1') # created from worksheet, so linked cell\nc1.col = 5  # Now c1 correponds to E1\nc1.value = \"hoho\"  # will change the value of E1\n\n# Or onliner\nworksheet.update_value('B1', 'hehe')\n\n# get a range of cells\ncell_list = worksheet.range('A1:C7')\ncell_list = worksheet.get_values(start='A1', end='C7', returnas='cells')\ncell_list = worksheet.get_row(2, returnas='cells')\n\n\n# add formula\nc1.formula = 'A1+C2'\nc1.formula # '=A1+C2'\n\n# get neighbouring cells\nc2 = c1.neighbour('topright') # you can also specify relative position as tuple eg (1,1)\n\n# set cell format\nc1.set_number_format(pygsheets.FormatType.NUMBER, '00.0000')\n\n# write notes on cell\nc1.note = \"yo mom\"\n\n# set cell color\nc1.color = (1.0, 1.0, 1.0, 1.0) # Red, Green, Blue, Alpha\n\n# set text format\nc1.text_format['fontSize'] = 14\nc1.set_text_format('bold', True)\n\n# sync the changes\n c1.update()\n\n# you can unlink a cell and set all required properties and then link it\n# So yu could create a model cell and update multiple sheets\nc.unlink()\nc.note = \"offine note\"\nc.link(wks1, True)\nc.link(wks2, True)\n\n```\n\n\u003c/details\u003e\n\n### DataRange Object [doc](http://pygsheets.readthedocs.io/en/latest/datarange.html)\n\nThe DataRange is used to represent a range of cells in a worksheet. They can be named or protected.\nAlmost all `get_` functions has a `returnas` param, set it to `range` to get a range object.\n\n\u003cdetails open\u003e \u003csummary\u003eshow code\u003c/summary\u003e\n\n```python\n# Getting a Range object\nrng = wks.get_values('A1', 'C5', returnas='range')\nrng.start_addr = 'A' # make the range unbounded on rows \u003cDatarange Sheet1!A:B\u003e\ndrange.end_addr = None # make the range unbounded on both axes \u003cDatarange Sheet1\u003e\n\n# Named ranges\nrng.name = 'pricesRange'  # will make this range a named range\nrng = wks.get_named_ranges('commodityCount') # directly get a named range\nrng.name = ''  # will delete this named range\n\n#Protected ranges\nrng.protected = True\nrng.editors = ('users', 'someemail@gmail.com')\n\n# Setting Format\n # first create a model cell with required properties\nmodel_cell = Cell('A1')\nmodel_cell.color = (1.0,0,1.0,1.0) # rose color cell\nmodel_cell.format = (pygsheets.FormatType.PERCENT, '')\n\n # Setting format to multiple cells in one go\nrng.apply_format(model_cell)  # will make all cell in this range rose color and percent format\n# Or if you just want to apply format, you can skip fetching data while creating datarange\nDatarange('A1','A10', worksheet=wks).apply_format(model_cell)\n\n# get cells in range\ncell = rng[0][1]\n\n```\n\u003c/details\u003e\n\n### Batching calls\n\nIf you are calling a lot of spreadsheet modification functions (non value update). you can merge them into a single call.\nBy doing so all the requests will be merged into a single call.\n\n```python\ngc.set_batch_mode(True)\nwks.merge_cells(\"A1\", \"A2\")\nwks.merge_cells(\"B1\", \"B2\")\nDatarange(\"D1\", \"D5\", wks).apply_format(cell)\ngc.run_batch() # All the above requests are executed here\ngc.set_batch_mode(False)\n\n```\nBatching also happens when you unlink worksheet. But in that case the requests are not merged.\n\n\n## How to Contribute\n\nThis library is still in development phase.\n \n* Follow the [Contributing to Open Source](https://opensource.guide/) Guide.\n* Branch off of the `staging` branch, and submit Pull Requests back to\n  that branch.  Note that the `master` branch is used for version\n  bumps and hotfixes only.\n* For quick testing the changes you have made to source, run the file `tests/manual_testing.py`. It will give you an IPython shell with latest code loaded.\n\n### Report Issues/Features\n\n* Please report bugs and suggest features via the [GitHub Issues](https://github.com/nithinmurali/pygsheets/issues).\n* Before opening an issue, search the tracker for possible duplicates.\n* If you have any usage questions, ask a question on stackoverflow with `pygsheets` Tag.\n\n## Run Tests\n* install `pip install -r requirements-dev.txt`\n* run `make test`\n\nNow that you have scrolled all the way down, **finding this library useful?**  \u003ca href=\"https://www.buymeacoffee.com/pygsheets\" target=\"_blank\"\u003e\u003cimg src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: auto !important;width: auto !important;\" \u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnithinmurali%2Fpygsheets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnithinmurali%2Fpygsheets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnithinmurali%2Fpygsheets/lists"}