Summarized:
- You can create a virtual_layer that combines every feature contained by a park. Or - when dealing with a lot of layers - it is preferrable to make use of a database, for example SpatiaLite where you create a view.
- Then you add a relation park-virtual_layer/view.
- In the print composer you can add a table and select as source: 'relation children'.
Only the 'linked' features will show up in the table.
In detail:
Suppose you have a polygon layer (parks), line layer and points layer.
Create a SpatiaLite database (How to save multiple layers from QGIS to a Spatialite db?) and load all your layers into it.
Make a view with the following code:
create or replace view parks_contains as
select a.id, a.in_park
from
(
select parklayer.id, layer1.attributeA as in_park
from parklayer
join layer1 on st_intersects(parklayer.geometry, layer1.geometry)
union
select parklayer.id, layer2.attributeB as in_park
from parklayer
join layer2 on st_contains(parklayer.geometry, layer2.geometry)
union
select parklayer.id, layer3.attributeC as in_park
from parklayer
join layer3 on st_contains(parklayer.geometry, layer3.geometry)
union
etc...
) as a
where in_park is not null
You can union as many layers as you want. Just be aware to name all outputfields the same. How it works:
In the main codeblock you make a join between the parkslayer and each other layer. In the join you define how the other features will be 'linked' to each parkattribute, using a command like st_within() or st_intersects() (for more detail look at http://www.gaia-gis.it/spatialite-2.4.0-4/spatialite-sql-2.4-4.html#p12)
For each feature that lies in a park there will be a row in the resulting table :
Load that new table into QGIS and add a relation project > project properties
In the printcomposer you can add a map, set it to be controlled by atlas. Add a table and choose 'Relation children' as Source.
I have found the solution.
Atlas generation TAB
Layers B, C and D
They need to be rule based (style) and need to contain the following rules (in Style):
"Feature ID" = attribute( $atlasfeature , 'Feature ID') - for visible records
"Feature ID" <> attribute( $atlasfeature , 'Feature ID') - for all records we don't want to see ( I styled it as transparent)
.....................................................................................................................................................................
Settings for the layer A, which works with ATLAS:
Configuration section:
Coverage layer: A
Hidden coverage layer: - TICKED
Filter with - NOT TICKED - this is important as the automation won't work otherwise
Output section:
Output filename expression: attribute($currentfeature, 'Feature ID') - this is not mandatory but will produce single files with the name = to the values from Feature ID column
Single file export when possible - NOT TICKED - this can be ticked in order to create a booklet, but not in my case
Sort by: Feature ID
.....................................................................................................................................................................
Item properties TAB
Below are my settings for the Map in the Item properties panel
.....................................................................................................................................................................
Thanks Jesse again. I hope this will help the others as well at some point.
Regards,
Maciek Drozda
Best Answer
Manual version
With this option, you manually add a row for each attribute, reusing the same expression. See below how to automatize this for all fieldnames at once.
Create a condition for each attribute manually
You should concatenate a row for each attribute, connecting them using pipes:
||
. Better use an if-condition:if >0
, then show the value, otherwise simply use an empty sting''
. The expression looks like this:I added the text field you asked for above using this exptession and the attribute table below so you can compare the values. The first attribute (
grassland
) has a value of0
and is thus not added to the text field:Automatize the expression
If you have dozens of attributes, it can get annoying to copy the expression and each time replace the name of the attribute three times per line. You can automatize this using this expression (to define the order in which the attributes appear, see below):
Explanation
With
map_akeys( attributes( ) )
(line 5) you get an array with all attribute-names. You can filter out some names witharray_filter
: in line 6, define which attribute names to skip (here:'id'
and'id2'
).Then use
array_foreach
to iterate: for each of the remaining attribute name, perform the following function.Define the pattern you used in the version above to create your output as a string (line 10). Instead of the attribute name, insert a generic name (here:
an
for attribute name), then replace that with the current element (each of the attribute names). Up to now, you have created a string that returns for each element of the array what you created before manually. Useeval
to evaluate the string - the string should be converted to a working function. Output is an array of strings. Convert the array to sting (line 2) and delete all the commas (line 1 and 17/18 respectively):Output with the automatized expression: as you see, all 0-values are skipped, as well as the 2 attributes we defined to skip (
id
andid2
). Only issue is that attributes are sorted in alphbetic order - for other sorting options, see in what follows:Change sort order
Ordering in the same sequence as fields appear in attribute table
See this answer to order the attributes not in alphabetic order as is the default using the function
attributes( )
, but in the same order as they appear in the attribute tableCustom defined ordering
To sort the entries in any arbitray order, you can use
array_prioritize( )
(available since QGIS 3.20) to define manually a custom order.Ordering depending on the attribute values
To order the results depending on their values (from highest to lowest value), modify the expression this way:
The result, showin the attribute table (bottom) and a text field with only those attribute values
>0
from the current atlas feature, ordered from highest to smallest attribute value: