2

I'm trying to create a script to handle with a google spreadsheet, but sometimes, it happens that when I use the command val = worksheet.cell(1, 2).value, the actual value is like =M7, therefore, it doesn't have a real value for the script. Is there any possible workaround to get the content from the "M7" cell and copy it to the cell I'm reading?

A sample sheet is here.

Sample code:

import gspread
from oauth2client.service_account import ServiceAccountCredentials

scope = ['https://spreadsheets.google.com/feeds']
spreadsheet_id = '1sfltKJ1-EBlXJReDSmb5KiqeNSXbHuuLH2d2O1_Qfyc'
credentials = ServiceAccountCredentials.from_json_keyfile_name('C:\credentials.json', scope)
client = gspread.authorize(credentials)
wb = client.open_by_key(spreadsheet_id)

ws = None
sheets = [s for s in wb.worksheets() if s.id == 0]
if sheets:
    ws = sheets[0]

values = ws.get_all_values(value_render_option='FORMULA')

print(values)

# if you run this code, you will see that for gspread, the stirng 'original_value' is only in the B2 cell.
# When the gspread module reads the D2 cell, it shows actually the formula, that is =B2
# Also, I need to used the param 'value_render_option='FORMULA'', because sometimes there is a hyperlink formula in the cell,
# so sometimes I need to read the real content of the cell.

# I hope you understand the formula

Resuming, if you run the above code, you will get this list:

[['', '', '', ''], ['', 'original_value', '', '=B2']]

But the expected output should be:

[['', '', '', ''], ['', 'original_value', '', 'original_value']]

UPDATE:

I have created an workaround for this issue, so if this is useful for anyone, the code will be below:

def column2number(col):
    num = 0
    for c in col:
        if c in string.ascii_letters:
            num = num * 26 + (ord(c.upper()) - ord('A')) + 1
    return num

values = ws.get_all_values(value_render_option='FORMULA')
for i in range(len(values)):
    for j in range(len(values[i])):
        # this will check a combination of any number of uppercase letters followed by any number of numbers, representing the column and the line, respectively.
        p = re.compile('^=[A-Z]+[0-9]+')
        try:
            # if the variable p is not null, we will retrieve the matched regex from the string, split it, and get only the letters.
            r = p.match(str(values[i][j])).group()
            output = re.split('(\d+)',r[1:])
            # this function 'column2number' will convert the column letters to its position numerically
            output[0] = column2number(output[0]) - 1
            output[1] = int(output[1]) - 1
            output[2] = i
            output.append(j)
            
            # the output is filled, respectivelly by: referenced column, referenced line, line where the content will be placed, column where the content will be placed

            values[i][j] = values[output[1]][output[0]]
        except AttributeError:
            pass
print(values)

This workaround will just replace the referencing formulas like =M7 by the existing content in the M7 cell.

João Casarin
  • 674
  • 2
  • 9
  • 27
  • Hello @Tanaike, could you help me with this question? I really appreciate your help, thanks. – João Casarin Dec 20 '20 at 16:10
  • Thank you for your comment. But I have to apologize for my poor English skill. Unfortunately, I cannot understand about your question. By this, I cannot think of the solution. I apologize for this. So in order to correctly understand about your question, can you provide the sample Spreadsheet including sample input and output you expect? By this, I would like to try to understand about your question. If you can cooperate to resolve your issue, I'm glad. – Tanaike Dec 21 '20 at 02:08
  • Hello @Tanaike, I'm sorry for tagging you here. Your english is really good, do not apologize for it :) About the topic, I updated it with a sample sheet, a sample code, and the actual and expected outputs. Ah, just to remember, I really need the `value_render_option='FORMULA'` to be able to read hyperlinks formulas. Thanks! – João Casarin Dec 21 '20 at 03:20
  • Thank you for replying and adding more information. From your updated question, I proposed a modification point as an answer. Could you please confirm it? If I misunderstood your question and that was not the result you expect, I apologize. – Tanaike Dec 21 '20 at 04:53
  • hello @Tanaike, how are you doing? I have updated my post with a possible solution, what do you think about that solution? Thanks. – João Casarin Dec 22 '20 at 04:29

1 Answers1

1

I believe your goal as follows.

  • You want to retrieve the cell values using gspread.
  • You don't want to retrieve the formulas.

Modification points:

  • When I saw the document of get_all_values, when value_render_option='FORMULA' is used, the formula is retrieved when the cell has the formula. So when you want to retrieve the cell values which is the formula, please use value_render_option='FORMATTED_VALUE' and value_render_option='UNFORMATTED_VALUE'.
    • When I saw the script of gspread, it seems that FORMATTED_VALUE is the default value. Ref

When above points are reflected to your script, it becomes as follows.

Modified script:

From:
values = ws.get_all_values(value_render_option='FORMULA')
To:
values = ws.get_all_values()

or

values = ws.get_all_values(value_render_option='UNFORMATTED_VALUE')

Reference:

Added:

From your replying, I understood you want to retrieve the formula of hyperlink when the formula of hyperlink is put to the cell. For this, I would like to propose the following script.

Sample script:

values = ws.get_all_values()
formulas = ws.get_all_values(value_render_option='FORMULA')
for i, r in enumerate(formulas):
    for j, c in enumerate(r):
        if '=hyperlink' in c:
            values[i][j] = c
print(values)
  • In this sample script, the values and formulas are retrieved and when =hyperlink is included in the formula, the formula is retrieved. I thought that this method might be a simple.
Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • I thought of changing the render option, but as I said, if I change that, I will not be able to get the hyperlink formulas.. For example: with `value_render_option='FORMULA'` I get `=hyperlink("https://google.com";"google")`, and without the option, I just get `google` as output... See? using the option breaks one part of script, and not using breaks another part.. – João Casarin Dec 21 '20 at 12:43
  • @João Casarin Thank you for replying. I deeply apologize for my poor English skill and my poor skill. I couldn't notice about the comment line in your script. From your replying, I added one more sample script as an answer. Could you please confirm it? If that was not the result you expect, I apologize again. – Tanaike Dec 22 '20 at 00:21
  • thanks for your answer... I appreciate your effort for trying to help me, but running your code, I get an error on the line `if '=hyperlink' in c:`: `TypeError: argument of type 'int' is not iterable`... But that's okay! – João Casarin Dec 22 '20 at 04:15
  • but I was able to create an workaround for this using regex and the module string, I'll update my post right now adding the algorithm I thought! Thanks for your help!! – João Casarin Dec 22 '20 at 04:18
  • @João Casarin Thank you for replying. Unfortunately, I cannot understand about your script. Because the result values are the same for both my proposed script and your updated script. And also, I cannot replicate of ``I get an error on the line if '=hyperlink' in c:: TypeError: argument of type 'int' is not iterable``. I apologize for my poor skill again. Can I ask you about the detail information for replicating the issue? By this, I would like to confirm it. – Tanaike Dec 22 '20 at 05:02
  • I'm sorry for the inconvenience, but it actually worked.. I guess I was implementing your code wrongly. By the way, coudl you explain how your code works? I'm not sure about the steps it goes through... Thanks! – João Casarin Dec 22 '20 at 05:03
  • @João Casarin Thank you for replying. From your replying, I understood that my proposed script worked for your situation. About `I'm not sure about the steps it goes through`, in this case, I retrieves both the cell values and the formulas, when the formula of `=hyperlink` is used in the cell, it is copied to the values. By this, the result is obtained. If this was not the direction you expect, I apologize again. – Tanaike Dec 22 '20 at 05:07
  • Oh, now I see how it works... Actually it seems very simpler than my script, I really appreciate it! I will choose your answer as the solution for this thread. As always, thanks for your big help! Have a good year! – João Casarin Dec 22 '20 at 15:22
  • @João Casarin Thank you for replying. I'm glad it is useful for you. Thank you, too. – Tanaike Dec 22 '20 at 23:05