Как из двух идентичных программ сделать одну (Python 3.7, qt Frame)
требовалось создать программу для проведения abc и xyz анализа данных из Excel файла. Отдельно две программы написать получилось (кривовато, правда). А вот чтобы она была одна и по кнопке проводился бы и тот и другой одновременно - не получается. Код одной из них прилагаю
import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QTableWidgetItem, QTableWidget, QHeaderView, QFrame
from openpyxl import load_workbook
import ABC
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
# Строка данных
class Record:
# Число по порядку
number: int
# Поставщик
supplier: str
# Товар
good: str
# Потребность
need: float
# Цена товара
price: float
# Ожидаемая окупаемость
income: float
# Доля реализации по позиции
prez: float
# Доля реализации по позиции с возрастающим итогом
prezbig: float
# Группа
group: str
# Инициализатор
def __init__(self, number, supplier, good, need, price, income):
self.number = number
self.supplier = supplier
self.good = good
self.need = need
self.price = price
self.income = income
self.prez = -1
self.prezbig = -1
self.group = ''
# Главный класс приложения
class ExampleApp(QtWidgets.QMainWindow, ABC.Ui_MainWindow):
# Список записей из файла excel
records = []
# Инициализатор
def __init__(self):
super().__init__()
self.setupUi(self)
self.tableWidget.setColumnCount(6)
self.tableWidget.setHorizontalHeaderLabels(['№',
'Поставщики',
'Товар',
'Потребность,\nшт.',
'Цена за 1 шт.,\nруб.',
'Ожидаемая\nокупаемость,\nруб.']
)
self.tableWidget.setColumnWidth(0, 5)
self.tableWidget.setColumnWidth(1, 150)
self.tableWidget.setColumnWidth(2, 150)
self.tableWidget.setColumnWidth(3, 90)
self.tableWidget.setColumnWidth(4, 120)
self.tableWidget.setColumnWidth(5, 120)
self.tableWidget.setRowCount(0)
self.tableWidget.verticalHeader().setVisible(0)
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.tableWidget_2.setColumnCount(6)
self.tableWidget_2.setColumnWidth(0, 5)
self.tableWidget_2.setColumnWidth(1, 150)
self.tableWidget_2.setColumnWidth(2, 125)
self.tableWidget_2.setColumnWidth(3, 150)
self.tableWidget_2.setColumnWidth(4, 150)
self.tableWidget_2.setColumnWidth(5, 55)
self.tableWidget_2.setHorizontalHeaderLabels(['№',
'Товар',
'Ожидаемая\nокупаемость,\nруб.',
'Доля реализации\nпо позиции,\n%',
'Долея реализации\nпо позиции\nс нарастающим итогом,\n%',
'Группа'
]
)
self.tableWidget_2.setRowCount(0)
self.tableWidget_2.verticalHeader().setVisible(0)
self.tableWidget_2.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.pushButton.clicked.connect(self.loaddata)
self.pushButton_2.clicked.connect(self.abcanaliz)
self.pushButton_3.clicked.connect(self.createreport)
# Заполняет список записей из файла excel
def filldata(self):
try:
self.records.clear()
if self.lineEdit.text() == '':
raise NotImplementedError('Введен неправильный диапазон ячеек в excel листе.')
scells = self.lineEdit.text().split(':')
words = [chr(_) for _ in range(ord(scells[0][0]), ord(scells[1][0]) + 1)]
scells = [int(_[1:]) for _ in scells]
if words.__len__() != 6:
raise NotImplementedError('Введен неправильный диапазон ячеек в excel листе.')
wb = load_workbook('data.xlsx');
sheet = wb['Лист1']
for row in range(scells[0], scells[1] + 1):
args = []
for col in enumerate(words):
val = sheet[col[1] + row.__str__()].value
if col[0] == 5 or col[0] == 4:
val = round(val, 2)
if val is None:
raise NotImplementedError('Введен неправильный диапазон ячеек в excel листе.')
args.append(val)
if col[0] == 5:
self.records.append(Record(*args))
args.clear()
except TypeError:
return 'Последняя колонка данных в excel листе должна быть заполнена цифрами, а не формулами.'
except Exception as excep:
return excep.__str__()
finally:
try:
wb.close()
except:
pass
return ''
# Обработчик нажатия кнопки "Загрузить данные из excel"
def loaddata(self):
err = self.filldata()
if err == '':
self.showdata(self.tableWidget, ['number', 'supplier', 'good', 'need', 'price', 'income'])
self.statusbar.showMessage('')
else:
self.statusbar.showMessage(err)
# Выводит данные в указанную таблицу (верхнюю или нижнюю)
def showdata(self, table: QTableWidget, collist):
table.setRowCount(0)
for rec in self.records:
table.setRowCount(table.rowCount() + 1)
for col in enumerate(collist):
table.setItem(table.rowCount() - 1, col[0],
QTableWidgetItem(rec.__dict__[col[1]].__str__(), 0))
# Обработчик нажатия кнопки "ABC анализ"
def abcanaliz(self):
ssum = sum([_.income for _ in self.records])
for rec in self.records:
rec.prez = round(rec.income / ssum * 100, 2)
self.records.sort(key=lambda rec: rec.prez, reverse=True)
val = 0
for rec in self.records:
rec.prezbig = round(round(val, 2) + rec.prez, 2)
val = rec.prezbig
for rec in self.records:
if rec.prezbig <= 80:
rec.group = 'A'
elif rec.prezbig <= 95:
rec.group = 'B'
else:
rec.group = 'C'
self.showdata(self.tableWidget_2, ['number', 'good', 'income', 'prez', 'prezbig', 'group'])
# Обработчик нажатия кнопки "Отчет"
def createreport(self):
if self.records.__len__() != 0:
doc = Document()
doc.add_heading('АВС анализ', 0).alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
doc.add_paragraph().add_run(
' Ниже, в таблице представлены результаты проведенного АВС анализа.')
doc.add_paragraph().add_run(
' Товары группы А это наиболее важные товары. Их запасы необходимо часто контролировать. ' +
'Они требуют наиболшего учета. С этой группы требуется начинать управление запасами' +
' и тратить на нее наибольшее время. Доля в результате 80%.')
doc.add_paragraph().add_run(
' Товары группы В это наиболее важные товары. Их запасы можно контролировать реже.' +
' Доля в результате 15%.')
doc.add_paragraph().add_run(
' Группа С. Эти товары просто должны быть в наличии. Их запасы контролируются' +
' реже чем запасы предыдущих групп. Доля в результате 5%.')
table = doc.add_table(rows=self.records.__len__() + 1, cols=9)
table.style = 'Table Grid'
hdr = table.rows[0].cells
hdr[0].text = '№'
hdr[1].text = 'П-к'
hdr[2].text = 'Товар'
hdr[3].text = 'Потр.,\nшт.'
hdr[4].text = 'Ц.\nруб.'
hdr[5].text = 'Ок-сть,\nруб.'
hdr[6].text = 'Д.реал.\nпо поз.,\n%'
hdr[7].text = 'Д.реал.\nпо поз.\nс нар.ит.,\n%'
hdr[8].text = 'Гр.'
flds = ['number', 'supplier', 'good', 'need', 'price', 'income', 'prez', 'prezbig', 'group']
for rec in enumerate(self.records, 1):
for col in range(0, 9):
table.rows[rec[0]].cells[col].text = rec[1].__dict__[flds[col]].__str__()
doc.save('ABCAnaliz.docx')
# Главная функция приложения
def main():
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(
app.styleSheet() + " QTableWidget{gridline-color: #0000ff;} QHeaderView::section{ border: 1px solid #0000ff; border-bottom: 1px solid #0000ff; }");
window = ExampleApp()
window.show()
app.exec_()
main()