About converting simple data
This topic shows how to convert a feature class from one data source (such as a shapefile) to a feature class in another data source (such as a geodatabase feature class). The new feature class should not be created beforehand; the following code example does that (and fails if the feature class already exists).
The IFeatureDataConverter interface works with the ArcCatalog IGxDialog mini-browser. As this example does not use an ArcCatalog IGxDialog mini-browser to convert a shapefile to a geodatabase feature class, the following objects must first be created:
- A name object for the source dataset. Creating this typically requires creating a name object for the source dataset's workspace.
- A name object for the new target dataset. Creating this requires creating a name object for the target dataset's workspace.
- The geometry definition for the new feature class.
- A fields collection for the new feature class.
- A query filter, to select a subset of the source dataset's features or fields (optional).
- A name object for the target feature class's feature dataset, if it is to be created within one (optional).
- A configuration keyword, if the target workspace is a geodatabase (optional).
Creating source and target name objects
The following name objects are required for the conversion:
- One for the source feature class
- One for the target feature class
When creating a feature class name object, a name object for the containing workspace is also necessary.
The following code example shows how to create name objects for a shapefile workspace and a file geodatabase workspace:
[C#]
// Create a name object for the source (shapefile) workspace and open it.
IWorkspaceName sourceWorkspaceName = new WorkspaceNameClass
{
WorkspaceFactoryProgID = "esriDataSourcesFile.ShapefileWorkspaceFactory",
PathName = @"C:\Data\Shapefiles"
};
IName sourceWorkspaceIName = (IName)sourceWorkspaceName;
IWorkspace sourceWorkspace = (IWorkspace)sourceWorkspaceIName.Open();
// Create a name object for the target (file GDB) workspace and open it.
IWorkspaceName targetWorkspaceName = new WorkspaceNameClass
{
WorkspaceFactoryProgID = "esriDataSourcesGDB.FileGDBWorkspaceFactory", PathName
= @"C:\Data\Public.gdb"
};
IName targetWorkspaceIName = (IName)targetWorkspaceName;
IWorkspace targetWorkspace = (IWorkspace)targetWorkspaceIName.Open();
[VB.NET]
' Create a name object for the source workspace and open it.
Dim sourceWorkspaceName As IWorkspaceName = New WorkspaceNameClass With _
{ _
.WorkspaceFactoryProgID = "esriDataSourcesFile.ShapefileWorkspaceFactory", _
.PathName = "C:\Data\Shapefiles" _
}
Dim sourceWorkspaceIName As IName = CType(sourceWorkspaceName, IName)
Dim sourceWorkspace As IWorkspace = CType(sourceWorkspaceIName.Open(), IWorkspace)
' Create a name object for the target workspace and open it.
Dim targetWorkspaceName As IWorkspaceName = New WorkspaceNameClass With _
{ _
.WorkspaceFactoryProgID = "esriDataSourcesGDB.FileGDBWorkspaceFactory", _
.PathName = "C:\Data\Public.gdb" _
}
Dim targetWorkspaceIName As IName = CType(targetWorkspaceName, IName)
Dim targetWorkspace As IWorkspace = CType(targetWorkspaceIName.Open(), IWorkspace)
To build feature class name objects, the following are required:
- Name objects for the containing workspaces (which were just created)
- Names of the source and target feature classes
In this example, the shapefile to be copied is named "Can_Mjr_Cities," but to abbreviate it in the target geodatabase, it will be renamed "Cities." The following code example shows how to build these feature class name objects:
[C#]
// Create a name object for the source dataset.
IFeatureClassName sourceFeatureClassName = new FeatureClassNameClass();
IDatasetName sourceDatasetName = (IDatasetName)sourceFeatureClassName;
sourceDatasetName.Name = "Can_Mjr_Cities";
sourceDatasetName.WorkspaceName = sourceWorkspaceName;
// Create a name object for the target dataset.
IFeatureClassName targetFeatureClassName = new FeatureClassNameClass();
IDatasetName targetDatasetName = (IDatasetName)targetFeatureClassName;
targetDatasetName.Name = "Cities";
targetDatasetName.WorkspaceName = targetWorkspaceName;
[VB.NET]
' Create a name object for the source dataset.
Dim sourceFeatureClassName As IFeatureClassName = New FeatureClassNameClass()
Dim sourceDatasetName As IDatasetName = CType(sourceFeatureClassName, IDatasetName)
sourceDatasetName.Name = "Can_Mjr_Cities"
sourceDatasetName.WorkspaceName = sourceWorkspaceName
' Create a name object for the target dataset.
Dim targetFeatureClassName As IFeatureClassName = New FeatureClassNameClass()
Dim targetDatasetName As IDatasetName = CType(targetFeatureClassName, IDatasetName)
targetDatasetName.Name = "Cities"
targetDatasetName.WorkspaceName = targetWorkspaceName
When setting the IDatasetName.Name property, ensure that the formatting is appropriate for the data source. For example, ArcSDE feature classes can require qualification and Coverages also use a format different from other data sources.
Creating output feature class fields and geometry
Dataset name objects (including feature class name objects) can be cast to the IName interface, from where the IName.Open method can be called to open the actual dataset. The IFieldChecker interface should then be used to convert the source's fields collection to a new collection that is compatible with the target workspace, as different data sources have different restrictions on field properties, such as the maximum length of a field name. If an error is found, an enumerator of field errors (accessed through the IEnumFieldError interface) can be traversed and an error returned. For more information, see IFieldChecker.Validate and IFieldError. See the following code example:
[C#]
// Open source feature class to get field definitions.
IName sourceName = (IName)sourceFeatureClassName;
IFeatureClass sourceFeatureClass = (IFeatureClass)sourceName.Open();
// Create the objects and references necessary for field validation.
IFieldChecker fieldChecker = new FieldCheckerClass();
IFields sourceFields = sourceFeatureClass.Fields;
IFields targetFields = null;
IEnumFieldError enumFieldError = null;
// Set the required properties for the IFieldChecker interface.
fieldChecker.InputWorkspace = sourceWorkspace;
fieldChecker.ValidateWorkspace = targetWorkspace;
// Validate the fields and check for errors.
fieldChecker.Validate(sourceFields, out enumFieldError, out targetFields);
if (enumFieldError != null)
{
// Handle the errors in a way appropriate to your application.
Console.WriteLine("Errors were encountered during field validation.");
}
[VB.NET]
' Open source feature class to get field definitions.
Dim sourceName As IName = CType(sourceFeatureClassName, IName)
Dim sourceFeatureClass As IFeatureClass = CType(sourceName.Open(), IFeatureClass)
' Create the objects and references necessary for field validation.
Dim fieldChecker As IFieldChecker = New FieldCheckerClass()
Dim sourceFields As IFields = sourceFeatureClass.Fields
Dim targetFields As IFields = Nothing
Dim enumFieldError As IEnumFieldError = Nothing
' Set the required properties for the IFieldChecker interface.
fieldChecker.InputWorkspace = sourceWorkspace
fieldChecker.ValidateWorkspace = targetWorkspace
' Validate the fields and check for errors.
fieldChecker.Validate(sourceFields, enumFieldError, targetFields)
If Not enumFieldError Is Nothing Then
' Handle the errors in a way appropriate to your application.
Console.WriteLine("Errors were encountered during field validation.")
End If
Do not add or remove fields from the target fields collection. Doing so causes the conversion to fail. To restrict the fields created in the target feature class, see the Executing the conversion section in this topic regarding the use of a query filter.
The geometry definition for the target feature class should be obtained by cloning the geometry definition from the source feature class. The following code example shows how to do this:
[C#]
// Find the shape field.
String shapeFieldName = sourceFeatureClass.ShapeFieldName;
int shapeFieldIndex = sourceFeatureClass.FindField(shapeFieldName);
IField shapeField = sourceFields.get_Field(shapeFieldIndex);
// Get the geometry definition from the shape field and clone it.
IGeometryDef geometryDef = shapeField.GeometryDef;
IClone geometryDefClone = (IClone)geometryDef;
IClone targetGeometryDefClone = geometryDefClone.Clone();
IGeometryDef targetGeometryDef = (IGeometryDef)targetGeometryDefClone;
[VB.NET]
' Find the shape field.
Dim shapeFieldName As String = sourceFeatureClass.ShapeFieldName
Dim shapeFieldIndex As Integer = sourceFeatureClass.FindField(shapeFieldName)
Dim shapeField As IField = sourceFields.Field(shapeFieldIndex)
' Get the geometry definition from the shape field and clone it.
Dim geometryDef As IGeometryDef = shapeField.GeometryDef
Dim geometryDefClone As IClone = CType(geometryDef, IClone)
Dim targetGeometryDefClone As IClone = geometryDefClone.Clone()
Dim targetGeometryDef As IGeometryDef = CType(targetGeometryDefClone, IGeometryDef)
Once a geometry definition exists for the target feature class, any necessary modifications to it can be made through the IGeometryDefEdit interface, such as changing the grid count, grid size, or spatial reference. Doing this is not necessary; typically, the existing values are acceptable. The following code example shows how to change the grid count and size of the target's geometry definition:
[C#]
// Cast the IGeometryDef to the IGeometryDefEdit interface.
IGeometryDefEdit targetGeometryDefEdit = (IGeometryDefEdit)targetGeometryDef;
// Set the IGeometryDefEdit properties.
targetGeometryDefEdit.GridCount_2 = 1;
targetGeometryDefEdit.set_GridSize(0, 0.75);
[VB.NET]
' Cast the IGeometryDef to the IGeometryDefEdit interface.
Dim targetGeometryDefEdit As IGeometryDefEdit = CType(targetGeometryDef, IGeometryDefEdit)
' Set the IGeometryDefEdit properties.
targetGeometryDefEdit.GridCount_2 = 1
targetGeometryDefEdit.GridSize_2(0) = 0.75
Executing the conversion
The following types of restrictions can be applied to the conversion:
- Number of features that accompany the conversion (through attribute constraints)
- Number of fields that are created in the new feature class
Both of these restrictions can be applied through using a query filter, specifically the IQueryFilter.WhereClause and IQueryFilter.SubFields properties. If spatial constraints are also necessary, the ISpatialFilter interface can also be used. Applying constraints is optional and a null value can be passed to the conversion method in lieu of a query filter if they are not applicable.
The following code example shows how to create a query filter resulting in the target feature class only containing cities from a single province and only four of the original fields:
[C#]
// Create a query filter to only select cities with a province (PROV) value of 'NS.'
IQueryFilter queryFilter = new QueryFilterClass();
queryFilter.WhereClause = "PROV = 'NS'";
queryFilter.SubFields = "Shape, NAME, TERM, Pop1996";
[VB.NET]
' Create a query filter to only select cities with a province (PROV) value of 'NS.'
Dim queryFilter As IQueryFilter = New QueryFilterClass()
queryFilter.WhereClause = "PROV = 'NS'"
queryFilter.SubFields = "Shape, NAME, TERM, Pop1996"
Convert the feature class by calling IFeatureDataConverter.ConvertFeatureClass. Though rarely needed, rejected features can be reported using the IEnumInvalidObject and IInvalidObjectInfo interfaces. See the following code example:
[C#]
// Create the converter and run the conversion.
IFeatureDataConverter featureDataConverter = new FeatureDataConverterClass();
IEnumInvalidObject enumInvalidObject = featureDataConverter.ConvertFeatureClass
(sourceFeatureClassName, queryFilter, null, targetFeatureClassName,
targetGeometryDef, targetFields, "", 1000, 0);
// Check for errors.
IInvalidObjectInfo invalidObjectInfo = null;
enumInvalidObject.Reset();
while ((invalidObjectInfo = enumInvalidObject.Next()) != null)
{
// Handle the errors in a way appropriate to the application.
Console.WriteLine("Errors occurred for the following feature: {0}",
invalidObjectInfo.InvalidObjectID);
}
[VB.NET]
' Create the converter and run the conversion.
Dim featureDataConverter As IFeatureDataConverter = New FeatureDataConverterClass()
Dim enumInvalidObject As IEnumInvalidObject = featureDataConverter.ConvertFeatureClass(sourceFeatureClassName, queryFilter, Nothing, targetFeatureClassName, targetGeometryDef, targetFields, "", 1000, 0)
' Check for errors.
Dim invalidObjectInfo As IInvalidObjectInfo = Nothing
enumInvalidObject.Reset()
Do While Not (invalidObjectInfo) Is Nothing
' Handle the errors in a way appropriate to the application.
Console.WriteLine("Errors occurred for the following feature: {0}", invalidObjectInfo.InvalidObjectID)
invalidObjectInfo = enumInvalidObject.Next()
Loop
Complete code example
The following code example is the concatenation of the previous code examples:
[C#]
public void ConvertShapefileToFeatureClass()
{
// Create a name object for the source (shapefile) workspace and open it.
IWorkspaceName sourceWorkspaceName = new WorkspaceNameClass
{
WorkspaceFactoryProgID = "esriDataSourcesFile.ShapefileWorkspaceFactory",
PathName = @"C:\Data\Shapefiles"
};
IName sourceWorkspaceIName = (IName)sourceWorkspaceName;
IWorkspace sourceWorkspace = (IWorkspace)sourceWorkspaceIName.Open();
// Create a name object for the target (file GDB) workspace and open it.
IWorkspaceName targetWorkspaceName = new WorkspaceNameClass
{
WorkspaceFactoryProgID = "esriDataSourcesGDB.FileGDBWorkspaceFactory",
PathName = @"C:\Data\Public.gdb"
};
IName targetWorkspaceIName = (IName)targetWorkspaceName;
IWorkspace targetWorkspace = (IWorkspace)targetWorkspaceIName.Open();
// Create a name object for the source dataset.
IFeatureClassName sourceFeatureClassName = new FeatureClassNameClass();
IDatasetName sourceDatasetName = (IDatasetName)sourceFeatureClassName;
sourceDatasetName.Name = "Can_Mjr_Cities";
sourceDatasetName.WorkspaceName = sourceWorkspaceName;
// Create a name object for the target dataset.
IFeatureClassName targetFeatureClassName = new FeatureClassNameClass();
IDatasetName targetDatasetName = (IDatasetName)targetFeatureClassName;
targetDatasetName.Name = "Cities";
targetDatasetName.WorkspaceName = targetWorkspaceName;
// Open source feature class to get field definitions.
IName sourceName = (IName)sourceFeatureClassName;
IFeatureClass sourceFeatureClass = (IFeatureClass)sourceName.Open();
// Create the objects and references necessary for field validation.
IFieldChecker fieldChecker = new FieldCheckerClass();
IFields sourceFields = sourceFeatureClass.Fields;
IFields targetFields = null;
IEnumFieldError enumFieldError = null;
// Set the required properties for the IFieldChecker interface.
fieldChecker.InputWorkspace = sourceWorkspace;
fieldChecker.ValidateWorkspace = targetWorkspace;
// Validate the fields and check for errors.
fieldChecker.Validate(sourceFields, out enumFieldError, out targetFields);
if (enumFieldError != null)
{
// Handle the errors in a way appropriate to your application.
Console.WriteLine("Errors were encountered during field validation.");
}
// Find the shape field.
String shapeFieldName = sourceFeatureClass.ShapeFieldName;
int shapeFieldIndex = sourceFeatureClass.FindField(shapeFieldName);
IField shapeField = sourceFields.get_Field(shapeFieldIndex);
// Get the geometry definition from the shape field and clone it.
IGeometryDef geometryDef = shapeField.GeometryDef;
IClone geometryDefClone = (IClone)geometryDef;
IClone targetGeometryDefClone = geometryDefClone.Clone();
IGeometryDef targetGeometryDef = (IGeometryDef)targetGeometryDefClone;
// Cast the IGeometryDef to the IGeometryDefEdit interface.
IGeometryDefEdit targetGeometryDefEdit = (IGeometryDefEdit)targetGeometryDef;
// Set the IGeometryDefEdit properties.
targetGeometryDefEdit.GridCount_2 = 1;
targetGeometryDefEdit.set_GridSize(0, 0.75);
// Create a query filter to only select cities with a province (PROV) value of 'NS.'
IQueryFilter queryFilter = new QueryFilterClass();
queryFilter.WhereClause = "PROV = 'NS'";
queryFilter.SubFields = "Shape, NAME, TERM, Pop1996";
// Create the converter and run the conversion.
IFeatureDataConverter featureDataConverter = new FeatureDataConverterClass();
IEnumInvalidObject enumInvalidObject = featureDataConverter.ConvertFeatureClass
(sourceFeatureClassName, queryFilter, null, targetFeatureClassName,
targetGeometryDef, targetFields, "", 1000, 0);
// Check for errors.
IInvalidObjectInfo invalidObjectInfo = null;
enumInvalidObject.Reset();
while ((invalidObjectInfo = enumInvalidObject.Next()) != null)
{
// Handle the errors in a way appropriate to the application.
Console.WriteLine("Errors occurred for the following feature: {0}",
invalidObjectInfo.InvalidObjectID);
}
}
[VB.NET]
Public Sub ConvertShapefileToFeatureClass()
' Create a name object for the source workspace and open it.
Dim sourceWorkspaceName As IWorkspaceName = New WorkspaceNameClass With _
{ _
.WorkspaceFactoryProgID = "esriDataSourcesFile.ShapefileWorkspaceFactory", _
.PathName = "C:\Data\Shapefiles" _
}
Dim sourceWorkspaceIName As IName = CType(sourceWorkspaceName, IName)
Dim sourceWorkspace As IWorkspace = CType(sourceWorkspaceIName.Open(), IWorkspace)
' Create a name object for the target workspace and open it.
Dim targetWorkspaceName As IWorkspaceName = New WorkspaceNameClass With _
{ _
.WorkspaceFactoryProgID = "esriDataSourcesGDB.FileGDBWorkspaceFactory", _
.PathName = "C:\Data\Public.gdb" _
}
Dim targetWorkspaceIName As IName = CType(targetWorkspaceName, IName)
Dim targetWorkspace As IWorkspace = CType(targetWorkspaceIName.Open(), IWorkspace)
' Create a name object for the source dataset.
Dim sourceFeatureClassName As IFeatureClassName = New FeatureClassNameClass()
Dim sourceDatasetName As IDatasetName = CType(sourceFeatureClassName, IDatasetName)
sourceDatasetName.Name = "Can_Mjr_Cities"
sourceDatasetName.WorkspaceName = sourceWorkspaceName
' Create a name object for the target dataset.
Dim targetFeatureClassName As IFeatureClassName = New FeatureClassNameClass()
Dim targetDatasetName As IDatasetName = CType(targetFeatureClassName, IDatasetName)
targetDatasetName.Name = "Cities"
targetDatasetName.WorkspaceName = targetWorkspaceName
' Open source feature class to get field definitions.
Dim sourceName As IName = CType(sourceFeatureClassName, IName)
Dim sourceFeatureClass As IFeatureClass = CType(sourceName.Open(), IFeatureClass)
' Create the objects and references necessary for field validation.
Dim fieldChecker As IFieldChecker = New FieldCheckerClass()
Dim sourceFields As IFields = sourceFeatureClass.Fields
Dim targetFields As IFields = Nothing
Dim enumFieldError As IEnumFieldError = Nothing
' Set the required properties for the IFieldChecker interface.
fieldChecker.InputWorkspace = sourceWorkspace
fieldChecker.ValidateWorkspace = targetWorkspace
' Validate the fields and check for errors.
fieldChecker.Validate(sourceFields, enumFieldError, targetFields)
If Not enumFieldError Is Nothing Then
' Handle the errors in a way appropriate to your application.
Console.WriteLine("Errors were encountered during field validation.")
End If
' Find the shape field.
Dim shapeFieldName As String = sourceFeatureClass.ShapeFieldName
Dim shapeFieldIndex As Integer = sourceFeatureClass.FindField(shapeFieldName)
Dim shapeField As IField = sourceFields.Field(shapeFieldIndex)
' Get the geometry definition from the shape field and clone it.
Dim geometryDef As IGeometryDef = shapeField.GeometryDef
Dim geometryDefClone As IClone = CType(geometryDef, IClone)
Dim targetGeometryDefClone As IClone = geometryDefClone.Clone()
Dim targetGeometryDef As IGeometryDef = CType(targetGeometryDefClone, IGeometryDef)
' Cast the IGeometryDef to the IGeometryDefEdit interface.
Dim targetGeometryDefEdit As IGeometryDefEdit = CType(targetGeometryDef, IGeometryDefEdit)
' Set the IGeometryDefEdit properties.
targetGeometryDefEdit.GridCount_2 = 1
targetGeometryDefEdit.GridSize_2(0) = 0.75
' Create a query filter to only select cities with a province (PROV) value of 'NS.'
Dim queryFilter As IQueryFilter = New QueryFilterClass()
queryFilter.WhereClause = "PROV = 'NS'"
queryFilter.SubFields = "Shape, NAME, TERM, Pop1996"
' Create the converter and run the conversion.
Dim featureDataConverter As IFeatureDataConverter = New FeatureDataConverterClass()
Dim enumInvalidObject As IEnumInvalidObject = featureDataConverter.ConvertFeatureClass(sourceFeatureClassName, queryFilter, Nothing, targetFeatureClassName, targetGeometryDef, targetFields, "", 1000, 0)
' Check for errors.
Dim invalidObjectInfo As IInvalidObjectInfo = Nothing
enumInvalidObject.Reset()
Do While Not (invalidObjectInfo) Is Nothing
' Handle the errors in a way appropriate to the application.
Console.WriteLine("Errors occurred for the following feature: {0}", invalidObjectInfo.InvalidObjectID)
invalidObjectInfo = enumInvalidObject.Next()
Loop
End Sub
See Also:
Copying and pasting geodatabase datasetsTo use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
ESRI.ArcGIS.System (ESRI.ArcGIS.esriSystem)ESRI.ArcGIS.Geodatabase ESRI.ArcGIS.Geometry ESRI.ArcGIS.Display
Development licensing | Deployment licensing |
---|---|
ArcGIS for Desktop Basic | ArcGIS for Desktop Basic |
ArcGIS for Desktop Standard | ArcGIS for Desktop Standard |
ArcGIS for Desktop Advanced | ArcGIS for Desktop Advanced |
Engine Developer Kit | Engine |