hi I have a code of a telegram bot I am trying to connect it to a Excel file. The code is of Bot taking input and updating it to the excel worksheetk the error is // 2024-07-14 11:27:16,343 – main – ERROR – Error fetching Excel data: 400 Client Error: Bad Request for url: https://graph.microsoft.com/v1.0/me/drive/items/61814971F1322FC0!xxxx/earnify.xlsx/worksheets/Sheet1/range(address=’A1:F1000′)
2024-07-14 11:27:16,344 – main – ERROR – Failed to fetch Excel data. Unable to verify username. //
the ms graph output is
{"error":{"code":"InvalidAuthenticationToken","message":"Access token is empty.","innerError":{"date":"2024-07-14T11:56:25","request-id":"2cd7d68d-dbd0-49f0-909b-2bd0eb54xxxx","client-request-id":"2cd7d68d-dbd0-49f0-909b-2bd0eb54xxxx"}}}
and the Code is
# Function to get access token
def get_access_token():
authority = f"https://login.microsoftonline.com/ed586964-ec89-4ecb-95bf-df20fb9axxxx"
app = msal.ConfidentialClientApplication(CLIENT_ID, authority=authority, client_credential=CLIENT_SECRET)
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
if "access_token" in result:
return result['access_token']
else:
logger.error(f"Failed to retrieve access token: {result.get('error')}")
raise Exception("Could not retrieve access token")
# Function to read Excel file from OneDrive
def read_excel():
access_token = get_access_token()
if not access_token:
logger.error("Failed to obtain access token. Unable to read Excel.")
return None
headers = {
'Authorization': f'Bearer {access_token}',
'Accept': 'application/json',
}
url = f'https://graph.microsoft.com/v1.0/me/drive/items/61814971F1322FC0!xxxx/earnify.xlsx/worksheets/Sheet1/range(address='A1:F1000')'
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching Excel data: {e}")
return None
# Function to update Excel file in OneDrive
def update_excel(range_address, values):
access_token = get_access_token()
if not access_token:
logger.error("Failed to obtain access token. Unable to update Excel.")
return False
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json',
}
url = f'https://graph.microsoft.com/v1.0/me/drive/items/61814971F1322FC0!xxxx/workbook/worksheets/Sheet1/range(address='A1:F1000')'
try:
data = {
"values": values
}
response = requests.patch(url, headers=headers, json=data)
response.raise_for_status()
return True
except requests.exceptions.RequestException as e:
logger.error(f"Error updating Excel data: {e}")
return False
I first thought the Client Value is the Client secret as it had two ids one client value and client secret id in certificates and secrets in azure portal. so i changed it with client value but it didn’t worked so i rechanged the values but no luck. I am stuck i also thought of using google spreadsheet but the process to integrate it is too lengthy.
Someone help me out on this…
P.s : I changed python library to 2.7 or something casue one attribute was renamed in the latest version and it was causing an issue so maybe i think that is the problem or something else check it out is the values correct
2
Answers
I see more issues.
You are authenticating with client secret without singed-in user, but you are calling
/me
endpoint./me
endpoint can be called only when you are signed-in on behalf of a user.With client secret and application permissions, you can’t access workbook API. Workbook API doesn’t support application permissions.
In
read_excel
function, there is wrong endpointYou probably forgot to replace
earnify.xlsx
byworkbook
Try to change authentication and authenticate with a user. Also check that you granted delegated permission Files.ReadWrite to your Entra application.
https://learn.microsoft.com/en-us/entra/msal/python/#basic-usage
I agree with @user2250152, your code is using client credentials flow that works with permission of Application type. As mentioned in this MS Document, Application type permissions are not supported for updating worksheet
To call
/me
endpoints, you need to switch to delegated flows like interactive flow or authorization code flow for generating token.Initially, I registered one Entra ID application and granted
Files.ReadWrite
permission of Delegated type as below:In my case, I used interactive flow for which redirect URI should be http://localhost added in
Mobile & desktop applications
platform along with enabling public client flow option:I have one Excel file with below sample data in my OneDrive account:
Now, I ran below modified python code that asks user to sign with interactive flow and updates excel successfully with below response:
Response:
To confirm that, I checked the same in OneDrive where Excel data updated successfully like this: