With VBA, I can edit arbitrary workbook metadata like so, and it will be reflected on SharePoint:
With ThisWorkbook
.ContentTypeProperties("Property A") = 1
.ContentTypeProperties("Prop B") = “Something”
End With
Now, I am hoping to do the same with openpyxl
I can do this for properties without spaces:
wb.properties.title = 'test'
but properties with spaces won't work--I try this and the script runs, but nothing shows on SharePoint:
setattr(wb.properties, 'Project Title', 'hello')
wb.properties.__dict__['Project Number'] = '12'
This can be done with xlsxwriter
import xlsxwriter
workbook = xlsxwriter.Workbook(wb_path)
workbook.set_custom_property('Project Title', 'hello')
workbook.close()
but it will create a new workbook...
According to this https://foss.heptapod.net/openpyxl/openpyxl/-/merge_requests/384/diffs?commit_id=e00ce36aa92ae4fffa7014e460a8999681d73b8b
I could simply do
wb.custom_doc_props.add(k, v), but I'm getting no attribute custom_doc_props with the latest version (I believe), 3.0.10.
I installed the 3.2.0b1 version with pip, and now get AttributeError: 'CustomDocumentPropertyList' object has no attribute 'add'. I guess the method isn't fully implemented yet
This works with version 3.1.0 of openpyxl. You can download via pip with
python -m pip install https://foss.heptapod.net/openpyxl/openpyxl/-/archive/branch/3.1/openpyxl-branch-3.1.zip
and assign properties like so
from openpyxl.packaging.custom import (
BoolProperty,
DateTimeProperty,
FloatProperty,
IntProperty,
LinkProperty,
StringProperty,
CustomPropertyList,
)
props = CustomPropertyList()
props.append(StringProperty(name='hello world', value='foo bar'))
wb.custom_doc_props = props
wb.save(...)
Data is preserved on SharePoint. More info here: https://foss.heptapod.net/openpyxl/openpyxl/-/blob/branch/3.1/doc/workbook_custom_doc_props.rst
Ok I'm new to python but...I really like it. I have been trying to figure this out for awhile and thought someone could help that knows a lot more than I.
So what I would like to do is use pygsheets and combine batch the updates with one api call vs several. I have been searching for examples or ideas and found if you unlink and link it will do this? I tried and it speed it up only a little bit, then I looked and you could use update.values vs update.value. I have got it to work with the something like this wk1.update_values('A2:C4',[[1,2,3],[4,5,6],[7,8,9]]) but what if you want the updates to be in specific cell locations vs a range like a2:c4? I appreciate any advice in advance.
https://pygsheets.readthedocs.io/en/latest/worksheet.html#pygsheets.Worksheet.update_values
https://pygsheets.readthedocs.io/en/latest/sheet_api.html?highlight=batch_updates#pygsheets.sheet.SheetAPIWrapper.values_batch_update
import pygsheets
gc = pygsheets.authorize() # This will create a link to authorize
# Open spreadsheet
GS_ID = ''
File_Tab_Name = 'File1'
Main_Topic = 'Main Topic'
Actual_Company_Name = 'Company Name'
Street = 'Street Address'
City_State_Zip = 'City State Zip'
Phone_Number = 'Phone Number'
# 2. Open spreadsheet by key
sh = gc.open_by_key(GS_ID)
sh.title = File_Tab_Name
wk1 = sh[0]
wk1.title = File_Tab_Name
#wk1.update_values('A2:C4',[[1,2,3],[4,5,6],[7,8,9]])
wk1.update_values([['a1'],['h1'],['i3']],[[Main_Topic],[Actual_Company_Name],[Street]]) ### is this possible
#wk1.unlink()
#wk1.title = File_Tab_Name
#wk1.update_value("a1",Main_Topic) ###Topic
#wk1.update_value("h1",Actual_Company_Name) ###Company Name
#wk1.update_value("i3",Street) ###Street Address
#wk1.update_value("i4",City_State_Zip) ###City State Zip
#wk1.update_value("i5",Phone_Number) ### Phone Number
#wk1.link() # will do all the updates
From what I could undersand you want to batch update values. you can use the update_values_batch function.
wks.update_values_batch(['A1:A2', 'B1:B2'], [[[1],[2]], [[3],[4]]])
# or
wks.update_values_batch([((1,1), (2,1)), 'B1:B2'], [[[1,2]], [[3,4]]], 'COLUMNS')
# or
wks.update_values_batch(['A1:A2', 'B1:B2'], [[[1,2]], [[3,4]]], 'COLUMNS')
see doc here.
NB: update pygsheets to latest version or install from gitub
pip install --upgrade https://github.com/nithinmurali/pygsheets/archive/staging.zip
Unfortunately, pygsheets has no method for updating multiple ranges in batch. Instead, you can use gspread.
gspread has batch_update method where you can update multiple cell or range at once.
Example:
Code:
import gspread
gc = gspread.service_account()
sh = gc.open_by_key("insert spreadsheet key here").sheet1
sh.batch_update([{
'range': 'A1:B1',
'values': [['42', '43']],
}, {
'range': 'A2:B2',
'values': [['44', '45']],
}])
Output:
References:
gspread:batch_update()
gspread Authentication
it seems that I can't update the sheet (worksheet) name,
what to do?
sh = gc.open('My worksheet')
worksheet = sh.get_worksheet(0)
worksheet.update_title = 'my sheet'
Please take a look at the documentation. You can see that update_title is supposed to be a function call which you call as shown below.
worksheet.update_title('my sheet')
I am writing a telegram bot, where I want to store the information that the user will input in a excel spreadsheet. Two libraries the I am using are teleport and openpyxl. I am facing a problem that data is not writing in excel file.
Here is my code:
import telebot
import openpyxl
bot = telebot.TeleBot("TOKEN")
wb = openpyxl.load_workbook('results.xlsx')
ws = wb['Poll']
last_row = ws.max_row + 1
#bot.message_handler(content_types=['text'])
def handle_text(message):
if message.text == '/start':
bot.send_message(message.from_user.id, 'Hello Welcome')
user_id = str(message.from_user.id)
ws.cell(row = last_row, column = 1).value = user_id #here is where the problem is
wb.save('results.xlsx')
bot.polling(none_stop=True, timeout=60)
The code is not giving any mistakes, moreover, if I put ws.cell line before #bot.message_handle and give some value it works. It is just not working inside the decorator. Does anyone know how to fix this problem?
Thanks!
Your code currently has a fixed value for the row where you write data so you will always overwrite the same cells. Much better simply to append to the worksheet:
ws.append([user_id])
I'm having some trouble with PasteSpecial in python. Here's the sample code:
import win32com.client as win32com
from win32com.client import constants
xl = win32com.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
wb = xl.Workbooks.Add ()
Sheet1 = wb.Sheets("Sheet1")
# Fill in some summy formulas
for i in range(10):
Sheet1.Cells(i+1,1).Value = "=10*"+str(i+1)
Sheet1.Range("A1:A16").Copy()
Sheet1.Range("C1").Select()
Sheet1.PasteSpecial(Paste=constants.xlPasteValues)
I'm getting the following error:
TypeError: Paste() got an unexpected keyword argument 'Paste'
I know that paste is a keyword argument because of the MSDN here:
http://msdn.microsoft.com/en-us/library/office/ff839476(v=office.15).aspx
Any idea why it won't let me do this? Can't really find much on the web.
Edit for solution(s):
import win32com.client as win32com
from win32com.client import constants
xl = win32com.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
wb = xl.Workbooks.Add ()
Sheet1 = wb.Sheets("Sheet1")
# Fill in some summy formulas
for i in range(10):
Sheet1.Cells(i+1,1).Value = "=10*"+str(i+1)
Sheet1.Range("A1:A16").Copy()
Sheet1.Range("C1").PasteSpecial(Paste=constants.xlPasteValues)
# OR this I just found right after I posted this works as well:
xl.Selection.PasteSpecial(Paste=constants.xlPasteValues)
You can get value for xlPasteFormats by execute macro in Excel vb:
Sub Macro2()
Range("A7").Select
ActiveCell.FormulaR1C1 = xlPasteFormats
End Sub
The value for xlPasteFormats is -4122
In Python script you can use
xlSheet.Range("A7:H7").Copy()
xlSheet.Range("A%s:H%s"%(r,r)).PasteSpecial(Paste=-4122)
I don't work with python but to do a PasteSpecial in Excel-VBA, you have to mention the cell where you want to perform the pastespecial, so try like
Sheet1.Range("C1").PasteSpecial(Paste=constants.xlPasteValues)
If you want a simple paste then I guess this should work
Sheet1.Paste