Create a Drop down list using XLWings in Python - python

I have tried this code, but this is for validation. I want a code to create a new drop down menu.
app = xw.App(visible=True)
wb = app.books.open('Test.xlsx')
sht = wb.sheets['Sheet1']
Formula1='"Dog,Cat,Bat"'
dv = sht.range('A1').api.Validation.Formula1
I have tried using openpyxl it is working but it doesn't save a file when the file is open.

xlwings is a wrapper of win32com, which is similar to VBA. With recording VBA macro for reference, the following code should work.
import xlwings as xw
app = xw.App(visible=True)
wb = app.books.open('Test.xlsx')
sht = wb.sheets['Sheet1']
Formula1='Dog,Cat,Bat' # remove the redundant "
# set up validation
sht.range('A1').api.Validation.Add(Type=3, Formula1=Formula1)
The exploring steps:
Record a macro for the default steps to create a list type data validation:
Sub Macro1()
'
' Macro1 Macro
'
'
Range("A1").Select
Application.WindowState = xlMaximized
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="Dog,Cat,Bat"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub
Indeed, we did only two key steps and kept the rest default:
select List from validation criteria dropdown list
type the source for list
So, the above code should be simplified as
' VBA
Range("A1").Validation.Add Type:=xlValidateList, Formula1:="Dog,Cat,Bat"

Related

How to add a macro to an Excel document?

I recently began working with macros and VBA for work however my knowledge is currently very limited so please bear with me. I recently wrote a macro to apply a simple standardized format to all excel documents I send out to others. The macro has been working when I apply the macro from inside of excel, however I also have some automated reports I send out using python and I would like to use this macro on these reports as well to format them prior to sending.
My question is essentially, how do I add a macro to an existing excel document, how do I then execute that macro from python, and then save the resulting excel document?
I do not have much experience in using VBA code or interacting with this using python so I am not too sure where to start so any guidance would be much appreciated.
Below is the Macro I am looking to use
Sub Delphi_macro()
Columns("A:A").Select
Selection.Delete Shift:=xlToLeft
Cells.Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
ActiveSheet.ListObjects.Add(xlSrcRange, Range("a1").CurrentRegion, , xlYes).Name = _
"Table1"
Range("Table1[#All]").Select
ActiveSheet.ListObjects("Table1").TableStyle = "TableStyleLight9"
ActiveWindow.DisplayGridlines = False
With ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
ActiveWindow.FreezePanes = True
ActiveWindow.SmallScroll Down:=0
Cells.Select
Cells.EntireColumn.AutoFit
End Sub
Add your Macro to a Module, and then Export the Module. After exporting the module you can use this python code to add it/import it and run it.
xl = win32com.client.Dispatch("Excel.Application")
xl.Workbooks.Add
wb = xl.ActiveWorkbook
wb.VBProject.VBComponents.Import "Full Path\VBA_Exported_Macro.bin"
xl.Application.Run("Module1.Delphi_macro")
xl.DisplayAlerts = False
wb.DoNotPromptForConvert = True
wb.CheckCompatibility = False
wb.SaveAs('final_outfile.xlsx', FileFormat=51, ConflictResolution=2) # Macro disapears here
xl.Application.Quit()
del xl
xl = None
In the code above this is creating a fresh Excel Workbook, adding the macro, running it and then Saves the file WITHOUT the macro. You can change that and instead open an existing workbook and save as Macro enabled excel to retain the macro.

How to set Excel PageBreak with xlwings in python?

Need help with setting PageBreak excel file with xlwings package in python.
According to Microsoft website: https://learn.microsoft.com/zh-tw/office/vba/api/excel.range.pagebreak
I've tried
app = xw.App(visible=True, add_book=False)
wb = app.books.open("raw_data/" + raw_file_name, update_links=False)
sht = wb.sheets['sheet1']
sht.api.Rows(24).PageBreak = 'xlPageBreakManual' # I would like to set on row 24
and the program stuck forever. Does anyone know how to solve the problem?
Thanks
xlwings does not know what xlPageBreakManual is unless its referenced. Nevertheless in this case it's not necessary. The default is to add a manual Page Break therefore syntax is only; sht.api.Rows(24).PageBreak = True. If you then check the PageBreak status on row 24; print(sht.api.Rows(24).PageBreak) it should return -4135 which is the excel constant for xlPageBreakManual.
You can use the constants to set the type of PageBreak, e.g. the line sht.api.Rows(24).PageBreak = True could also be written as sht.api.Rows(24).PageBreak = -4135 or sht.api.Rows(24).PageBreak = PageBreak.xlPageBreakManual
The page break values can be referenced from the xlwings constants using the syntax from xlwings.constants import PageBreak. My example shown below sets the page break at row 24 then shows the status of the previous, actual and ensuing rows. The previous and ensuing rows have a status of -4142 i.e. no page break while row 24 is -4135.
The code then removes the page break using xlPageBreakNone and the three rows 23-25 are all -4142 again.
For this test I used xlwings v0.26.1
import xlwings as xw
from xlwings.constants import PageBreak
### Constant values for reference
# xlPageBreakAutomatic = -4105
# xlPageBreakManual = -4135
# xlPageBreakNone = -4142
app = xw.App(visible=True, add_book=False)
sht = xw.Book("book.xlsx").sheets['Sheet1']
print("Add Page break at row 24")
sht.api.Rows(24).PageBreak = True
# sht.api.Rows(24).PageBreak = -4135 # This does the same as the line above
# sht.api.Rows(24).PageBreak = PageBreak.xlPageBreakManual # As does this line
print('Row23: ' + str(sht.api.Rows(23).PageBreak))
print('Row24: ' + str(sht.api.Rows(24).PageBreak))
print('Row25: ' + str(sht.api.Rows(25).PageBreak))
print("\nDelete Page break at row 24")
sht.api.Rows(24).PageBreak = PageBreak.xlPageBreakNone
print('Row23: ' + str(sht.api.Rows(23).PageBreak))
print('Row24: ' + str(sht.api.Rows(24).PageBreak))
print('Row25: ' + str(sht.api.Rows(25).PageBreak))
Note attempting to manually set a page break to -4105 (xlPageBreakAutomatic) fails which I would expect.

python Copy excel file Char into word file failure.(Use Clipboard) (Word.Application)

I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this
python code Exec failure: process[word.Selection.Paste] is Invalid.
from win32com import client
excel = client.Dispatch("Excel.Application")
word = client.Dispatch("Word.Application")
doc = word.Documents.Open("D:/python/My_Work/exe/word-opt/word_file.docx")
book = excel.Workbooks.Open("D:/python/My_Work/exe/word-opt/excel_file.xlsx")
char1=sheet.ChartObjects(1).Copy
doc.Bookmarks("BookMark2").Range.Select
word.Selection.Paste
doc.Save()
doc.Close()
the Same VBA code Exec OK:
Sub test()
Set dataExcel = CreateObject("Excel.Application")
Set Workbook = dataExcel.Workbooks.Open(ThisWorkbook.Path & "\excel_file.xlsx")
Set Sheet = Workbook.Worksheets(1)
Dim WordApp As Word.Application
Dim WordDoc As Word.Document
Set WordApp = New Word.Application
WordApp.Visible = True
Set WordDoc = WordApp.Documents.Open(ThisWorkbook.Path & "\word_file.docx")
Sheet.ChartObjects(1).Copy
WordDoc.Bookmarks("BookMark2").Range.Select
WordApp.Selection.Paste
WordDoc.Save
WordDoc.Close
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub
ex: File [excel_file.xlsx] in Only a chart.

Python + Win32: Paste header from one Excel workbook to the top of another

I want to format an Excel report automatically. I generate the raw data using Python for reports, but they need pretty formatting (colors, bold font, borders) on them before they go to a Project Manager.
My current approach is using the pywin32 package, copying the header from a Template file, and pasting it into my Output report.
I am having trouble with the .Paste() methods, for instance, if I try to specify the destination with .Paste(Destination=Range('A1:A100') it will throw an error. If I attempt output_worksheet.used_range.Paste() it will not recognize used_range as valid either.
Additionally my current code doesn't exit out of Excel.
Finally my code pastes the header into row 16 instead of starting from the top:
template_path = tests.path + r"\Box Tracking Report Regents Template.xlsx"
timestamp = datetime.datetime.now().strftime("%m-%d-%Y %I%M%p")
output_path = tests.path + r"\Box Tracking Report " + timestamp + ".xlsx"
# (... write my pandas dataframe in ...)
def paste_formatting(tab_name):
excel_instance = win32com.client.gencache.EnsureDispatch("Excel.Application")
template = excel_instance.Workbooks.Open(template_path)
template_workbook = excel_instance.Workbooks.Item(1)
template_worksheet = template_workbook.Worksheets(tab_name)
used_range = template_worksheet.UsedRange
used_range.Copy()
output_excel = excel_instance.Workbooks.Open(output_path)
output_workbook = excel_instance.Workbooks.Item(2)
output_worksheet=output_workbook.Worksheets(tab_name)
output_worksheet.Paste()
output_workbook.Close()
template_workbook.Close()
paste_formatting('Regents Box Tracking Report')
This is what I get:
With #chucklukowski's comment:
def paste_formatting(tab_name):
excel_instance = win32com.client.gencache.EnsureDispatch("Excel.Application")
template = excel_instance.Workbooks.Open(template_path)
template_workbook = excel_instance.Workbooks.Item(1)
template_worksheet = template_workbook.Worksheets(tab_name)
used_range = template_worksheet.UsedRange
used_range.Copy()
output_excel = excel_instance.Workbooks.Open(output_path)
output_workbook = excel_instance.Workbooks.Item(2)
output_worksheet=output_workbook.Worksheets(tab_name)
output_worksheet.Paste(output_worksheet.Range('A1'))
output_workbook.Save()
output_workbook.Close()
template_workbook.Close()
excel_instance.Quit()
del excel_instance
paste_formatting('Regents Box Tracking Report')
Still messy, but probably better than calling an Excel VBA macro from the template itself (which was going to be my last ditch approach).

Libre office uno api save as xls

As far i have following code to force an ods to recalc all values in spred sheet and save it that into several formats.
But i can not find the filter for XLS.
Has anyone an idea how to find it out?
import uno
from com.sun.star.beans import PropertyValue
def _toProperties(**args):
props = []
for key in args:
prop = PropertyValue()
prop.Name = key
prop.Value = args[key]
props.append(prop)
return tuple(props)
# start first
# libreoffice --headless --accept="socket,host=0,port=8001,tcpNoDelay=1;urp"
inputFile = 'file:///home/user/Downloads/in.ods'
outputFile = 'file:///home/user/Downloads/out.xls'
# import the OpenOffice component context
local = uno.getComponentContext()
# access the UnoUrlResolver service - this will allow to connect to OpenOffice.org program
resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
# load the context and you are now connected - you can access OpenOffice via its API mechanism
context = resolver.resolve("uno:socket,host=localhost,port=8001;urp;StarOffice.ServiceManager")
remoteContext = context.getPropertyValue("DefaultContext")
# service responsible for the current document called desktop
desktop = context.createInstanceWithContext("com.sun.star.frame.Desktop", remoteContext)
document = desktop.getCurrentComponent()
# load, calculateAll(), save
document = desktop.loadComponentFromURL(inputFile, "_blank", 0, ())
document.calculateAll()
# ods
# document.storeAsURL(outputFile, ())
# pds
#document.storeToURL(outputFile, _toProperties(FilterName="calc_pdf_Export"))
# csv
#document.storeToURL(outputFile, _toProperties(FilterName="Text - txt - csv (StarCalc)"))
# xls
document.storeToURL(outputFile, _toProperties(FilterName="calc_MS_Excel_40"))
# xlsx
#document.storeToURL(outputFile, _toProperties(FilterName="Calc Office Open XML"))
document.dispose()
Use the following basic macro to get a list of all available filter names
' DannyB Tue Oct 28, 2003 9:49 am
' http://www.oooforum.org/forum/viewtopic.phtml?t=3549
Sub writer_dumpFilterNames
oFF = createUnoService( "com.sun.star.document.FilterFactory" )
oFilterNames = oFF.getElementNames()
' Now print the filter names.
' For i = LBound( oFilterNames ) To UBound( oFilterNames )
' Print oFilterNames(i)
' Next
' Create a Writer doc and save the filter names to it.
oDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0, Array() )
oText = oDoc.getText()
oCursor = oText.createTextCursor()
oCursor.gotoEnd( False )
' Print the filter names into a Writer document.
For i = LBound( oFilterNames ) To UBound( oFilterNames )
oText.insertString( oCursor, oFilterNames(i), False )
oText.insertControlCharacter( oCursor, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False )
Next
End Sub
The code will create a new Writer document and put the names there (originally only printed the names, line 8-10)
Does this help you?

Categories

Resources