Package: safexl
safexl - The Safe Way to ExcelA wrapper around the pywin32 module for easier use and automated cleanup of Excel Application COM objectsThe pywin32 library grants extraordinary capabilities to interact with Windows applications,
but includes many oddities usually learned through trial and error, as seen in Stack Overflow posts such as these:COM: excelApplication.Application.Quit() preserves the processCan't close Excel completely using win32com on PythonLoading addins when Excel is instantiated programmaticallyAutoFilter method of Range class failed (Dispatch vs EnsureDispatch)My experience with automating Excel using pywin32 lead me to createsafexl, a pywin32 wrapper centered around easier use and
automated cleanup of Excel Application COM objects in Python. The main functionality of this package is a context-managedapplicationgenerator that you can use inside awithblock, built with some pywin32 best practices in place and a few psutil
tools focused on working with Excel.InstallYou can import the library with pip:pip install safexlOr you can download ithereat GitHub.This module requires:pywin32psutilUsageThis package makes writing pywin32 code in Python as simple as:importsafexlwithsafexl.application(kill_after=False,maximize=True,include_addins=True)asapp:wb=app.Workbooks.Add()ws=wb.ActiveSheetrng=ws.Range("B1")rng.Value="Hello, World!"rng.Interior.Color=safexl.colors.rgbRed# colors are includedrng.EntireColumn.AutoFit()ws.Columns("A").Delete(Shift=safexl.xl_constants.xlToLeft)# constants are included# This results in Excel being opened to a Sheet where cell "A1" has 'Hello, World!' in it with a red backgroundIf you've programmatically worked with Excel in a Win32 environment before, this code should look very familiar,
as I am not altering the COM object itself before yielding it to you inside awithblock; I am instead providing
a means to create and delete it more easily.If you would like to alter the COM object (for things like turning off ScreenUpdating
while your code runs), then please see thePerformancesection near the bottom.In this way, the following two code snippets will have the same effect:1.) without safexlimportpythoncomimportwin32com.clientpythoncom.CoInitialize()app=win32com.client.Dispatch("Excel.Application")try:######################## Your code goes here ########################finally:app.Quit()delapppythoncom.CoUninitialize()2.) with safexlimportsafexlwithsafexl.application(kill_after=True)asapp:######################## Your code goes here ########################As you can see, using safexl results in a lot less boilerplate code, from 9 lines to 2.Theapplicationwrapper comes with 3 boolean parameters to indicate what you would like to do with the application once yourwithblock is complete:kill_after- kill the Excel process upon leaving thewithblockmaximize- Optional / Defaults toTrue- Will not be used if you setkill_after=True. Maximizes each Excel Window for
each Workbook added during thewithblock.include_addins- Optional / Defaults toFalse- Will not be used if you setkill_after=True. Loads your installed Excel
Add-ins to the newly created instance (with a performance hit to do so).In the event of an error occuring inside yourwithblock, thesafexl.applicationcleanup process will carefully remove any new
workbooks you've opened in Excel, leaving any workbooks you already had open prior to thewithblock untouched. The same goes
for if you chose to setkill_after=True; only the Workbooks you create inside thewithblock will be closed.
In addition to theapplicationwrapper, I have included an handful of other tools to make working with Excel even easier, including:is_excel_open()kill_all_instances_of_excel()close_workbooks(app, workbooks)see_excel(app, window_state)workbooks_currently_open(app)last_row(worksheet)last_column(worksheet)worksheet_name_sanitization(worksheet_name)PerformanceA number of performance enhancing options can be set on Excel Application objects, and will come in handy most whenever you are
working with large workbooks and amounts of data. In my balance between allowing you the most freedom to do what you wish with the
application object and wrapping your object for safer error handling, I am yielding a bare pywin32 application object to you
inside thewithblock. If you wish to take advantage of the various performance enhancing settings available natively in the
Excel Application, I suggest using your own error handling inside thewithblock, to verify that the settings get switched back
to normal when you're finished, even if you encounter an error during your work. Using safexl in this way would look something
like this:importsafexlwithsafexl.application(kill_after=False)asapp:try:app.ScreenUpdating=Falseapp.DisplayStatusBar=Falseapp.EnableEvents=Falsewb=app.Workbooks.Add()# can only set calculation once at least 1 workbook is openapp.Calculation=safexl.xl_constants.xlCalculationManual######################## Your code goes here ########################exceptExceptionase:# if you don't re-raise the error here, you will not be warned that an error occured# or get the benefit of reading the error messageraiseeelse:passfinally:app.ScreenUpdating=Trueapp.DisplayStatusBar=Trueapp.EnableEvents=Trueapp.Calculation=safexl.xl_constants.xlCalculationAutomaticA note on setting the CalculationUnfortunately, due to an oddity in the Excel Application OOP design, even though the Calculation mode is set on the Application object
(instead of the Workbook object) if no workbooks are open or visible in your instance of the Application, then the constant for
an "#N/A" error is returned, as seen by code like this:>>> import win32com.client
>>> import pythoncom
>>> pythoncom.CoInitialize()
>>> app = win32com.client.Dispatch("Excel.Application")
>>> app.Calculation  # expect constant for #N/A
-2146826246
>>> wb = app.Workbooks.Add()
>>> app.Calculation  # expect XlCalculation constant
-4105
>>> wb.Close()
>>> app.Calculation  # expect constant for #N/A
-2146826246More can be read about how Excel handles Calculation modes at these links:How Excel determines the current mode of calculationExcel: 'Unable to set the Calculation property of the Application class'Suffice it to say, even though we think about the calculation mode being an attribute of each individual workbook, it is actuallysetat the application level. I'm assuming this was for performance and/or sanity reasons, but the end result is that you are unable to
get or set a proper Calculation mode for the application until you open a workbook first.CookbookCreate & Save Workbook without viewing Applicationimportsafexlwithsafexl.application(kill_after=True)asapp:wb=app.Workbooks.Add()######################## Your code goes here ########################wb.SaveAs("Cookbook.xlsx")wb.Close()Create a Workbook & View it Without Savingimportsafexlwithsafexl.application(kill_after=False,maximize=True,include_addins=True)asapp:wb=app.Workbooks.Add()######################## Your code goes here ########################Minimize All Excel Windows that are Currently Openimportsafexlwithsafexl.application(kill_after=True)asapp:safexl.see_excel(app.Workbooks,safexl.xl_constants.xlMinimized)Send Pandas Dataframe to Excel Worksheetimportsafexlimportpandasaspddata={'A':[1,2,3],'B':[4,5,6],'C':[7,8,9]}df=pd.DataFrame(data)withsafexl.application(kill_after=False)asapp:wb=app.Workbooks.Add()ws=wb.ActiveSheetdf.to_clipboard(excel=True)ws.Paste()ws.Range("A1").Select()# Otherwise entire dataframe range will be selected upon viewingSimilar Packages to ConsiderxlwingsOpenPyXLXlsxWriterContact MeThePoetCoder at gmail.com