I am working with an existing raster attribute table. I wonder how can I add a new field to it and then loop through the existing records to populate this new field? Of course I have done this many times for a feature class and a database table but I do not know how to do it with a raster table. I work with VBA. Any code please? Thanks.
2 Answers
VBA sample code is here:
Public Sub CalculateArea(raster As IRaster, areaField As String) Dim bandCol As IRasterBandCollection Dim band As IRasterBand Set bandCol = raster Set band = bandCol.Item(0) Dim hasTable As Boolean band.hasTable hasTable If (hasTable = False) Then Exit Sub End If If (AddVatField(raster, areaField, esriFieldTypeDouble, 38) = True) Then ' calculate cell size Dim rstProps As IRasterProps Set rstProps = raster Dim pnt As IPnt Set pnt = rstProps.MeanCellSize Dim cellSize As Double cellSize = (pnt.X + pnt.Y) / 2# ' get fields index Dim attTable As ITable Set attTable = band.AttributeTable Dim idxArea As Long, idxCount As Long idxArea = attTable.FindField(areaField) idxCount = attTable.FindField("COUNT") ' using update cursor Dim gridTableOp As IGridTableOp Set gridTableOp = New gridTableOp Dim cellCount As Long, cellArea As Double Dim updateCursor As ICursor, updateRow As IRow Set updateCursor = gridTableOp.Update(band.RasterDataset, Nothing, False) Set updateRow = updateCursor.NextRow() Do Until updateRow Is Nothing cellCount = CLng(updateRow.Value(idxCount)) cellArea = cellCount * (cellSize * cellSize) updateRow.Value(idxArea) = cellArea updateCursor.updateRow updateRow Set updateRow = updateCursor.NextRow() Loop End If End Sub
Private Function AddVatField(raster As IRaster, fieldName As String, fieldType As esriFieldType, fieldLength As Long) As Boolean Dim bandCol As IRasterBandCollection Dim band As IRasterBand Set bandCol = raster Set band = bandCol.Item(0) Dim hasTable As Boolean band.hasTable hasTable If (hasTable = True) Then Dim attTable As ITable Set attTable = band.AttributeTable If (attTable.FindField(fieldName) -1) Then AddVatField = True Exit Function End If Dim newField As IField Dim fieldEdit As IFieldEdit Set newField = New Field Set fieldEdit = newField With fieldEdit .Name = fieldName .Type = fieldType .Editable = True .IsNullable = True .Length = fieldLength End With Dim gridTableOp As IGridTableOp Set gridTableOp = New gridTableOp gridTableOp.AddField band.RasterDataset, newField AddVatField = True Exit Function End If AddVatField = False End Function
-
@ MapPlus: Although I did it with another way, many thanks for the answer.– DemetrisCommented Nov 23, 2011 at 13:48
you could use IGridTableOp interface. reference: http://www.onspatial.com/2011/11/arcobjectsgrid-vatvalue-attribute-table.html
bool AddVatField(IRaster raster, string fieldName, esriFieldType fieldType, int fieldLength) { IRasterBandCollection bandCol = (IRasterBandCollection)raster; IRasterBand band = bandCol.Item(0); bool hasTable = false; band.HasTable(out hasTable); if (hasTable) { ITable attTable = band.AttributeTable; if (attTable.FindField(fieldName) != -1) { return true; } IField newField = new FieldClass(); IFieldEdit fieldEdit = (IFieldEdit)newField; fieldEdit.Name_2 = fieldName; fieldEdit.Type_2 = fieldType; fieldEdit.Editable_2 = true; fieldEdit.IsNullable_2 = true; fieldEdit.Length_2 = fieldLength; IGridTableOp gridTableOp = new GridTableOpClass(); gridTableOp.AddField(band.RasterDataset, newField); System.Runtime.InteropServices.Marshal.ReleaseComObject(gridTableOp); return true; } return false; }
void CalculateArea(IRaster raster, string areaField) { IRasterBandCollection bandCol = (IRasterBandCollection)raster; IRasterBand band = bandCol.Item(0); bool hasTable = false; band.HasTable(out hasTable); if (!hasTable) return; // Add Field if (AddVatField(raster, areaField, esriFieldType.esriFieldTypeDouble, 38)) { // calculate cell size IRasterProps rstProps = (IRasterProps)raster; IPnt pnt = rstProps.MeanCellSize(); double cellSize = (pnt.X + pnt.Y) / 2.0; // get fields index ITable attTable = band.AttributeTable; int idxArea = attTable.FindField(areaField); int idxCount = attTable.FindField("COUNT"); // using update cursor IGridTableOp gridTableOp = new GridTableOpClass(); ICursor updateCursor = gridTableOp.Update(band.RasterDataset, null, false); IRow updateRow = updateCursor.NextRow(); while (updateRow != null) { int cellCount = Convert.ToInt32(updateRow.get_Value(idxCount)); double cellArea = cellCount * (cellSize * cellSize); updateRow.set_Value(idxArea, cellArea); updateCursor.UpdateRow(updateRow); updateRow = updateCursor.NextRow(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(gridTableOp); System.Runtime.InteropServices.Marshal.ReleaseComObject(updateCursor); } }
-
1Welcome to gis.stackexchange @MapPlus. We are trying to collect the best answers and save them for future users. When posting an answer, please include all necessary details in the answer text instead of just linking them. Links can break easily and then the answer would be worthless. Commented Nov 20, 2011 at 20:11
-
1I suppose that the above code is in Python. Do you have any code in VBA?– DemetrisCommented Nov 21, 2011 at 6:51
-