I am trying to print Excel files to pdf with xlwings. I am using the excel api for this.
I have tried it in two ways:
1/ Using the PrintOut() call with PrintToFile argument:
wb.api.PrintOut(PrintToFile=True, PrToFileName="5.pdf", Preview=True)
The problem here is Excel just prints the file, ignoring my additional settings.
2/ Using ExportAsFixedFormat
wb.api.ExportAsFixedFormat(0, str(SwmId) + ".pdf")
Here Excel flashes a bit, but does not do anything in the end.
For the record: I can't use a macro and call it from Python because I have about a thousand of these Excel files. So, I can't put the macro in every single one of them. It would probably be a workaround to create a custom function in VBA and than call it every file. But, honestly, it would be easier if I could just do this directly from Python, in one line of code.
Below is a self-standing code example of what worked on my machine to print an excel workbook to pdf (using the ExportAsFixedFormat method):
# Environment
# -----------
# OS: Windows 10
# Excel: 2013
# python: 3.7.4
# xlwings: 0.15.8
import os
import xlwings as xw
# Initialize new excel workbook
book = xw.Book()
sheet = book.sheets[0]
sheet.range("A1").value = "dolphins"
# Construct path for pdf file
current_work_dir = os.getcwd()
pdf_path = os.path.join(current_work_dir, "workbook_printout.pdf")
# Save excel workbook to pdf file
print(f"Saving workbook as '{pdf_path}' ...")
book.api.ExportAsFixedFormat(0, pdf_path)
# Open the created pdf file
print(f"Opening pdf file with default application ...")
os.startfile(pdf_path)
xlwings documentation recommends using xw.App():
from pathlib import Path
import xlwings as xw
import os
with xw.App() as app:
# user will not even see the excel opening up
app.visible = False
book = app.books.open(path_to_excelfile)
sheet = book.sheets[0]
sheet.page_setup.print_area = '$A$1:$Q$66'
sheet.range("A1").value = "experimental"
# Construct path for pdf file
current_work_dir = os.getcwd()
pdf_file_name = "pdf_workbook_printout.pdf"
pdf_path = Path(current_work_dir, pdf_file_name)
# Save excel workbook as pdf and showing it
sheet.to_pdf(path=pdf_path, show=True)
Related
I'm currently trying to do the following:
Open up an .xml file that's already in spreadsheet format with Excel
Save the .xml file as .xlsx without corrupting the file
Other options that I can take via Python are:
Convert the .xml to .xlsx
Copy specific columns (A1:AC6000) to another Excel workbook
Import an XML file directly in an Excel workbook.
I failed at all of them and can't think of a different way so here I am asking for help. My latest code is here:
# importing openpyxl module
import openpyxl as xl;
# opening the source excel file
file = 'C:\\Users\\ddejean\\Desktop\\HESKlogin\\Downloads\\data.xlsx'
wb1 = xl.load_workbook(file)
ws1 = wb1['Sheet1']
# opening the destination excel file
filename1 = 'C:\\Users\\ddejean\\Desktop\\HESKlogin\\Downloads\\updated.xlsx'
wb2 = xl.load_workbook(filename1)
ws2 = wb2['Sheet1']
# calculate total number of rows and
# columns in source excel file
mr = ws1.max_row
mc = ws1.max_column
# copying the cell values from source
# excel file to destination excel file
for i in range (1, mr + 1):
for j in range (1, mc + 1):
# reading cell value from source excel file
c = ws1.cell(row = i, column = j)
# writing the read value to destination excel file
ws2.cell(row = i, column = j).value = c.value
# saving the destination excel file
wb2.save(filename1)
I also tried changing the format of the file which ultimately corrupted the file:
A = r"C:\\Users\\ddejean\\Desktop\\HESKlogin\\Downloads\\data.xml"
pre, ext = os.path.splitext(A)
B = os.rename(A, pre + ".xlsx")
I tried importing the file into Excel which was terrible since none of the data in xml have properly name attributes to differentiate the data. I also tried calling a macro, but I get an error with each macro on my network, so I disposed of that alternative.
Any assistance you can give would be much appreciated! I also think it's important to say that I'm a noob.
This works for me :)
import os
import win32com.client as win32
import requests as r
import pandas as pd
hesk = "C:\\Users\\ddejean\\Desktop\\TEST\\hesk.xml"
folder = "C:\\Users\\ddejean\\Desktop\\TEST"
output = "C:\\Users\\ddejean\\Desktop\\TEST\\output.csv"
cd = os.path.dirname(os.path.abspath(folder))
xmlfile = os.path.join(cd, hesk)
csvfile = os.path.join(cd, output)
# EXCEL COM TO SAVE EXCEL XML AS CSV
if os.path.exists(csvfile):
os.remove(csvfile)
try:
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.OpenXML(xmlfile)
wb.SaveAs(csvfile, 6)
wb.Close(True)
except Exception as e:
print(e)
finally:
# RELEASES RESOURCES
wb = None
excel = None
I used xlwings to open excel workbook. It worked fine up to last month. But today, when I run the same code, it opened my worksheet but convert my worksheet name into lowercase.
Anybody know why is that? And how can I keep my original captalization?
I am using windows 10.
Example, when I run below code, the ABC.xlsx automatically converted abc.xlsx by xlwings.
import xlwings as xw
fullPath = ''\\\\xxx\\xxx\\ABC.xlsx'
psw = '123'
wb = xw.Book(fullPath, password = psw)
I had the same issue and I am not sure why it does that (I think it only happens to protected workbooks). An easy fix is renaming the file again as follows:
import os
old_file_name = os.path.split(fullPath)[0] +'\\' + os.path.split(fullPath)[1].lower()
new_file_name = fullPath
os.rename(old_file_name, new_file_name)
This code assumes that your path and file are saved under fullPath.
Open excel,then click file->New->Blank workbook, we can get a blank workbook. We can input some information.
I want to use Python to save the created Excel to the path we set.
import win32com.client
import os
excel = win32com.client.Dispatch("Excel.Application")
xlsx_fullname = os.path.abspath("Book1")
workBook = excel.Workbooks.Open(xlsx_fullname)
excel.ExecuteExcel4Macro("FDSFORCERECALC(False)")
workBook.Save()
workBook.Close(True)
excel.Application.Quit()
I used this code, but I can't use python to select this excel file. It's not working
Change
xlsx_fullname = os.path.abspath("Book1")
workBook = excel.Workbooks.Open(xlsx_fullname)
...
workBook.Save()
to
workBook = excel.ActiveWorkbook
...
workBook.SaveAs(Filename="c:/path/to/your desired filename.xlsx")
I am trying to convert an Excel file to an HTML file while keeping the format of the workbook.
Using Excel, I am able to switch from xlsx to htm: File -> Save as -> Web page (*.html, *.htm)
Using Python, I am always getting something gibberish like the below image as workbook.htm or workbook.html.
import xlwings as xw
file_path = "*.xlsx"
excel_app = xw.App(visible=False)
wb = excel_app.books.open(file_path)
wb.save("*.html")
wb.save("*.htm")
from xlsx2html import xlsx2html
xlsx2html('*xlsx', '*.htm')
xlsx2html('*xlsx', '*.html')
I have used dummy files, I am just trying to go from the xlsx file to the htm/hmtl file using Python and keeping the format, e.g. background colors, borders, etc.
I used to have such problem. I also used xlwings library, customized it and success. You find and edit in the file xlwings/_xlwindows.py as follows:
def save(self, path=None):
saved_path = self.xl.Path
source_ext = os.path.splitext(self.name)[1] if saved_path else None
target_ext = os.path.splitext(path)[1] if path else '.xlsx'
if saved_path and source_ext == target_ext:
file_format = self.xl.FileFormat
else:
ext_to_file_format = {'.xlsx': FileFormat.xlOpenXMLWorkbook,
'.xlsm': FileFormat.xlOpenXMLWorkbookMacroEnabled,
'.xlsb': FileFormat.xlExcel12,
'.xltm': FileFormat.xlOpenXMLTemplateMacroEnabled,
'.xltx': FileFormat.xlOpenXMLTemplateMacroEnabled,
'.xlam': FileFormat.xlOpenXMLAddIn,
'.xls': FileFormat.xlWorkbookNormal,
'.xlt': FileFormat.xlTemplate,
'.xla': FileFormat.xlAddIn,
'.html': FileFormat.xlHtml # ---> add new
}
I am trying to run a VBA Macro in an xlsm workbook using python 3.7 in Spyder. This workbook has two worksheets.
The code that I have currently runs and saves the new file with no problems, however it is not triggering the VBA like it should.
I know this macro works because if I manually click the button in Excel, it works just fine.
Could someone assist with this? I checked the Macro Settings under the Trust Center and all macros are enabled so I do not think it is a permissions issue, however I am not an admin on this pc.
The code is below:
import os
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
wb = xl.Workbooks.Open("Z:\FolderName\FolderName2\FileName.xlsm")
xl.Application.Run("MacroName")
wb.SaveAs("Z:\FolderName\FolderName2\FileName1.xlsm")
wb.Close()
xl.Quit()
This can be done easily through xlwings. Once I switched to that library then I was able to quickly get this script working.
First make sure you have your All.xlsm file in your current working or in your User/Documents(Sometimes it working from yourDocuments directory and sometimes not, so better to have in both)
pass your macro name along with the file name that contains the macro you can make change to Parameters like ReadOnly or Savechanges according to your requirement
And be make sure to deleta xl object after each run
import win32com.client
xl =win32com.client.dynamic.Dispatch('Excel.Application')
xl.Workbooks.Open(Filename = XYZ.xls, ReadOnly= 1)
xl.Application.Run('All.xlsm!yourmacroname')
xl.Workbooks(1).Close(SaveChanges=1)
xl.Application.Quit()
del xl
Running Excel Macro from Python
To Run a Excel Marcro from python, You don't need almost nothing. Below a script that does the job. The advantage of Updating data from a macro inside Excel is that you immediatly see the result. You don't have to save or close the workbook first. I use this methode to update real-time stock quotes. It is fast and stable.
This is just an example, but you can do anything with macros inside Excel.
from os import system, path
import win32com.client as win32
from time import sleep
def isWorkbookOpen(xlPath, xlFileName):
SeachXl = xlPath + "~$" + xlFileName
if path.exists(SeachXl):
return True
else:
return False
def xlRunMacro(macroLink):
PathFile = macroLink[0]
xlMacro = macroLink[1]
isLinkReady = False
# Create the link with the open existing workbook
win32.pythoncom.CoInitialize()
xl = win32.Dispatch("Excel.Application")
try:
wb = win32.GetObject(PathFile)
isLinkReady = True
except:
NoteToAdd = 'Can not create the link with ' + PathFile
print(NoteToAdd)
if isLinkReady:
# If the link with the workbook exist, then run the Excel macro
try:
xl.Application.Run(xlMacro)
except:
NoteToAdd = 'Running Excel Macro ' + xlMacro + ' failed !!!'
print(NoteToAdd)
del xl
def mainProgam(macroSettings):
FullMacroLink = []
PathFile = macroSettings[0] + macroSettings[1]
FullMacroLink.append(PathFile)
FullModuleSubrout = macroSettings[1] + '!' + macroSettings[2] + '.' + macroSettings[3]
FullMacroLink.append(FullModuleSubrout)
if isWorkbookOpen(macroSettings[0], macroSettings[1]) == False:
# If the workbook is not open, Open workbook first.
system(f'start excel.exe "{PathFile}"')
# Give some time to start up Excel
sleep(2)
xlRunMacro(FullMacroLink)
def main():
macroSettings = []
# The settings below will execute the macro example
xlPath = r'C:\test\\' # Change add your needs
macroSettings.append(xlPath)
workbookName = 'Example.xlsm' # Change add your needs
macroSettings.append(workbookName)
xlModule = "Updates" # Change add your needs
macroSettings.append(xlModule)
xlSubroutine = "UpdateCurrentTime" # Change add your needs
macroSettings.append(xlSubroutine)
mainProgam(macroSettings)
if __name__ == "__main__":
main()
exit()
VBA Excel Macro
Option Explicit
Sub UpdateCurrentTime()
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("Current-Time")
With sht
sht.Cells(2, 1).Value = Format(Now(), "hh:mm:ss")
End With
End Sub
You can use it also as a dynamic module too. Save the module above as RunExcelMacro.py in Your python project. After just use the following lines:
from RunExcelMacro import mainProgam
mainProgram(macroSettings)
It will do the job, succes ...
You need to reference the module name as well
Example here my vba code under Module1
Option Explicit
Public Sub Example()
MsgBox "Hello 0m3r"
End Sub
and here is my python
from win32com.client import Dispatch
def run_excel_macro():
try:
excel = Dispatch("Excel.Application")
excel.Visible = True
workbook = excel.Workbooks.Open(
r"D:\Documents\Book1.xlsm")
workbook.Application.Run("Module1.Example")
workbook.SaveAs(r"D:\Documents\Book5.xlsm")
excel.Quit()
except IOError:
print("Error")
if __name__ == "__main__":
run_excel_macro()