Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I've been working on this for a little while now, and can not seem to get this thing working.

I've managed to export a geodatabase feature class and shapefile to a shapefile, but what I'm struggling with right now is writing an in-memory feature layer (one that is created based on a selection of features) to a shapefile/geodatabase.

If anyone can help me with a code snippet (doesn't matter the language), or some links to some dark corner of the ESRI docs, I would be much obliged.

UPDATE

I used the following code to create the IFeatureLayer:

IFeatureSelection featureSelection = (IFeatureSelection)layer;
if (featureSelection.SelectionSet.Count > 0)
{
    IFeatureLayerDefinition2 featDef = (IFeatureLayerDefinition2)featureSelection;
    IFeatureLayer fLayer = featDef.CreateSelectionLayer(
        String.Format( CultureInfo.InvariantCulture,
            "{0}_Selection", layer.Name ),
        true, "", "" );

    featureSelection.Clear();

    if (fLayer != null)
    {
        _hook.FocusMap.AddLayer( fLayer );
        _hook.ActiveView.Refresh();
    }
}

This creates and adds a new layer to the TOC.

What I'm missing now is taking that Feature selection and saving this to a Shapefile (for now).

The code example I've been working with is from esri code snippets but I'm getting stuck on the following:

IDataset sourceDataset = (IDataset)_layer;

IWorkspace sourceWorkspace;
IPropertySet propertySet = sourceDataset.Workspace.ConnectionProperties;
sourceWorkspace = sourceDataset.Workspace.WorkspaceFactory.Open( propertySet, 0 );

if (sourceDataset.FullName != null)
{
    // HERE - Invalid Cast Exception.
    IWorkspaceName sourceWorkspaceName = (IWorkspaceName)sourceDataset.FullName;
}

The full exception is here:

Unable to cast COM object of type 'System.__ComObject' to interface type 'ESRI.ArcGIS.Geodatabase.IWorkspaceName'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{FADD975C-E36F-11D1-AA81-00C04FA33A15}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

I guess the exception is thrown because the FullName property though is not empty is not compatible because of the type of COM object it is wrapping.

Any thoughs?

Thanks for your help

share|improve this question
1  
Are you looking to avoid using the geoprocessor? You could use FeatureClassToFeatureClass and it should be able to handle the in-memory feature layer. –  blah238 May 23 '12 at 21:26
2  
Try code from here. –  Kirk Kuykendall May 23 '12 at 21:31
    
@blah238 I am trying to avoid the geoprocessor, though the reasons are for doing so are pride and spite. –  OptimizePrime May 23 '12 at 22:14
    
@KirkKuykendall I might be able to make that work, I'll give it a go tomorrow morning and update the question with the code. Thanks –  OptimizePrime May 23 '12 at 22:15
2  
To get the workspacename of a featurelayer's data source, I would do this: cast IFeatureLayer.Featureclass as IDataset, then cast the dataset.FullName as IDatasetName, then get IDatasetName.WorkspaceName. –  Kirk Kuykendall May 24 '12 at 17:43

1 Answer 1

up vote 2 down vote accepted

Ok Folk, This took some time to get worked out, mainly because it is a part of the ArcObjects API that I haven't worked with often, or frustration clouding pragmatic thought, or an extremely large (misleading) API. I would like to thank Kirk Kuykendall for some additional resources and ideas on this and other sites.

Here is the solution. It has been lightly tested but its there for all.

public static bool ExportLayerToShapefile(
        string shapePath, 
        string shapeName, 
        ILayer source,
        out IEnumFieldError fieldErrors,
        out IEnumInvalidObject invalidObjects)
{
    IGeoFeatureLayer sourceFeatLayer = (IGeoFeatureLayer)source;
    IFeatureLayer sfeatlayer = (IFeatureLayer)sourceFeatLayer;
    IFeatureClass sfeatClass = sfeatlayer.FeatureClass;
    IDataset sdataset = (IDataset)sfeatClass;
    IDatasetName sdatasetName = (IDatasetName)sdataset.FullName;

    ISelectionSet sSelectionSet = (
        (ITable)source).Select( new QueryFilter(),
        esriSelectionType.esriSelectionTypeHybrid,
        esriSelectionOption.esriSelectionOptionNormal,
        sdataset.Workspace );

    IWorkspaceFactory factory;
    factory = new ShapefileWorkspaceFactory();
    IWorkspace targetWorkspace = factory.OpenFromFile( shapePath, 0 );
    IDataset targetDataset = (IDataset)targetWorkspace;

    IName targetWorkspaceName = targetDataset.FullName;
    IWorkspaceName tWorkspaceName = (IWorkspaceName)targetWorkspaceName;

    IFeatureClassName tFeatClassname = (IFeatureClassName)new FeatureClassName();
    IDatasetName tDatasetName = (IDatasetName)tFeatClassname;
    tDatasetName.Name = shapeName;
    tDatasetName.WorkspaceName = tWorkspaceName;

    IFieldChecker fieldChecker = new FieldChecker();
    IFields sFields = sfeatClass.Fields;
    IFields tFields = null;

    fieldChecker.InputWorkspace = sdataset.Workspace;
    fieldChecker.ValidateWorkspace = targetWorkspace;

    fieldChecker.Validate( sFields, out fieldErrors, out tFields );
    if (fieldErrors != null)
    {
        IFieldError fieldError = null;
        while((fieldError = fieldErrors.Next()) != null)
        {
            Console.WriteLine(fieldError.FieldError + " : " + fieldError.FieldIndex);
        }
        Console.WriteLine( "[ExportDataViewModel.cs] Errors encountered during field validation" );
    }

    string shapefieldName = sfeatClass.ShapeFieldName;
    int shapeFieldIndex = sfeatClass.FindField( shapefieldName );
    IField shapefield = sFields.get_Field( shapeFieldIndex );
    IGeometryDef geomDef = shapefield.GeometryDef;
    IClone geomDefClone = (IClone)geomDef;
    IClone targetGeomDefClone = geomDefClone.Clone();
    IGeometryDef tGeomDef = (IGeometryDef)targetGeomDefClone;

    IFeatureDataConverter2 featDataConverter = (IFeatureDataConverter2)new FeatureDataConverter();
    invalidObjects = featDataConverter.ConvertFeatureClass(
        sdatasetName,
        null,
        sSelectionSet,
        null,
        tFeatClassname,
        tGeomDef,
        tFields,
        "",
        1000, 0 );

    string fullpath = System.IO.Path.Combine( shapePath, shapeName );
    return System.IO.File.Exists( fullpath );
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.