QGIS – How to Only Label with Visible Features in Print Composer

labelingprint-composerpyqgisqgisqgsexpression

I am curious if there is a way to get all features from a certain layer that are visible in the current map. I am aware that this could be done using the checkbox in the attribute table object but I want to use the label object instead of the attribute table.

Basic Example:
I want to print out plans of individual parcels of land in different municipalities. Instead of having to edit the plan header manually every time (parcel number, municipality,…), it should automatically display the name of the municipality, depending on the current 'field of view' of the map window of the print composer. The individual parcel in focus on one map always lies within a municipality. Two layers exist for this purpose: Parcels (with parcel number; Polygon) Municipalities (with municipality name to be displayed in the label; Polygon)

TLDR: I want a certain attribute value to appear in a label but only for those features visible within the current map extend.

QGIS 3.22.15

Best Answer

You want to go with something like the following:

[%aggregate(layer:= 'Municipalities', aggregate:='concatenate', expression:="namefield", filter:=intersects($geometry, transform(map_get(item_variables('map item'), 'map_extent_center'), @project_crs, 'EPSG-code of data'))%]

aggregate() grabs you some data, in this case from a layer called 'Municipalities' - replace this with whatever your layer is named. Beware, you'd have to make sure that the layer of interest is always named the same in all projects you want to use this map template for, otherwise it wont work.

The expression will 'concatenante' the info it grabs, and it will grab what fits the following expression, in this case the content of the "namefield", aka the field containing your municipality names. Please replace accordingly.

Since we don't want to grab everything, we need to add a filter, in this case intersects(), which checks which $geometry of the layer we want to grab data from, overlays with the center of our map extent (map_get(item_variables('map item'), 'map_extent_center')).

In order for the intersection to work flawlessly for all projects (if you have projects using different CRS), you should add the transform() part to the expression, which in this case converts the coordinates of the map item center from the project CRS to the CRS of your layer you want to grab data from.

The [% and %] are added by the text field item when you add an expression via the GUI.

If you want to grab info from several layers, you need to concatenate that info, e.g. using ||.