Select to view content in your preferred language

Custom Clip function unable to save to default GDB location

261
1
09-27-2023 09:00 PM
ArnoldATK
New Contributor

Hi I'm using ArcGIS Pro 2.9

I've created a custom tool that clips layers but I can't seem to save it to my default gdb.

 

// This works
string projectDirectory = Project.Current.HomeFolderPath;

// This does not
string projectDirectory = Project.Current.DefaultGeodatabasePath;

 


The problem with this is that I have additional functions that only seem to work with the clipped layer if it is saved in a GDB folder, not if it's in the project directory at the same level as the GDB file.

Why can't I save my clipped layer inside of the default GDB, especially when if you run the clip function manually it defaults to the default GDB location of the current project?

My custom clip function

public static class ClipHelper
    {
        public static async Task<bool> ClipLayers(string inputLayerUrl, FeatureLayer clipLayer, string outputLayerUrl)
        {
            try
            {
                // Ensure the clipLayer is not null and has features
                if (clipLayer == null)
                {
                    MessageBox.Show("Clip layer is null.");
                    return false;
                }

                // Check if the clipLayer has no features
                if (clipLayer.GetFeatureClass().GetCount() == 0)
                {
                    MessageBox.Show("Clip layer has no features. Clipping cannot proceed.");
                    return false;
                }

                // Create the parameter array for the Clip tool
                var parameters = Geoprocessing.MakeValueArray(
                    inputLayerUrl,   // Input Features or Dataset
                    clipLayer,       // Clip Features (FeatureLayer)
                    outputLayerUrl   // Output Features or Dataset
                );

                // Run the Clip geoprocessing tool
                IGPResult result = await Geoprocessing.ExecuteToolAsync("analysis.Clip", parameters);

                if (result.IsFailed)
                {
                    MessageBox.Show($"Clip operation failed: {result.ErrorMessages}");
                    return false;
                }
                else
                {
                    // MessageBox.Show("Clip operation completed successfully.");
                    return true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error during clip operation: {ex.Message}");
                return false;
            }
        }

    }

 Where I'm running it:

private async Task ExportLayers(string clipLayerName)
        {
            await QueuedTask.Run(async () =>
            {
                // Get the current project's directory
                string projectDirectory = Project.Current.HomeFolderPath;
                //string projectDirectory = Project.Current.DefaultGeodatabasePath;

                // Find the clip layer by name
                var clipLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>()
                    .FirstOrDefault(lyr => lyr.Name.Equals(clipLayerName));

                if (clipLayer == null)
                {
                    MessageBox.Show($"The '{clipLayerName}' layer was not found in the table of contents.");
                    return;
                }

                foreach (var selectedItem in selectedItems)
                {
                    Debug.WriteLine("Selected Item: " + selectedItem.LayerName);

                    // Check if there are specific URLs for this layer
                    if (selectedItem.SubLayers != null && selectedItem.SubLayers.Count > 0)
                    {
                        foreach (var subLayer in selectedItem.SubLayers)
                        {
                            // Access sublayer properties
                            string subLayerName = subLayer.SubLayerName;
                            string specificUrl = subLayer.SpecificUrl;

                            Debug.WriteLine($"SubLayer Name: {subLayerName}, Specific URL: {specificUrl}");

                            // Append "clipped" to the sublayer name for the output
                            string outputName = subLayerName + "_clipped";

                            // Create an output URL with the same name in the project directory
                            //string outputUrl = System.IO.Path.Combine(projectDirectory, outputName);
                            string outputUrl = projectDirectory + '\\' +  outputName;
                            Debug.WriteLine(outputUrl);
                            // Call the ClipLayers method with the reference to the clip layer
                            
                            bool clipResult = await ClipHelper.ClipLayers(specificUrl, clipLayer, outputUrl);

                            if (clipResult)
                            {
                                AddLocalFileToMap(specificUrl);
                                // Import symbology from the original layer to the clipped sublayer
                                ImportSymbology(subLayerName, outputName);
                                // Remove the original sublayer from the map (optional)
                                RemoveLayerByName(subLayerName);
                            }
                            else
                            {
                                // Handle the case where clipping failed
                                MessageBox.Show($"Clipping sublayer {subLayerName} failed.");
                            }
                        }
                    }
                    else
                    {
                        // Use a default URL or handle the case where sublayers are not available
                        MessageBox.Show("No sublayers available for this layer.");
                    }
                }
                Debug.WriteLine("Selected item count: " + selectedItems.Count);
            });
        }
0 Kudos
1 Reply
GKmieliauskas
Esri Regular Contributor

Hi,

Have you checked your project database for existence of output name 

subLayerName + "_clipped"

?

You need to check your project database and delete old one featureclass if exists or generate unique name when forming output featureclass name.

I would recommend you to run ExecuteToolAsync with GPToolExecuteEventHandler parameter as in sample.

You will get possibility to get information about invalid geoprocessing parameters.

            var result = await Geoprocessing.ExecuteToolAsync(tool_path, args, null, _cts.Token,
                (event_name, o) =>  // implement delegate and handle events
                {
                    switch (event_name)
                    {
                        case "OnValidate": // stop execute if any warnings
                            if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning))
                                _cts.Cancel();
                            break;

                        case "OnProgressMessage":
                            string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o });
                            System.Windows.MessageBox.Show(msg);
                            _cts.Cancel();
                            break;

                        case "OnProgressPos":
                            string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o });
                            System.Windows.MessageBox.Show(msg2);
                            _cts.Cancel();
                            break;
                    }
                });

 

0 Kudos