Search code examples
pythonsmartsheet-apismartsheet-api-2.0smartsheet-api-1.1

Smartsheet Python API unlock rows 1-30 from 40 sheets


I have approximately 40 sheets contained in a folder, and each one of these sheets have rows locked for editing from row 3 to row 45 (approx). I'm trying to make a python script using the Smartsheet Python API that iterates into each sheet of that folder, and once inside the sheet, unlocks the entire row 3 to 45, and then proceeds with the same action in the next sheet of the folder.

My code is as follows:

import smartsheet
access_token = '2vdafasdfadfasdfasdf'
client = smartsheet.Smartsheet(access_token)
# ID de la carpeta que contiene las hojas
folder_id = '123456789'  # Reemplaza con el ID de tu carpeta

def unlock_rows(sheet_id, start_row, end_row):
    sheet = client.Sheets.get_sheet(sheet_id)
    rows_to_update = []

    for row in sheet.rows[start_row-1:end_row]:
        # Modify the actual Row object
        row.locked = False
        rows_to_update.append(row)  # Append the modified Row object

    # Actualiza las filas en la hoja
    response = client.Sheets.update_rows(sheet_id, rows_to_update)
    if response.message == 'SUCCESS':
        print(f"Unlocked rows {start_row} to {end_row} in sheet {sheet.name}")
    else:
        print(f"Failed to unlock rows in sheet {sheet.name}: {response}")


# Obtén todas las hojas en la carpeta
folder = client.Folders.get_folder(folder_id)
sheets = folder.sheets

# Itera sobre cada hoja y desbloquea las filas
for sheet in sheets:
    sheet_id = sheet.id
    unlock_rows(sheet_id, 3, 30)  # Ajusta el rango de filas si es necesario

print("Rows unlocked successfully.")

When I run the script, I get this result from Python:

{"response": {"statusCode": 400, "reason": "Bad Request", "content": {"errorCode": 1008, "message": "Unable to parse request.", "refId": "36e3d096-06fd-4042-adc6-aa14c2e4aa77"}}}
Failed to unlock rows in sheet HOJAPRUEBA1: {"result": {"code": 1008, "errorCode": 1008, "message": "Unable to parse request.", "name": "ApiError", "recommendation": "Do not retry without fixing the problem. ", "refId": "36e3d096-06fd-4042-adc6-aa14c2e4aa77", "shouldRetry": false, "statusCode": 400}}
Rows unlocked successfully.

Solution

  • This error is likely being caused by the fact that you cannot use the Row objects from a Get Sheet response within an Update Rows request. The reason for this is that the Row objects that are returned within a Get Sheet response contain several read-only properties (i.e., properties that cannot be updated) -- for example, properties like created-date. So when you take a Row object from a Get Sheet response (which contains a mix of read-only properties and updateable properties) and try to use it within an Update Rows request, Smartsheet returns an error -- because it does not allow read-only properties within an Update Rows request.

    The fix for this is simple -- just create a new Row object for each row you want to update in the sheet -- in your case, populating only 2 properties in each Row object: id and locked. And add each newly created Row object to the rows_to_update collection within the for loop that's processing the rows.

    In your code, this means replacing this for block:

    for row in sheet.rows[start_row-1:end_row]:
        # Modify the actual Row object
        row.locked = False
        rows_to_update.append(row)  # Append the modified Row object
    

    With this for block instead:

    for row in sheet.rows[start_row-1:end_row]:
    
        # Build the updated Row object
        row_to_update = smartsheet.models.Row()
        row_to_update.id = row.id
        row_to_update.locked = False
    
        # Add updated row to rows_to_update collection
        rows_to_update.append(row_to_update)
    

    Here's your code again, updated to incorporate this suggested change:

    import smartsheet
    access_token = '2vdafasdfadfasdfasdf'
    client = smartsheet.Smartsheet(access_token)
    
    # ID de la carpeta que contiene las hojas
    folder_id = '1250867123906436'  # Reemplaza con el ID de tu carpeta
    
    def unlock_rows(sheet_id, start_row, end_row):
        sheet = client.Sheets.get_sheet(sheet_id)
        rows_to_update = []
    
        for row in sheet.rows[start_row-1:end_row]:
    
            # Build the updated Row object
            row_to_update = smartsheet.models.Row()
            row_to_update.id = row.id
            row_to_update.locked = False
    
            # Add updated row to rows_to_update collection
            rows_to_update.append(row_to_update)
    
        # Actualiza las filas en la hoja
        response = client.Sheets.update_rows(sheet_id, rows_to_update)
        if response.message == 'SUCCESS':
            print(f"Unlocked rows {start_row} to {end_row} in sheet {sheet.name}")
        else:
            print(f"Failed to unlock rows in sheet {sheet.name}: {response}")      
    
    # Obtén todas las hojas en la carpeta
    folder = client.Folders.get_folder(folder_id)
    sheets = folder.sheets
    
    # Itera sobre cada hoja y desbloquea las filas
    for sheet in sheets:
        sheet_id = sheet.id
        unlock_rows(sheet_id, 3, 30)  # Ajusta el rango de filas si es necesario
    
    print("Script complete.")
    

    Finally, a couple of notes about your print statements:

    • The statement print(f"Unlocked rows {start_row} to {end_row} in sheet {sheet.name}") can be misleading/incorrect -- since even if the sheet contains less than 30 rows, this statement will still print Unlocked rows 3 to 30 in sheet [sheet name].

    • The statement at the end of your script print("Rows unlocked successfully.") is not effective/accurate, as that message will always be printed, no matter the outcome of your script (i.e., even if the row updates are unsuccessful). You'll notice that I've changed this statement to print("Script complete.") in the code sample I've posted above.