CS4820-Winter2020 student project to create a COUNTER SUSHI R5 harvester and related functionality app for Windows and Mac
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

757 lines
31 KiB

"""This module handles all operations involving the visual tab."""
import calendar
import datetime
import json
import os
from _operator import itemgetter
from typing import Sequence
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QFont
import xlsxwriter
from datetime import date
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QFileDialog, QDialog
import GeneralUtils
from GeneralUtils import *
import ManageDB
import ManageVendors
from Settings import SettingsModel
from ui import MessageDialog, VisualTab
from Constants import *
class VisualController:
"""Controls the Visual tab
:param visual_ui: The UI for visual_widget.
"""
def __init__(self, visual_ui: VisualTab.Ui_visual_tab, settings: SettingsModel):
self.settings = settings
# set up and configure report type combobox
self.report_parameter = visual_ui.search_report_parameter_combobox_2
self.report_parameter.addItems(ALL_REPORTS)
self.report_parameter.currentTextChanged[str].connect(self.on_report_parameter_changed)
# set up and configure cost ratio combobox
self.cost_parameter = visual_ui.cost_ratio_option_combobox
COST_TYPE_ALL = ('Cost in Local Currency with Tax', 'Cost in Local Currency', 'Cost in Original Currency')
self.cost_parameter.addItems(COST_TYPE_ALL)
# set up and configure cost ratio frame
self.frame_cost = visual_ui.edit_cost_ratio_frame
self.frame_cost.setEnabled(False)
# set up and configure top num frame
self.top_num_frame = visual_ui.edit_top_num_frame
self.top_num_frame.setEnabled(False)
# set up top num spinbox and configure lower and upper bounds
self.top_num_edit = visual_ui.top_num_spinbox
# set up chart type radio buttons
self.h_bar_radio = visual_ui.radioButton
self.v_bar_radio = visual_ui.radioButton_3
self.line_radio = visual_ui.radioButton_4
self.v_bar_radio.setChecked(True)
# set up calculations type radio buttons
self.monthly_radio = visual_ui.monthly_radioButton
self.yearly_radio = visual_ui.yearly_radioButton
self.topNum_radio = visual_ui.topnum_radioButton
self.costRatio_radio = visual_ui.costratio_radioButton
# configure calculation type radio buttons and connect with method
self.monthly_radio.setChecked(True)
self.monthly_radio.toggled.connect(self.on_calculation_type_changed)
self.yearly_radio.toggled.connect(self.on_calculation_type_changed)
self.topNum_radio.toggled.connect(self.on_calculation_type_changed)
self.costRatio_radio.toggled.connect(self.on_calculation_type_changed)
# set up start year dateedit
self.start_year_parameter = visual_ui.search_start_year_parameter_dateedit_2
self.start_year_parameter.setDate(date.today())
# set up end year dateedit
self.end_year_parameter = visual_ui.search_end_year_parameter_dateedit_2
self.end_year_parameter.setDate(date.today())
# set up name label
self.name_label = visual_ui.visual_name_label
# set up name combobox
self.name_combobox = visual_ui.visual_name_parameter_combobox
self.name = None
self.metric = visual_ui.metric_Type_comboBox
self.metric.addItems(DATABASE_REPORTS_METRIC)
self.vendor = visual_ui.visual_vendor_parameter_combobox
self.vendor.currentTextChanged.connect(self.on_vendor_changed)
self.vendor_parameter = None
self.vendor_parameter = self.vendor.currentText()
vendors_json_string = GeneralUtils.read_json_file(ManageVendors.VENDORS_FILE_PATH)
vendor_dicts = json.loads(vendors_json_string)
self.vendor.clear()
self.vendor.addItem("")
self.vendor.addItems([vendor_dict['name'] for vendor_dict in vendor_dicts])
# set up the search clauses
self.and_clause_parameters = None
# set up create chart button
self.create_chart_button = visual_ui.create_chart_button
self.create_chart_button.clicked.connect(self.createChart)
# set up customize chart field
self.chart_title_edit = visual_ui.chart_title_lineEdit
self.horizontal_axis_edit = visual_ui.horizontal_axis_lineEdit
self.vertical_axis_edit = visual_ui.vertical_axis_lineEdit
# set up open file and open folder check box
self.open_file = visual_ui.open_file_checkBox
self.open_folder = visual_ui.open_folder_checkBox
self.file_name = None
self.data = []
self.temp_results = []
self.top_num = None
self.results = None
self.names = []
self.costs_names = []
def update_settings(self, settings: SettingsModel):
"""Called when the settings are saved
:param settings: the new settings"""
self.settings = settings
self.local_currency = self.settings.default_currency
#self.load_currency_list()
def database_updated(self, code: int):
"""Called when the database is updated
:param code: the exit code of the update"""
self.fill_names()
def load_vendor_list(self, vendors: Sequence[ManageVendors.Vendor]):
"""Updates the vendor list combobox
:param vendors: the new list of vendors"""
self.vendor.clear()
self.vendor.addItem("")
self.vendor.addItems([vendor.name for vendor in vendors])
def on_calculation_type_changed(self):
"""Invoke when calculation type is changed"""
if self.topNum_radio.isChecked():
self.top_num_frame.setEnabled(True)
self.frame_cost.setEnabled(False)
self.name_combobox.setEnabled(False)
self.name_label.setEnabled(False)
if self.costRatio_radio.isChecked():
self.top_num_frame.setEnabled(False)
self.frame_cost.setEnabled(True)
self.name_combobox.setEnabled(True)
self.name_label.setEnabled(True)
if self.monthly_radio.isChecked() or self.yearly_radio.isChecked():
self.top_num_frame.setEnabled(False)
self.frame_cost.setEnabled(False)
self.name_combobox.setEnabled(True)
self.name_label.setEnabled(True)
def on_report_parameter_changed(self, text):
"""Invoke when report type is changed"""
self.metric.clear()
if text in DATABASE_REPORTS:
self.metric.addItems(DATABASE_REPORTS_METRIC)
self.name_label.setText('Database')
if text in ITEM_REPORTS:
self.metric.addItems(ITEM_REPORTS_METRIC)
self.name_label.setText('Item')
if text in PLATFORM_REPORTS:
self.metric.addItems(PLATFORM_REPORTS_METRIC)
self.name_label.setText('Platform')
if text in TITLE_REPORTS:
self.metric.addItems(TITLE_REPORTS_METRIC)
self.name_label.setText('Title')
if self.vendor.currentText():
self.fill_names()
def on_vendor_changed(self):
"""Invoke when vendor is changed"""
self.vendor_parameter = self.vendor.currentText()
if self.report_parameter.currentText():
self.fill_names()
def fill_names(self, only_get_costs_names: bool = False):
"""Fill name field combobox"""
self.name_combobox.clear()
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
if not only_get_costs_names:
names_sql_text, names_data = ManageDB.get_names_sql_text(self.report_parameter.currentText(), self.vendor_parameter)
names_results = ManageDB.run_select_sql(connection, names_sql_text, names_data)
if names_results:
self.names = [result[0] for result in names_results]
else:
self.names = []
if self.settings.show_debug_messages: print(names_results)
costs_sql_text, costs_data = ManageDB.get_names_with_costs_sql_text(self.report_parameter.currentText(),
self.vendor_parameter,
int(self.start_year_parameter.text()),
int(self.end_year_parameter.text()))
costs_results = ManageDB.run_select_sql(connection, costs_sql_text, costs_data)
if costs_results:
self.costs_names = [result[0] for result in costs_results]
else:
self.costs_names = []
if self.settings.show_debug_messages: print(costs_results)
connection.close()
model = QStandardItemModel()
for name in self.names:
item = QStandardItem(name)
if name in self.costs_names:
font = QFont()
font.setBold(True)
item.setFont(font)
model.appendRow(item)
self.name_combobox.setModel(model)
else:
print('Error, no connection')
# submit search result to database and open results
def createChart(self):
"""Invoke when user click on create chart"""
# get report type
report = self.report_parameter.currentText()
# get start year
start_year = self.start_year_parameter.text()
# get end year
end_year = self.end_year_parameter.text()
# get name
name = self.name_combobox.currentText()
# get metric
metric = self.metric.currentText()
# get vendor
vendor = self.vendor.currentText()
self.top_num = -1
self.temp_results = []
message = ""
message1 = ""
message2 = ""
message3 = ""
message4 = ""
if name == "" and self.topNum_radio.isChecked() == False:
message4 = "- Enter/Choose " + self.name_label.text() + "\n"
if vendor == "" and self.topNum_radio.isChecked() == False:
message1 = "- Choose a Vendor \n"
if start_year > end_year or (int(start_year) > datetime.datetime.now().year or int(end_year) > datetime.datetime.now().year) :
currentYear = datetime.datetime.now().year
message3 = "- Start Year must be less than End Year and they cannot be greater than " + str(
currentYear) + "\n"
message = message1 + message4 + message3
if message != "":
message = "To Create Chart check the following: \n" + message
GeneralUtils.show_message(message)
if self.monthly_radio.isChecked() and message == "":
# sql query to get search results
sql_text, data = ManageDB.monthly_chart_search_sql_text(report, start_year, end_year, name, metric, vendor)
print(sql_text) # testing
headers = tuple([field['name'] for field in ManageDB.get_monthly_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
print(self.results)
self.results.insert(0, headers)
print(self.results)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1 and self.monthly_radio.isChecked():
self.process_default_data()
self.open_file_folder()
if name != "" and start_year <= end_year and len(self.results) <= 1:
message4 = name + " of " + metric + " NOT FOUND in " + report + " for the chosen year range!"
GeneralUtils.show_message(message4)
if self.yearly_radio.isChecked() and message == "":
# sql query to get search results
sql_text, data = ManageDB.yearly_chart_search_sql_text(report, start_year, end_year, name, metric, vendor)
print(sql_text) # testing
headers = tuple([field['name'] for field in ManageDB.get_yearly_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
print(self.results)
self.results.insert(0, headers)
print(self.results)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1 and self.yearly_radio.isChecked():
self.process_yearly_data()
self.open_file_folder()
if name != "" and start_year <= end_year and len(self.results) <= 1:
message4 = name + " of " + metric + " NOT FOUND in " + report + " for the chosen year range!"
GeneralUtils.show_message(message4)
if self.costRatio_radio.isChecked() and message == "":
# sql query to get search results
sql_text, data = ManageDB.cost_chart_search_sql_text(report, start_year, end_year, name, metric, vendor)
print(sql_text) # testing
headers = tuple([field['name'] for field in ManageDB.get_cost_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
print(self.results)
self.results.insert(0, headers)
print(self.results)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1 and self.costRatio_radio.isChecked():
self.process_cost_ratio_data()
self.open_file_folder()
if name != "" and start_year <= end_year and len(self.results) <= 1:
message4 = name + " of " + metric + " NOT FOUND in " + report + " for the chosen year range!"
GeneralUtils.show_message(message4)
if self.topNum_radio.isChecked() and message == "":
self.top_num = int(self.top_num_edit.text())
if self.top_num == 0:
self.top_num = None
if self.vendor.currentText() == "":
vendor = None
sql_text, data = ManageDB.top_number_chart_search_sql_text(report, start_year, end_year, metric, vendor,
self.top_num)
headers = tuple([field['name'] for field in ManageDB.get_top_number_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
self.results.insert(0, headers)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1:
self.process_top_X_data()
self.open_file_folder()
elif start_year <= end_year:
message5 = self.name_label.text() + " of " + metric + " Not Found in " + report + " for the chosen year range!"
GeneralUtils.show_message(message5)
def open_file_folder(self):
"""Invoke to open file or folder"""
if self.open_folder.isChecked():
open_file_or_dir(os.path.dirname(self.file_name))
if self.open_file.isChecked():
open_file_or_dir(self.file_name)
if not self.open_file.isChecked():
show_message('Results saved to ' + self.file_name)
# process_data distributes the usage data for monthly in an array accordingly
def process_default_data(self):
"""Invoked when calculation type: monthly is selected"""
m = len(self.results)
self.legendEntry = [] # legend entry data
for i in range(1, m):
self.legendEntry.append(self.results[i][3])
# data is an array with the sorted usage figures
self.data = []
for i in range(0, m):
data1 = []
n = len(self.results[i])
for j in range(4, n): # from jan to dec only
data1.append(self.results[i][j])
self.data.append(data1)
# testing to make sure its working good
print(self.data[0]) # this is the first column in the excel file/vertical axis data in the chart
print(self.data[1])
print(len(self.data))
self.chart_type()
def process_yearly_data(self):
"""Invoked when calculation type: yearly is selected"""
m = len(self.results)
self.legendEntry = [] # legend entry data
self.legendEntry.append(self.metric.currentText())
# data is an array with the sorted usage figures
self.data = []
data1 = [] # year
data2 = [] # reporting_period_total
for i in range(1, m):
data1.append(self.results[i][3])
self.data.append(data1)
for i in range(1, m):
data2.append(self.results[i][4])
self.data.append(data2)
# testing to make sure its working good
print(self.data[0]) # this is the first column in the excel file/vertical axis data in the chart
print(self.data[1])
print(len(self.data))
self.chart_type()
def process_cost_ratio_data(self):
"""Invoked when calculation type: cost ratio is selected"""
m = len(self.results) #length of self.results
self.legendEntry = [] # legend entry data contains column names
# data is an array of array with year, cost per metric, total and cost in separate arrays
self.data = []
data1 = [] # year
data2 = [] # cost per metric
data3 = [] # reporting_period_total
data4 = [] # cost
# retrieve year and add it to array
for i in range(1, m):
data1.append(self.results[i][3])
self.data.append(data1)
# retrieve cost and total and finding cost per metric and adding it to array
if self.cost_parameter.currentText() == 'Cost in Local Currency with Tax':
self.legendEntry.append('Cost in Local Currency with Tax Per Metric')
self.legendEntry.append('Cost in Local Currency with Tax')
for i in range(1, m):
cost = self.results[i][7]
if self.results[i][7] is None:
cost = 0
data4.append(cost)
data2.append(cost / self.results[i][8])
self.data.append(data2)
self.data.append(data4)
if self.cost_parameter.currentText() == 'Cost in Local Currency':
self.legendEntry.append('Cost in Local Currency Per Metric')
self.legendEntry.append('Cost in Local Currency')
for i in range(1, m):
cost = self.results[i][6]
if self.results[i][6] is None:
cost = 0
data4.append(cost)
data2.append(cost / self.results[i][8])
self.data.append(data2)
self.data.append(data4)
if self.cost_parameter.currentText() == 'Cost in Original Currency':
self.legendEntry.append('Cost in Original Currency Per Metric')
self.legendEntry.append('Cost in Original Currency')
for i in range(1, m):
cost = self.results[i][4]
if self.results[i][4] is None:
cost = 0
data4.append(cost)
data2.append(cost / self.results[i][8])
self.data.append(data2)
self.data.append(data4)
# retrieve reporting_period_total and add it to array
for i in range(1, m):
data3.append(self.results[i][8])
self.data.append(data3)
# add column header to legend entry
self.legendEntry.append(self.metric.currentText())
# testing to see data in array of array
print(self.data[0]) # first column in excel (year)
print(self.data[1]) # second column (cost per metric)
# print(self.data[2]) # third column (cost)
# print(self.data[4]) # fourth column (total)
# print(len(self.data)) #testing
self.chart_type()
def process_top_X_data(self):
"""Invoked when calculation type: top # is selected"""
m = len(self.results)
#print(self.results)
print(m)
self.temp_results = []
self.legendEntry = [] # legend entry data
self.legendEntry.append(self.results[0][3])
self.legendEntry.append(self.results[0][4])
for i in range(1, m):
self.temp_results.append(self.results[i])
self.temp_results = sorted(self.temp_results, key=itemgetter(4))
print(len(self.temp_results))
print(self.temp_results)
n = len(self.temp_results)
# data is an array with the sorted usage figures
self.data = []
data1 = [] # name(database, title,...)
data2 = [] # reporting total
data3 = [] # rankings
data4 = [] # optional vendor column
# get all name(database,title,...)
data = self.temp_results[0][0]
data1.append(data)
for i in range(1, n): # get database
data = self.temp_results[i][0]
data1.append(data)
self.data.append(data1)
print(data1)
# get all reporting total
metri = self.temp_results[0][3]
data2.append(metri)
for i in range(1, n): # get reporting total
metri = self.temp_results[i][3]
data2.append(metri)
self.data.append(data2)
print(data2)
# get all ranking
rank = self.temp_results[0][4]
data3.append(rank)
for i in range(1, n):
rank = self.temp_results[i][4]
data3.append(rank)
self.data.append(data3)
# will add vendor column to chart if the user do not enter anything in vendor
if self.vendor.currentText() == "":
self.legendEntry.append(self.results[0][2])
for i in range(0, n):
rank = self.temp_results[i][2]
data4.append(rank)
self.data.append(data4)
self.chart_type()
# get chart type checked
def chart_type(self):
"""Invoked to determine which chart type is selected by user"""
if self.h_bar_radio.isChecked():
self.horizontal_bar_chart()
if self.v_bar_radio.isChecked():
self.vertical_bar_chart()
if self.line_radio.isChecked():
self.line_chart()
# get file name and titles from user
def customizeChart(self):
"""Invoked to get information from user to customize chart.
It is highly recommended that user write the details like year, report type, calculation type,.. in chart title"""
chart_title = self.chart_title_edit.text()
horizontal_axis_title = self.horizontal_axis_edit.text()
vertical_axis_title = self.vertical_axis_edit.text()
return chart_title, horizontal_axis_title, vertical_axis_title
# add titles to chart and styles
@staticmethod
def add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title):
"""Invoked to add information to customize the chart
:param chart1: the chart to add details to
:param chart_title: the chart title
:param horizontal_axis_title: the horizontal axis title
:param vertical_axis_title: the vertical axis title"""
# Add a chart title and some axis labels.
chart1.set_title({'name': chart_title})
chart1.set_x_axis({'name': horizontal_axis_title})
chart1.set_y_axis({'name': vertical_axis_title})
# Set an Excel chart style.
chart1.set_style(11)
# create file with ext and add sheet to file
def createFile(self):
"""Invoked to create xlsx file"""
self.file_name = choose_save(EXCEL_FILTER)
if self.file_name != '':
if not self.file_name.lower().endswith('.xlsx'):
self.file_name += '.xlsx'
workbook = xlsxwriter.Workbook(self.file_name)
# add sheet to xlsx file
worksheet = workbook.add_worksheet()
return workbook, worksheet
# Add the worksheet data that the charts will refer to.
def populateData(self, vertical_axis_title, worksheet, workbook):
"""Invoked to create xlsx file
:param vertical_axis_title: the vertical axis title
:param worksheet: the worksheet in the xlsx file
:param workbook: the workbook"""
bold = workbook.add_format({'bold': 1})
#headings = [vertical_axis_title]
headings = [""]
for i in range(0, len(self.legendEntry)):
headings.append(self.legendEntry[i])
worksheet.write_row('A1', headings, bold)
worksheet.write_column('A2', self.data[0])
n = ord('A') + 1
if self.costRatio_radio.isChecked() == False:
for i in range(1, len(self.data)):
worksheet.write_column(chr(n) + '2', self.data[i])
n = n + 1
if self.costRatio_radio.isChecked() == True:
# Add a number format for cells with money.
currency = self.process_currency()
money = workbook.add_format({'num_format': currency})
for i in range(1, len(self.data)-1):
worksheet.write_column(chr(n) + '2', self.data[i], money)
n = n + 1
worksheet.write_column(chr(n) + '2', self.data[len(self.data)-1])
# process currency
def process_currency(self):
"""Invoke to determine between local or original currency for cost"""
if self.cost_parameter.currentText() == 'Cost in Local Currency with Tax' or self.cost_parameter.currentText() == 'Cost in Local Currency':
local_currency = self.settings.default_currency
currency = self.get_currency_code(local_currency)
if self.cost_parameter.currentText() == 'Cost in Original Currency':
original_currency = self.results[1][5]
currency = self.get_currency_code(original_currency)
return currency
# return currency code for excel
def get_currency_code(self, local_currency):
"""Invoke to find currency being used"""
if local_currency == 'CAD':
currency = '[$CAD] #,###.#########################_)'
if local_currency == 'USD':
currency = '[$USD] #,###.#########################_)'
if local_currency == 'EUR':
currency = '[$EUR] #,###.#########################_)'
if local_currency == 'JPY':
currency = '[$JPY] #,###.#########################_)'
if local_currency == 'GBP':
currency = '[$GBP] #,###.#########################_)'
if local_currency == 'CHF':
currency = '[$CHF] #,###.#########################_)'
if local_currency == 'AUD':
currency = '[$AUD] #,###.#########################_)'
return currency
# create chart and add series to it
def configureSeries(self, workbook, chart_type):
"""Invoked to create xlsx file
:param workbook: the workbook
:param chart_type: the chart type"""
chart1 = workbook.add_chart({'type': chart_type})
n = len(self.data[0])
# Configure the first series.
chart1.add_series({
'name': '=Sheet1!$B$1',
'categories': '=Sheet1!$A$2:$A$'+str(n+1),
'values': '=Sheet1!$B$2:$B$'+str(n+1),
})
# Configure any subsequent series. Note use of alternative syntax to define ranges.
# no more series will be added if top # and cost ratio are not selected
if self.top_num == -1 and self.costRatio_radio.isChecked() == False:
m = 2
for i in range(2, len(self.data)):
chart1.add_series({
'name': ['Sheet1', 0, m],
'categories': ['Sheet1', 1, 0, n, 0],
'values': ['Sheet1', 1, m, n, m],
})
m = m + 1
return chart1
def horizontal_bar_chart(self):
"""Invoked to create a horizontal bar chart"""
# get titles from customizeChart
chart_title, horizontal_axis_title, vertical_axis_title = self.customizeChart()
# create xlsx file and add sheet file
workbook, worksheet = self.createFile()
# add data to worksheet
self.populateData(vertical_axis_title, worksheet, workbook)
# create horizontal bar chart and add series to it
chart1 = self.configureSeries(workbook, 'bar')
# Add a chart title and some axis labels.
self.add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title)
# Insert the chart into the worksheet (with an offset).
worksheet.insert_chart('F2', chart1, {'x_scale': 2, 'y_scale': 2})
workbook.close()
# Completion message
message_completion = "Done!"
GeneralUtils.show_message(message_completion)
def vertical_bar_chart(self):
"""Invoked to create a vertical bar chart"""
# get titles from customizeChart
chart_title, horizontal_axis_title, vertical_axis_title = self.customizeChart()
# create xlsx file and add sheet file
workbook, worksheet = self.createFile()
# add data to worksheet
self.populateData(vertical_axis_title, worksheet, workbook)
# create horizontal bar chart and add series to it
chart1 = self.configureSeries(workbook, 'column')
# Add a chart title and some axis labels.
self.add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title)
# Insert the chart into the worksheet (with an offset).
worksheet.insert_chart('F2', chart1, {'x_scale': 2, 'y_scale': 2})
workbook.close()
# Completion message
message_completion = "Done!"
GeneralUtils.show_message(message_completion)
def line_chart(self):
"""Invoked to create a line chart"""
# get titles from customizeChart
chart_title, horizontal_axis_title, vertical_axis_title = self.customizeChart()
# create xlsx file and add sheet file
workbook, worksheet = self.createFile()
# Add data to worksheet
self.populateData(vertical_axis_title, worksheet, workbook)
# create horizontal bar chart and add series to it
chart1 = self.configureSeries(workbook, 'line')
# Add a chart title and some axis labels.
self.add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title)
# Insert the chart into the worksheet (with an offset).
worksheet.insert_chart('F2', chart1, {'x_scale': 2, 'y_scale': 2})
workbook.close()
# Completion message
message_completion = "Done!"
GeneralUtils.show_message(message_completion)