QGis(四)shp向量圖層新增新欄位
阿新 • • 發佈:2019-02-09
新增一個新的欄位到shp檔案中,並且從Excel裡匯入資料到該欄位。原shp檔案裡的欄位ID應該與Excel裡的欄位ID一一對應才能正確的匯入。下圖分別是shp的欄位和Excel的欄位
將class欄位新增到shp中去:
(1)從Excel中讀取資料(為了讀取方便,存為.csv或者txt檔案)
返回的readlist是所有行的資料,下面要根據Id來將每一行後面的class欄位插入shp檔案QStringList readFromCSV(QString mfilename) { QStringList readlist; if (mfilename !="") { QFileInfo csvFI(mfilename); QString ext = csvFI.suffix(); if ( ext == "csv" || ext == "txt") { QFile *importFile = new QFile(mfilename); if ( !importFile->open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::information(NULL, "error", "Cannot open import file !", QMessageBox::Yes | QMessageBox::No); return readlist; } readlist.clear(); QTextStream readIn(importFile);//讀入檔案 while ( !readIn.atEnd()) //讀取每一行 { readlist.push_back(readIn.readLine()); } importFile->close(); } } return readlist; }
(2)插入class欄位及值到shp
首先要建立新欄位名,然後再插入值
generateIdIndex()是為了得到Id對應的FeatureID,因為屬性欄位Id和要素的FeatureID是不一致的。bool ImportLandInfo::insertInfo(QString mShpfile) { QgsVectorLayer * newLayer; newLayer = new QgsVectorLayer(mShpfile, fileinfo.baseName(), "ogr"); if ( newLayer != NULL) { qDebug("newLayer is valid"); } else { return false; } QStringList readlist = readFromCSV(“F:\\data.csv”);//Excel檔案 //建立新欄位 QList<QgsField> newFieldList; QStringList fields = readlist.at(0).split(",", QString::SkipEmptyParts); //得到Excel的欄位名 for (int i = 0; i < fields.count(); ++i) { QString fieldname; if ( fields.at(i) == "Id" ) { continue; } else { fieldname = fields.at(i); } QgsField shpField( fieldname, QVariant::String); newFieldList.push_back( shpField ); } QgsVectorDataProvider* vectorProvider = newLayer->dataProvider(); vectorProvider->addAttributes( newFieldList ); //新欄位中插入值 QMap<int, int> idmap = generateIdIndex(); //由原shp圖層得到QMap<ID, featureId> int fieldIndex = -1; //每個待插入欄位的索引號 int IdIndex = -1; // ID欄位的索引號 for (int j = 0; j < readlist.count(); ++j) { QString filed; QgsChangedAttributesMap changeMap; QgsAttributeMap changeAttributeMap; QStringList field = readlist.at( j ).split(",", QString::SkipEmptyParts); for ( int k = 0; k < field.count(); ++k) { if ( field.at(k) == "Id" ) { IdIndex = k; continue; } if ( j == 0) //第一行時是計算欄位在屬性表中的index { fieldIndex = vectorProvider->fieldNameIndex( field.at(k) ); break; } else //不是第一行則插入 { changeAttributeMap.insert( fieldIndex + k - 1, QVariant( field.at(k) ) ); } } if ( j == 0) { continue; } int ID = field.at(IdIndex).toInt(); QMap<int, int>::iterator i = idmap.find( ID); //找到指定ID對應的要素id(featureId) int featureId = i.value(); changeMap.insert( featureId, changeAttributeMap ); vectorProvider->changeAttributeValues( changeMap ); } delete vectorProvider; return true; }
QMap<int, int> ImportLandInfo::generateIdIndex() { QMap<int, int> idMap; QgsVectorLayer * orignalLayer; QFileInfo fileinfo(moriginalShpfile); orignalLayer = new QgsVectorLayer(moriginalShpfile, fileinfo.baseName(), "ogr"); if ( orignalLayer != NULL) { qDebug("newLayer is valid"); } QgsVectorDataProvider* vectorProvider = orignalLayer->dataProvider(); QgsFeature feature; int idIndex = vectorProvider->fieldNameIndex( "Id" ); int count = orignalLayer->featureCount(); for ( int i = 0; i < count; ++i) { orignalLayer->featureAtId( i, feature); const QgsAttributeMap &attributes = feature.attributeMap(); int id = -1; id = attributes[ idIndex].toInt(); idMap.insert( id, feature.id()); } return idMap; }
這樣欄位class的值就新增到shp中去了。結果如圖: