I am trying to develop an automatic layout export using PyQGIS. I have several layers with objects and a separate layer to create an atlas of 4 elements. enter image description here

I also prepared a layout in which there is a map and 3 blocks with legends containing different layers. enter image description here

Each legend block, with the exception of the upper one, has X and Y redefined using the Expression Editor so that the legend block is located one under the other and "sticks" to the previous one. This works fine if you manually run the atlas preview and click the refresh page button. Legend blocks, depending on the number of elements, are located under each other and do not climb on top of each other. Here is example:

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def GetItemX(LayoutName, ItemName, feature, parent):
    layout_name = LayoutName
    item_name = ItemName
    manager = QgsProject.instance().layoutManager()
    layout = manager.layoutByName(layout_name)
    item = layout.itemById(item_name)
    item_position = item.positionWithUnits()
    item_x = item_position.x()
    return item_x

(Code for collecting Y and Heght is similar)

I want to automate this process using PyQGIS. I created a script that automatically creates an atlas and prescribed at the time of rendering the same page update using layout.refresh(). However, this does not work and as a result I get files where one legend fits on another, i.e. the page is not refreshed and there is no recalculation of X and Y by Expressions set.

My code below:

project = QgsProject.instance()
manager = project.layoutManager()
layout = manager.layoutByName('Atlas')
atlas = layout.atlas()

i = 0
while atlas.next():
    exporter = QgsLayoutExporter(layout)
    pdfpath = 'mypath' + str(i) + '.pdf'
    exporter.exportToPdf(pdfpath, exporter.PdfExportSettings())

That's what I get in the end:

enter image description here

1 Answer 1


Years ago, I wrote a layout exporter that turns selected layers on/off and prints to pdfs. To refresh the layout, I ran



exporter = QgsLayoutExporter(layout)

The layout.refresh() might solve your problems. I just re-read your code, and you are using the refresh(). But you use it before the QgsLayoutExporter(layout). Would it help if you move the refresh() to after the QgsLayoutExporter(layout)?

  • 2
    The OP is already using layout.refresh(). So, this doesn't answer the question. Commented Jan 25, 2023 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.