Access excel with macros using openpyxl - python

I have an .xlsm file with lots of macros and sheets, which provides some graphs when filled in. I want to open the .xlsm file in python and fill some values to the macros in order to get the graphs . I have tried the following code but it seems that when I open the new file a message that the file is corrupted pops-up.
I use python 2.74 and openpyxl version is 2.4.8
import openpyxl
from xlwt import easyxf
book = openpyxl.load_workbook('macroexcel.xlsm',keep_vba=True) #opens excel file
sheet = book.get_sheet_by_name('SheetName') #Get the sheet name
sheet['K34'] = 'Value' #Assign value to a cell connected to the macro
book.save('newexcel.xlsm') #Save
Is there a way to get access to the values in the macros, select them and extract the graphs using python.?
Thanks.

Try this - How To: Add and Call Excel Macro from Python Using Pandas, Win32 and PyMySQL.
It suggests Python to initiate a win32com.client.Dispatch('Excel.Application') to start Excel. Then, having access to the application layer, xl.Application.Run("Macro1").

Related

Openpyxl-Made changes to excel and store it in a dataframe, how to kill the Excel without saving all the changes and avoid further recovery dialogue?

I need to open and edit my Excel with openpyxl, store the excel as a dataframe, and close the excel without any changes. Are there any ways to kill the excel and disable the auto-recovery dialogue which may pop out later?
The reason I'm asking is that my code worked perfectly fine in Pycharm, however after I packed it into .exe with pyinstaller, the code stopped working, the error said "Excel cannot access the file, there are serval possible reasons, the file name or path does not exist, or the file is being used by another program, or the workbook you are saving has the same name as a currently open workbook.
I assume it is because the openpyxl did not really close the excel, and I exported it to a different folder with the same file name.
Here is my code:
wb1 = openpyxl.load_workbook(my_path, keep_vba=True)
ws1 = wb1["sheet name"]
making changes...
ws1_df = pd.DataFrame(ws1.values)
wb1.close()
Many thanks ahead :)
The following way you can do this. solution
from win32com.client import Dispatch
# Start excel application
xl = Dispatch('Excel.Application')
# Open existing excel file
book = xl.Workbooks.Open('workbook.xlsx')
# Some arbitrary excel operations ...
# Close excel application without saving file
book.Close(SaveChanges=False)
xl.Quit()

'[Errno 13]' Permission denied: Openpyxl and win32com conflict

I'm using win32com to run macros in excel and openpyxl to modify cell values. In the process of debugging, I attempted to create a simplified version of existing code but still ran into the same
[Errno 13] Permission denied:'C:\\Users\\NAME\\Desktop\\old\\Book1.xlsx'.
I believe that the error is caused by the two packages (win32com and openpyxl) opening the same file and, when attempting to save/close, cannot close the instance open in the other package.
When I attempt to save/close with openpyxl before saving/closing with win32com, I run into the permission denied error. This makes sense; Openpyxl probably does not have permission to close the excel instance open through win32com. Code is below:
wb.save(r"C:\Users\NAME\Desktop\old\Book1.xlsx")
xel.Workbooks(1).Close(SaveChanges=True)
However, when I switch the order:
xel.Workbooks(1).Close(SaveChanges=True)
wb.save(r"C:\Users\NAME\Desktop\old\Book1.xlsx")
Excel attempts to save a backup file (randomly named "522FED10" or "35C0ED10", etc.) and when I press save, Excel crashes.
What's the workaround? I was thinking that you could use win32com to run the macros, save under a different filename, then use openpyxl to access that file and edit values. However, this is extremely inefficient (I'm dealing with excel files that have hundreds of thousands of rows of data). I could consider just using win32com, but that would require a revamp of a system.
Simple code:
import openpyxl as xl
import win32com.client
xel=win32com.client.Dispatch("Excel.Application")
xel.Workbooks.Open(Filename=r"C:\Users\NAME\Desktop\old\Book1.xlsx")
wb = xl.load_workbook(r"C:\Users\NAME\Desktop\old\Book1.xlsx")
ws = wb.active
xel.visible = False
xel.Cells(1,1).Value = 'Hello Excel'
ws.cell(row = 1,column = 2).value = "test"
xel.Workbooks(1).Close(SaveChanges=True)
wb.save(r"C:\Users\NAME\Desktop\old\Book1.xlsx")
Current issue
You should definitely not mix win32com and openpyxl operations.
The win32com statement xel.Workbooks.Open() loads the workbook contents into a memory space controlled by an Excel process. The openpyxl xl.load_workbook() statement on the other hand loads the workbook contents into a completely separate memory space controlled by a Python process.
Hence any subsequent win32com commands will do nothing to affect the workbook that's living inside the python-process-controlled memory, and vice versa any openpxyl commands will do nothing to affect the workbook that's living inside the Excel-process-controlled memory.
Solution
You mentioned that you have to run some excel macros. This rules out an openpyxl-only solution. My suggestion would be to use xlwings, which is in essence a powerful and user-friendly wrapper around the win32com API.
Here is a simple example of how you can execute Excel macros and manually update cell values within a single python script:
import xlwings as xw
# Start Excel app (invisibly in the background)
app = xw.App(visible=False)
# Load excel file into active Excel app
book = app.books.open(r"Book1.xlsm")
# Instruct Excel to execute the pre-existing excel macro named "CleanUpMacro"
book.macro("CleanUpMacro")()
# Instruct Excel to write a cell value in the first sheet
book.sheets["Sheet1"].range('A1').value = 42
# Save workbook and terminate Excel application
book.save()
book.close()
app.kill()

Unable to save formulas under excel file when it is saved using openpyxl lib

Formulas in the excel sheet are getting removed when it is saved through an openpyxl python script.
Is there any way to save excel file without removing formulas using a python script
Expected: Formulas should not be removed and data should be read through openpyxl lib
Actual: Data is read, but formulas are getting removed
If you read file with data_only = True argument you read value from formula, but not formula.
From docs
data_only controls whether cells with formulae have either the formula (default) or the value stored the last time Excel read the sheet.
Though xlswings, this issue is resolved
I am able to successfully resolve this issue for my assignment.
First do not use data_only parameter. Only define the excel and the sheet using -
e.g.:
exl = openpyxl.load_workbook(exlFile)
sheet = exl["Sheet1"]
now again define the same excel this time using data_only=true
exl1 = openpyxl.load_workbook(exlFile, data_only=True)
sheet1 = exl1["Sheet1"]
Now while reading the data from excel, use sheet1 while writing back to excel, use sheet.
Also while saving the workbook, use exl.save(exlFile) instead of exl1.save(exlFile)
With this I was able to retain all the formulas and also could update the required cells.
Let me know if this is sufficient or need more info.

How do I find next available column in Xls file and write there using xlrd/xlwt in Python

I am writing a selenium script where I need to store username password information of all the accounts I am creating.
So I am using xlrd and xlwt to write information in an excel file but I am not able to find a way how script automatically detects next available row in the sheet and writes the info there. I am very new to Python.
Thanks in advance.
You can get the number of rows and append information like this:
file = xlrd.open_workbook('accounts.xls', formatting_info=True)
row_number = file.sheet_by_index(0).nrows
sheet = wb.get_sheet(0)
sheet.write(row_number, 0, 'blabla')

Copy data from MS Access to MS Excel using Python

I've been spending the better part of the weekend trying to figure out the best way to transfer data from an MS Access table into an Excel sheet using Python. I've found a few modules that may help (execsql, python-excel), but with my limited knowledge and the modules I have to use to create certain data (I'm a GIS professional, so I'm creating spatial data using the ArcGIS arcpy module into an access table)
I'm not sure what the best approach should be. All I need to do is copy 4 columns of data from access to excel and then format the excel. I have the formatting part solved.
Should I:
Iterate through the rows using a cursor and somehow load the rows into excel?
Copy the columns from access to excel?
Export the whole access table into a sheet in excel?
Thanks for any suggestions.
I eventually found a way to do this. I thought I'd post my code for anyone who may run into the same situation. I use some GIS files, but if you don't, you can set a variable to a directory path instead of using env.workspace and use a cursor search instead of the arcpy.SearchCursor function, then this is doable.
import arcpy, xlwt
from arcpy import env
from xlwt import Workbook
# Set the workspace. Location of feature class or dbf file. I used a dbf file.
env.workspace = "C:\data"
# Use row object to get and set field values
cur = arcpy.SearchCursor("SMU_Areas.dbf")
# Set up workbook and sheet
book = Workbook()
sheet1 = book.add_sheet('Sheet 1')
book.add_sheet('Sheet 2')
# Set counter
rowx = 0
# Loop through rows in dbf file.
for row in cur:
rowx += 1
# Write each row to the sheet from the workbook. Set column index in sheet for each column in .dbf
sheet1.write(rowx,0,row.ID)
sheet1.write(rowx,1,row.SHAPE_Area/10000)
book.save('C:\data\MyExcel.xls')
del cur, row
I currently use the XLRD module to suck in data from an Excel spreadsheet and an insert cursor to create a feature class, which works very well.
You should be able to use a search cursor to iterate through the feature class records and then use the XLWT Python module (http://www.python-excel.org/) to write the records to Excel.
You can use ADO to read the data from Access(Here are the connection strings for Access 2007+(.accdb files) and Access 2003-(.mdb files)) and than use Excel's Range.CopyFromRecordset method(assuming you are using Excel via COM) to copy the entire recordset into Excel.
The best approach might be to not use Python for this task.
You could use the macro recorder in Excel to record the import of the External data into Excel.
After starting the macro recorder click Data -> Get External Data -> New Database Query and enter your criteria. Once the data import is complete you can look at the code that was generated and replace the hard coded search criteria with variables.
Another idea - how important is the formatting part? If you can ditch the formatting, you can output your data as CSV. Excel can open CSV files, and the CSV format is much simpler then the Excel format - it's so simple you can write it directly from Python like a text file, and that way you won't need to mess with Office COM objects.

Categories

Resources