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"
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.
I am trying to insert a calculated field in PIVOT TABLE created using win32com python library. But when i execute my code excel gives me error "References, names and arrays are not supported in Pivot Table formulas"
import win32com.client
Excel = win32com.client.gencache.EnsureDispatch('Excel.Application')
win32c = win32com.client.constants
Wb = Excel.Workbooks.Open('MyWorkbook')
Excel.Visible = True
Ws = Wb.Sheets('PR Jan20')
Wb.Sheets.Add()
Wb.ActiveSheet.Name = 'PivotSheet'
WsP = Wb.Sheets('PivotSheet')
MaxR = Ws.UsedRange.Rows.Count
MaxC = Ws.UsedRange.Columns.Count
C1 = Ws.Cells(1,1)
C2 = Ws.Cells(MaxR, MaxC)
PivotSourceRange = Ws.Range(C1,C2)
PCache = Wb.PivotCaches().Create(SourceType=win32c.xlDatabase, SourceData=PivotSourceRange,Version=win32c.xlPivotTableVersion14)
PTable = PCache.CreatePivotTable(TableDestination=WsP.Range('B2'), TableName='RegisterPivot', DefaultVersion=win32c.xlPivotTableVersion14)
PTable.PivotFields('Party').Orientation = win32c.xlRowField
PTable.PivotFields('Party').Position = 1
PTable.AddDataField(PTable.PivotFields('Gross Kgs'))
PTable.AddDataField(PTable.PivotFields('Amount (RS.)'))
#till above this line code is working fine
#this below line is causing issue
PTable.CalculatedFields().Add('Average Purchase Rate', '= Amount (RS.) / Gross Kgs')
'Excel Error'
I have managed to resolve the above issue. The problem was with the column name "Amount (RS.)" i renamed the column to "Amount" and everything worked fine. I think VBA is not comfortable with () parenthesis in Pivot Field name.
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).
I have to perform a large number of replacements in some documents, and the thing is, I would like to be able to automate that task. Some of the documents contain common strings, and this would be pretty useful if it could be automated. From what I read so far, COM could be one way of doing this, but I don't know if text replacement is supported.
I'd like to be able to perform this task in python? Is it possible? Could you post a code snippet showing how to access the document's text?
Thanks!
I like the answers so far;
here's a tested example (slightly modified from here)
that replaces all occurrences of a string in a Word document:
import win32com.client
def search_replace_all(word_file, find_str, replace_str):
''' replace all occurrences of `find_str` w/ `replace_str` in `word_file` '''
wdFindContinue = 1
wdReplaceAll = 2
# Dispatch() attempts to do a GetObject() before creating a new one.
# DispatchEx() just creates a new one.
app = win32com.client.DispatchEx("Word.Application")
app.Visible = 0
app.DisplayAlerts = 0
app.Documents.Open(word_file)
# expression.Execute(FindText, MatchCase, MatchWholeWord,
# MatchWildcards, MatchSoundsLike, MatchAllWordForms, Forward,
# Wrap, Format, ReplaceWith, Replace)
app.Selection.Find.Execute(find_str, False, False, False, False, False, \
True, wdFindContinue, False, replace_str, wdReplaceAll)
app.ActiveDocument.Close(SaveChanges=True)
app.Quit()
f = 'c:/path/to/my/word.doc'
search_replace_all(f, 'string_to_be_replaced', 'replacement_str')
See if this gives you a start on word automation using python.
Once you open a document, you could do the following.
After the following code, you can Close the document & open another.
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "test"
.Replacement.Text = "test2"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchKashida = False
.MatchDiacritics = False
.MatchAlefHamza = False
.MatchControl = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
The above code replaces the text "test" with "test2" and does a "replace all".
You can turn other options true/false depending on what you need.
The simple way to learn this is to create a macro with actions you want to take, see the generated code & use it in your own example (with/without modified parameters).
EDIT: After looking at some code by Matthew, you could do the following
MSWord.Documents.Open(filename)
Selection = MSWord.Selection
And then translate the above VB code to Python.
Note: The following VB code is shorthand way of assigning property without using the long syntax.
(VB)
With Selection.Find
.Text = "test"
.Replacement.Text = "test2"
End With
Python
find = Selection.Find
find.Text = "test"
find.Replacement.Text = "test2"
Pardon my python knowledge. But, I hope you get the idea to move forward.
Remember to do a Save & Close on Document, after you are done with the find/replace operation.
In the end, you could call MSWord.Quit (to release Word object from memory).
If this mailing list post is right, accessing the document's text is a simple as:
MSWord = win32com.client.Dispatch("Word.Application")
MSWord.Visible = 0
MSWord.Documents.Open(filename)
docText = MSWord.Documents[0].Content
Also see How to: Search for and Replace Text in Documents. The examples use VB and C#, but the basics should apply to Python too.
Checkout this link: http://python.net/crew/pirx/spam7/
The links on the left side point to the documentation.
You can generalize this using the object model, which is found here:
http://msdn.microsoft.com/en-us/library/kw65a0we(VS.80).aspx
You can also achieve this using VBScript. Just type the code into a file named script.vbs, then open a command prompt (Start -> Run -> Cmd), then switch to the folder where the script is and type: cscript script.vbs
strFolder = "C:\Files"
Const wdFormatDocument = 0
'Select all files in strFolder
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='" & strFolder & "'} Where " _
& "ResultClass = CIM_DataFile")
'Start MS Word
Set objWord = CreateObject("Word.Application")
Const wdReplaceAll = 2
Const wdOrientLandscape = 1
For Each objFile in colFiles
If objFile.Extension = "doc" Then
strFile = strFolder & "\" & objFile.FileName & "." & objFile.Extension
strNewFile = strFolder & "\" & objFile.FileName & ".doc"
Wscript.Echo "Processing " & objFile.Name & "..."
Set objDoc = objWord.Documents.Open(strFile)
objDoc.PageSetup.Orientation = wdOrientLandscape
'Replace text - ^p in a string stands for new paragraph; ^m stands for page break
Set objSelection = objWord.Selection
objSelection.Find.Text = "String to replace"
objSelection.Find.Forward = TRUE
objSelection.Find.Replacement.Text = "New string"
objSelection.Find.Execute ,,,,,,,,,,wdReplaceAll
objDoc.SaveAs strNewFile, wdFormatDocument
objDoc.Close
Wscript.Echo "Ready"
End If
Next
objWord.Quit