The following code selects the range of a pivot table and saves down as picture. How would it go to select the pivot table by its name (e.g., "Pivot1") and not by the range?
import win32com.client as win32
import sys
from pathlib import Path
import win32com.client as win32
from PIL import ImageGrab
excel_path = "C:/Prueba/GOOG-copia.xlsm"
excel = win32.DispatchEx('Excel.Application')
excel.Visible = False
excel.DisplayAlerts = False
wb = excel.Workbooks.Open(Filename=excel_path)
ws = wb.Worksheets('Cacaca')
win32c = win32.constants
ws.Range("A3:B8").CopyPicture(Format=win32c.xlBitmap)
img = ImageGrab.grabclipboard()
image_path = 'C:/Prueba/test.png'
img.save(image_path)
excel.Quit()
You can select named ranges by using the range method:
wb.Worksheets('Cacaca').Range("Pivot1").Select()
When using the Win32 library, you can often try the process with VBA first as the Win32 calls tend to map to VBA.
Update - Here is the code to list all pivot tables in a Workbook:
# create dictionary of Pivot tables by sheet
dd = {}
ShtCnt = excel.Sheets.Count
for s in range(ShtCnt):
#print("Sheet Name:", wb.Sheets(s+1).Name)
dd[wb.Sheets(s+1).Name] = []
cnt = wb.Sheets(s+1).PivotTables().Count
for x in range(cnt):
#print(wb.Sheets(s+1).PivotTables(x+1).Name)
dd[wb.Sheets(s+1).Name].append(wb.Sheets(s+1).PivotTables(x+1).Name)
print(dd)
Related
I have some code to convert an excel file from excel to PDF. Although I know that openpyxl has methods to assign column width value, wrap text and add cell border, I am looking for a way to do it with win32com module. This is because I already have opened the Excel file with win32com and I can save execution time by not having to load the Excel file with openpyxl again.
# Import Module
from win32com import client
# Open Microsoft Excel
excel = client.gencache.EnsureDispatch('Excel.Application')
# Make excel work in the background without appearing
excel.Visible = False
# Read Excel File
wb = excel.Workbooks.Open(r'C:\Spaced out data.xlsx')
ws = wb.Worksheets('Sheet1')
# Adjust page setup to landscape
ws.PageSetup.Orientation = 1
# Set Zoom to false because you want to fit all columns to the width of 1 page.
ws.PageSetup.Zoom = False
# Allow rows to be on multiple pages
ws.PageSetup.FitToPagesTall = False
# Fit all columns to the width of 1 page.
ws.PageSetup.FitToPagesWide = 1
# Convert into PDF File
ws.ExportAsFixedFormat(0, r'C:\Spaced out data.pdf')
wb.Close(SaveChanges=False)
excel.Quit()
My "go to" is to record an Excel macro and use it as a basis to write the Python code. After recording a column width change, enable wrap, and change some borders I came up with this:
from win32com import client
excel = client.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
wb = excel.Workbooks.Open(r'c:\users\metolone\test.xlsx')
ws = wb.Worksheets('Sheet1')
ws.Range("A:F").ColumnWidth = 10
ws.Range("A1:F1").WrapText = True
ws.Range("A1:F15").Borders(client.constants.xlEdgeLeft).LineStyle = client.constants.xlContinuous
ws.Range("A1:F15").Borders(client.constants.xlEdgeLeft).Weight = client.constants.xlThick
ws.PageSetup.Orientation = 1
ws.PageSetup.Zoom = False
ws.PageSetup.FitToPagesTall = False
ws.PageSetup.FitToPagesWide = 1
ws.ExportAsFixedFormat(0, r'c:\users\metolone\test.pdf')
wb.Close(SaveChanges=False)
excel.Quit()
Set the column width for specific range(row or column) or specific column:
import os
import win32com.client as win32
from win32com.client import Dispatch
file = os.getcwd() + os.sep + 'Portfolio.xls'
excel = Dispatch('Excel.Application')
workbook = excel.Workbooks.Open(file)
worksheet = workbook.Worksheets("Portfolio")
excel.DisplayAlerts = False
excel.Visible = False
worksheet.Range("A1:A14").ColumnWidth = 25 #Specify the rows in range
worksheet.Columns(1).ColumnWidth = 25 #Specific Column number
worksheet.Range("B:B").ColumnWidth = 25
worksheet.Columns.AutoFit() #Use autofit
workbook.Save()
workbook.Close()
excel.Application.Quit()
How does it work to select a pivot table with Python and then copy it to a .png?
I am trying wb.Worksheets("Test").PivotTables(1) but it keeps throwing an error...
win32c = win32.constants
ws.PivotTables("PivotTable1").CopyPicture(Format=win32c.xlBitmap)
img = ImageGrab.grabclipboard()
image_path = 'C:/Prueba/test.png'
img.save(image_path)
excel.Quit()
Error:
AttributeError: '<win32com.gen_py.Microsoft Excel 16.0 Object
Library.PivotTable instance at 0x2569187443096>' object has no
attribute 'CopyPicture'
As mentioned in the comments, you can use Excel automation to copy a pivot table to an image file.
For this code, I used a sample Excel file which can be found here:
https://www.timeatlas.com/wp-content/uploads/pivot_table_example.xlsx
Here is the code to copy the pivot table from the sample file:
from win32com.client import Dispatch
import win32com.client as win32
from PIL import ImageGrab
ExcelFile = 'C:/tmp/pivot_table_example.xlsx'
SheetName = "Sheet2" # sheet with pivot table
ImgFile = 'C:/tmp/test.png'
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True
excel.Workbooks.Open(ExcelFile)
excel.Sheets(SheetName).Select()
excel.Sheets(SheetName).PivotTables(1).TableRange1.Select() # select first pivot table
excel.Sheets(SheetName).PivotTables(1).TableRange1.Copy()
img = ImageGrab.grabclipboard()
img.save(ImgFile)
excel.Quit()
In Billing Roster - SOW.xlsx I have new column data one is named as SOW and other is named SOW Description (Match value for SOW).
And now when i open ACFC_Resource_Allocation.xlsx excel and for an example if select a value in D2 (SOW) cell from the dropdown i should get a matching value into E2 cell after the selection from dropdown.
I only have an idea than a vlookup from Excel like below should solve my case. Not sure how to achieve in python.
=VLOOKUP(D2,'[Billing Roster - SOW.xlsx]SOW List'!$A$1:$B$14,1,FALSE)
Tried below code
from openpyxl import *
from openpyxl.styles import *
import webbrowser
import pandas
from openpyxl.worksheet.datavalidation import DataValidation
# Read all Excels into pandas dataframes
sowexcel = pandas.read_excel('Billing Roster - SOW.xlsx')
#Load the existing Resource Allocation Excel
wb = load_workbook('ACFC_Resource_Allocation.xlsx')
allocationsheet = wb.active
def load():
maxrow = allocationsheet.max_row
sow_list = sowexcel['SOW #'].tolist()
column_sow = ','.join(sow_list)
validator_sow = DataValidation(type='list', formula1='"{}"'.format(column_sow), allow_blank=True)
allocationsheet.add_data_validation(validator_sow)
validator_sow.add('D2:D%s' %maxrow)
# save the file
wb.save('ACFC_Resource_Allocation.xlsx')
wb.close()
# Driver code
if __name__ == "__main__":
load()
file_open = webbrowser.open('ACFC_Resource_Allocation.xlsx')
I have a number of HTML files that I need to open up or import into a single Excel Workbook and simply save the Workbook. Each HTML file should be on its own Worksheet inside the Workbook.
My existing code does not work and it crashes on the workbook.Open(html) line and probably will on following lines. I can't find anything searching the web specific to this topic.
import win32com.client as win32
import pathlib as path
def save_html_files_to_worksheets(read_directory):
read_path = path.Path(read_directory)
save_path = read_path.joinpath('Single_Workbook_Containing_HTML_Files.xlsx')
excel_app = win32.gencache.EnsureDispatch('Excel.Application')
workbook = excel_app.Workbooks.Add() # create a new excel workbook
indx = 1 # used to add new worksheets dependent on number of html files
for html in read_path.glob('*.html'): # loop through directory getting html files
workbook.Open(html) # open the html in the newly created workbook - this doesn't work though
worksheet = workbook.Worksheets(indx) # each iteration in loop add new worksheet
worksheet.Name = 'Test' + str(indx) # name added worksheets
indx += 1
workbook.SaveAs(str(save_path), 51) # win32com requires string like path, 51 is xlsx extension
excel_app.Application.Quit()
save_html_files_to_worksheets(r'C:\Users\<UserName>\Desktop\HTML_FOLDER')
The following code does half of want I want, if this helps. It will convert each HTML file into a separate Excel file. I need each HTML file in one Excel file with multiple WorkSheets.
import win32com.client as win32
import pathlib as path
def save_as_xlsx(read_directory):
read_path = path.Path(read_directory)
excel_app = win32.gencache.EnsureDispatch('Excel.Application')
for html in read_path.glob('*.html'):
save_path = read_path.joinpath(html.stem + '.xlsx')
wb = excel_app.Workbooks.Open(html)
wb.SaveAs(str(save_path), 51)
excel_app.Application.Quit()
save_as_xlsx(r'C:\Users\<UserName>\Desktop\HTML_FOLDER')
Here is a link to a sample HTML file you can use, the data in the file is not real: HTML Download Link
One solution would be to open the HTML file into a temporary workbook, and copy the sheet from there into the workbook containing all of them:
workbook = excel_app.Application.Workbooks.Add()
sheet = workbook.Sheets(1)
for path in read_path.glob('*.html'):
workbook_tmp = excel_app.Application.Workbooks.Open(path)
workbook_tmp.Sheets(1).Copy(Before=sheet)
workbook_tmp.Close()
# Remove the redundant 'Sheet1'
excel_app.Application.ShowAlerts = False
sheet.Delete()
excel_app.Application.ShowAlerts = True
I believe pandas will make your job much easier.
pip install pandas
Here's an example on how to get multiple tables from a wikipedia html and input it into a Pandas DataFrame and save it to disk.
import pandas as pd
url = "https://en.wikipedia.org/wiki/List_of_American_films_of_2017"
wikitables = pd.read_html(url, header=0, attrs={"class":"wikitable"})
for idx,df in enumerate(wikitables):
df.to_csv('{}.csv'.format(idx),index=False)
For your use case, something like this should work:
import pathlib as path
import pandas as pd
def save_as_xlsx(read_directory):
read_path = path.Path(read_directory)
for html in read_path.glob('*.html'):
save_path = read_path.joinpath(html.stem + '.xlsx')
dfs_from_html = pd.read_html(html, header=0,)
for idx, df in enumerate(dfs_from_html):
df.to_excel('{}.xlsx'.format(idx),index=False)
** Make sure to set the correct html attribute in the pd.read_html function.
How about this?
Sub From_XML_To_XL()
'UpdatebyKutoolsforExcel20151214
Dim xWb As Workbook
Dim xSWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
Dim xCount As Long
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Application.ScreenUpdating = False
Set xSWb = ThisWorkbook
xCount = 1
xFile = Dir(xStrPath & "\*.xml")
Do While xFile <> ""
Set xWb = Workbooks.OpenXML(xStrPath & "\" & xFile)
xWb.Sheets(1).UsedRange.Copy xSWb.Sheets(1).Cells(xCount, 1)
xWb.Close False
xCount = xSWb.Sheets(1).UsedRange.Rows.Count + 2
xFile = Dir()
Loop
Application.ScreenUpdating = True
xSWb.Save
Exit Sub
ErrHandler:
MsgBox "no files xml", , "Kutools for Excel"
End Sub
I would like to read the text from a text box in an Excel File and save that value to a variable. The problem I am having is with the reading of the TextBox. I have tried several methods, this one showed the most promise, as it does not generate an error, but it does not elicit the desired result either. Any suggestions are appreciated. See code below.
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open("C:\\users\\khillstr\\Testing\\Scripts\\Book1.xlsx")
excel.Visible = False
ws = wb.Worksheets
canvas = excel.ActiveSheet.Shapes
for shp in canvas.CanvasItems:
if shp.TextFrame.Characters:
print shp.TextFrame.Characters
else:
print "no"
Canvas has to do with graphics in excel files. I think you want access to the cells. Below is code that prints out each row as a tuple.
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open("C:\\users\\khillstr\\Testing\\Scripts\\Book1.xlsx")
excel.Visible = False
sheet = wb.Worksheets(1)
for row in sheet.UsedRange.Value:
print row
To get the text in a textbox object on a sheet you need to use shp.TextFrame.Characters.Caption as the Characters method returns a Characters object and not a string.
import win32com.client as win32
file_name = 'path_to_excel'
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(self.file_name)
excel.Visible = False
sheet = wb.Worksheets(1)
deep = lambda r,c: sheet.Cells(r,c)
print(deep(row_num,col_num))
excel.Application.Quit()
This code will open an excel located at 'path_to_excel' and read a cell located at (Row_Number = row_num, Column_Number = col_num)