GoogleSheets
Google Sheets is a spreadsheet program that is part of the free web-based Google applications to create and format spreadsheets. Use this integration to create and modify spreadsheets.
Utilities · Google Sheets
Details
| ID | GoogleSheets |
|---|---|
| Provider | |
| Category | Utilities |
| From Version | 6.1.0 |
| Docker Image | demisto/googleapi-python3:1.0.0.10182333 |
| Supported Modules | Agentix XSIAM Cloud Posture Security |
README
Google Sheets is a spreadsheet program that is part of the free web-based Google applications to create and format spreadsheets. Use this integration to create and modify spreadsheets.
This integration was integrated and tested with version 4 of Google Sheets API.
Configure Google Sheets in Cortex
| Parameter | Description | Required |
|---|---|---|
| Service Account Key | A service account key from Google. | True |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Email - Associate to Google Drive | Used to impersonate a Google workspace user, so the spreadsheets is created in the associated Google Drive and is easily accessible from a UI. This parameter is used during the authentication process. |
False |
Known limitations
You can only delete a spreadsheet with the Google Drive integrations.
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
google-sheets-spreadsheet-create
Create a new spreadsheet.
Base Command
google-sheets-spreadsheet-create
Input
| Argument Name | Description | Required |
|---|---|---|
| title | The title of the spreadsheet to create. | Required |
| locale | The locale of the spreadsheet to create. Default is en. | Optional |
| cell_format_type | The type of the cell format of the spreadsheet to create. Possible values are: NUMBER, TEXT, PERCENT, CURRENCY, DATE, TIME, DATE_TIME, SCIENTIFIC. Default is TEXT. | Optional |
| cell_format_backgroundColor | A comma-separated list of background colors in the following order - red,green,blue,alpha. All values must be between 0-1. If chosen, you must specify all fields. | Optional |
| cell_format_textformat_font_size | Cell font size in the spreadsheet to create. Default is 11. | Optional |
| cell_format_textformat_text_direction | Cell text direction in the spreadsheet to create. Possible values are: LEFT_TO_RIGHT, RIGHT_TO_LEFT. Default is LEFT_TO_RIGHT. | Optional |
| sheet_title | Sets the title of the first sheet in the spreadsheet to create. | Required |
| sheet_type | Sets the type of the first sheet in the spreadsheet to create. Possible values are: GRID, OBJECT, DATASOURCE. Default is GRID. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.properties.title | Unknown | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | Unknown | Spreadsheet ID. |
Command example
!google-sheets-spreadsheet-create title=NewSpreadsheet sheet_title=newSheetTitle cell_format_backgroundColor=1,1,1,1 cell_format_textformat_font_size=11 cell_format_type=TEXT
Context Example
{
"GoogleSheets": {
"Spreadsheet": {
"properties": {
"autoRecalc": "ON_CHANGE",
"defaultFormat": {
"backgroundColor": {
"blue": 1,
"green": 1,
"red": 1
},
"backgroundColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"padding": {
"bottom": 2,
"left": 3,
"right": 3,
"top": 2
},
"textFormat": {
"bold": false,
"fontFamily": "arial,sans,sans-serif",
"fontSize": 10,
"foregroundColor": {},
"foregroundColorStyle": {
"rgbColor": {}
},
"italic": false,
"strikethrough": false,
"underline": false
},
"verticalAlignment": "BOTTOM",
"wrapStrategy": "OVERFLOW_CELL"
},
"locale": "en",
"spreadsheetTheme": {
"primaryFontFamily": "Arial",
"themeColors": [
{
"color": {
"rgbColor": {}
},
"colorType": "TEXT"
},
{
"color": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"colorType": "BACKGROUND"
},
{
"color": {
"rgbColor": {
"blue": 0.95686275,
"green": 0.52156866,
"red": 0.25882354
}
},
"colorType": "ACCENT1"
},
{
"color": {
"rgbColor": {
"blue": 0.20784314,
"green": 0.2627451,
"red": 0.91764706
}
},
"colorType": "ACCENT2"
},
{
"color": {
"rgbColor": {
"blue": 0.015686275,
"green": 0.7372549,
"red": 0.9843137
}
},
"colorType": "ACCENT3"
},
{
"color": {
"rgbColor": {
"blue": 0.3254902,
"green": 0.65882355,
"red": 0.20392157
}
},
"colorType": "ACCENT4"
},
{
"color": {
"rgbColor": {
"blue": 0.003921569,
"green": 0.42745098,
"red": 1
}
},
"colorType": "ACCENT5"
},
{
"color": {
"rgbColor": {
"blue": 0.7764706,
"green": 0.7411765,
"red": 0.27450982
}
},
"colorType": "ACCENT6"
},
{
"color": {
"rgbColor": {
"blue": 0.8,
"green": 0.33333334,
"red": 0.06666667
}
},
"colorType": "LINK"
}
]
},
"timeZone": "Etc/GMT",
"title": "NewSpreadsheet"
},
"sheets": [
{
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 1000
},
"index": 0,
"sheetId": 387199274,
"sheetType": "GRID",
"title": "newSheetTitle"
}
}
],
"spreadsheetId": "1yRsYph-litbiP4opkjzWwVzJ3ZyOybYL5D2f840-uog",
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1yRsYph-litbiP4opkjzWwVzJ3ZyOybYL5D2f840-uog/edit?ouid=103020731686044834269"
}
}
}
Human Readable Output
Success
spreadsheet Id spreadsheet title 1yRsYph-litbiP4opkjzWwVzJ3ZyOybYL5D2f840-uog NewSpreadsheet
google-sheets-spreadsheet-get
Returns the spreadsheet of the given ID. If include_grid_data is set to true and no ranges given, will defaultly return the first 500 rows and 20 columns of the first sheet.
Base Command
google-sheets-spreadsheet-get
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | ID of the spreadsheet to get. | Required |
| include_grid_data | True if grid data should be returned. This parameter is ignored if a field mask was set in the request. Possible values are: true, false. Default is false. | Optional |
| ranges | Works only with include_grid_data = True. The ranges to retrieve from the spreadsheet. Ranges are specified using A1 notation. For example, Sheet1!A1:D5. For further explanation and examples, see https://developers.google.com/sheets/api/guides/concepts#expandable-1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.spreadsheetTitle | Unknown | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | Unknown | SpreadSheet ID. |
| GoogleSheets.Spreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.sheets.title | Unknown | Sheet title. |
| GoogleSheets.Spreadsheet.sheets.index | Unknown | Sheet index. |
| GoogleSheets.Spreadsheet.sheets.sheetId | Unknown | Sheet ID. |
| GoogleSheets.Spreadsheet.sheets.gridProperties | Unknown | Sheet grid properties. |
| GoogleSheets.Spreadsheet.sheets.rowData | Unknown | Sheet row data. |
Command example
!google-sheets-spreadsheet-get spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk
Context Example
{
"GoogleSheets": {
"Spreadsheet": {
"sheets": [
{
"gridProperties": {
"columnCount": 26,
"rowCount": 1000
},
"index": 0,
"rowData": [],
"sheetId": 0,
"title": "Sheet1"
},
{
"gridProperties": {
"columnCount": 26,
"rowCount": 1000
},
"index": 1,
"rowData": [],
"sheetId": 3,
"title": "newSheetTitle"
}
],
"spreadsheetId": "1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk",
"spreadsheetTitle": "NewSpreadsheet",
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269"
}
}
}
Human Readable Output
Success
NewSpreadsheet
spreadsheet Id spreadsheet url 1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269 Content
SheetId Sheet title 0 Sheet1 3 newSheetTitle
Command example
!google-sheets-spreadsheet-get spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk,1meYzOYg7oCK7zYGBJu_hw3iQ_oEvJ6EecCBOV8ZQvFA
Human Readable Output
Success
NewSpreadsheet
spreadsheet Id spreadsheet url 1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269 Content
SheetId Sheet title 0 Sheet1 3 newSheetTitle
SpreadSheet2
spreadsheet Id spreadsheet url 1meYzOYg7oCK7zYGBJu_hw3iQ_oEvJ6EecCBOV8ZQvFA https://docs.google.com/spreadsheets/d/1meYzOYg7oCK7zYGBJu_hw3iQ_oEvJ6EecCBOV8ZQvFA/edit?ouid=103020731686044834269 Content
SheetId Sheet title 1144878200 Sheet1
Command example
!google-sheets-spreadsheet-get spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk include_grid_data=true ranges=newSheetTitle!A1:F10
Context Example
{
"GoogleSheets": {
"Spreadsheet": {
"sheets": [
{
"gridProperties": {
"columnCount": 26,
"rowCount": 1000
},
"index": 1,
"rowData": [
{
"values": [
"a",
"b",
"c",
"d",
"!"
]
},
{
"values": []
},
{
"values": [
"1",
"2",
"3",
"4",
"5"
]
},
{
"values": [
"a",
"b",
"c",
"d",
"!"
]
},
{
"values": [
"a",
"b",
"c",
"d",
"!"
]
}
],
"sheetId": 3,
"title": "newSheetTitle"
}
],
"spreadsheetId": "1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk",
"spreadsheetTitle": "NewSpreadsheet",
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269"
}
}
}
Human Readable Output
Success
spreadsheet Id spreadsheet url 1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269 Name: newSheetTitle Sheet Id: 3
col 0 col 1 col 2 col 3 col 4 a b c d ! 1 2 3 4 5 a b c d ! a b c d !
google-sheets-sheet-create
Adds a new sheet. When a sheet is added at a given index, all subsequent sheet indexes are incremented.
Base Command
google-sheets-sheet-create
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID in which to create a new sheet. | Required |
| echo_spreadsheet | Include the spreadsheet in the response. Possible values are: true, false. Default is false. | Optional |
| sheet_title | Sheet title to create. | Required |
| sheet_index | The index of the sheet within the spreadsheet. | Optional |
| sheet_type | Sheet type to create. Possible values are: GRID, OBJECT, DATA_SOURCE. Default is GRID. | Optional |
| right_to_left | True if the sheet is a right_to_left sheet instead of a left_to_right sheet. Possible values are: false, true. | Optional |
| tab_color | A comma-separated list of the color of the tab in the UI in the following order - red,green,blue,alpha. All values must be between 0-1. If chosen, you must specify all fields. | Optional |
| hidden | True if the sheet is hidden in the UI. False if it is visible. | Optional |
| sheet_id | The ID of the sheet to create. (Needs to be unique. If not specified, the sheet ID will be generated by Google Sheets. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | Unknown | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | Unknown | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-sheet-create spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk sheet_title=newSheetTitle sheet_id=3 sheet_index=2 tab_color=1,1,1,1 right_to_left=false
Human Readable Output
Success
google-sheets-sheet-duplicate
Duplicates the contents of a sheet.
Base Command
google-sheets-sheet-duplicate
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID from which to copy a sheet. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: true, false. Default is false. | Optional |
| source_sheet_id | The ID of the sheet to copy. | Required |
| new_sheet_index | If set, the ID of the new sheet. If not set, an ID is chosen. If set, the ID must not conflict with any existing sheet ID and it must be non-negative number. | Optional |
| new_sheet_name | The name of the new sheet. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-sheet-duplicate new_sheet_name=duplicated_sheet spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk source_sheet_id=3 echo_spreadsheet=true
Context Example
{
"GoogleSheets": {
"Spreadsheet": {
"replies": [
{
"duplicateSheet": {
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 997
},
"index": 0,
"sheetId": 2030116478,
"sheetType": "GRID",
"tabColor": {
"blue": 1,
"green": 1,
"red": 1
},
"tabColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"title": "duplicated_sheet"
}
}
}
],
"spreadsheetId": "1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk",
"updatedSpreadsheet": {
"properties": {
"autoRecalc": "ON_CHANGE",
"defaultFormat": {
"backgroundColor": {
"blue": 1,
"green": 1,
"red": 1
},
"backgroundColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"padding": {
"bottom": 2,
"left": 3,
"right": 3,
"top": 2
},
"textFormat": {
"bold": false,
"fontFamily": "arial,sans,sans-serif",
"fontSize": 10,
"foregroundColor": {},
"foregroundColorStyle": {
"rgbColor": {}
},
"italic": false,
"strikethrough": false,
"underline": false
},
"verticalAlignment": "BOTTOM",
"wrapStrategy": "OVERFLOW_CELL"
},
"locale": "en",
"spreadsheetTheme": {
"primaryFontFamily": "Arial",
"themeColors": [
{
"color": {
"rgbColor": {}
},
"colorType": "TEXT"
},
{
"color": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"colorType": "BACKGROUND"
},
{
"color": {
"rgbColor": {
"blue": 0.95686275,
"green": 0.52156866,
"red": 0.25882354
}
},
"colorType": "ACCENT1"
},
{
"color": {
"rgbColor": {
"blue": 0.20784314,
"green": 0.2627451,
"red": 0.91764706
}
},
"colorType": "ACCENT2"
},
{
"color": {
"rgbColor": {
"blue": 0.015686275,
"green": 0.7372549,
"red": 0.9843137
}
},
"colorType": "ACCENT3"
},
{
"color": {
"rgbColor": {
"blue": 0.3254902,
"green": 0.65882355,
"red": 0.20392157
}
},
"colorType": "ACCENT4"
},
{
"color": {
"rgbColor": {
"blue": 0.003921569,
"green": 0.42745098,
"red": 1
}
},
"colorType": "ACCENT5"
},
{
"color": {
"rgbColor": {
"blue": 0.7764706,
"green": 0.7411765,
"red": 0.27450982
}
},
"colorType": "ACCENT6"
},
{
"color": {
"rgbColor": {
"blue": 0.8,
"green": 0.33333334,
"red": 0.06666667
}
},
"colorType": "LINK"
}
]
},
"timeZone": "Etc/GMT",
"title": "NewSpreadsheet"
},
"sheets": [
{
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 997
},
"index": 0,
"sheetId": 2030116478,
"sheetType": "GRID",
"tabColor": {
"blue": 1,
"green": 1,
"red": 1
},
"tabColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"title": "duplicated_sheet"
}
},
{
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 1000
},
"index": 1,
"sheetId": 0,
"sheetType": "GRID",
"tabColor": {
"blue": 1,
"green": 1,
"red": 1
},
"tabColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"title": "Sheet1"
}
},
{
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 997
},
"index": 2,
"sheetId": 3,
"sheetType": "GRID",
"tabColor": {
"blue": 1,
"green": 1,
"red": 1
},
"tabColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"title": "newSheetTitle"
}
}
],
"spreadsheetId": "1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk",
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269"
}
}
}
}
Human Readable Output
Success
NewSpreadsheet
spreadsheet Id spreadsheet url 1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269 Content
SheetId Sheet title 2030116478 duplicated_sheet 0 Sheet1 3 newSheetTitle
google-sheets-sheet-copy-to
Copies a single sheet from a spreadsheet to another spreadsheet.
Base Command
google-sheets-sheet-copy-to
Input
| Argument Name | Description | Required |
|---|---|---|
| source_spreadsheet_id | Spreadsheet ID to copy from. | Required |
| source_sheet_id | The ID of the sheet to copy. | Required |
| destination_spreadsheet_id | The ID of the spreadsheet to copy the sheet to. | Required |
Context Output
There is no context output for this command.
Command example
!google-sheets-sheet-copy-to source_sheet_id=3 source_spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk destination_spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk
Human Readable Output
Success
google-sheets-sheet-delete
Delete a sheet from a spreadsheet by ID.
Base Command
google-sheets-sheet-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet from which to delete sheet. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: true, false. Default is false. | Optional |
| sheet_id | ID of sheet to delete. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-sheet-delete sheet_id=3 spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk
Human Readable Output
Success
google-sheets-sheet-clear
Clears values from a spreadsheet. The caller must specify the spreadsheet ID and range. Only values are cleared. All other properties of the cell (such as formatting, data validation, etc..) are kept.
Base Command
google-sheets-sheet-clear
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID to update. | Required |
| range | A1 notation or R1C1 notation of the values to clear. A1 notation example, Sheet1!A1:D5. For further explanation and examples, see https://developers.google.com/sheets/api/guides/concepts#expandable-1. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-sheet-clear spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk range=newSheetTitle!2:2
Human Readable Output
Success
Command example
!google-sheets-sheet-clear range=newSheetTitle spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk
Human Readable Output
Success
google-sheets-range-delete
Deletes a range of cells, shifting other cells into the deleted area.
Base Command
google-sheets-range-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: true, false. Default is false. | Optional |
| sheet_id | The sheet this range is in. | Required |
| start_row_index | The start row (inclusive) of the range, or not set if unbounded. | Required |
| end_row_index | The end row (exclusive) of the range, or not set if unbounded. | Required |
| start_column_index | The start column (inclusive) of the range, or not set if unbounded. | Required |
| end_column_index | The end column (exclusive) of the range, or not set if unbounded. | Required |
| shift_dimension | The dimension from which deleted cells will be replaced with. If ROWS, existing cells will be shifted upward to replace the deleted cells. If COLUMNS, existing cells will be shifted left to replace the deleted cells. Possible values are: ROWS, COLUMNS. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-range-delete spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk sheet_id=3 shift_dimension=COLUMNS start_row_index=0 end_row_index=2 start_column_index=0 end_column_index=2
Human Readable Output
Success
google-sheets-dimension-delete
Deletes the dimensions from the sheet. Note that the indexing starts from 0.
Base Command
google-sheets-dimension-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: true, false. Default is false. | Optional |
| dimension_type | The dimension of the span. Possible values are: ROWS, COLUMNS. | Required |
| sheet_id | The sheet this span is in. | Required |
| start_index | The start (inclusive) of the span, or not set if unbounded. | Required |
| end_index | The end (exclusive) of the span, or not set if unbounded. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-dimension-delete dimension_type=ROWS sheet_id=3 spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk start_index=0 end_index=3 echo_spreadsheet=true
Context Example
{
"GoogleSheets": {
"Spreadsheet": {
"replies": [
{}
],
"spreadsheetId": "1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk",
"updatedSpreadsheet": {
"properties": {
"autoRecalc": "ON_CHANGE",
"defaultFormat": {
"backgroundColor": {
"blue": 1,
"green": 1,
"red": 1
},
"backgroundColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"padding": {
"bottom": 2,
"left": 3,
"right": 3,
"top": 2
},
"textFormat": {
"bold": false,
"fontFamily": "arial,sans,sans-serif",
"fontSize": 10,
"foregroundColor": {},
"foregroundColorStyle": {
"rgbColor": {}
},
"italic": false,
"strikethrough": false,
"underline": false
},
"verticalAlignment": "BOTTOM",
"wrapStrategy": "OVERFLOW_CELL"
},
"locale": "en",
"spreadsheetTheme": {
"primaryFontFamily": "Arial",
"themeColors": [
{
"color": {
"rgbColor": {}
},
"colorType": "TEXT"
},
{
"color": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"colorType": "BACKGROUND"
},
{
"color": {
"rgbColor": {
"blue": 0.95686275,
"green": 0.52156866,
"red": 0.25882354
}
},
"colorType": "ACCENT1"
},
{
"color": {
"rgbColor": {
"blue": 0.20784314,
"green": 0.2627451,
"red": 0.91764706
}
},
"colorType": "ACCENT2"
},
{
"color": {
"rgbColor": {
"blue": 0.015686275,
"green": 0.7372549,
"red": 0.9843137
}
},
"colorType": "ACCENT3"
},
{
"color": {
"rgbColor": {
"blue": 0.3254902,
"green": 0.65882355,
"red": 0.20392157
}
},
"colorType": "ACCENT4"
},
{
"color": {
"rgbColor": {
"blue": 0.003921569,
"green": 0.42745098,
"red": 1
}
},
"colorType": "ACCENT5"
},
{
"color": {
"rgbColor": {
"blue": 0.7764706,
"green": 0.7411765,
"red": 0.27450982
}
},
"colorType": "ACCENT6"
},
{
"color": {
"rgbColor": {
"blue": 0.8,
"green": 0.33333334,
"red": 0.06666667
}
},
"colorType": "LINK"
}
]
},
"timeZone": "Etc/GMT",
"title": "NewSpreadsheet"
},
"sheets": [
{
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 1000
},
"index": 0,
"sheetId": 0,
"sheetType": "GRID",
"tabColor": {
"blue": 1,
"green": 1,
"red": 1
},
"tabColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"title": "Sheet1"
}
},
{
"properties": {
"gridProperties": {
"columnCount": 26,
"rowCount": 997
},
"index": 1,
"sheetId": 3,
"sheetType": "GRID",
"tabColor": {
"blue": 1,
"green": 1,
"red": 1
},
"tabColorStyle": {
"rgbColor": {
"blue": 1,
"green": 1,
"red": 1
}
},
"title": "newSheetTitle"
}
}
],
"spreadsheetId": "1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk",
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269"
}
}
}
}
Human Readable Output
Success
NewSpreadsheet
spreadsheet Id spreadsheet url 1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk https://docs.google.com/spreadsheets/d/1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk/edit?ouid=103020731686044834269 Content
SheetId Sheet title 0 Sheet1 3 newSheetTitle
google-sheets-data-paste
Inserts data into the spreadsheet starting at the specified coordinate.
Base Command
google-sheets-data-paste
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: true, false. Default is false. | Optional |
| sheet_id | The sheet this coordinate is in. | Required |
| row_index | The row index of the coordinate. | Required |
| column_index | The column index of the coordinate. | Required |
| data | The data to insert. If data_kind is delimiter, the delimiter will be ‘,’ and the data should be in the following format cell1, cell2, cell3… If data_kind is html, enter a single value. | Required |
| data_kind | How to interpret the data inserted in data argument. Possible values are: delimiter, html. | Required |
| paste_type | The way the data should be pasted. Possible values are: NORMAL, VALUES, FORMAT, NO_BORDERS, FORMULA, DATA_VALIDATION, CONDITIONAL_FORMATTING. Default is NORMAL. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-data-paste column_index=0 row_index=2 data_kind=delimiter data=1,2,3,4,5 spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk sheet_id=3
Human Readable Output
Success
google-sheets-find-replace
Finds and replaces data in cells over a range, sheet, or all sheets.
Base Command
google-sheets-find-replace
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: true, false. Default is false. | Optional |
| find | The value to find. | Required |
| replacement | The value to use as the replacement. | Required |
| sheet_id | The sheet to find/replace. | Optional |
| all_sheets | True to find/replace over all sheets. Possible values are: True, False. | Optional |
| match_case | True if the search is case sensitive. Possible values are: True, False. | Optional |
| match_entire_cell | True if the find value should match the entire cell. Possible values are: True, False. | Optional |
| range_sheet_id | The sheet this range is on. | Optional |
| range_start_row_Index | The start row (inclusive) of the range, or not set if unbounded. | Optional |
| range_end_row_Index | The end row (exclusive) of the range, or not set if unbounded. | Optional |
| range_start_column_Index | The start column (inclusive) of the range, or not set if unbounded. | Optional |
| range_end_column_Index | The end column (exclusive) of the range, or not set if unbounded. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-find-replace find=e replacement=! spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk all_sheets=True
Human Readable Output
Success
google-sheets-value-update
Sets values in a range of a spreadsheet. The caller must specify the spreadsheet ID, range, and a valueInputOption.
Base Command
google-sheets-value-update
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| range | The A1 notation of the values to update. For example, Sheet1!A1:D5. For further explanation and examples, see https://developers.google.com/sheets/api/guides/concepts#expandable-1. | Required |
| input_option | Determines how input data should be interpreted. Possible values are: RAW, USER_ENTERED. | Required |
| major_dimension | The major dimension of the values. Possible values are: ROWS, COLUMNS. | Required |
| values | The data that was read or to be written. This is an array of arrays. The outer array representing all the data and each inner array representing a major dimension. Each item in the inner array corresponds to one cell. To be entered in the following format - [1,2,3],[4,5,6] where each bracket will be the row or column, and each value inside will correspond to a cell. | Required |
Context Output
There is no context output for this command.
Command example
!google-sheets-value-update input_option=RAW major_dimension=ROWS range=newSheetTitle!A1:E5 values=[a,b,c,d,e],[a,b,c,d,e],[a,b,c,d,e],[a,b,c,d,e],[a,b,c,d,e] spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk
Human Readable Output
Success
google-sheets-value-append
Appends values to a spreadsheet. The input range is used to search for existing data and find a “table” within that range. Values will be appended to the next row of the table, starting with the first column of the table. See the guide (https://developers.google.com/sheets/api/guides/values#appending_values) and sample code (https://developers.google.com/sheets/api/samples/writing#append_values) for specific details of how tables are detected and data is appended. The caller must specify the spreadsheet ID, range, and a valueInputOption. The valueInputOption only controls how the input data will be added to the sheet (column-wise or row-wise), it does not influence what cell the data starts being written to.
Base Command
google-sheets-value-append
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| range | The A1 notation of a range to search for a logical table of data. Values are appended after the last row of the table. A1 notation example, Sheet1!A1:D5 For further explanation and examples, see https://developers.google.com/sheets/api/guides/concepts#expandable-1. | Required |
| input_option | The way input data should be interpreted. Possible values are: RAW, USER_ENTERED. | Optional |
| insert_option | The way input data should be inserted. Possible values are: OVERWRITE, INSERT_ROWS. | Required |
| major_dimension | The major dimension of the values. Possible values are: ROWS, COLUMNS. | Required |
| values | The data that was read or to be written. This is an array of arrays. The outer array representing all the data and each inner array representing a major dimension. Each item in the inner array corresponds to one cell. To be entered in the following format - [1,2,3],[4,5,6] where each bracket will be the row or column, and each value inside will correspond to a cell. | Required |
Context Output
There is no context output for this command.
Command example
!google-sheets-value-append insert_option=OVERWRITE major_dimension=ROWS range=newSheetTitle!A1:D5 spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk input_option=RAW values=[77,77,77],[777,777,777]
Human Readable Output
Success
google-sheets-spreadsheet-update
This is a custom update command, used to apply any of the Google Sheets API options. Applies one or more updates to the spreadsheet. Each request is validated before being applied. If any request is not valid, the entire request will fail and nothing will be applied.
Base Command
google-sheets-spreadsheet-update
Input
| Argument Name | Description | Required |
|---|---|---|
| spreadsheet_id | Spreadsheet ID. | Required |
| echo_spreadsheet | True to add the spreadsheet to the output. Possible values are: False, True. Default is False. | Optional |
| requests | JSON input according to the method documentation and object documentation - for advanced users’ free use (Google Sheets API) https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/batchUpdate. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleSheets.Spreadsheet.updatedSpreadsheet.properties.title | String | Spreadsheet title. |
| GoogleSheets.Spreadsheet.spreadsheetId | String | Spreadsheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.spreadsheetUrl | Unknown | Spreadsheet URL. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.sheetId | String | Sheet ID. |
| GoogleSheets.Spreadsheet.updatedSpreadsheet.sheets.title | String | Sheet title. |
Command example
!google-sheets-spreadsheet-update spreadsheet_id=1EwL7rqcSVdkXCAwuGt4jIiDrDUEKW3bmP63dqTBolfk requests=`{"requests": [{"copyPaste": {"destination": {"startRowIndex": 0, "startColumnIndex": 0, "endRowIndex": 5, "endColumnIndex": 5, "sheetId": 3}, "pasteOrientation": "TRANSPOSE", "source": {"sheetId": 3, "startRowIndex": 0, "startColumnIndex": 0, "endColumnIndex": 5, "endRowIndex": 5}, "pasteType": "PASTE_NORMAL"}}]}`
Human Readable Output
Success
Configuration parameters
service_account_credentials— (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsuser_id— Email - Associate to Google Drive
Commands (14)
-
google-sheets-data-pasteInserts data into the spreadsheet starting at the specified coordinate.
-
google-sheets-dimension-deleteDeletes the dimensions from the sheet. Note that the indexing starts from 0.
-
google-sheets-find-replaceFinds and replaces data in cells over a range, sheet, or all sheets.
-
google-sheets-range-deleteDeletes a range of cells, shifting other cells into the deleted area.
-
google-sheets-sheet-clearClears values from a spreadsheet. The caller must specify the spreadsheet ID and range. Only values are cleared. All other properties of the cell (such as formatting, data validation, etc..) are kept.
-
google-sheets-sheet-copy-toCopies a single sheet from a spreadsheet to another spreadsheet.
-
google-sheets-sheet-createAdds a new sheet. When a sheet is added at a given index, all subsequent sheet indexes are incremented.
-
google-sheets-sheet-deleteDelete a sheet from a spreadsheet by ID.
-
google-sheets-sheet-duplicateDuplicates the contents of a sheet.
-
google-sheets-spreadsheet-createCreate a new spreadsheet.
-
google-sheets-spreadsheet-getReturns the spreadsheet of the given ID. If include_grid_data is set to true and no ranges given, will defaultly return the first 500 rows and 20 columns of the first sheet.
-
google-sheets-spreadsheet-updateThis is a custom update command, used to apply any of the Google Sheets API options. Applies one or more updates to the spreadsheet. Each request is validated before being applied. If any request is not valid, the entire request will fail and nothing will be applied.
-
google-sheets-value-appendAppends values to a spreadsheet. The input range is used to search for existing data and find a "table" within that range. Values will be appended to the next row of the table, starting with the first column of the table. See the guide (https://developers.google.com/sheets/api/guides/values#appending_values) and sample code (https://developers.google.com/sheets/api/samples/writing#append_values) for specific details of how tables are detected and data is appended. The caller must specify the spreadsheet ID, range, and a valueInputOption. The valueInputOption only controls how the input data will be added to the sheet (column-wise or row-wise), it does not influence what cell the data starts being written to.
-
google-sheets-value-updateSets values in a range of a spreadsheet. The caller must specify the spreadsheet ID, range, and a valueInputOption.
import ast import json import urllib.parse import demistomock as demisto # noqa: F401 import httplib2 import urllib3 from CommonServerPython import * # noqa: F401 from googleapiclient.discovery import Resource, build from oauth2client import service_account from CommonServerUserPython import * # noqa SERVICE_ACCOUNT_FILE = "token.json" SCOPES = ["https://www.googleapis.com/auth/spreadsheets"] # Disable insecure warnings urllib3.disable_warnings() # pylint: disable=no-member """ CONSTANTS """ DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR # Matches one or more bracket-enclosed groups, e.g. "[1,2,3]" or "[1,2,3],[4,5,6]". # Used to validate that the `values` argument is in the expected list-of-lists format. BRACKET_LIST_PATTERN = re.compile(r"\[(.*?)\]") # HELPER FUNCTIONS def prepare_result(response: dict, args: dict, readable_comment: str) -> CommandResults: """ This function is for the UPDATE command result formatting echo_spreadsheet is false then the HR will be only success or failed. If echo_spreadsheet is true then we prepare the HR. In any case substitute the response to the output. Args: response: the response from the google API args: demisto.args readable_comment: (str) a comment for the UI Returns: The command result ready for the server """ markdown = f"### Successfully {readable_comment}\n" if argToBoolean(args.get("echo_spreadsheet")): human_readable = { "spreadsheet Id": response.get("spreadsheetId"), "spreadsheet url": response.get("updatedSpreadsheet", {}).get("spreadsheetUrl"), } table_title = response.get("updatedSpreadsheet", {}).get("properties", {}).get("title", "") markdown += tableToMarkdown(table_title, human_readable, headers=["spreadsheet Id", "spreadsheet url"]) markdown += "\n" sheets = response.get("updatedSpreadsheet", {}).get("sheets") # this is an array of sheet dicts markdown += tableToMarkdown("Content", create_list_id_title(sheets), headers=["SheetId", "Sheet title"]) outputs = response results = CommandResults( readable_output=markdown, outputs_prefix="GoogleSheets.Spreadsheet", outputs_key_field="spreadsheetId", outputs=outputs ) return results def create_list_id_title(sheets: list) -> list: """ Args: this function gets a list of all the sheets of a spreadsheet a sheet is represented as a dict format with the following fields "sheets" : [ { "properties": { "sheetId": 0, "title": "Sheet1", "index": 0, "sheetType": "GRID", "gridProperties": { "rowCount": 1000, "columnCount": 26 } } }, ... ] Returns : the output of the function will be a list of dict in the format [{'sheetId' : 123 , 'sheet title': 'title'},...] """ result = [] for sheet in sheets: sheetId = sheet.get("properties").get("sheetId") sheet_title = sheet.get("properties").get("title") result.append({"SheetId": sheetId, "Sheet title": sheet_title}) return result def handle_values_input(values: str) -> list: """ Args: values (str): A string representation of values in the form of "[1,2,3],[4,5,6]..." Returns: (list) A list of lists of the values for this example [[1,2,3],[4,5,6]...] """ # Validate that the user has entered valid values if not values or not BRACKET_LIST_PATTERN.findall(values): raise ValueError("Wrong format of values entered, please check the documentation") # Converting the values the user entered into an array of arrays values_as_array = ast.literal_eval(values) # Checks whether the given values are a singular empty list, such as "[]". # if that's the case, it will convert it to [[]] (a list of lists). if isinstance(values_as_array, list) and len(values_as_array) == 0: values_as_array = [values_as_array] # Checks whether the given values are a single non-empty list, e.g., "[1,2,3]". # in such a case, it will convert it to [[1,2,3]] (a list of lists). elif not all(isinstance(item, list) for item in values_as_array): values_as_array = [values_as_array] # Handling all values including the `None` value to be string res_for_values_req = [] for element in values_as_array: if not element: res_for_values_req.append([""]) continue res_for_values_req.append([str(value) for value in element]) return res_for_values_req def markdown_single_get(response: dict) -> str: """ Args: response (dict): The response from the api call Returns: (str): a mark down representation string Action: creates for a single spreadsheet a mark down with 2 tables table 1: spreadsheet id and title table 2: all the sheets under this spreadsheet id and title this function will be executed only for include_grid_data = False """ human_readable = { "spreadsheet Id": response.get("spreadsheetId", {}), "spreadsheet url": response.get("spreadsheetUrl", {}), } markdown = tableToMarkdown( response.get("properties", {}).get("title", {}), human_readable, headers=["spreadsheet Id", "spreadsheet url"] ) markdown += "\n" sheets = response.get("sheets", []) sheets_titles = create_list_id_title(list(sheets)) markdown += tableToMarkdown("Content", sheets_titles, headers=["SheetId", "Sheet title"]) return markdown def markdown_single_get_include_grid_data(response: dict) -> str: """ Args: response (dict): The response from the API call, after it was processed by context_single_get_output Returns: markdown to present the data of the spreadsheet including its sheets and their data. When: this function will be executed when the get_spreadsheet will be called with the argument include_grid_data as True """ human_readable = { "spreadsheet Id": response.get("spreadsheetId", {}), "spreadsheet url": response.get("spreadsheetUrl", {}), } markdown = tableToMarkdown( response.get("properties", {}).get("spreadsheetTitle", {}), human_readable, headers=["spreadsheet Id", "spreadsheet url"] ) markdown += "\n" markdown += make_markdown_matrix(response.get("sheets", [])) return markdown def make_markdown_matrix(sheets: list) -> str: """ Args: sheets (list) : a list of the spreadsheets sheets after process of context_single_get_parse Returns (str): This function returns a table representation of the sheet. if the sheet is empty the function will return EmptySheet. Action: The functions defines the table number of cols by finding the longest row. """ markdown = "" for sheet in sheets: markdown += f'### ***Name: {sheet.get("title", {})} Sheet Id: {sheet.get("sheetId", {})}***' # find the max number of columns in the table max_row_len = max(list(map(lambda elem: len(elem.get("values")), sheet.get("rowData")))) # noqa: C417 if max_row_len == 0: markdown += "\n**Empty Sheet**\n" else: markdown += "\n|" # this will form a header with no content for i in range(max_row_len): markdown += f"col {i} |" markdown += "\n" markdown += "|" for _ in range(max_row_len): markdown += "-------------- | " markdown += "\n" row_data = sheet.get("rowData") for row in row_data: markdown += "|" values = row.get("values") for value in values: markdown += (value or "") + " |" markdown += "\n" return markdown def context_single_get_parse(response: dict, include_grid_data: bool) -> dict: """ Args: response (dict): The response from the Google API call. include_grid_data (bool): will determine in what manner to parse the response Returns: a filtered response with the desired data. will parse differently for include_grid_data bool """ output_dict = { "spreadsheetId": response.get("spreadsheetId"), "spreadsheetUrl": response.get("spreadsheetUrl"), "spreadsheetTitle": response.get("properties", {}).get("title"), "sheets": parse_sheets_for_get_response(response.get("sheets", []), include_grid_data), } return output_dict def parse_sheets_for_get_response(sheets: list, include_grid_data: bool) -> list: """ Args: sheets (list): this is the sheets list from the Google API response include_grid_data (bool): will determine in what manner to parse the response Returns: list : The sheets after the relevant data was extracted. This function will be called only upon include_grid_data = true """ sheet_lst = [] for sheet in sheets: output_sheet = {} properties = sheet.get("properties", {}) output_sheet["title"] = properties.get("title") output_sheet["sheetId"] = properties.get("sheetId") output_sheet["index"] = properties.get("index") output_sheet["gridProperties"] = properties.get("gridProperties") row_data: list = [] if not include_grid_data: output_sheet["rowData"] = [] sheet_lst.append(output_sheet) continue response_rows_data = sheet.get("data", {})[0].get("rowData", None) if not response_rows_data: row_data.append({"values": []}) else: for response_values in response_rows_data: values = [] if not response_values: row_data.append({"values": []}) else: for response_cell_data in response_values.get("values"): if not response_cell_data: values.append("") else: values.append(response_cell_data.get("formattedValue")) row_data.append({"values": values}) output_sheet["rowData"] = row_data sheet_lst.append(output_sheet) return sheet_lst def default_ranges_if_not_specified(spreadsheet: str, ranges: str, include_grid_data: bool, service: Resource) -> str | None: """ Args: ranges: (str) A Google A1 notation ranges include_grid_data: (bool) argument specified by the user spreadsheet (str): The spreadsheet ID service (Google Resource): google-api discovery resource (google api client) Returns: (str) - A1 notation: The original ranges if specified or a default range if not Action: if include_grid_data is specified without a range, instead of overflowing the server with all the spreadsheet data we will take only a default range 500 rows 120 columns """ if not ranges and include_grid_data: response = service.spreadsheets().get(spreadsheetId=spreadsheet).execute() first_sheet_title = response.get("sheets", [])[0].get("properties", {}).get("title") default_range = first_sheet_title + "!A1:T500" return default_range elif ranges == "None": return None else: return ranges # COMMANDS def create_spreadsheet(service: Resource, args: dict) -> CommandResults: """ Args: service (Google Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults) command result ready for the server Action : creates a new spreadsheet """ rgb_format = argToList(args.get("cell_format_backgroundColor")) rgb_format = rgb_format if rgb_format else [1, 1, 1, 1] spreadsheet = { "properties": { "title": args.get("title"), "locale": args.get("locale", "en"), "defaultFormat": { "numberFormat": { "type": args.get("cell_form_at_type", "TEXT"), }, "backgroundColor": {"red": rgb_format[0], "green": rgb_format[1], "blue": rgb_format[2], "alpha": rgb_format[3]}, "textFormat": { "fontFamily": args.get("cell_format_textformat_family", "ariel"), "fontSize": args.get("cell_format_textformat_font_size", 11), }, "textDirection": args.get("cell_format_text_direction", "LEFT_TO_RIGHT"), }, }, "sheets": [ { "properties": { "title": args.get("sheet_title"), "sheetType": args.get("sheet_type", "GRID"), } } ], } spreadsheet = remove_empty_elements(spreadsheet) response = service.spreadsheets().create(body=spreadsheet).execute() human_readable = { "spreadsheet Id": response.get("spreadsheetId"), "spreadsheet title": response.get("properties").get("title"), } markdown = tableToMarkdown( "Successfully created a spreadsheet", human_readable, headers=["spreadsheet Id", "spreadsheet title"] ) results = CommandResults( readable_output=markdown, outputs_prefix="GoogleSheets.Spreadsheet", outputs_key_field="spreadsheetId", outputs=response ) return results def update_spreadsheet(service: Resource, args: dict) -> CommandResults: """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: CommandResults Action: updates a spreadsheet by a user costume update request """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = safe_load_json(args.get("requests")) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "updated the spreadsheet" return prepare_result(response, args, readable_comment) def get_spreadsheet(service: Resource, args: dict) -> CommandResults: """ Args: service - google-api discovery resource (google api client) args - demisto.args() for the api call output : command result action : gets a single or multiple spreadsheets """ spread_sheets_ids = argToList(args.get("spreadsheet_id")) include_grid_data = argToBoolean(args.get("include_grid_data", False)) ranges = args.get("ranges") markdown = "" if not spread_sheets_ids: raise DemistoException("No spreadsheet ID given") if len(spread_sheets_ids) > 1: for spreadsheet in spread_sheets_ids: response = service.spreadsheets().get(spreadsheetId=spreadsheet).execute() markdown += markdown_single_get(response) markdown += "---\n" markdown = "### Success\n\n" + markdown return CommandResults(readable_output=markdown) else: ranges = default_ranges_if_not_specified(spread_sheets_ids[0], str(ranges), include_grid_data, service) request = service.spreadsheets().get(spreadsheetId=spread_sheets_ids[0], ranges=ranges, includeGridData=include_grid_data) response = request.execute() output_response = context_single_get_parse(response, include_grid_data) if include_grid_data: markdown = markdown_single_get_include_grid_data(output_response) else: markdown = markdown_single_get(response) markdown = "### Success\n" + markdown results = CommandResults( readable_output=markdown, outputs_prefix="GoogleSheets.Spreadsheet", outputs_key_field="spreadsheetId", outputs=output_response, ) return results def create_sheet(service: Resource, args: dict) -> CommandResults: """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: CommandResults Action: creates a new sheet in a spreadsheet """ spreadsheet_id = args.get("spreadsheet_id") rgb_format = argToList(args.get("tab_color")) rgb_format = rgb_format if rgb_format else [1, 1, 1, 1] request_to_update = { "requests": [ { "addSheet": { "properties": { "sheetId": args.get("sheet_id", None), "title": args.get("sheet_title", None), "index": args.get("sheet_index", None), "sheetType": args.get("sheet_type", "GRID"), "rightToLeft": argToBoolean(args.get("right_to_left", False)), "tabColor": {"red": rgb_format[0], "green": rgb_format[1], "blue": rgb_format[2], "alpha": rgb_format[3]}, "hidden": args.get("hidden", False), } } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet"), } request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "created a new sheet" results = prepare_result(response, args, readable_comment) return results def duplicate_sheet(service: Resource, args: dict) -> CommandResults: """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults) : the command result containing the duplicate spreadsheet sheet update api call Action : duplicates a sheet within a spreadsheet """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = { "requests": [ { "duplicateSheet": { "sourceSheetId": args.get("source_sheet_id"), "insertSheetIndex": args.get("new_sheet_index"), "newSheetName": args.get("new_sheet_name"), } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet"), } request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "duplicated the sheet" results = prepare_result(response, args, readable_comment) return results def copy_to_sheet(service: Resource, args: dict) -> CommandResults: """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Copies a spreadsheet sheet from one spreadsheet to another """ spreadsheet_id_to_copy = args.get("source_spreadsheet_id") sheet_id_to_copy = args.get("source_sheet_id") copy_sheet_to_another_spreadsheet_request_body = { "destination_spreadsheet_id": args.get("destination_spreadsheet_id"), } request = ( service.spreadsheets() .sheets() .copyTo( spreadsheetId=spreadsheet_id_to_copy, sheetId=sheet_id_to_copy, body=copy_sheet_to_another_spreadsheet_request_body ) ) request.execute() # we don't save the response because there is no need for output or HR results = CommandResults(readable_output="### Successfully copied the sheet") return results def delete_sheet(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: deletes a sheet from a spreadsheet """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = { "requests": [ { "deleteSheet": { "sheetId": args.get("sheet_id"), } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet"), } request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "deleted the sheet" results = prepare_result(response, args, readable_comment) return results def clear_sheet(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Clears a sheet from a spreadsheet """ spreadsheet_id = args.get("spreadsheet_id") ranges = args.get("range") request = service.spreadsheets().values().clear(spreadsheetId=spreadsheet_id, range=ranges, body={}) request.execute() # we don't save the response because there is no need for output or HR results = CommandResults(readable_output="### Successfully cleared the sheet") return results def dimension_delete_sheet(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: deletes a specified dimension from a sheet in a specified spreadsheet """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = { "requests": [ { "deleteDimension": { "range": { "dimension": args.get("dimension_type"), "sheetId": args.get("sheet_id"), "startIndex": args.get("start_index"), "endIndex": args.get("end_index"), } } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet"), } request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "deleted dimensions" results = prepare_result(response, args, readable_comment) return results def range_delete_sheet(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Deletes a specified range from a sheet in a specified spreadsheet """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = { "requests": [ { "deleteRange": { "range": { "sheetId": args.get("sheet_id"), "startRowIndex": args.get("start_row_index"), "endRowIndex": args.get("end_row_index"), "startColumnIndex": args.get("start_column_index"), "endColumnIndex": args.get("end_column_index"), }, "shiftDimension": args.get("shift_dimension"), } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet"), } request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "deleted range" results = prepare_result(response, args, readable_comment) return results def data_paste_sheets(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Inserts data into a spreadsheet sheet """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = { "requests": [ { "pasteData": { "coordinate": { "sheetId": args.get("sheet_id"), "rowIndex": args.get("row_index"), "columnIndex": args.get("column_index"), }, "data": args.get("data"), "type": f"PASTE_{args.get('paste_type')}", } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet", None), } request_to_update = remove_empty_elements(request_to_update) kind = args.get("data_kind") paste_data = request_to_update.get("requests")[0].get("pasteData") # adding a field to the paste data sub dict so that it will fit the api call needed if kind == "delimiter": paste_data[kind] = "," else: paste_data[kind] = "true" request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "pasted the data" results = prepare_result(response, args, readable_comment) return results def find_replace_sheets(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Finds a vaule in the spreadsheets sheet and replaces it. """ spreadsheet_id = args.get("spreadsheet_id") request_to_update = { "requests": [ { "findReplace": { "find": args.get("find"), "replacement": args.get("replacement"), "sheetId": args.get("sheet_id"), "allSheets": args.get("all_sheets"), "matchCase": args.get("match_case"), "matchEntireCell": args.get("match_entire_cell"), "range": { "sheetId": args.get("range_sheet_id"), "startRowIndex": args.get("range_start_row_Index"), "endRowIndex": args.get("range_end_row_Index"), "startColumnIndex": args.get("range_start_column_Index"), "endColumnIndex": args.get("range_end_column_Index"), }, } } ], "includeSpreadsheetInResponse": args.get("echo_spreadsheet"), } request_to_update = remove_empty_elements(request_to_update) response = service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=request_to_update).execute() readable_comment = "found and replaced" results = prepare_result(response, args, readable_comment) return results def value_update_sheets(service: Resource, args: dict) -> CommandResults: """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Updates values in the spreadsheets sheet """ spreadsheet_id = args.get("spreadsheet_id") input_option = args.get("input_option") ranges = args.get("range") value_range_body = { "majorDimension": args.get("major_dimension"), "values": handle_values_input(str(args.get("values"))), } request = ( service.spreadsheets() .values() .update(spreadsheetId=spreadsheet_id, range=ranges, valueInputOption=input_option, body=value_range_body) ) request.execute() markdown = "### Successfully updated sheet values" return CommandResults(readable_output=markdown) def value_append_sheets(service: Resource, args: dict) -> CommandResults: # pragma: no cover """ Args: service (discovery Resource): google-api discovery resource (google api client) args (dict): demisto.args() for the api call Returns: (CommandResults): Command result with only readable output Action: Appends values to a spreadsheets sheet """ spreadsheet_id = args.get("spreadsheet_id") range_ = args.get("range") input_option = args.get("input_option") insert_option = args.get("insert_option") value_range_body = { "majorDimension": args.get("major_dimension"), "values": handle_values_input(str(args.get("values"))), } request = ( service.spreadsheets() .values() .append( spreadsheetId=spreadsheet_id, range=range_, valueInputOption=input_option, insertDataOption=insert_option, body=value_range_body, ) ) request.execute() markdown = "### Successfully appended values to the sheet" return CommandResults(readable_output=markdown) def get_http_client_with_proxy(proxy: bool, insecure: bool): # pragma: no cover """ Args: proxy (bool): Whether to use a proxy. insecure (bool): Whether to disable ssl and use an insecure connection. Returns: httplib2 object with the proper settings for google api client Action: Create a http client with proxy with whom to use when using a proxy. """ if proxy: proxies = handle_proxy() https_proxy = proxies.get("https") http_proxy = proxies.get("http") proxy_conf = https_proxy if https_proxy else http_proxy # if no proxy_conf - ignore proxy if proxy_conf: if not proxy_conf.startswith("https") and not proxy_conf.startswith("http"): proxy_conf = "https://" + proxy_conf parsed_proxy = urllib.parse.urlparse(proxy_conf) proxy_info = httplib2.ProxyInfo( proxy_type=httplib2.socks.PROXY_TYPE_HTTP, proxy_host=parsed_proxy.hostname, proxy_port=parsed_proxy.port, proxy_user=parsed_proxy.username, proxy_pass=parsed_proxy.password, ) return httplib2.Http(proxy_info=proxy_info, disable_ssl_certificate_validation=insecure) return httplib2.Http(disable_ssl_certificate_validation=insecure) def build_and_authenticate(params: dict): # pragma: no cover """ Args: params (dict): demisto.params() - we use the service account key and proxy and insecure parameters in order to build the Google API resource. Returns: Google Resource Manager API Service object via which commands in the integration will make API calls """ service_account_credentials = params.get("service_account_credentials", {}) try: service_account_credentials = service_account_credentials.get("password") service_account_credentials = json.loads(service_account_credentials) except Exception as e: raise DemistoException(f"\nProblem with json format please validate the correctness\ of your service account json. Json parser error {e}") try: credentials = service_account.ServiceAccountCredentials.from_json_keyfile_dict(service_account_credentials, scopes=SCOPES) except KeyError as e: raise DemistoException(f"There is a problem with the authentication of the Service account credentials.\ Please check the correctness of your credentials. You are missing the following key\ in the service account {e}") except ValueError as e: raise DemistoException(f"(There is a problem with the authentication of the Service account credentials\ The cred are of the wrong type. Google error is : {e})") # add delegation to help manage the UI - link to a google-account if params.get("user_id"): credentials = credentials.create_delegated(params.get("user_id")) proxy = params.get("proxy", False) disable_ssl = params.get("insecure", False) if proxy or disable_ssl: http_client = credentials.authorize(get_http_client_with_proxy(proxy, disable_ssl)) return build("sheets", "v4", http=http_client) else: return build("sheets", "v4", credentials=credentials) def test_module() -> str: # pragma: no cover return "ok" """ MAIN FUNCTION """ def main() -> None: # pragma: no cover """ main function, parses params and runs command functions """ command = demisto.command() demisto.debug(f"Command being called is {command}") try: service = build_and_authenticate(demisto.params()) if command == "test-module": return_results(test_module()) elif command == "google-sheets-spreadsheet-create": return_results(create_spreadsheet(service, demisto.args())) elif command == "google-sheets-spreadsheet-get": return_results(get_spreadsheet(service, demisto.args())) elif command == "google-sheets-spreadsheet-update": return_results(update_spreadsheet(service, demisto.args())) elif command == "google-sheets-sheet-create": return_results(create_sheet(service, demisto.args())) elif command == "google-sheets-sheet-duplicate": return_results(duplicate_sheet(service, demisto.args())) elif command == "google-sheets-sheet-copy-to": return_results(copy_to_sheet(service, demisto.args())) elif command == "google-sheets-sheet-delete": return_results(delete_sheet(service, demisto.args())) elif command == "google-sheets-sheet-clear": return_results(clear_sheet(service, demisto.args())) elif command == "google-sheets-dimension-delete": return_results(dimension_delete_sheet(service, demisto.args())) elif command == "google-sheets-range-delete": return_results(range_delete_sheet(service, demisto.args())) elif command == "google-sheets-data-paste": return_results(data_paste_sheets(service, demisto.args())) elif command == "google-sheets-find-replace": return_results(find_replace_sheets(service, demisto.args())) elif command == "google-sheets-value-update": return_results(value_update_sheets(service, demisto.args())) elif command == "google-sheets-value-append": return_results(value_append_sheets(service, demisto.args())) else: raise NotImplementedError(f'Command "{demisto.command()}" is not implemented.') # Log exceptions and return errors except Exception as e: return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()