PyQGIS – Exporting Map to PDF Without Specific Layout

exportpdfpyqgis

I want to export a map to PDF with PyQGIS. I do not need to add a legend or any additional information; I just want to export the extent visible to a PDF.

If I do this manually, I just go to Project –> Import/Export –> Export Map to PDF.

All programmatic explanations involve creating a special layout and exporting from there. There's probably a very simple way to do this, but I haven't found it yet.

Code below – the export piece (borrowed from the internet and slightly modified) is the only part that doesn't work, because I honestly don't know what to put for "layoutByName()." Is there a default layout? This probably has more to do with being new to QGIS than coding, but I'm stuck.

import qgis.utils
from qgis.utils import iface

#select features
temporaryCompaction = QgsProject.instance().mapLayersByName('Temporarycompaction')[0]
iface.setActiveLayer(temporaryCompaction)

iface.mapCanvas().setSelectionColor(QColor('red'))
expression = "to_date(Date) = to_date('2021-09-08', 'yyyy-MM-dd')"
temporaryCompaction.selectByExpression(expression)

#create layer from selected features and import to Layers
fn = r'U:\skelley\public\QGISstuff\PacTrustMergin-2test/newLayer.gpkg'
writer = QgsVectorFileWriter.writeAsVectorFormat(temporaryCompaction, fn, 'utf-8', driverName='GPKG', onlySelected=True)
selected_layer = iface.addVectorLayer(fn, '', 'ogr')
del(writer)

#copy styles from parent layer
copyLayer = QgsProject.instance().mapLayersByName('Temporarycompaction')[0]
iface.setActiveLayer(copyLayer)
iface.actionCopyLayerStyle().trigger()

#paste styles to new layer
pasteLayer = QgsProject.instance().mapLayersByName('newLayer')[0]
iface.setActiveLayer(pasteLayer)
iface.actionPasteLayerStyle().trigger()

#turn off Temporarycompaction layer
toggleOff = QgsProject.instance().mapLayersByName('Temporarycompaction')[0]
iface.setActiveLayer(toggleOff)
QgsProject.instance().layerTreeRoot().findLayer(toggleOff.id()).setItemVisibilityChecked(False)

#export to pdf
dailyReport = r'U:\skelley\public\QGISstuff\PacTrustMergin-2test\tempDailyReports\dailyReport1.pdf'
projectInstance = QgsProject.instance()
layoutmanager = projectInstance.layoutManager()
layout_item = layoutmanager.layoutByName(????)  
export = QgsLayoutExporter(layout_item)
export.exportToPDF(dailyReport, QgsLayoutExporter.PDFExportSettings())

Best Answer

To export the visible map extent to pdf you don't necessarily need a layout at all. You can instead use the QgsMapRendererCustomPainterJob class. It allows to render the map canvas to a custom painter. The painter can draw its contents to any image file or in combination with QPrinter print to pdf.

QPrinter has various methods to configure pdf output parameters such as page size, resolution, page orientation, margins, etc.. Take a look at the linked documentation for QPrinter

from qgis.PyQt.QtPrintSupport import QPrinter

settings = iface.mapCanvas().mapSettings()

printer = QPrinter(QPrinter.HighResolution)
printer.setOutputFileName(r'C:\your\path\to\export.pdf')
printer.setOutputFormat(QPrinter.PdfFormat)

# some optional settings to modify pdf output 
# I used some arbitrary values here, change it to your needs
printer.setPageOrientation(QPageLayout.Orientation.Portrait)
outputSize = settings.outputSize()
printer.setPaperSize(QSizeF(outputSize * 25.4 / settings.outputDpi()), QPrinter.Millimeter)
printer.setPageMargins(0, 0, 0, 0, QPrinter.Millimeter)
printer.setResolution(settings.outputDpi())
settings.setFlag(Qgis.MapSettingsFlag.ForceVectorOutput, True)

dest_painter = QPainter(printer)
dest_painter.setRenderHint(QPainter.Antialiasing)

render_job = QgsMapRendererCustomPainterJob(settings, dest_painter)
render_job.renderSynchronously()

dest_painter.end()

Related Question