Экспорт в Excel формы ввода данных Pyqt c помощью openpyxl
Возникла проблема с экспортом формы ввода данных из Pyqt5 в Excel c помощью openpyxl.
Основной "затык" в динамически добавляемых QLineEdit и QGroupBox.
Я находил как присваивать новым добавляемым через кнопку QLineEdit уникальные названия и считывать с них значения в файл Excel, но никак не получается провернуть это к целому блоку QGroupBox с вложенными в нем динамически добавляемыми QLineEdit.
Надеюсь внятно изъяснился, я только учусь. Например:
from datetime import datetime
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, QLabel, QGroupBox, QHBoxLayout, QVBoxLayout, QDialog, QGridLayout, QComboBox, QDateEdit
from PyQt5 import QtCore
class TextApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
'''задаем сетку и основные блоки'''
self.maingrid = QVBoxLayout(self)
firstlay = QHBoxLayout(self)
secondlay = QHBoxLayout(self)
'''добавляем информацию в шапку'''
maininfo = QGroupBox('main info', self)
maininfogrid = QGridLayout(self)
fio = QLabel('fio', self)
fioline = QLineEdit(self)
date = QLabel('date', self)
dateline = QDateEdit(self)
dateline.setDate(QtCore.QDate.currentDate())
dateline.setCalendarPopup(True)
maininfogrid.addWidget(fio, 1, 0)
maininfogrid.addWidget(fioline, 1, 1)
maininfogrid.addWidget(date, 2, 0)
maininfogrid.addWidget(dateline, 2, 1)
maininfo.setLayout(maininfogrid)
'''добавляем основные кнопки'''
addwork = QPushButton('add work', self)
addwork.clicked.connect(self.add_work)
printreport = QPushButton('print report', self)
self.maingrid.addLayout(firstlay)
self.maingrid.addLayout(secondlay)
firstlay.addWidget(maininfo)
secondlay.addWidget(addwork)
secondlay.addWidget(printreport)
workwidget = NewWork()
self.maingrid.addWidget(workwidget)
self.show()
def add_work(self):
workwidget = NewWork()
self.maingrid.addWidget(workwidget)
class NewWork(QGroupBox):
def __init__(self):
super().__init__()
self.initwork()
def initwork(self):
thirdlay = QHBoxLayout(self)
workinfo = QGroupBox('work info', self)
materialinfo = QGroupBox('material info', self)
machineinfo = QGroupBox('machine info', self)
personinfo = QGroupBox('person info', self)
'''задаем вспомогательную сетку данных о работе, расстоянии и стороне'''
self.workgrid = QGridLayout(self)
work = QLabel('work', self)
workline = QLineEdit(self)
self.workgrid.addWidget(work, 2, 0)
self.workgrid.addWidget(workline, 2, 1)
pk_begin = QLabel('pk begin', self)
pkbline = QLineEdit(self)
self.workgrid.addWidget(pk_begin, 3, 0)
self.workgrid.addWidget(pkbline, 3, 1)
pk_end = QLabel('pk end', self)
pkeline = QLineEdit(self)
self.workgrid.addWidget(pk_end, 4, 0)
self.workgrid.addWidget(pkeline, 4, 1)
storona = QComboBox(self)
storona.addItems(['choose side', 'left side', 'right side', 'all side'])
self.workgrid.addWidget(storona, 5, 0, 1, 0)
workinfo.setLayout(self.workgrid)
'''создаем основную кнопку, вызываем функцию по клику и добавляем в основную сетку'''
machinelay = QGridLayout(self)
machine = QPushButton('add machine', self)
machine.clicked.connect(self.add_machine)
machinelay.addWidget(machine, 1, 0, 1, 0)
'''создаем вспомогательные сетки добавляемых полей техники и присоединяем к основной сетке техники'''
self.machinename = QVBoxLayout(self)
self.machineline = QVBoxLayout(self)
self.machinenumber = QVBoxLayout(self)
self.numberline = QVBoxLayout(self)
self.owner = QVBoxLayout(self)
self.ownerline = QVBoxLayout(self)
machinelay.addLayout(self.workgrid, 2, 0, QtCore.Qt.AlignTop)
machinelay.addLayout(self.machinename, 2, 1)
machinelay.addLayout(self.machineline, 2, 2)
machinelay.addLayout(self.machinenumber, 2, 3)
machinelay.addLayout(self.numberline, 2, 4)
machinelay.addLayout(self.owner, 2, 5)
machinelay.addLayout(self.ownerline, 2, 6)
'''присоединяем разметку к группировке'''
machineinfo.setLayout(machinelay)
'''устанавливаем принадлежности сеток'''
thirdlay.addWidget(workinfo)
thirdlay.addWidget(materialinfo)
thirdlay.addWidget(machineinfo)
thirdlay.addWidget(personinfo)
self.show()
def add_machine(self):
'''создаем кнопки и поля, задаем фиксированную ширину и присоединяем к вспомогательным сеткам'''
machine_add = QLabel('machine', self)
machine_add.setFixedHeight(20)
self.machinename.addWidget(machine_add)
line_add = QLineEdit(self)
line_add.setFixedHeight(20)
self.machineline.addWidget(line_add)
number_add = QLabel('number', self)
number_add.setFixedHeight(20)
self.machinenumber.addWidget(number_add)
line_add1 = QLineEdit(self)
line_add1.setFixedHeight(20)
self.numberline.addWidget(line_add1)
owner_add = QLabel('owner', self)
owner_add.setFixedHeight(20)
self.owner.addWidget(owner_add)
line_add2 = QLineEdit(self)
line_add2.setFixedHeight(20)
self.ownerline.addWidget(line_add2)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = TextApp()
sys.exit(app.exec_())
Ответы (1 шт):
Вы не правильно применяете layout к widgetу. Все подклассы QWidget могут использовать макеты для управления своими дочерними элементами.
Функция QWidget::setLayout() применяет макет к виджету.
self.mainLayout = QVBoxLayout()self.setLayout(self.mainLayout)или
self.mainLayout = QVBoxLayout(self)это одно и то же!
Рекомендую вам почитать https://doc.qt.io/qt-5/layout.html и https://doc.qt.io/qt-5/qwidget.html#setLayout
я немного упростил структуру вашего приложения, но все равно достать данные способом, который вы задумали, будет очень тяжело.
я наполнил метод
print_reportнекой функциональностью, которая сработает по клику на кнопку 'print report'.В первой части - показано как вытащить данные из
QGroupBox('main info')и это только цветочки... как вытаскивать данные из другихQGroupBoxстрашно и подумать.Предлагаю вам попробовать создать, например словарь,
self.mainDict = {}и заполнять его по ходу дела.Во второй части - метод
print_reportнемного показано как доставать данные из этого словаря.
import sys
from pprint import pprint as pp
from datetime import datetime
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit, \
QLabel, QGroupBox, QHBoxLayout, QVBoxLayout, QDialog, QGridLayout, \
QComboBox, QDateEdit, QFormLayout
from PyQt5 import QtCore
class NewWork(QGroupBox):
def __init__(self, parent=None):
super(NewWork, self).__init__(parent)
self.row = 2
self.parent = parent
self.numNewWork = parent.numNewWork
print(self.numNewWork)
self.setStyleSheet("background: teal;")
self.hide()
def initwork(self):
workinfo = QGroupBox(f'work info {self.numNewWork}')
materialinfo = QGroupBox(f'material info {self.numNewWork}')
machineinfo = QGroupBox(f'machine info {self.numNewWork}')
personinfo = QGroupBox(f'person info {self.numNewWork}')
workline = QLineEdit()
pkbline = QLineEdit()
pkeline = QLineEdit()
storona = QComboBox()
storona.addItems(['choose side', 'left side', 'right side', 'all side'])
self.workgrid = QFormLayout(workinfo)
self.workgrid.addRow('work', workline)
self.workgrid.addRow('pk begin', pkbline)
self.workgrid.addRow('pk end', pkeline)
self.workgrid.addWidget(storona)
machinelay = QGridLayout(machineinfo)
machine = QPushButton('add machine')
machine.clicked.connect(lambda ch, lay=machinelay: self.add_machine(lay, r=self.row))
machinelay.addWidget(machine, 1, 0, 1, 0)
thirdlay = QHBoxLayout()
thirdlay.addWidget(workinfo)
thirdlay.addWidget(materialinfo)
thirdlay.addWidget(machineinfo)
thirdlay.addWidget(personinfo)
self.parent.mainDict[f'work info {self.numNewWork}'] = (workline, pkbline, pkeline, storona)
self.parent.mainDict[f'machine info {self.numNewWork}'] = []
return thirdlay # ---->>>
def add_machine(self, lay, r=2):
#print(lay, r)
name = lay.parent().title()
line_add = QLineEdit(self)
line_add1 = QLineEdit(self)
line_add2 = QLineEdit(self)
lay.addWidget(QLabel('<h3>machine</h3>'), r, 1)
lay.addWidget(line_add, r, 2)
lay.addWidget(QLabel('number'), r, 3)
lay.addWidget(line_add1, r, 4)
lay.addWidget(QLabel('owner'), r, 5)
lay.addWidget(line_add2, r, 6)
self.row += 1
self.parent.mainDict[name].append([line_add, line_add1, line_add2])
class TextApp(QWidget):
def __init__(self):
super().__init__()
self.mainDict = {}
self.initUI()
def initUI(self):
maininfo = QGroupBox('main info')
maininfogrid = QFormLayout(maininfo)
fioline = QLineEdit(self)
dateline = QDateEdit(self)
dateline.setDate(QtCore.QDate.currentDate())
dateline.setCalendarPopup(True)
maininfogrid.addRow('fio', fioline)
maininfogrid.addRow('date', dateline)
addwork = QPushButton('add work', self)
addwork.clicked.connect(self.add_work)
printreport = QPushButton('print report', self)
printreport.clicked.connect(self.print_report)
secondlay = QHBoxLayout()
secondlay.addWidget(addwork)
secondlay.addWidget(printreport)
self.maingrid = QVBoxLayout(self)
self.maingrid.addWidget(maininfo)
self.maingrid.addLayout(secondlay)
self.mainDict['main info'] = (fioline, dateline)
self.numNewWork = 1
self.add_work()
def add_work(self):
workwidget = NewWork(self)
thirdlay = workwidget.initwork() # <<<----
self.maingrid.addLayout(thirdlay)
self.numNewWork += 1
def print_report(self):
# первая часть
print(f'\n layout().count() -> {self.layout().count()}')
print(self.layout().itemAt(0))
print(f'\t -> {self.layout().itemAt(0).widget()} ')
print(f'\t -> {self.layout().itemAt(0).widget().children()}')
print(f'\t -> {self.layout().itemAt(0).widget().children()[2].text()}')
print(f'\t -> {self.layout().itemAt(0).widget().children()[4].dateTime().toString("dd-MM-yyyy")}')
print(f'{"-"*30}\n')
# втора часть
pp(self.mainDict)
print('\nmain info:')
print('\t', self.mainDict['main info'][0].text())
print('\t', self.mainDict['main info'][1].dateTime().toString("dd-MM-yyyy"))
# 'work info 1'
print('work info 1:')
print('\t', self.mainDict['work info 1'][0].text())
print('\t', self.mainDict['work info 1'][1].text())
print('\t', self.mainDict['work info 1'][2].text())
print('\t', self.mainDict['work info 1'][3].currentText())
# 'machine info 1'
_list = self.mainDict['machine info 1']
if _list:
print('machine info 1:')
for i in _list:
print('\t', i[0].text(), i[1].text(), i[2].text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = TextApp()
ex.show()
sys.exit(app.exec_())
