From c89de2e6a648b9bb8c721ce818e44493a64f7ee8 Mon Sep 17 00:00:00 2001 From: Luca Angemi Date: Thu, 11 Jul 2024 09:05:22 +0200 Subject: [PATCH] Append multiple rows in Google Sheets (#120829) Co-authored-by: Franck Nijhof --- .../components/google_sheets/__init__.py | 22 +++++++++------- .../components/google_sheets/strings.json | 2 +- tests/components/google_sheets/test_init.py | 26 +++++++++++++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/google_sheets/__init__.py b/homeassistant/components/google_sheets/__init__.py index fc104cc5c22..3f34b23d522 100644 --- a/homeassistant/components/google_sheets/__init__.py +++ b/homeassistant/components/google_sheets/__init__.py @@ -41,7 +41,7 @@ SHEET_SERVICE_SCHEMA = vol.All( { vol.Required(DATA_CONFIG_ENTRY): ConfigEntrySelector(), vol.Optional(WORKSHEET): cv.string, - vol.Required(DATA): dict, + vol.Required(DATA): vol.Any(cv.ensure_list, [dict]), }, ) @@ -108,15 +108,19 @@ async def async_setup_service(hass: HomeAssistant) -> None: raise HomeAssistantError("Failed to write data") from ex worksheet = sheet.worksheet(call.data.get(WORKSHEET, sheet.sheet1.title)) - row_data = {"created": str(datetime.now())} | call.data[DATA] columns: list[str] = next(iter(worksheet.get_values("A1:ZZ1")), []) - row = [row_data.get(column, "") for column in columns] - for key, value in row_data.items(): - if key not in columns: - columns.append(key) - worksheet.update_cell(1, len(columns), key) - row.append(value) - worksheet.append_row(row, value_input_option=ValueInputOption.user_entered) + now = str(datetime.now()) + rows = [] + for d in call.data[DATA]: + row_data = {"created": now} | d + row = [row_data.get(column, "") for column in columns] + for key, value in row_data.items(): + if key not in columns: + columns.append(key) + worksheet.update_cell(1, len(columns), key) + row.append(value) + rows.append(row) + worksheet.append_rows(rows, value_input_option=ValueInputOption.user_entered) async def append_to_sheet(call: ServiceCall) -> None: """Append new line of data to a Google Sheets document.""" diff --git a/homeassistant/components/google_sheets/strings.json b/homeassistant/components/google_sheets/strings.json index e498e36723e..0723456224f 100644 --- a/homeassistant/components/google_sheets/strings.json +++ b/homeassistant/components/google_sheets/strings.json @@ -48,7 +48,7 @@ }, "data": { "name": "Data", - "description": "Data to be appended to the worksheet. This puts the values on a new row underneath the matching column (key). Any new key is placed on the top of a new column." + "description": "Data to be appended to the worksheet. This puts the values on new rows underneath the matching column (key). Any new key is placed on the top of a new column." } } } diff --git a/tests/components/google_sheets/test_init.py b/tests/components/google_sheets/test_init.py index 014e89349e2..700783a2e30 100644 --- a/tests/components/google_sheets/test_init.py +++ b/tests/components/google_sheets/test_init.py @@ -214,6 +214,32 @@ async def test_append_sheet( assert len(mock_client.mock_calls) == 8 +async def test_append_sheet_multiple_rows( + hass: HomeAssistant, + setup_integration: ComponentSetup, + config_entry: MockConfigEntry, +) -> None: + """Test service call appending to a sheet.""" + await setup_integration() + + entries = hass.config_entries.async_entries(DOMAIN) + assert len(entries) == 1 + assert entries[0].state is ConfigEntryState.LOADED + + with patch("homeassistant.components.google_sheets.Client") as mock_client: + await hass.services.async_call( + DOMAIN, + "append_sheet", + { + "config_entry": config_entry.entry_id, + "worksheet": "Sheet1", + "data": [{"foo": "bar"}, {"foo": "bar2"}], + }, + blocking=True, + ) + assert len(mock_client.mock_calls) == 8 + + async def test_append_sheet_api_error( hass: HomeAssistant, setup_integration: ComponentSetup,