Question about error when saving xlsm file using xlwings - python

I want to open an xlsm file via xlwings and then edit it and save it. However, some problems arose.
If I run the code with no excel file working, or just open another excel file and do not edit the excel file, it works fine. However, if I open an Excel file and do some work, for example open a blank Excel file and enter 'test' in cell A1, and run the code, sometimes it works, but sometimes it becomes unresponsive in the third line.(wb_xl = xw.Book(copy)) In this case, the code does not jump from the third line in an unresponsive state. What makes more sense is that the code works fine in some cases.
I want to know when the code works fine in all cases.
And there is one more problem.
If this code is executed while working with another Excel, only wb_xl should be terminated. I don't want another Excel to be closed. I want to exit only wb_xl. However, when the app.quit() code is executed, all open Excels are closed. In this case, how can I close only the Excel(wb_xl) opened through the code without closing the working Excel?
import xlwings as xw
copy = 'C:/Users/ijung/Desktop/210919_Mk_Lot_test/210922_101test.xlsm'
wb_xl = xw.Book(copy) #sometimes no response in this line
ws_xl = wb_xl.sheets['Main']
app = xw.apps.active
ws_xl.range('A1').value = 'test'
wb_xl.save()
app.quit()
#wb_xl.app.kill()
#wb_xl.close()
I also used openpyxl. However, in this part of wb_open.save(copy), an error such as xml.etree.ElementTree.ParseError: mismatched tag: line 20, column 8 occurred. When I use xlsx, the save works fine, but when I use xlsm, an error occurs.
import openpyxl
wb_open = openpyxl.load_workbook(copy, read_only = False, keep_vba = True)
ws_open = wb_open.active
ws_open.cell(1,1).value = 'test'
wb_open.save(copy) #error
wb_open.close()
As a result, the purpose of this code is to open the xlsm file by executing this code even when working with another Excel, edit and save, and close only this xlsm file.However, using multiple packages and searching multiple sites could not solve the problem.I'm under a lot of stress with this issue. Any help would be greatly appreciated. Please help me.
Thanks in advance.

openpyxl does not works with xlsm files that contains form objects
I think the problem is in app.quit() you are closing the excel instance, just use wb_xl.close()
import xlwings as xw
copy = 'C:/Users/ijung/Desktop/210919_Mk_Lot_test/210922_101test.xlsm'
wb_xl = xw.Book(copy) #sometimes no response in this line
ws_xl = wb_xl.sheets['Main']
#app = xw.apps.active # don't needed
ws_xl.range('A1').value = 'test'
wb_xl.save()
wb_xl.close()
This should only close the book, take a look this post has insteresting answers

Related

Run Excel macro from different Excel file

I know there already are many questions regarding this topic, but I couldn't figure out a solution that works out for me.
I want to run an Excel macro stored in an 'xlsm' file, but I need to run it on a different Excel file ('xlsx').
Whenever I try the code below, I get an error message saying that the macro wasn't found, so I suppose the problem has to do with the pathing.
This is what I have:
import win32com.client
import os
try:
excel = win32com.client.Dispatch('Excel.Application')
excel_path = r'C:\Users\martin\Desktop\testing_excel.xlsx'
workbook = excel.Workbooks.Open(excel_path, ReadOnly=1)
excel.Application.Run("'macro_testing.xlsm'!local_macro")
workbook.Save()
excel.Quit()
print('Macro run succesfully')
except Exception as e:
print(e)
excel.Quit()
The 'xlsm' file with the macro is named 'macro_testing.xlsm', and the macro name is 'local_macro'.
Thanks in advance!
When I have to do similar, I store the macro in a command book (.xlsm) - or even .xlam that is called from the command book (which is .xlsm) and it then opens, manipulates, saves and closes .xlsx as appropriate.
If you try to run it from within an .xlsx, you'll never be able to save the code that has done the run, not exactly advisable for repetitive workflows.
So,
macro_testing.xlsm could have another sub which would be something like:
sub runExternal()
with Sheets("Sheet1").
extPath = cells(1,2)
extBook = cells(2,2)
'Declaring the path & workbook to use within the master workbook's "Sheet1"
workbooks.open(extPath & extBook) ReadOnly:False
call local_macro()
application.displayalerts = false 'Just in case there are any GUI prompts
workbooks(extBook).close saveChanges:=True
application.displayalerts = true
end sub
For anybody there who was experiencing the same problem I had, what I finally did was open the two Excel files, like this:
import os
excel_path = os.path.abspath('Excel_to_run_macro.xlsx')
if os.path.exists(excel_path):
xl = win32com.client.Dispatch('Excel.Application')
xl.Workbooks.Open(os.path.abspath('Excel_with_macro.xlsm'), ReadOnly=1)
workbook = xl.Workbooks.Open(excel_path, ReadOnly=1)
xl.Application.Run("'Excel_with_macro.xlsm'!Macro_name")
workbook.Save()
xl.Application.Quit()
del xl

openpyxl error raise ValueError('Min value is {0}'.format(self.min)) in opening heavy file with formatting

I'm trying to use openpyxl for the first time on a very heavy file, that happens to be over 20 500 Ko, has a lot of formatting and a VBA macro.
My code keeps returning the following error:
File " \Anaconda3\lib\site-packages\openpyxl\styles\alignment.py", line 52, in __init__
self.relativeIndent = relativeIndent
File " \Anaconda3\lib\site-packages\openpyxl\descriptors\base.py", line 107, in __set__
raise ValueError('Min value is {0}'.format(self.min))
ValueError: Min value is 0
Would anyone know what the problem is / how to access the file despite it? I'm trying to post data into an existent Excel file to simplify processes and replace a heavy VBA code. So I can't just post it into a different xlsx file and call it using a VBA code (that would defeat the purpose).
Thanks a lot!
Here is my code :
wb = load_workbook(filename='C:/dev/CodeRep/ProjectName/MainFile 2021_01.xlsm', read_only = False, keep_vba = True)
The traceback says that there is a problem with the Alignment definition in the workbook's stylesheet. openpyxl follows the OOXML specification very closely to minimise unpleasant surprises later, this is why it tends to raise exceptions or give warnings rather than let things pass.
For more details we'll need to see the XML source for the stylesheet, or the Alignments part at least. You can find this by unzipping the XLSM file and looking for the styles.xml file. That will give you more information and also allow you to submit a bug report to openpyxl.
Preprocess the file
I solved this issue by preprocessing the excel file.
Found that mi problem was at "*/myfile.xlsx/xl/styles.xml" where several xf tags had an attribute indent="-1", and openpyxl only supports non-negative values, raising that exception when a negative value is found.
After some time spent trying to override entire openpyxl hierarchy in order to catch the exception, I decided to process the XLSX.
Here is my code:
def fix_xlsx(file_name):
with zipfile.ZipFile(file_name) as input_file, zipfile.ZipFile(file_name + ".out", "w") as output_file:
# Iterate over files
for inzipinfo in input_file.infolist():
with input_file.open(inzipinfo) as infile:
if "xl/styles.xml" in inzipinfo.filename:
# Read, Process & Write
lines = infile.readlines()
new_lines = b"\n".join([line.replace(b'indent="-1"', b'indent="0"') for line in lines])
output_file.writestr(inzipinfo.filename, new_lines)
else:
# Read & Write
output_file.writestr(inzipinfo.filename, b"\n".join([line for line in infile.readlines()]))
# Replace file
os.replace(file_name + ".out", file_name)
Disclaimer:
I must say this is not a very elegant solution as the entire file is processed, and an auxiliary file is used.
Also I am not so expert at excel to tell wheter changing that indent="-1" to indent="0" for those tags might cause format problems in the file. This is my working solution and can't really tell the effect of those tags.
I had the same issue — the file wasn't accepted by Openpyxl.
I just opened the file in MS Excel and saved it to a new file. And it worked after that.
I got the same error and wasn't able to figure out the exact cause, but noticed when I ran my python script in a different environment it worked without issue.
I realized it may have had something to do with the versions of the openpyxl and xlrd packages I was using so I downgraded them to openpyxl==3.0.4 and xlrd==1.2.0 (previously using openpyxl==3.0.7 and xlrd==2.0.1) and that solved my issue.
I ran into this issue, my solution was to pinpoint what was causing the error in the spreadsheet (had something to do with a table that was recently modified) and reconstruct that table in the worksheet. much easier for me than debugging openpyxl or xml.

How to ignore "Enable Editing" in excel after writing data using openpyxl

I am using a Excel template which have 6 tabs (All unprotected) and writing the data on each worksheet using openpyxl module.
Once the excel file is created and when tried to open the generated file, its not showing all data untill and unless I click "Enable editing" pop up.
Is there any attribute to disable in openpyxl.
This sounds like Windows has quarantined files received over a network. As this is done when the files are received, there is no way to avoid this when creating the files.
I solved this for me.
I found the answer here:
https://codereview.stackexchange.com/questions/240136/python-script-for-refreshing-and-preprocessing-data-in-excel-report-files
I only used the refresh function and it basically opened the excel file, click/refreshed, and closed/saved. You see an Excel file appear briefly on the screen. I'll insert this in a loop to go through all the files I am creating. It might take a little while to run hundreds, but much faster than open-click-save.
Here is all the code I used:
import win32com.client as win32
def refresh(directory, file_name):
xlapp = win32.DispatchEx('Excel.Application')
xlapp.DisplayAlerts = False
xlapp.Visible = True
xlbook = xlapp.Workbooks.Open(directory + '\\' + file_name)
xlbook.RefreshAll()
xlbook.Save()
xlbook.Close()
xlapp.Quit()
return()

How can I check if a specific workbook (Excel file) is opened? After I find out, how can I close it?

I created a Python script which scrapes a website, grabs the information I need and writes it in an Excel file. The problem is that, sometimes, after I check what has been written, I forget to close the Excel file and the script no longer runs (due to the fact that the file is already opened)
To open/write/save/close the Excel file, I am using the openpyxl library, but I don't know how to check if that specific file is opened and how to close it afterwards.
#writing to excel
pathexcel = r'C:\Users\...\Data.xlsx'
wb = load_workbook(pathexcel)
sheet = wb.active
sheet.append(row1)
sheet.append(row2)
sheet.append(row3)
wb.save(pathexcel)
Thank you!

Openpyxl NotImplementedError Only When Loading Workbook

I have been working on a program to input some data into an excel file using Openpyxl with options of either loading an existing file or creating a new file. While creating a new file allows me to write the data to the excel file without any problems but loading from an existing file and trying to write new data to new rows raises a NotImplementedError with the line:
ws['A' + str(row)] = gene]
even though it was the same for writing to a new file.
Any help would be greatly appreciated!
Update: Thanks Charlie, after removing use_iterators from:
wb = load_workbook(filename=file_name+'.xlsx', use_iterators=True), the code let me write to the file.
If you open a file in read-only mode, why do you expect to be able to edit it? The exception is raised for exactly this reason.
Remove use_iterators when opening the file to avoid this.

Categories