I am trying to convert an excel file to PDF. Using Print chosen worksheets in excel files to pdf in python and Python - Converting XLSX to PDF, I wrote the code below.
This converts the excel to PDF without a problem but it opens the excel file. I thought the point of the .Visible = False was to prevent this? I would like the excel object to stay hidden because I am doing this to over 100 files and I do not want excel opening up 100 times.
import win32com.client
import os
import re
nm = 'Sample.xlsx'
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = False
wb = excel.Workbooks.Open('{0}\\{1}'.format(os.getcwd(), nm))
wb.WorkSheets('Report').Select()
nm_pdf = re.sub('.xlsx', '.pdf', nm, count = 1)
wb.ActiveSheet.ExportAsFixedFormat(0, '{0}\\{1}'.format(os.getcwd(), nm_pdf))
#excel.Quit()
Neither of the methods above worked for me but finally this did the job, maybe it's gonna be of some use for someone:
excel.ScreenUpdating = False
excel.DisplayAlerts = False
excel.EnableEvents = False
*set it all back to True after you finish processing the file.
to anyone who has this problem, this is what helped me:
excel = client.Dispatch("Excel.Application")
excel.Interactive = False
excel.Visible = False
The "Interactive = False" part is what i was missing. Visible set to False by itself didn't do the trick. Also don't forge to close the workbook.
Related
I'm trying to create a Python script (I'm using Python 3.7.3 with UTF-8 encoding on Windows 10 64-bit with Microsoft Office 365) that exports user selected worksheets to PDF, after the user has selected the Excel-files.
The Excel-files contain a lot of different settings for page setup and each worksheet in each Excel-file has a different page setup.
The task is therefore that I need to read all current variables regarding page setup to be able to assign them to the related variables for export.
The problem is when I'm trying to get Excel to return the current print area of the worksheet, which I can't figure out.
As far as I understand I need to be able to read the current print area, to be able to set it for the export.
The Excel-files are a mixture of ".xlxs" and ".xlsm".
I've tried using all kind of different methods from the Excel VBA documentation, but nothing has worked so far e.g. by adding ".Range" and ".Address" etc.
I've also tried the ".UsedRange", but there is no significant difference in the cells that I can search for and I can't format them in a specific way so I can't use this.
I've also tried using the "IgnorePrintAreas = False" variable in the "ExportAsFixedFormat"-function, but that didn't work either.
#This is some of the script.
#I've left out irrelevant parts (dialogboxes etc.) just to make it shorter
#Import pywin32 and open Excel and selected workbook.
import win32com.client as win32
excel = win32.gencache.EnsureDispatch("Excel.Application")
excel.Visible = False
wb = excel.Workbooks.Open(wb_path)
#Select the 1st worksheet in the workbook
#This is just used for testing
wb.Sheets([1]).Select()
#This is the line I can't get to work
ps_prar = wb.ActiveSheet.PageSetup.PrintArea
#This is just used to test if I get the print area
print(ps_prar)
#This is exporting the selected worksheet to PDF
wb.Sheets([1]).Select()
wb.ActiveSheet.ExportAsFixedFormat(0, pdf_path, Quality = 0, IncludeDocProperties = True, IgnorePrintAreas = False, OpenAfterPublish = True)
#This closes the workbook and the Excel-file (although Excel sometimes still exists in Task Manager
wb.Close()
wb = None
excel.Quit()
excel = None
If I leave the code as above and try and open a test Excel-file (.xlxs) with a small PrintArea (A1:H8) the print function just gives me a blank line.
If I add something to .PrintArea (as mentioned above) I get 1 of 2 errors:
"TypeError: 'str' object is not callable".
or
"ps_prar = wb.ActiveSheet.PageSetup.PrintArea.Range
AttributeError: 'str' object has no attribute 'Range'"
I'm hoping someone can help me in this matter - thanks, in advance.
try
wb = excel.Workbooks.OpenXML(wb_path)
insead of
wb = excel.Workbooks.Open(wb_path)
My problem was with a german version of ms-office. It works now. Check here https://social.msdn.microsoft.com/Forums/de-DE/3dce9f06-2262-4e22-a8ff-5c0d83166e73/excel-api-interne-namen?forum=officede
i need to print an excel sheet and need to do it using some kind of python script. So far i have used win32com in my script and i also got it done to get a printout using the following code:
import win32com.client
o = win32com.client.Dispatch("Excel.Application")
o.Visible = 1
wb = o.Workbooks.Open(r'C:\test.xlsx')
ws = wb.Worksheets[1]
ws.PrintOut()
Unfortunately before i actually print the excel-sheet i need to adjust the print settings of this sheet/file: change format to landscape and change to small/narrow margin.
I have found this site that might contain just what i need:
https://msdn.microsoft.com/en-us/library/aa220363(v=office.11).aspx
Unfortunately so far i have not been able to change the desired print properties. I hope someone can help me with this or at least get me headed into the right direction.
You can edit the print settings using the PageSetup Method (https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2003/aa173425%28v%3doffice.11%29). Does not seem to have a narrow/wide/normal margin setting as you normally see in the excel application, but you can specify the margins yourself.
ws.PageSetup.Zoom = False
ws.PageSetup.FitToPagesTall = 1
ws.PageSetup.FitToPagesWide = 1
ws.PageSetup.PrintArea = print_area
ws.PageSetup.LeftMargin = 25
ws.PageSetup.RightMargin = 25
ws.PageSetup.TopMargin = 50
ws.PageSetup.BottomMargin = 50
wb.ExportAsFixedFormat(0, path_to_pdf)
I am using ExportAsFixedFormat, but I guess this should work for PrintOut() too.
Reference: Print chosen worksheets in excel files to pdf in python
EDIT:
The FitToPagesTall (fits all rows on one page) and FitToPagesWide (fits all columns on one page) settings will mess up your eventual print area if you have them both set to True. You will need to specify at least one of them as False to see your margin settings take effect.
ws.PageSetup.FitToPagesTall = False
ws.PageSetup.FitToPagesWide = 1
I'm trying to do some work on a complex Excel Workbook which has a large number of variables which have been created and used using the Name Box feature. See picture attached for example/detail.
I'd like to store or change DeathRate or maybe read all the Name Boxes and create a dictionary between names and locations of the cell from outside Excel.
I'm using the win32com library in Python but I guess I could switch to another Excel reader as long as it copes with XLSX files.
Has someone come across this before?
Found the solution, see code below:
import os
from win32com.client import Dispatch #win32com is based around cells beginning at one.
app_xl = Dispatch("Excel.Application")
WORKING_DIR = os.getcwd()
excelPath = WORKING_DIR + "\SampleModel.xls"
wb = app_xl.Workbooks.Open(excelPath)
# Get Named Boxes
name_box_list = [x for x in app_xl.ActiveWorkbook.Names]
name_box_map = {x.Name:x.Value for x in name_box_list}
print name_box_list
print name_box_map
# Change Named Boxes
name_box_list[0].Name = u'NewName'
name_box_list[0].Value = u'=model!$B$5'
name_box_map = {x.Name:x.Value for x in name_box_list}
I have an MS Excel Workbook that I would like to open and then loop through the tabs and create and save a workbook for each tab in the original workbook. So I open file A and there are tabs 1, 2, 3 and create and save a file B, C, D each with one a unique tab in it. I have the code for the VBA which creates a single copy of a worksheet but when I attempt to do this in Python I end up with all the tabs in each workbook. The following is the VBA that works:
Sub ConvertTabsToFiles()
Dim currPath As String
currPath = Application.ActiveWorkbook.Path
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each xWs In ThisWorkbook.Sheets
xWs.Copy
Application.ActiveWorkbook.SaveAs Filename:=currPath & "\" & xWs.Name & ".xlsx"
Application.ActiveWorkbook.Close False
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
The following is the Python Code that does not work:
xlApp = win32.com.client.Dispatch("Excel.Application")
xlwb = xlApp.Workbooks.Open("C:\Inputfile.xlsx")
for sheet in xlwb.Worksheets:
sheet.Copy
xlApp.ActiveWorkbook.SaveAs("C:\Users\user\AppData\Local\Temp\\"+ sheet.Name+".xlsx")
Your help is really appreciated, I am stumped. Thanks ahead of time.
Thanks for Schollii, I was able to get on the right track. The following is what worked for me, I hope it helps you:
for sheet in xlwb.Worksheets:
xlApp = win32com.client.Dispatch("Excel.Application")
nwb = xlApp.WorkbookAdd()
sheet.Copy(Before=nwb.Sheet(1))
nwb.SaveAs("C:\Users\user\AppData\Local\Temp\\" +sheet.Name+ ".xlsx")
nwb.Close(True)
Thank you everyone. Especially Schollii for getting me on the right track. Also Thanks TankorSmash for the answer, too.
You can save individual sheets via the SaveAs method:
for sheet in xlwb.Worksheets:
filename = r"C:\Users\user\AppData\Local\Temp\" + sheet.Name + ".xlsx"
sheet.SaveAs(filename)
print('Saved sheet to', filename)
Note I put the 'r' prefix to the string otherwise the backslashes get interpreted by Python as special characters unless doubled which obfuscates the string.
for newer version of excel the codes changes from
xlApp.WorkbookAdd()
to
xlApp.Workbooks.Add()
I've seen from various questions on here that if an instance of Excel is opened from Python using:
xl = win32com.client.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
wb = xl.Workbooks.Open('Test.xlsx')
Then it does not load the default add-ins. I've tried forcing my add-in to load by instead running:
xl = win32com.client.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
addin = xl.Workbooks.Open('C:/path/addIn.xll')
wb = xl.Workbooks.Open('Test.xlsx')
However, when I do this an instance of Excel opens and I get a security message asking me to verify I want to open this add-in. If I click "Enable this add-in for this session only" Excel immediately closes and does not open my desired xlsx file.
Does anyone have any ideas how to force the add-in to load and then to allow me to open my file?
Thanks very much for your help!
I have actually managed to resolve this by borrowing something from this MSDN article relating to doing the same thing with VBA:
http://support.microsoft.com/default.aspx?scid=KB;en-us;q213489
The following now works perfectly:
xl = win32com.client.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
xl.RegisterXLL('C:/path/addin.xll')
wb = xl.Workbooks.Open('Test.xlsx')
I had the same problem, but couldn't use xl.RegisterXLL('C:/path/addin.xla') from the accepted answer, because it only works with .XLL files, and I had a .XLA file.
Instead, I found that this worked:
xl = win32com.client.gencache.EnsureDispatch('Excel.Application')
# Need to load the addins before opening the workbook
addin_path = r'C:\path\addin.xla'
xl.Workbooks.Open(addin_path)
xl.AddIns.Add(addin_path).Installed = True
wb = xl.Workbooks.Open(r"C:\my_workbook.xlsm")
I have had much better success using Excel via win32com than any of the other methods, but you might want to look at pyxll (https://www.pyxll.com/introduction.html). Here are a few other things:
Have you checked that addin.Installed == True?
Have you tried AddIns.Add("c:\windows\addins\TSXL\TSXL.xll").Installed = True?
Try xl.DisplayAlerts=False before opening the workbooks
Have you tried the four steps in last answer of Automating Excel via COM/Python - standard addins won't load at startup, I copy them here:
Open the XLA / XLL file representing the addin in question
Set addins(addin_name).Installed = False
Addins(addin_name).Add(addin_file_path)
Set addins(addin_name).Installed = True