14

I am using openpyxl to write to a workbook. But that workbook needs to be closed in order to edit it. Is there a way to write to an open Excel sheet? I want to have a button that runs a Python code using the commandline and fills in the cells.

The current process that I have built is using VBA to close the file and then Python writes it and opens it again. But that is inefficient. That is why I need a way to write to open files.

4
  • 1
    Do you specifically want to use openpyxl? I generally prefer xlrd and xlwt for their flexibility with the same. Commented Jan 4, 2017 at 23:26
  • 1
    I have no reason to use openpyxl specifically. So far I have been able to synchronize VBA and python and openpyxl is doing a decent job. Why do you suggest using xlwt or xlrd? Commented Jan 6, 2017 at 16:22
  • 1
    @SashaZd This is off topic but you mentioned xlwt as an option. Openpyxl has been giving me some issues with formatting. Is xlwt better in terms of that? Does it maintain the Excel formatting? Commented Jan 13, 2017 at 17:09
  • 2
    Yes it does. I've used it for really complicated Excel-Python integrations including formula and type conversions in the past. It should be a better solution than OpenPyxl Commented Jan 13, 2017 at 23:06

5 Answers 5

11

If you're a Windows user there is a very easy way to do this. If we use the Win32 Library we can leverage the built-in Excel Object VBA model.

Now, I am not sure exactly how your data looks or where you want it in the workbook but I'll just assume you want it on the sheet that appears when you open the workbook.

For example, let's imagine I have a Panda's DataFrame that I want to write to an open Excel Workbook. It would like the following:

import win32com.client
import pandas as pd

# Create an instance of the Excel Application & make it visible.
ExcelApp = win32com.client.GetActiveObject("Excel.Application")
ExcelApp.Visible = True

# Open the desired workbook
workbook = ExcelApp.Workbooks.Open(r"<FILE_PATH>")

# Take the data frame object and convert it to a recordset array
rec_array = data_frame.to_records()

# Convert the Recordset Array to a list. This is because Excel doesn't recognize 
# Numpy datatypes.
rec_array = rec_array.tolist()

# It will look something like this now.
# [(1, 'Apple', Decimal('2'), 4.0), (2, 'Orange', Decimal('3'), 5.0), (3, 'Peach', 
# Decimal('5'), 5.0), (4, 'Pear', Decimal('6'), 5.0)]

# set the value property equal to the record array.
ExcelApp.Range("F2:I5").Value = rec_array

Again, there are a lot of things we have to keep in mind as to where we want it pasted, how the data is formatted and a whole host of other issues. However, at the end of the day, it is possible to write to an open Excel file using Python if you're a Windows' user.

Sign up to request clarification or add additional context in comments.

2 Comments

This solution is working for me however due to ExcelApp.Workbooks.Open(), the script tries to reopen the excel sheet. Is there a way just to get the already open excel file?
If you want to use the active workbook instead of writing this: python workbook = ExcelApp.Workbooks.Open(r"<FILE_PATH>") You would write this: python workbook = ExcelApp.ActiveWorkbook This represents the Active Workbook or the, in other words, the workbook that you currently have your cursor in.
3

Generally, two different processes shouldn't not be writing to the same file because it will cause synchronization issues.

A better way would be to close the existing file in parent process (aka VBA code) and pass the location of the workbook to python script.

The python script will open it and write the contents in the cell and exit.

2 Comments

So the VBA code executes the Python code and closes the Excel file. The Python code does its work and writes it to the same Excel file that was closed and then opens it. But the kind of tool that I am trying to build will involve a lot of interaction and everytime that happens, I do not want the Excel workbook to be closed and edited and then opened again. Just like VBA code can write to an Excel file that is open, I am trying to achieve the same thing using Python.
I don't think excel workbook has any kind of synchronization primitives to allow two concurrent writes. Python doesn't know that VBA code has already opened the file and same applies to VBA code too. I agree with you that there may be lot of interactions but the resulting end product may be more reliable. Also, I don't think opening and closing a file multiple times is time consuming.
3

No this is not possible because Excel files do not support concurrent access.

1 Comment

What does COM have to do with openpyxl?
2

I solved this doing the follow: Create an intermediary excel file to recieve data from python and then create a connexion between this file and the main file. The excel has a tool that allow automatically refresh imported data from another workbook. Look this LINK

wb = openpyxl.load_workbook(filename='meanwhile.xlsm', read_only=False, keep_vba=True)

...

wb.save('meanwhile.xlsm')

In sequence open your main excel file:

On the Data tab, create a connexion with the "meanwhile" workbook, then in the Connections group, click the arrow next to Refresh, and then click Connection Properties.

Click the Usage tab.

Select the Refresh every check box, and then enter the number of minutes between each refresh operation.

Comments

1

Using below code I have achieved, writing the Excel file using python while it is open in MS Execl. This solution is for Windows OS, not sure for others.

from kiteconnect import KiteConnect
import xlwings as xw

wb = xw.Book('winwin_safe_trader_youtube_watchlist.xlsx')
sht = wb.sheets['Sheet1']
stocks_list = sht.range('A2').expand("down").value
watchlist = []
time.sleep(10)

for name in stocks_list:
    symbol = "NSE:" + name
    watchlist.append(symbol)

print(datetime.datetime.today().time())
data = kite.quote(watchlist)
df = pd.DataFrame(data).transpose()
df = df.drop(['depth', 'ohlc'], 1)
print(df)
sht.range('B1').value = df
time.sleep(1)
wb.save('winwin_safe_trader_youtube.xlsx')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.