5

I am trying to update an existing field on a shapefile using data from another shapefile. Basically, each attribute table contains an ID field that I want to use to update a field called "address".

So far, I have tried to use the processing alg "qgis:joinattributestable" and QgsVectorJoinInfo(). Both of these solutions however seem to create temporary join fields that are of no use to me.

Is this something that is possible with QGIS?

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
JamieTasker
  • 429
  • 4
  • 10

1 Answers1

5

You could use something like the following which:

  1. Joins your shapefiles using QgsVectorJoinInfo()
  2. Updates the address field
  3. Removes the join

# Change names to match your layer names
layer_1_name = str("layer_1")
layer_2_name = str("layer_2")

for layer in QgsMapLayerRegistry.instance().mapLayers().values():
    if layer.name() == layer_1_name:
        qgis.utils.iface.setActiveLayer(layer)
        layer_1 = qgis.utils.iface.activeLayer()    
    if layer.name() == layer_2_name:
        qgis.utils.iface.setActiveLayer(layer)
        layer_2 = qgis.utils.iface.activeLayer()

# Set up join parameters            
layer_1_Field='ID'
layer_2_Field='ID'
joinObject = QgsVectorJoinInfo()
joinObject.joinLayerId = layer_2.id()
joinObject.joinFieldName = layer_2_Field
joinObject.targetFieldName = layer_1_Field
joinObject.memoryCache = True
layer_1.addJoin(joinObject)

# Define original field and joined field to update
original_field = layer_1.fieldNameIndex('address') 
joined_field = layer_1.fieldNameIndex(layer_2_name + '_address')

layer_1.startEditing()
for feat in layer_1.getFeatures():
    layer_1.changeAttributeValue(feat.id(), original_field, feat.attributes()[joined_field])

# Save the changes
layer_1.commitChanges()

# Remove join 
layer_1.removeJoin(layer_2.id())

The code was adapted from an earlier answer.

Joseph
  • 75,746
  • 7
  • 171
  • 282
  • Thanks a bunch for that, worked without a hitch. Is there a way to get it to work using layers opened with 'QgsVectorLayer()'?

    I've tried to assign my layers as follows but the join does not seem to work: ' Layer 1 = QgsVectorLayer("path", "name". "ogr) Layer 2 = QgsVectorLayer("path","name,"ogr")

    Thanks

    – JamieTasker Jan 04 '17 at 15:37
  • @JamieTasker - Most welcome! You defined the layers but did you load them using QgsMapLayerRegistry.instance().addMapLayers([layer1, layer2])? – Joseph Jan 04 '17 at 15:41
  • 1
    Excellent, that's exactly what I was after!

    Thanks ever so much for your help!

    – JamieTasker Jan 04 '17 at 15:54
  • @JamieTasker - Glad it was helpful ;) – Joseph Jan 04 '17 at 15:56
  • For anyone reading this using QGIS 3.x : QgsMapLayerRegistry is gone from QGIS 3.x; it's functionality has moved to QgsProject.

    So you would use: for layer in QgsProject.instance().mapLayers().values(): instead of for layer in QgsMapLayerRegistry.instance().mapLayers().values():

    – grego Oct 27 '21 at 23:25