Exception Occurred (..) - 'Microsoft Excel', 'SaveAs ... class failed' - python-3.x

This code basically does what it needs to do. But it does throw an error sometimes whereas I would expect the code to work as all data necessary is present.
So what it does is: (1) Read in users (2) Add information to the Excel dashboard, such as header information, word clouds and profile picture.
Then it saves the Excel file. It sometimes, randomly almost, gives an error: (pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'Open method of Workbooks class failed', 'xlmain11.chm', 0, -2146827284), None)). What part of the code could cause this?
import os
import xlwings as xw
import pandas as pd
import openpyxl
def get_users(file_name):
"""Read all the users from the csv file."""
users = []
f = open(file_name, 'r')
for line in f:
user = line.strip().split(',')
screen_name = user[0]
users.append(screen_name)
f.close()
return users
def read_csv_file(file_name):
"""Return csv file with accounts."""
data = []
f = open(file_name, 'r')
for line in f:
temp = tuple(line.strip().split(';'))
data.append(temp)
f.close()
return data
def write_panda_to_excel(df, start_cell, wb):
"""Write Pandas DataFrame to Excel."""
sht = wb.sheets['Input']
sht.range(start_cell).value = df
def add_word_cloud(name, cell, wb):
"""Add the WordCloud to Sheet2 """
sht = wb.sheets['Sheet2']
name = os.getcwd() + '\\' + name
rng = sht.range(cell)
sht.pictures.add(name, top=rng.top, left=rng.left, width=325, height=155)
def add_profile_picture(user, cell, wb):
#Add charts to dashboard.
sht = wb.sheets['Sheet1']
picture = [f for f in os.listdir('.') if f.startswith(user + '.')][0]
name = os.getcwd() + '\\' + picture
rng = sht.range(cell)
sht.pictures.add(name, top=rng.top, left=rng.left, width=70, height=90)
app = xw.App(visible=False)
# Read users
os.chdir('../FolderA/')
file_name = 'accounts_file.csv'
users = get_users(file_name)
os.chdir('../Data')
for i, user in enumerate(users):
try:
#count += 1
print(100 * '-')
print(len(users), i+1, user)
# go to directory where the dashboard is stored
os.chdir('../Folder5/FolderE')
wb = xw.Book('Twitter - Individuele Rapportage.xlsm')
os.chdir('../../Data/' + user)
# Remove file if exists
xl = [e for e in os.listdir('.') if e.endswith('.xlsm')]
for e in xl:
os.remove(e)
# add user name to title of Dashboard
sht = wb.sheets['Input_Data']
# add the csv data and profile pictures the other data to the dashboard
df = pd.read_csv(user + '_header_info.csv', sep=',')
write_panda_to_excel(df, 'A1', wb)
cell = 'L20'
try:
add_profile_picture(user, cell, wb)
except:
os.chdir('../../Folder6')
with open('Twitter - Profile picture Error.txt', 'a') as ExceptFile:
ExceptFile.write(str(user) + '\n')
os.chdir('../Data/' + user)
name = user + '_WC.png'
cell = 'Y46'
add_word_cloud(name, cell, wb)
xlname = 'Twitter' + user + '.xlsm'
try:
wb.save(xlname)
wb.close()
except:
os.chdir('../../Folder6')
with open('Twitter - Dashboard Generation Errors.txt', 'a') as myfile:
myfile.write(str(user + "\n"))
myfile.close()
os.chdir('../Data/' + user)
os.chdir('..')
except OSError as exception:
print(exception)
os.chdir('..')
with open('dash_errors.txt', 'w') as dashboard_errors:
dashboard_errors.write(user+"\n")

Related

Python - Load multiple excel files with multiple sheets in it with specific columns

I have a problem scenario where I need to load excel files using Python
Load multiple excel files from a folder - Done
Each excel file has multiple sheets - Done
Need to load only required columns ('Receive Date','Process Date','Process Number','Task Name','Series','Office','Department','Unit Manager','AM'), other columns needs to be ignored/dropped and no error should be raised if the above columns does not exist in some sheets.
Load all the data into single data frame
------ Code -------
import pandas as pd
import os
import glob
def getfilepath():
path = 'C:/Users/Tracking Logs/'
files=(os.listdir(path))
allfiles = glob.glob(path+"*.xlsx")
def getdatafromexcel():
for file in allfiles:
rawdf = pd.read_excel(file,sheet_name=None,na_values='null',keep_default_na=False,dtype=object,date_parser=True)
cols=('Receive Date','Process Date','Process Number','Task Name','Series','Office','Department','Unit Manager','AM/AA/PC')
display(df)
getfilepath()
getdatafromexcel()
I found the solution:
import pandas as pd
import os
import glob
from IPython.display import HTML,display
from openpyxl import load_workbook
path = 'C:/Users/Tracking Logs/'
cols = ['Receive Date','Process Date','Task Name','Series','Office','Department','Unit Manager','AM/AA/PC']
def getfilepath(path):
files=(os.listdir(path))
allfiles = glob.glob(path+"*.xlsx")
#print('Allfiles: ',allfiles)
return allfiles
def getdatafromexcel(cols,allfiles):
for i in range(len(allfiles)):
print('\nCounter: ',i,' \nFilenames: ',allfiles[i])
wb = load_workbook(allfiles[i],read_only=True)
for sheetname in wb.sheetnames:
print('Sheetname: ',sheetname)
try:
df = pd.read_excel(allfiles[i],sheet_name=sheetname,na_values='null',usecols=cols,
keep_default_na=False,dtype=object)
Indexnames = df[(df["Task Name"] == '') & (df["Series"] == '') & (df["Office"] == '')].index
df.drop(Indexnames,inplace=True)
display(df)
fulldf=fulldf.append(df,ignore_index=True)
except Exception as e:
print(e)
finally:
print('this executed')
wb.close()
display(fulldf)
allfiles = getfilepath(path)
getdatafromexcel(cols,allfiles)
One can use pd.ExcelFile and pd.read_excel to get the required results.
def getdatafromexcel():
for file in allfiles:
xl = pd.ExcelFile(file)
res = len(xl.sheet_names)
if res>1:
for i in range(1, res+1):
df = pd.read_excel(file, sheet_name= '%d' %i)
# Do selection, preprocessing what you want here
if i == 1:
df.to_csv(<your_path> + '1.csv')
df_1 = pd.read_csv(<your_path> + '1.csv')
if i > 1:
df_1 = pd.concat([df_1, df])
else:
df_1 = pd.read_excel(file)
# Do selection, preprocessing what you what here
df_1.to_csv(<your_path> + '.csv', index= False)

How to save data using openpyxl with Python3 in a Excel file? Is there any way to take a bit of time to do that?

The procedure is :
Reading data from a txt file by line;
Then send the data to a serial port;
Save the data to a Excel file in a row with number/date/time
I have tried two methods, and both of them are worked.
But the is some problem:
The more data, the more time is taken when save the new data to the Excel file. For example, when write the data to the 10000 row, it's almost need 2 seconds (When I using append() to append a new row in the Excel file);
I want to send and save the data all the time, untill I stop the script in the Pycharm by click the STOP button. Once I did that, the Excel saved before is broken and CAN NOT open it again.
I want to solve these problem. Can anyone have any suggestions? Thank you so much!
Here is the code:
import serial
import serial.tools.list_ports
import time
import datetime
import sys
import os
import openpyxl
from openpyxl.styles import Font
from openpyxl.styles import PatternFill
from openpyxl.styles import Alignment
# The path to palce the Excel file
def creatfilepath(path):
# path -- The user input a path
if os.path.isdir(path):
datapath = path
print('\nM1:The path is OK, and the Excel file will be saved in {}'.format(datapath))
else:
if os.makedirs(path):
datapath = path
print('\nM2:The path does not exist, and scrip will creat the path {} to save the Excel'.format(datapath))
else:
datapath = os.getcwd()
print('\nM3:Creating the path is failed, and the Excel will be saved in same path {} where the script is.'.format(datapath))
return datapath
# Creating the Excel to save the data
def creatdatafile(filename, path, data_title):
# filename -- Excel filename
# path -- The path to save the Excel
# data_title -- Excel's title, which is a list and the default value is ['Number', 'Date', 'Time', 'Command', 'Type', 'Comment']
# Creating a Workbook
serial_data_1902_wb = openpyxl.Workbook()
# Accessing the active sheet
serial_data_1902_sheet = serial_data_1902_wb.active
# sheet'title
serial_data_1902_sheetname = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
serial_data_1902_sheet.title = serial_data_1902_sheetname
# Excel's filename
serial_data_1902_filename = filename + '_' + \
datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + '.xlsx'
# The absolute path
ab_path = path + "\\" + serial_data_1902_filename
serial_data_1902_wb.save(ab_path)
# Loading the Excel
active_data_file = openpyxl.load_workbook(ab_path)
# Accessing the sheet
active_datasheet = active_data_file[serial_data_1902_sheetname]
# Setting the title
row_title = data_title
active_datasheet.append(row_title)
# Freezing the 1st row
active_datasheet.freeze_panes = 'A2'
# Accessing the title's scope
title_scope = active_datasheet.dimensions
# Arial/12/Bold/
title_font_obj = Font(name='Arial', size=10, bold=True,
italic=False, strike=False, color='000000')
# Fill type
title_fill_obj = PatternFill(fill_type='solid', fgColor='7EC0EE')
# Alignment
title_align_obj = Alignment(
horizontal='center', vertical='center', wrap_text=False)
# Formating the 1st row
for rowOfCellObjects in active_datasheet[title_scope]:
for cellObject in rowOfCellObjects:
cellObject.font = title_font_obj
cellObject.fill = title_fill_obj
cellObject.alignment = title_align_obj
active_data_file.save(ab_path)
# Return the absolute path
if os.path.exists(ab_path):
print('\nM4:The Excel {} have created, and the path is {}'.format(
serial_data_1902_filename, path))
return ab_path
else:
print('\nE0:Creating Excel is failed, please check!')
sys.exit(0)
def isavailable(port):
port_list = list(serial.tools.list_ports.comports()
)
if len(port_list) <= 0:
print('\nE1:There is not serial port on the host!')
sys.exit(0)
else:
port_name_list = []
for port_objet in port_list:
port_name = port_objet[0]
port_name_list.append(port_name.lower())
print('\nM5:The serial ports is:{}'.format(port_name_list))
if port.lower() in port_name_list:
print('\nM6:')
else:
print('\nE2:')
sys.exit(0)
# Creating a vitural serial port and open it
def createport(port, baudrate=115200):
isavailable(port)
try:
serialport = serial.Serial(port, baudrate, timeout=1, write_timeout=1)
except ValueError:
sys.exit('\nE3:')
except (OSError, serial.SerialException):
sys.exit('\nE4:')
if serialport.is_open and port == serialport.portstr:
print('\nM7:')
serialport.flushInput()
else:
sys.exit('\nE5:')
return serialport
def savecommand(num, command_list, excelabpath, excelworkbook, excelsheet):
# num -- The number of command
# command_list -- A list which contain the data
# excelabpath -- The absolute path of Excel
# excelworkbook -- The Excel which save data
# excelsheet -- the sheet which save the data
try:
i = 0
for row in excelsheet.iter_rows(min_row=num+1, max_col=5, max_row=num+1):
for cell in row:
cell.value = command_list[i]
i += 1
if i < len(command_list):
continue
else:
break
excelworkbook.save(excelabpath)
except TypeError:
print('\nE10:')
def sendcommand(abpath, workbook, sheet, commandfile, port, intertime=0.5, commamd_num=1):
#
if not port.is_open:
try:
port.open()
except:
print('\nE6:')
else:
pass
try:
with open(commandfile, 'r', encoding='utf-8') as file_object:
for line in file_object:
if len(line) > 1 and (not line.startswith('#')):
command_hex = bytes.fromhex(
line.strip())
try:
print(commamd_num, " ", datetime.datetime.now(),
" ", line)
port.write(command_hex)
# The list contain the number/date/time/command
data_list = [commamd_num, datetime.datetime.now().strftime(
'%Y/%m/%d'), datetime.datetime.now().strftime('%H:%M:%S.%f'), line.strip()]
savecommand(commamd_num, data_list, abpath, workbook, sheet)
time.sleep(intertime)
commamd_num += 1
except serial.SerialTimeoutException:
print("\nE7:")
time.sleep(1)
port.write(command_hex)
# The list contain the number/date/time/command
data_list = [commamd_num, datetime.datetime.now().strftime(
'%Y/%m/%d'), datetime.datetime.now().strftime('%H:%M:%S.%f'), line.strip()]
savecommand (commamd_num, data_list, abpath, workbook, sheet)
time.sleep(intertime)
commamd_num += 1
else:
continue
except FileNotFoundError:
print('\nE8:')
sys.exit(0)
except PermissionError:
print('\nE9:')
sys.exit(0)
port.close()
if not port.is_open:
print('\nM9:')
return commamd_num
# ~~~~~~~~~~~~~~ The parameters of serial port ~~~~~~~~~~~~~~~~~~
# port number
comNumber = 2
# port name
comPort = 'com{}'.format(comNumber)
# baudRate
baudRate = 115200
# ~~~~~~~~~~~~~~ Other parameters ~~~~~~~~~~~~~~~~~~
# The path of command file
commandPath = r'.\1902.txt'
# The Excel path
savePath = r'D:\1902Code'
# The name of Excel
excelName = 'SerialData1902'
# The title
excelTitle = ['Number', 'Date', 'Time', 'Command', 'Type', 'Comment']
# The time between two command was sent
interTime = 0.01
#
isForever = 1
# ~~~~~~~~~~~~~~~~~~~~~ Begin ~~~~~~~~~~~~~~~~~~~
# Creating the path which save the Excel
excel_path = creatfilepath(savePath)
# Creating the Excel
excel_ab_path = creatdatafile(excelName, excel_path, excelTitle)
# Loading the Excel
excel_workbook = openpyxl.load_workbook(excel_ab_path)
# Accessing the sheet
excel_sheet = excel_workbook.active
# Creating the serial port
serial_port = createport(comPort, baudRate)
# The number of sending command and start with 1
command_num = 1
if isForever:
print('\nM10:')
while isForever:
command_num = sendcommand(excel_ab_path, excel_workbook, excel_sheet,
commandPath, serial_port, interTime, command_num)
elif isForever == 0:
print('\nM11:')
command_num = sendcommand(excel_ab_path, excel_workbook, excel_sheet,
commandPath, serial_port, interTime, command_num)
else:
print('\nE11:')

Using pandas pd.Excel File with user input for folder path and filename

I'm using pd.ExcelFile as below to open and parse a file, but currently only with the actual folder path and filename in one string.
wb = pd.ExcelFile(folder_path+filename)
I want to put this into a function, that asks the user to give a path and filename and deals with invalid input. I started something like the below, but it doesn't seem like the error is being generated inside the function anyway, and i'm not sure how to say 'while wb isn't a valid thing' to continue to prompt for a filepath until we get a valid one?
def Load_Parse():
folder_path = input('\nEnter the path to the qry_T spreadsheet here (include slashes at the start and at the end): ')
filename = input('\nEnter the name of the spreadsheet to be used here: ')
sheetname = input('\nEnter the sheet containing the data here, including the extension (e.g. "qry_Trajectory 2019.xlsx": ')
try:
wb = pd.ExcelFile(folder_path+filename)
except FileNotFoundError:
Any ideas?
I'll then parse the file using a similar method i hope:
df = wb.parse('filename')
using Pathlib, os and pandas and a few functions.
one of the key functions you'll need is the while True which keeps executing a block of code until it's true and you initiate a break
feel free to edit to your own spec.
Modules
from pathlib import Path
import os
import pandas as pd
from xlrd import XLRDError
In Action
df = load_parser()
out:
#Hello Umar.Hussain please enter a valid target directory
#C:\Users\UmarH\Files
#1 excels_0
#2 excels_1
#Choose a number between 1 and 2
1
#Your Choice is excels_0.xlsx
#Choose a Sheet - Lists all sheets
'Sheet1'
# returns dataframe
Main Function
def load_parser():
user = os.getlogin()
print(f"Hello {user} please enter a valid target directory")
cmd = input('')
p = file_tester(cmd,file_type='path')
print("Please select a number from the following file")
target_file = create_excel_dict(p)
target_df = enumerate_sheets(target_file)
return target_df
Helper Functions
def file_tester(string_path, file_type="path"):
path = Path(string_path)
while True:
if path.is_dir():
break
else:
cmd = input(f"Please Enter a Valid {file_type}")
path = Path(cmd)
return path
def create_excel_dict(target_path):
xlsx_dict = {i: x for i, x in enumerate(target_path.glob('*.xlsx'), 1)}
for k,v in xlsx_dict.items():
print(k,v.stem)
rng = [i for i in xlsx_dict.keys()]
file_choice = input(f'Choose a number between {rng[0]} and {rng[-1]}')
while True:
try:
file_choice = int(file_choice)
print(f"Your Choice is {xlsx_dict[file_choice]}")
break
except KeyError:
file_choice = input(f'Choose a number between {rng[0]} and {rng[-1]}')
return xlsx_dict[file_choice]
def enumerate_sheets(target_file):
xl = pd.ExcelFile(target_file)
for sheet in xl.sheet_names:
print(sheet)
target_sheet = input("Please Type Your sheet name")
while True:
try:
df = pd.read_excel(xl,sheet_name=target_sheet)
break
except XLRDError:
target_sheet = input("Please enter a sheet from above.")
return df

lat_long = lat.text.strip('() ').split(',') :AttributeError: 'list' object has no attribute 'text'

Need to find distance between 2 latitude and longitude. The Chrome is being controlled by the driver, then the latitude and longitudes are added to the suitable locations and the it also shows the distance value in the textbox, but it is not able to retrive that generated string of number.Here's the code.Kindly Help.
from selenium import webdriver
import csv
import time
with open('C:/Users/Nisarg.Bhatt/Documents/lats and
longs/Lat_long_cleaned/retail_first.csv', 'r') as f:
reader = csv.reader(f.read().splitlines(), delimiter = ',')
data = [row for row in reader]
filename='C:/Users/Nisarg.Bhatt/Documents/lats and
longs/Lat_long_cleaned/retail_first'
option= webdriver.ChromeOptions()
option.add_argument("-incognito")
path= "Y:/AppData/Local/chromedriver"
browser= webdriver.Chrome(executable_path=path)
url="https://andrew.hedges.name/experiments/haversine/"
browser.get(url)
print(browser.title)
crash = 1
results = []
new=[]
skipped = []
for i,row in enumerate(data[1:]):
print (i)
search = browser.find_element_by_name('lat1')
search_term = data[i+1][5]
search_1=browser.find_element_by_name("lon1")
search_term_1= data[i+1][6]
search_2 = browser.find_element_by_name('lat2')
search_term_2 = data[i+2][5]
search_3 = browser.find_element_by_name('lon2')
search_term_3 = data[i+2][6]
search.clear()
search_1.clear()
search_2.clear()
search_3.clear()
try:
search.send_keys(search_term)
search_1.send_keys(search_term_1)
search_2.send_keys(search_term_2)
search_3.send_keys(search_term_3)
except:
print ('Skiped %s' %search_term)
print (row)
skipped.append(row)
continue
search.submit()
time.sleep(1)
try:
lat = browser.find_elements_by_xpath("/html/body/form/p[4]/input[2]")
except:
alert = browser.switch_to_alert()
alert.accept()
browser.switch_to_default_content()
print ('Couldnt find %s' %search_term)
print (row)
skipped.append(row)
continue
lat_long = lat.text.strip('() ').split(',')
lat_long_clean = [float(n) for n in lat]
try:
browser.refresh()
except:
with open(filename + 'recovered' + '%i' %crash + '.csv' , "wb") as f:
writer = csv.writer(f)
writer.writerows(results)
crash +=1
print (lat_long_clean)
r = row
r.extend(lat_long_clean)
r.insert(0, i)
print (r)
results.append(r)
with open(filename + ".csv", "a") as f:
writer = csv.writer(f)
writer.writerow(r)
with open(filename + "comp.csv" , "wb") as f:
writer = csv.writer(f)
writer.writerows(results)

openpyxl - overwrite datasheet and preserve pivot table

I've seen a few answers around to this question but none of them are working.
eg: How to write to an existing excel file without breaking formulas with openpyxl?
Docs give nothing away it seems:
http://openpyxl.readthedocs.io/en/latest/api/openpyxl.reader.excel.html
I tried replacing xls.load_workbook with xls.reader.excel.load_workbook but it doesn't change anything.
My current code overwrites the data in the data sheet, but kills the pivot table functionality in the other sheet (the sheet is still there but only with values). Any idea how to keep the pivot table?
import pandas as pd
import openpyxl as xls
from shutil import copyfile
template_file = 'openpy_test.xlsx'
output_file = 'openpy_output.xlsx'
copyfile(template_file, output_file)
book = xls.load_workbook(output_file,guess_types=False,data_only=False)
writer = pd.ExcelWriter(output_file,engine='openpyxl')
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)
df.to_excel(writer,sheet_name='data',index=False,encoding='utf8')
writer.save()
I have also tried book.save('dummycopy.xlsx'), which also saves with a non-funcitoning pivot table. So I am sure the problem is related to the load_workbook function.
Package versions:
openpyxl 2.4.10 py36_0
pandas 0.20.3 py36hce827b7_2
i don't think openpyxl supports excel pivot tables currently. I had to switch to using win32com library.
here is a wrapper module i wrote to do specific stuff with pivot tables; it's basically VBA translated to python (record macros and read the VBA, it'll make sense). hope it helps. it's still a work in progress but should be enough for you to work with.
import os, datetime
import win32com.client as win32
win32c = win32.constants
import sys, datetime
letters = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ' #space to compensate for index. if letter is a if column is 1
def Pull_excel_workbook(path = '', filename = '', visible = False):
'''function to run excel on the given filename'''
if path == '': path = os.getcwd()
if filename == '': raise FileNotFoundError('Please supply a file')
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = visible
try: wb = excel.Workbooks.Open(path + filename)
except: print('Try again\n{}'.format(sys.exc_info()))
ws = wb.ActiveSheet
data = list(ws.UsedRange.Value) #2d list of rows and columns
src = '{}!R1C1:R{}C{}'.format(ws.Name, len(data), len(data[0]))
return excel, wb, src
#wb.SaveAs(path + filename)
def Create_pivottable(wb, src, table_name = 'Pivot'):
'''creates Pivot Table object in the wb in a new Pivot worksheet'''
ws = wb.Sheets.Add() #should also change wb.ActiveSheet to the new one.
ws.Name = table_name
tname = ws.Name
starting_point = (4,1) #row, column
pc = wb.PivotCaches().Add(SourceType = win32c.xlDatabase,
SourceData = src)
try:
pt = pc.CreatePivotTable(TableDestination = '{}!R{}C{}'.format(tname, starting_point[0], starting_point[1]),
TableName = table_name,
DefaultVersion = win32c.xlPivotTableVersion10 #15
)
except: #not sure if will work...
print('{}:{}:{}:{}'.format(wb, src, table_name, '{}!R{}C{}'.format(tname, starting_point[0], starting_point[1])))
#tabledestination format of RN Pivot!R4C1 is not correct format, should be 'RN Pivot'!R4C1
pt = pc.CreatePivotTable(TableDestination = '{}!R{}C{}'.format(tname, starting_point[0], starting_point[1]),
TableName = table_name,
DefaultVersion = win32c.xlPivotTableVersion15
)
wb.Sheets(ws.Name).Select()
wb.Sheets(ws.Name).Cells(3,1).Select()
def Add_to_Filter(wb, tname, field_name):
''' '''
field = wb.ActiveSheet.PivotTables(tname).PivotFields(field_name)
field.Orientation = win32c.xlPageField
field.Position = 1
def Add_to_Row(wb, tname, field_name, position = 1):
''' '''
field = wb.ActiveSheet.PivotTables(tname).PivotFields(field_name)
field.Orientation = win32c.xlRowField
field.Position = position
def Add_to_Column(wb, tname, field_name, position = 1):
''' '''
field = wb.ActiveSheet.PivotTables(tname).PivotFields(field_name)
field.Orientation = win32c.xlColumnField
field.Position = position
if position > 1:
text = 'maybe do something here....'
pass
def Add_to_Value(wb, tname, field_name, alias = '', calculation = 'xlSum'):
''' '''
if type(calculation) is str and calculation in win32c.__dict__['__dicts__'][0]:
calculation = win32c.__dict__['__dicts__'][0][calculation]
datafield = wb.ActiveSheet.PivotTables(tname).PivotFields(field_name)
wb.ActiveSheet.PivotTables(tname).AddDataField(datafield, alias, calculation)
def LtoC(letter):
global letters
col = letters.index(letter)
return col
def CtoL(col):
global letters
letter = letters[col]
return letter
def Format_pretty(wb, tname, row_to_colapse):
'''makes it look prettier'''
wb.ActiveSheet.PivotTables(tname).TableStyle2 = 'PivotStyleMedium9'
if type(row_to_colapse) is not str:
for row in row_to_colapse:
wb.ActiveSheet.PivotTables(tname).PivotFields(row).ShowDetail = False #collapses
wb.ActiveSheet.PivotTables(tname).PivotFields(row).RepeatLabels = True #repeats labels
else:
wb.ActiveSheet.PivotTables(tname).PivotFields(row_to_colapse).ShowDetail = False #collapses
wb.ActiveSheet.PivotTables(tname).PivotFields(row_to_colapse).RepeatLabels = True #repeats labels
wb.ActiveSheet.Columns('A:Z').EntireColumn.AutoFit()
wb.ActiveSheet.Range('A1').Select()
def Add_calcd_col(ws, col, row_start, row_end, formula, style = '', col_title = 'default'):
'''col and rows should be int
'''
letter = CtoL(col)
ws.Range('{0}{1}:{0}{2}'.format(letter, row_start, row_end)).Select()
ws.Cells(row_start, col).Value = col_title
for row in range(row_start + 1, row_end + 1):
ws.Cells(row, col).Value = formula.format(row)
ws.Range('{0}{1}:{0}{2}'.format(letter, row_start, row_end)).Style = style
#print("ws.Range('{0}1:{0}200'.format({0})).Style = style".format(letter))
#ws.Range('{0}1:{0}200'.format(letter)).Style = style
def Values_to_columns(wb,tname, position = 2):
''' '''
wb.ActiveSheet.PivotTables(tname).DataPivotField.Orientation = win32c.xlColumnField
wb.ActiveSheet.PivotTables(tname).DataPivotField.Position = position
def WB_save(wb, path, tname, filename):
'''clean save of the new file '''
#Format_pretty(wb, tname, 'Division') #that needs to be fixed....
new_filename = filename[:-5] + '-{}.xlsx'.format(datetime.date.today().strftime('%m.%d.%y'))
wb.SaveAs(path + new_filename)
def Pivot_refresh(path, filename, pivot_sheet_name, pivot_table_name = 'Pivot'):
'''function to refresh the pivot table
tested and functional with recruiting prod report'''
excel, wb, src = Pull_excel_workbook(path = path, filename = filename)
wb.Sheets(pivot_sheet_name).Select()
cell = 'A6' #need a better way for this
excel.Worksheets(pivot_sheet_name).Range(cell).PivotTable.RefreshTable()
#pvt = excel.Worksheets(pivot_sheet_name).Range(cell).PivotTable
#pvt.RefreshTable()
WB_save(wb, path, pivot_table_name, filename)
#pivot refresh
#new = filename[:-5] + '-{}.xlsx'.format(2)
#Pivot_refresh(path = path, filename = new, pivot_sheet_name = 'Pivot')
def Hide_columns(wb, tname, start, end):
'''Hides columns'''
if type(start) is not str: start = CtoL(start)
if type(end) is not str: end = CtoL(end)
wb.ActiveSheet.Columns('{}:{}'.format(start, end)).EntireColumn.Hidden = True

Resources