I'm using the Smartsheet Python SDK and attempting to update rows in a smartsheet in which many of the cells to be updated have existing links out to other sheets. I want to update the cell values with data from a pandas df, while keeping the links out intact. When I attempt to update_rows with new cell values (but keeping the original links_out_to_cells object attached to the original cell), I get API Error 1032: "The attribute(s) cell.linksOutToCells[] are not allowed for this operation." Does anyone know a good workaround for this issue?
Here is my evaluate_row_and_build_updates function (passing in the smartsheet row and the row from the pandas df -- the first value in each row in the smartsheet is meant to be preserved with the update)
def evaluate_row_and_build_updates(ss_row, df_ro):
new_row = smartsheet.models.Row()
new_row.id = ss_row.id
new_row.cells = ss_row.cells
empty_cell_lst = list(new_row.cells)[1:]
for i in range(len(empty_cell_lst)):
empty_cell_lst[i].value = df_row[1][i]
return new_row
When making the request to update the cell values on the source cells for the links you don't have to include the linksOutToCells object. You can just update the cells value. The link out to the other sheet will stay in place and the new cell value you added will be linked out to the other sheets.
It could look like this:
# Build new cell value
new_cell = smartsheet.models.Cell()
new_cell.column_id = <COLUMN_ID>
new_cell.value = "testing"
# Build the row to update
new_row = smartsheet.models.Row()
new_row.id = <ROW_ID>
new_row.cells.append(new_cell)
# Update rows
updated_row = smar_client.Sheets.update_rows(
<SHEET_ID>,
[new_row])
Running that code on a cell that has a link going out will keep the cell link in place.
Related
I have a Dashtable which has more than 1000 rows across multiple pages. I need to show the content of active cell by clicking on it.
It is working fine as along as I am not filtering the rows in dash table. As soon I apply the filter (filter the rows with some data) and click on the cell in the table, it shows me the old cell reference which means it is not displaying the content of the newly selected position but the old reference.
''''''''
**# call back function
#app.callback([Output('textareaReq', 'children')],
[Input('srctable', 'active_cell')],
[State('srctable', 'data')])
# code for active cell click
def get_active_cell_content(active_cell, data):
if active_cell:`enter code here`
location = active_cell
strRow = data[location['row']]
strActiveCell = strRow[location['column_id']]
if strActiveCell:
msg = strActiveCell
return (html.P(msg))**
'''''''''''''''
Pls note I am displaying the output in text area
I know this is an old question, but in case someone else comes looking for the answer, I managed to get this working as I was having the same issues.
Plotly (now?) lets you assign an ID column to a data table, so that when your table is filtered or sorted you can use this ID to reference the specific row, rather than relying on row number:
df['id'] = df['your_id_column']
Then, inside your callback, you can print the active_cell and get the id returned as row_id, which will adjust correctly when the data table is filtered and sorted:
{'row': 1, 'column': 11, 'column_id': 'reason', 'row_id': 'H_195202'}
Link to the relevant article. Hope this helps!
https://dash.plotly.com/datatable/interactivity
I am currently trying to import an excel sheet into Smartsheet, then take the rows of the imported sheet, and move them to the bottom of an existing sheet. To do this I am using the Sheets.move_row function. Below is a snippet of that code.
response = smart.Sheets.move_rows(
result.data.id,smart.models.CopyOrMoveRowDirective({
'row_ids': [**Help**],
'to': smart.models.CopyOrMoveRowDestination({'sheet_id': 1174866712913796})}))
To get information on the imported sheet I use the get_sheet command. My plan would be to then iterate through the sheet.row property and find where "id" is listed and then pull the number next to id into a comma delimited list.
Below is a snippet of me attempting to iterate through the row property, but I am unsure of how to pull out the row ids, and then put them into a comma delimited list.
sheet_info = smart.Sheets.get_sheet(result.data.id,_dir)
print(sheet_info)
for id in sheet_info.rows:
x = id
print (x) #this just prints the cells category
Any help would be appreciated, thanks. For further clarification on what I am trying to do please reference my previously posted question.
The following code snippet does what you've described.
sheetId = 3932034054809476
# get the sheet
sheet = smart.Sheets.get_sheet(sheetId)
# iterate through the rows array and build comma-delimited list of row ids
row_ids = ''
for row in sheet.rows:
row_ids += str(row.id) + ', '
# remove the final (excess) comma and space from the end of the row_ids string
row_ids = row_ids[:len(row_ids)-2]
print(row_ids)
UPDATE:
As #Isaaclele mentions in the comments below, the Copy or Move Row(s) operation requires that the rowIds parameter be specified as a number[]. The string value of the row_ids property in the code snippet above can be converted to this format as shown here:
row_ids = list(map(int, row_ids.split(',')))
Also note (as mentioned in the comments below) that the Copy or Move Row(s) operation requires the column names in the source sheet and the destination sheet to match exactly.
Set-up
I create a Pandas dataframe from all records in a google sheet like this,
df = pd.DataFrame(wsheet.get_all_records())
as explained in the Gspread docs.
Issue
It seems Python stays in limbo when I execute the command since today. I don't get any error; I interrupt Python with KeyboardInterrupt after a while.
I suspect Google finds the records too much; ±3500 rows with 18 columns.
Question
Now, I actually don't really need the entire sheet. The first 300 rows would do just fine.
The docs show values_list = worksheet.row_values(1), which would return the first row values in a list.
I guess I could create a loop, but I was wondering if there's a build-in / better solution?
I believe your goal as follows.
You want to retrieve the values from 1st row to 300 row from a sheet in Google Spreadsheet.
From I suspect Google finds the records too much; ±3500 rows with 18 columns., you want to retrieve the values from the columns "A" to "R"?
You want to convert the retrieved values to the dataFrame.
You want to achieve this using gspread.
In order to achieve this, I would like to propose the following sample script.
In this answer, I used the method of values_get.
Sample script:
spreadsheetId = "###" # Please set the Spreadsheet ID.
rangeA1notation = "Sheet1!A1:R300" # Please set the range using A1Notation.
client = gspread.authorize(credentials)
spreadsheet = client.open_by_key(spreadsheetId)
values = spreadsheet.values_get(rangeA1notation)
v = values['values']
df = pd.DataFrame(v)
print(df)
Note:
Please set the range as the A1Notation. In this case, when "A1:R300" instead of "Sheet1!A1:R300" is used, the values are retrieved from the 1st tab in the Spreadsheet.
When "A1:300" is used, the values are retrieved from the column "A" to the last column of the sheet.
When the 1st row is the header row and the data is after the 2nd row, please modify as follows.
From
df = pd.DataFrame(v)
To
df = pd.DataFrame(v[1:], columns=v[0])
Reference:
values_get
I used openpyxl package.
import openpyxl as xl
wb = xl.load_workbook('your_file_name')>
sheet = wb['name_of_your_sheet']
Specify your range.
for row in range(1, 300):
Now you can perform many opertions e.g this will point at row(1) & col(3) in first iteration
cell = sheet.cell(row, 3)
if you want to change the cell value
cell.value = 'something'
It's has pretty much all of it.
Here is a link to the docs: https://openpyxl.readthedocs.io/en/stable/
I'm trying to edit some information in an excel table using python. I have a list of registrations, pickup dates and delivery dates. I want to check if the registration exists in some of the cells of the excel document and then modify its corresponding pickup and delivery dates. I'm fairly new to python as a whole so this task, although at first seeming simple has proved to be quite challenging. How can I locate the specific table ID by checking if it holds a certain value?
Table for reference:
Alright so I solved the problem myself, posting this answer in case somebody else needs to do something similar.
I used the openpyxl library.
//Create a workbook reference an load it using the openpyxl load_workbook()
method by passing in the path to the excel workbook
workbook = openpyxl.load_workbook(workbook_path)
//Craete instance of a worksheet and pass the name of the worksheet you want to edit
current_worksheet = workbook['Sheet1']
//Get the number of rows so that we know how many registrations we need to edit
row_count = current_worksheet.max_row
//Loop through the registrations on the excel sheet, starting from 2 since 1 is the cell
containing "Car Registration"
for j in range(2, row_count):
//Use the worksheet instance and call the cell() method to point to a specific cell and
fetch the registration from that cell
registration_cell = current_worksheet.cell(row = j, column = 1)
current_registration_plate = registration_cell.value
//Compare the fetched registration with the registration we are trying to find. If so
create variables which point to two new cells using the same row where the id was found
(j), add the needed values into them using again .value. and break the loop
if (current_registration_plate == registration_plate):
pickup_cell = current_worksheet.cell(row = j, column = 2)
pickup_cell.value = pickup_value
dropoff_cell = current_worksheet.cell(row = j, column = 3)
dropoff_cell.value = dropoff_value
break
//Save changes to workbook after finishing the loop
workbook.save(workbook_path)
The Python API for Google sheets has a get method to get values from a spreadsheet, but it requires a range argument. I.e., your code must be something like this,
sheets_service = service.spreadsheets().values()
data = sheets_service.get(spreadsheetId = _GS_ID, range = _SHEET_NAME).execute()
and you cannot omit the range argument, nor will a value of '' work, or a value of 'Sheet1' or similar (unless there is a sheet named Sheet1).
What if I do not know the sheet name ahead of time? Can I reference the first or left-most sheet somehow? Failing that, is there a way to get a list of all the sheets? I have been looking at the API and have not found anything for that purpose, but this seems like such a basic need that I feel I'm missing something obvious.
You can retrieve the values and metadata of Spreadsheet using spreadsheets.get of Sheets API. By using the parameter of fields, you can retrieve various information of the Spreadsheet.
Sample 1 :
This sample retrieves the index, sheet ID and sheet name in Spreadsheet. In this case, index: 0 means the first sheet.
service.spreadsheets().get(spreadsheetId=_GS_ID, fields='sheets(properties(index,sheetId,title))').execute()
Sample 2 :
This sample retrieves the sheet name, the number of last row and last column of data range using sheet index. When 0 is used for the sheet index, it means the first sheet.
res = service.spreadsheets().get(spreadsheetId=_GS_ID, fields='sheets(data/rowData/values/userEnteredValue,properties(index,sheetId,title))').execute()
sheetIndex = 0
sheetName = res['sheets'][sheetIndex]['properties']['title']
lastRow = len(res['sheets'][sheetIndex]['data'][0]['rowData'])
lastColumn = max([len(e['values']) for e in res['sheets'][sheetIndex]['data'][0]['rowData'] if e])
Reference :
spreadsheets.get
Convert column index into corresponding column letter
For column, you can see the method about converting from index to letter at above thread.