Page 5 sur 18
Edit layers
Add a point in a shape
It is like projecting points. You have another full example about how to do it in a loop and from an API here (search Autres exemples d'APIs).
Just below a simple example.
(Attention to &)
myPath = r'C:\\Users\\georg\\Downloads\\' project = QgsProject.instance() project.removeAllMapLayers() project.clear() iface.mapCanvas().refresh() myLayer = QgsVectorLayer(myPath + 'peaks_selection/peaks_selection.shp', 'Peaks', 'ogr') project.addMapLayer(myLayer) crs = QgsCoordinateReferenceSystem.fromEpsgId(4326) project.setCrs(crs) project.setEllipsoid('EPSG:4326') # Add a point myPoints = project.mapLayersByName('Peaks')[0] aPoint = QgsVectorLayer(myPoints.dataProvider().dataSourceUri(), '', 'ogr') caps = aPoint.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: feat = QgsFeature(aPoint.fields()) feat.setAttributes([1, 'Fake peak']) feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6.0631, 44.8844))) res, outFeats = aPoint.dataProvider().addFeatures([feat])
Pack a shape/commit your edits
When you write a lot of features in a shape, or after deletion, it is good to pack your shape (to avoid some blank lines in the .dbf file for example). It is a kind of commit.
For example, if after some deletions, you remove your layer from QGIS, then you re-open it, and then then your do new changes, if you check the attributes table you will see some empty blank lines.
We will use GDAL/OGR and some SQL to pack our layer, with a id field named here OSM_ID:
import subprocess myOriginalShape = myPath + 'peaks_selection/peaks_selection.shp' myTempShape = myPath + 'peaks_selection/temp_peaks_selection.shp' # Pack with GDAL/OGR filtering with SQL cmd = [ 'ogr2ogr', '-f', 'ESRI Shapefile', myTempShape, myOriginalShape, '-sql', 'SELECT * FROM peaks_selection WHERE OSM_ID IS NOT NULL' ] subprocess.run(cmd)
And here a full example to edit, pack, rename and see the last edits:
(Attention to &)
import subprocess import time myPath = r'C:\\Users\\georg\\Downloads\\' myOriginalShape = myPath + 'peaks_selection/peaks_selection.shp' myTempShape = myPath + 'peaks_selection/temp_peaks_selection.shp' project = QgsProject.instance() project.removeAllMapLayers() project.clear() iface.mapCanvas().refresh() myLayer = QgsVectorLayer(myOriginalShape, 'Peaks', 'ogr') myLayer.setProviderEncoding('ISO-8859-1') project.addMapLayer(myLayer) crs = QgsCoordinateReferenceSystem.fromEpsgId(4326) project.setCrs(crs) project.setEllipsoid('EPSG:4326') # Add a point def addPoint(): myPoints = project.mapLayersByName('Peaks')[0] aPoint = QgsVectorLayer(myPoints.dataProvider().dataSourceUri(), '', 'ogr') caps = aPoint.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: feat = QgsFeature(aPoint.fields()) feat.setAttributes([1, 'Fake peak']) feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6.0631, 44.8844))) res, outFeats = aPoint.dataProvider().addFeatures([feat]) QTimer.singleShot(1000, addPoint) # Then pack/commit def myPacking(): cmd = [ 'ogr2ogr', '-f', 'ESRI Shapefile', myTempShape, myOriginalShape, '-sql', 'SELECT * FROM peaks_selection WHERE OSM_ID IS NOT NULL' ] subprocess.run(cmd) QTimer.singleShot(200, myPacking) # Clear project project = QgsProject.instance() project.removeAllMapLayers() project.clear() iface.mapCanvas().refresh() # Then delete/rename def myDeleteRename(): for ext in ['.shp', '.shx', '.dbf', '.prj']: old_file = myOriginalShape.replace('.shp', ext) new_file = myTempShape.replace('.shp', ext) if os.path.exists(old_file): os.remove(old_file) os.rename(new_file, old_file) QTimer.singleShot(200, myDeleteRename) # Clear project project = QgsProject.instance() project.removeAllMapLayers() project.clear() iface.mapCanvas().refresh() # Then reopen the layer updated def myReopen(): myLayer = QgsVectorLayer(myOriginalShape, 'Peaks', 'ogr') myLayer.setProviderEncoding('ISO-8859-1') project.addMapLayer(myLayer) crs = QgsCoordinateReferenceSystem.fromEpsgId(4326) project.setCrs(crs) project.setEllipsoid('EPSG:4326') QTimer.singleShot(200, myReopen) # Final refresh to see the last edits time.sleep(1) QgsProject.instance().reloadAllLayers()
Add fields in a layer
myLayer = QgsVectorLayer(r'C:/Users/Georges/Downloads/my layer/new_file.tab', 'new file', 'ogr') myLayerInstance = QgsProject.instance().mapLayersByName('new file')[0] myLayerInstance.startEditing() myLayerInstance.dataProvider().addAttributes([QgsField("newfield1", QVariant.String), QgsField("newfield2", QVariant.String)]) myLayerInstance.updateFields() myLayerInstance.commitChanges()
Delete a field
myLayer.dataProvider().deleteAttributes(['My field'])
Fill a field
myLayerInstance = QgsProject.instance().mapLayersByName('new file')[0] with edit(myLayerInstance): for feature in myLayerInstance.getFeatures(): # A VALUE feature['newfield1'] = 'Abc Xyz' # CONCATENATE OTHER FIELD feature['newfield2'] = feature['name'] + '-' + feature['id'] myLayerInstance.updateFeature(feature)
Create a shape
layer = QgsProject.instance().mapLayersByName('peaks')[0] layer.selectByExpression('"NAME" LIKE \'Aiguille%\'') root = r'C:/Users/georg/Downloads/Aiguilles/' if not os.path.exists(root): os.makedirs(root) file = str(root)+'Aiguilles.shp' writer = QgsVectorFileWriter.writeAsVectorFormat(layer, file, 'utf-8', driverName='ESRI Shapefile', onlySelected=True)