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.
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.