I am creating a script to export an attribute table in pdf format with PyQGIS 3. The number of features is different regarding the farmer's number of fields and features are sorted by the field id.
Regarding the number of fields, the attribute table may need to be extended to next page(s). I would like to repeat the main informations about the farm on the next page(s). Like a header only starting from the second page.
I first defined as many QgsLayoutItemLabel
as there were page (making if statements regarding the number of features) but it makes my script really heavy.
There is no map in the layout so I would like to know if it's possible to do it without using the atlas composer.
The following script allows to put my header on the 2nd page, and I would like to repeat it on the 3rd page without creating a new QgsLayoutItemLabel
.
project = QgsProject.instance()
layout = QgsPrintLayout(project)
BD = project.mapLayersByName('Base de données client')[0]
prop_field = BD.fields().indexFromName('Propriétaire')
prop = BD.getFeature(idCode).attribute(prop_field)
header1 = QgsLayoutItemLabel(layout)
header1.setText("Liste des contraintes - " + prop)
header1.setFont(QFont("Ms Shell Dlg 2", 11))
header1.setHAlign(Qt.AlignLeft)
header1.setMinimumSize(QgsLayoutSize(133.376, 8.215, QgsUnitTypes.LayoutMillimeters))
header1.attemptMove(QgsLayoutPoint(6, 3.590),page=1)
EDIT
I tried the following code that allows to duplicate an item, but I don't understand why both items are at the same location, on the 1st page, even if a different page is called:
# Crédit
def generateLayoutItemCredit(layoutn, pagenb):
credit_text = QgsLayoutItemLabel(layoutn)
credit_text.setText("Plan réalisé par le Club agroenvironnemental de l'Estrie")
credit_text.setFont(QFont("Ms Shell Dlg 2", 11))
credit_text.setHAlign(Qt.AlignLeft)
credit_text.setMarginX(3)
credit_text.setMinimumSize(QgsLayoutSize(130, 8, QgsUnitTypes.LayoutMillimeters))
credit_text.attemptMove(QgsLayoutPoint(6, 268),page=pagenb)
layoutn.addLayoutItem(credit_text) #add layout item inside the function
return credit_text
generateLayoutItemCredit(layout, 1)
generateLayoutItemCredit(layout, 2)
EDIT 2 Following the same logic as the answer provided, here is how a) I repeated a label only from the 2nd page and b) I repeated a label with the text changing for each page
a) Header repeated from the 2nd page
def generateLayoutItemHeader(layoutn, pagenb):
header_text = QgsLayoutItemLabel(layoutn)
header_text.setText("Liste des contraintes - " + prop)
header_text.setFont(QFont("Ms Shell Dlg 2", 11))
header_text.setHAlign(Qt.AlignLeft)
header_text.setMinimumSize(QgsLayoutSize(120, 8, QgsUnitTypes.LayoutMillimeters))
header_text.attemptMove(QgsLayoutPoint(9, 3),page=pagenb)
return header_text
# additionnal number of pages
pages_sup=4
for i in range(0, pages_sup):
page = QgsLayoutItemPage(layout)
page.setPageSize('Letter', QgsLayoutItemPage.Portrait)
layout.pageCollection().addPage(page)
for i in range(1, pages_sup + 1):
header = generateLayoutItemHeader(layout, i)
layout.addLayoutItem(header)
b) Updating the page number
def generateLayoutItemPage(layoutn, pagenb, label):
page_text = QgsLayoutItemLabel(layout)
page_text.setFont(QFont("Ms Shell Dlg 2", 10))
page_text.attemptMove(QgsLayoutPoint(193, 3.590),page=pagenb)
page_text.setHAlign(Qt.AlignRight)
page_text.setMinimumSize(QgsLayoutSize(15, 8.215, QgsUnitTypes.LayoutMillimeters))
page_text.setText(label)
return page_text
currPage = 1
for j in range(1, pages_sup + 1):
labelp = 'page' + str(currPage) + '/' + str(pages_sup + 1)
pagel = generateLayoutItemPage(layout, j-1, labelp)
currPage+=1
layout.addLayoutItem(pagel)