Select to view content in your preferred language

looping through shapefile attribute table - java

2459
16
Jump to solution
08-08-2012 12:58 PM
BrianVarela
Occasional Contributor
I am new to arcobjects and GIS in general so excuse my noobness.  I'm trying to create a console based application that eventually will raster some polygons then do some stats on the rasters but right now I just want to be able to list all the features?(a single attribute from a layer's attribute table) from a given layer/shapefile in an existing mxd.  Right now, I can initialize the arc engine, open an mxd, list all the layers within that mxd and open a shapefile from a layer within the mxd.

What I need help with is being able to loop through the attribute table for the shapefile I opened from the mxd.

Here is the code I have so far:


public class EngineTest {     @SuppressWarnings("deprecation")  public static void main(String[] args)     {         try         {             //Step 1: Initialize the Java Componet Object Model (COM) Interop.             EngineInitializer.initializeEngine();              //Step 2: Initialize a valid license.             new AoInitialize().initialize                 (esriLicenseProductCode.esriLicenseProductCodeEngine);              //Step 3 : Invoke ArcObjects.             MapDocument mapDocument = new MapDocument();              if (mapDocument.isPresent("D:\\Tellus_Sedimentary_Basin.mxd"))             {            mapDocument.open("D:\\Tellus_Sedimentary_Basin.mxd","");            mapDocument.setAuthor("Brian Varela");            IMap main_map = mapDocument.getMap(0);            IFeatureLayer layer = (IFeatureLayer) main_map.getLayer(0);            IFeatureClass classLayer = layer.getFeatureClass();            IDataLayer2 dataLayer = (IDataLayer2) layer;            IDatasetName name = (IDatasetName) dataLayer.getDataSourceName();            IWorkspaceName workspace = name.getWorkspaceName();            ListLayers((Map)mapDocument.getMap(0));            System.out.println("Layer "+layer.getName()+" located at "+workspace.getPathName()+" "+layer.getDisplayField());             }           }         catch (IOException ex)         {             System.out.println(ex.getMessage());             System.out.println("App failed.");         }         finally         {             try             {                 //Step 4: Release the license.                 new AoInitialize().shutdown();                 System.out.println("License released!");             }             catch (IOException ex)             {                 ex.printStackTrace();             }         }     } //End of method main.  public static void ListLayers(com.esri.arcgis.carto.Map map) {  try{   for(int i=0; i<map.getLayerCount(); i++)   {    System.out.println("Layer "+i+". "+map.getLayer(i).getName());   }  }catch(AutomationException ae)  {   ae.printStackTrace();  }catch(IOException e)  {   e.printStackTrace();  } }  } //End of class
0 Kudos
1 Solution

Accepted Solutions
BrianVarela
Occasional Contributor
I think I may have figured it out!  After looking up the last error I found a link to this post:
http://forums.esri.com/Thread.asp?c=159&f=1706&t=237300

And it turns out that my license never initialized. Once I fixed the license issue the program ran without any errors.

View solution in original post

0 Kudos
16 Replies
LeoDonahue
Deactivated User
Sorry for the short example.  You can probably figure out the missing parts.

    public void saveLayerEdits(String whereClause){
        
        IQueryFilter queryFilter;
        
        try {
            
            FeatureLayer fl = "however you get your featurelayer"
            IFeatureClass featureClass = fl.getFeatureClass();
            
            // Restrict the number of features to be updated using a QueryFilter and Where clause.
            queryFilter = new QueryFilter();
            queryFilter.setWhereClause(fl.getOIDFieldName() + " = " + whereClause);
            
            // Use IFeatureClass.Update to populate IFeatureCursor.
            IFeatureCursor updateCursor = featureClass.IFeatureClass_update(queryFilter, false);
            
            int theFieldIndex = featureClass.findField("The name of the field you want to update");
            
            // Loop through the cursor and update the values
            IFeature feature = null;
            while ((feature = updateCursor.nextFeature()) != null){
                feature.setValue(theFieldIndex, "The value you want this field to have");
                updateCursor.updateFeature(feature);
            }
            
            // If the cursor is no longer needed, release it.
            Cleaner.release(updateCursor);
            
        } catch (AutomationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


To get values call the getValue method and don't use the updateCursor, use a search cursor if you just want to read data from your shapefile.

If just searching, then:

featureClass.IFeatureClass_update(queryFilter, false);  becomes - featureClass.search(queryFilter, false);

setValue(index, value); becomes - getValue(index);  and just remove the updateFeature line after that.
0 Kudos
BrianVarela
Occasional Contributor
Thank you for your help but I'm still getting a java.lang.NullPointerException.  I didn't need the query part of your method so I reworked it a little bit:

My main method:
.
.
.
IMap main_map = mapDocument.getMap(0);
IFeatureLayer layer = (IFeatureLayer) main_map.getLayer(0);
listAttributes((FeatureLayer) layer);


The list attributes method:
public static void listAttributes(com.esri.arcgis.carto.FeatureLayer fl)
{
 
 try {
  IFeatureClass featureClass = fl.getFeatureClass();
  IFeatureCursor updateCursor = featureClass.search(null, false);
  int theFieldIndex = featureClass.findField("BASIN_NAME");
  IFeature feature = null;
  while((feature = updateCursor.nextFeature()) != null)
  {
   System.out.println( (String)feature.getValue(theFieldIndex));
  }
  } catch (AutomationException e) {
  e.printStackTrace();
 } catch (IOException e) {
  e.printStackTrace();
 }
}
0 Kudos
LeoDonahue
Deactivated User
I'm still getting a java.lang.NullPointerException.

Bummer.

On what line?
0 Kudos
BrianVarela
Occasional Contributor
Bummer.

On what line?


I'm still getting the NullPointer on
IFeatureCursor updateCursor = featureClass.search(null, false);


the documentation says:
"If a null value is passed to the filter parameter, the feature cursor will return all of the features from the feature class."
0 Kudos
LeoDonahue
Deactivated User
That is probably because your fl is an IFeatureLayer, when you need a FeatureLayer.
0 Kudos
BrianVarela
Occasional Contributor
That is probably because your fl is an IFeatureLayer, when you need a FeatureLayer.


How can I get the FeatureLayer from an mxd?  I tried casting it from the IMap:
listAttributes((FeatureLayer) main_map.getLayer(0));

but that didn't work; I've been trying to use the API but there is just a lot there.
0 Kudos
LeoDonahue
Deactivated User
FeatureLayer fl = (FeatureLayer) getLayerByName("your layer name as it is spelled in the map document");

    /**
     * ESRI sample method to get feature class layer by name, instead of index.
     * @param layerName the layer name as <code>String</code>. 
     * @return layer as <code>FeatureLayer</code>.
     */
    public FeatureLayer getLayerByName(String layerName) {
        FeatureLayer layer = null;
        try {
            for (int i = 0; i < s_iMap.getLayerCount(); i++) {
                if (s_iMap.getLayer(i).getName().equalsIgnoreCase(layerName)) {
                    layer = (FeatureLayer) s_iMap.getLayer(i);
                    break;
                }
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Returns the featurelayer
        return layer;
    }


s_iMap is a reference to the current IMap of your map document.
0 Kudos
BrianVarela
Occasional Contributor
FeatureLayer fl = (FeatureLayer) getLayerByName("your layer name as it is spelled in the map document");

    /**
     * ESRI sample method to get feature class layer by name, instead of index.
     * @param layerName the layer name as <code>String</code>. 
     * @return layer as <code>FeatureLayer</code>.
     */
    public FeatureLayer getLayerByName(String layerName) {
        FeatureLayer layer = null;
        try {
            for (int i = 0; i < s_iMap.getLayerCount(); i++) {
                if (s_iMap.getLayer(i).getName().equalsIgnoreCase(layerName)) {
                    layer = (FeatureLayer) s_iMap.getLayer(i);
                    break;
                }
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Returns the featurelayer
        return layer;
    }


s_iMap is a reference to the current IMap of your map document.


Thanks again but I tried to use that method and I still get the NullPointer =(
I then looked at the code and it looks like ESRI's method was doing the same thing I tried before except they loop through the layers looking for the name that matches:

ESRI's code that creates the Feature layer:
layer = (FeatureLayer) s_iMap.getLayer(i)


looks like what I was trying:
listAttributes((FeatureLayer) main_map.getLayer(0))
0 Kudos
LeoDonahue
Deactivated User
Well, keep at it.  Sooner or later you will debug your code and realize that the method is not the problem.

In your code, what is to the left of this line?  IFeatureLayer or FeatureLayer?
listAttributes((FeatureLayer) main_map.getLayer(0))
0 Kudos