Thank you for your help.
With that file, I could build a suitable solution.
I only need to figure out how to make a UI-less macro now.
Original Message:
Sent: 09-22-2025 14:28
From: Ronny Schneider
Subject: Using Select by Layer macro by API
I'm still on vacation until about mid October, but I quickly got me a trial license.
The attached code is basically the one I posted in the other thread, and despite a typo it works.
Have you checked out my training videos https://www.dropbox.com/scl/fo/7j7skk1rou5ixjjqm216x/h?rlkey=jk61t50kurct88uydriocsyt1&st=24lbqwjc&dl=0
I'm not a software developer and they might be a bit lengthy but should give you an idea about using the object browser and finding attribute names as well.
They have been recorded long before V5.90, so they show the old macro folder location. Just ignore that and use the new one "C:\ProgramData\Trimble\MacroCommands3".
Have a look at video "00 Setup VS and start from Template (no sound - from GIF recorder)" in order to see how to populate the object browser.
And video "Macro 3" as an example on how to find available attributes and methods.
My public GitHub repo in case you haven't seen the post about it. https://github.com/RonnySchneider/SCR_Macros_Public
------------------------------
Ronny Schneider
Original Message:
Sent: 09-22-2025 03:53
From: Eero Isola
Subject: Using Select by Layer macro by API
Hello,
Below is my current code, but it cannot fetch layer data from the object.

Selection.py
# -*- coding: utf-8 -*-"""Step-by-Step Layer Selection WizardInteractive wizard that guides users through layer selection process step by step.Each step is executed when the user clicks "Next" button."""import clrclr.AddReference('IronPython.Wpf')import wpffrom System.IO import StreamReaderfrom System.Windows.Controls import StackPanelfrom System import Stringfrom System.Collections.Generic import List# Core references - try multiple approachesfor asm in ['Trimble.Sdk','Trimble.Vce.Core','Trimble.Vce.Geometry']: try: clr.AddReference(asm) except: pass# UI and Command referencesfor asm in ['Trimble.Vce.UI.UIManager', 'Trimble.Vce.UI.BaseCommands', 'Trimble.Vce.UI.Controls']: try: clr.AddReference(asm) except: pass# Add Trimble.Vce.UI.Wpf assembly referencetry: clr.AddReference(r"C:\Program Files\Trimble\Trimble Business Center\Trimble.Vce.UI.Wpf.dll")except: try: clr.AddReference("Trimble.Vce.UI.Wpf") except: pass# Multiple approaches to access GlobalSelectionGlobalSelection = NoneSelectionContextMenuHandler = None# Try primary importtry: from Trimble.Vce.Core import GlobalSelection print("✅ GlobalSelection imported from Trimble.Vce.Core")except Exception as e: print(f"❌ Primary GlobalSelection import failed: {e}")# Try alternative imports if primary failedif GlobalSelection is None: try: import Trimble.Vce.Core as VceCore if hasattr(VceCore, 'GlobalSelection'): GlobalSelection = VceCore.GlobalSelection print("✅ GlobalSelection found via Trimble.Vce.Core module") except Exception as e: print(f"❌ Alternative GlobalSelection import failed: {e}")# Try UI context importtry: from Trimble.Vce.UI.Wpf import SelectionContextMenuHandlerexcept: SelectionContextMenuHandler = Nonetry: from Trimble.Vce.Interfaces.Client import CommandGranularityexcept: CommandGranularity = Nonetry: from Trimble.Vce.Interfaces.SnapIn import IMemberManagementexcept: IMemberManagement = None# ---------- Setup ----------def Setup(cmdData, macroFileFolder): cmdData.Key = "LayerSelectWizard" cmdData.CommandName = "LayerSelectionWizard" cmdData.Caption = "_Layer Selection Wizard" cmdData.UIForm = "Selection" try: cmdData.Version = 2.1 cmdData.MacroAuthor = "Assistant" cmdData.MacroInfo = "Step-by-step wizard that guides users through layer selection process with multiple selection access methods." except: pass try: cmdData.DefaultTabKey = "Macros" cmdData.DefaultTabGroupKey = "Selection" cmdData.ShortCaption = "LayerWiz" cmdData.ToolTipTitle = "Layer Selection Wizard" cmdData.ToolTipTextFormatted = "Interactive wizard that guides you through selecting all objects on the same layer(s) step by step." except: pass if CommandGranularity: for name in ['Selection','ObjectSelection','Components']: if hasattr(CommandGranularity, name): try: cmdData.CommandGranularity = getattr(CommandGranularity, name) break except: pass try: cmdData.RequireSelection = False # Allow starting without selection except: pass# ---------- Step-by-Step UI Panel ----------class Selection(StackPanel): def __init__(self, currentProject, macroFileFolder): try: # Load the XAML file with StreamReader(macroFileFolder + r"\Selection - Copy.xaml") as s: wpf.LoadComponent(self, s) except Exception as e: print(f"Error loading XAML: {e}") self._create_fallback_ui() self.currentProject = currentProject self.cmdManager = None # Selection access - try to establish during initialization self.selection_accessor = None self._establish_selection_access() # Wizard state self.current_step = 1 self.total_steps = 5 self.initial_selection = [] self.layers_found = set() self.objects_on_layers = [] self.wizard_completed = False # Step definitions self.steps = { 1: { 'title': 'Initialize Components', 'description': 'Checking TBC components and connections...', 'action': self._step1_initialize }, 2: { 'title': 'Analyze Selection', 'description': 'Analyzing currently selected objects...', 'action': self._step2_analyze_selection }, 3: { 'title': 'Extract Layers', 'description': 'Extracting layer information from selected objects...', 'action': self._step3_extract_layers }, 4: { 'title': 'Find Layer Objects', 'description': 'Finding all objects on the identified layers...', 'action': self._step4_find_objects }, 5: { 'title': 'Select Objects', 'description': 'Selecting all objects on the same layers...', 'action': self._step5_select_objects } } def _establish_selection_access(self): """Try multiple methods to access TBC selection""" # Method 1: Direct GlobalSelection if GlobalSelection is not None: self.selection_accessor = GlobalSelection print("✅ Using direct GlobalSelection access") return # Method 2: Try to access via current project if self.currentProject: try: # Some TBC versions expose selection through project if hasattr(self.currentProject, 'Selection'): self.selection_accessor = self.currentProject.Selection print("✅ Using project-based selection access") return # Try accessing via project's selection items if hasattr(self.currentProject, 'SelectedItems'): self.selection_accessor = self.currentProject.SelectedItems print("✅ Using project SelectedItems access") return except Exception as e: print(f"Project-based selection access failed: {e}") # Method 3: Try to access via reflection/late binding try: import Trimble.Vce.Core as Core if hasattr(Core, 'Application'): app = Core.Application if hasattr(app, 'Selection'): self.selection_accessor = app.Selection print("✅ Using application-based selection access") return except Exception as e: print(f"Application-based selection access failed: {e}") print("❌ Warning: No selection access method established") def _get_selected_objects_multiple_methods(self): """Get selected objects using multiple fallback methods""" selected_objects = [] # Method 1: Use established selection accessor if self.selection_accessor: try: # If it's GlobalSelection-like if hasattr(self.selection_accessor, 'Items') and self.currentProject: items_accessor = self.selection_accessor.Items(self.currentProject) if items_accessor: for obj in items_accessor: selected_objects.append(obj) if selected_objects: return selected_objects # If it's a direct collection elif hasattr(self.selection_accessor, '__iter__'): for obj in self.selection_accessor: selected_objects.append(obj) if selected_objects: return selected_objects # If it has a Count and indexer elif hasattr(self.selection_accessor, 'Count'): count = self.selection_accessor.Count for i in range(count): try: obj = self.selection_accessor[i] selected_objects.append(obj) except: continue if selected_objects: return selected_objects except Exception as e: print(f"Selection accessor method failed: {e}") # Method 2: Try direct GlobalSelection even if initially failed if GlobalSelection is not None: try: items_accessor = GlobalSelection.Items(self.currentProject) if items_accessor: for obj in items_accessor: selected_objects.append(obj) if selected_objects: return selected_objects except Exception as e: print(f"Direct GlobalSelection method failed: {e}") # Method 3: Try command manager to get selection if self.cmdManager: try: cmd_selection = getattr(self.cmdManager, 'Selection', None) if cmd_selection: if hasattr(cmd_selection, '__iter__'): for obj in cmd_selection: selected_objects.append(obj) if selected_objects: return selected_objects except Exception as e: print(f"Command manager selection method failed: {e}") # Method 4: Try project-based approaches if self.currentProject: try: # Try various project selection properties for prop_name in ['SelectedObjects', 'Selection', 'CurrentSelection', 'SelectedItems']: if hasattr(self.currentProject, prop_name): selection_prop = getattr(self.currentProject, prop_name) if selection_prop and hasattr(selection_prop, '__iter__'): for obj in selection_prop: selected_objects.append(obj) if selected_objects: return selected_objects except Exception as e: print(f"Project selection method failed: {e}") return selected_objects def _select_objects_multiple_methods(self, objects): """Select objects using multiple fallback methods""" success_count = 0 # Method 1: Use established selection accessor if self.selection_accessor: try: # Clear selection first if hasattr(self.selection_accessor, 'Clear'): self.selection_accessor.Clear() # Add objects if hasattr(self.selection_accessor, 'Add'): for obj in objects: try: self.selection_accessor.Add(obj) success_count += 1 except: continue if success_count > 0: return success_count # Try bulk selection if hasattr(self.selection_accessor, 'Set') and self.currentProject: serial_list = List[int]() for obj in objects: try: serial = getattr(obj, 'SerialNumber', None) if serial is not None: serial_list.Add(serial) except: continue if serial_list.Count > 0: try: self.selection_accessor.Items(self.currentProject).Set(serial_list) return serial_list.Count except Exception as e: print(f"Bulk selection failed: {e}") except Exception as e: print(f"Selection accessor method failed: {e}") # Method 2: Try direct GlobalSelection if GlobalSelection is not None: try: GlobalSelection.Clear() for obj in objects: try: GlobalSelection.Add(obj) success_count += 1 except: continue if success_count > 0: return success_count except Exception as e: print(f"Direct GlobalSelection failed: {e}") # Method 3: Try command manager selection if self.cmdManager: try: cmd_selection = getattr(self.cmdManager, 'Selection', None) if cmd_selection and hasattr(cmd_selection, 'Set'): serial_list = [] for obj in objects: try: serial = getattr(obj, 'SerialNumber', None) if serial is not None: serial_list.append(serial) except: continue if serial_list: cmd_selection.Set(serial_list) return len(serial_list) except Exception as e: print(f"Command manager selection failed: {e}") return success_count def _create_fallback_ui(self): """Create a basic UI if XAML loading fails""" from System.Windows.Controls import TextBlock, Button from System.Windows import Thickness, FontWeights # Add a header header = TextBlock() header.Text = "Layer Selection Wizard (Fallback UI)" header.FontWeight = FontWeights.Bold header.Margin = Thickness(5) self.Children.Add(header) # Add status display self.StatusText = TextBlock() self.StatusText.Margin = Thickness(5) self.Children.Add(self.StatusText) # Add next button self.NextButton = Button() self.NextButton.Content = "Next" self.NextButton.Margin = Thickness(5) self.NextButton.Click += self.NextClicked self.Children.Add(self.NextButton) def OnLoad(self, cmd, buttons, event): """Called by TBC after the panel is created""" # Store command manager reference try: self.cmdManager = cmd except: self.cmdManager = None # Re-establish selection access with command manager context self._establish_selection_access() # Initialize the wizard self._initialize_wizard() def _initialize_wizard(self): """Initialize the wizard interface""" self._update_step_display() self._update_status("Welcome to the Layer Selection Wizard! Click 'Next' to begin.") def _update_step_display(self): """Update the step indicator and progress bar""" try: if hasattr(self, 'StepIndicator'): self.StepIndicator.Text = f"Step {self.current_step} of {self.total_steps}" if hasattr(self, 'ProgressBar'): self.ProgressBar.Value = self.current_step if hasattr(self, 'StepDescription') and self.current_step in self.steps: step_info = self.steps[self.current_step] self.StepDescription.Text = f"{step_info['title']}: {step_info['description']}" # Update button states if hasattr(self, 'BackButton'): self.BackButton.IsEnabled = self.current_step > 1 if hasattr(self, 'NextButton'): if self.wizard_completed: self.NextButton.Content = "Finish" elif self.current_step >= self.total_steps: self.NextButton.Content = "Complete" else: self.NextButton.Content = "Next" # Show debug button after step 1 if hasattr(self, 'DebugButton'): from System.Windows import Visibility self.DebugButton.Visibility = Visibility.Visible if self.current_step > 1 else Visibility.Collapsed except Exception as e: print(f"Error updating step display: {e}") def NextClicked(self, sender, e): """Handle Next button click""" if self.wizard_completed: # Close the wizard self.CloseClicked(sender, e) return if self.current_step <= self.total_steps: # Execute current step if self.current_step in self.steps: step_info = self.steps[self.current_step] self._update_status(f"Executing: {step_info['title']}...") try: step_info['action']() except Exception as e: self._update_status(f"❌ Error in {step_info['title']}: {e}") return # Move to next step if self.current_step < self.total_steps: self.current_step += 1 self._update_step_display() else: self.wizard_completed = True self._update_step_display() self._update_status("✅ Wizard completed! All objects on the same layers have been selected.") self._show_results() def BackClicked(self, sender, e): """Handle Back button click""" if self.current_step > 1: self.current_step -= 1 self.wizard_completed = False self._update_step_display() self._update_status(f"Returned to step {self.current_step}") def _step1_initialize(self): """Step 1: Initialize and check components""" self._update_status("Checking TBC components...") # Check selection access if self.selection_accessor is None and GlobalSelection is None: self._update_status("❌ No selection access method available") raise Exception("Cannot access TBC selection system") else: self._update_status("✅ Selection access established") # Check currentProject if self.currentProject is None: self._update_status("❌ Current project not available") raise Exception("Current project not available") else: proj_type = self.currentProject.GetType().Name self._update_status(f"✅ Current project available: {proj_type}") # Check command manager if self.cmdManager: self._update_status("✅ Command manager available") else: self._update_status("⚠ Command manager not available (some features may be limited)") self._update_status("✅ Step 1 complete: Components initialized") def _step2_analyze_selection(self): """Step 2: Analyze current selection""" self._update_status("Analyzing current selection...") # Get current selection using multiple methods self.initial_selection = self._get_selected_objects_multiple_methods() if not self.initial_selection: self._update_status("❌ No objects currently selected") raise Exception("Please select objects in TBC before proceeding") self._update_status(f"✅ Found {len(self.initial_selection)} selected objects:") # List selected objects for i, obj in enumerate(self.initial_selection[:5], 1): # Show first 5 obj_info = self._get_object_info(obj) self._update_status(f" {i}. {obj_info}") if len(self.initial_selection) > 5: self._update_status(f" ... and {len(self.initial_selection) - 5} more objects") self._update_status("✅ Step 2 complete: Selection analyzed") def _step3_extract_layers(self): """Step 3: Extract layer information""" self._update_status("Extracting layer information...") # Extract layers from selected objects self.layers_found = self._get_layers_from_objects(self.initial_selection) if not self.layers_found: self._update_status("❌ Could not determine layers from selected objects") raise Exception("No layer information found in selected objects") self._update_status(f"✅ Found {len(self.layers_found)} unique layers:") for layer in self.layers_found: self._update_status(f" - {layer}") # DEBUG: Print detailed layer extraction information self._update_status("") self._update_status("=== LAYER EXTRACTION DEBUG ===") self._update_status(f"Total objects analyzed: {len(self.initial_selection)}") self._update_status(f"Unique layers found: {len(self.layers_found)}") # Debug each object's layer information for i, obj in enumerate(self.initial_selection, 1): try: obj_type = obj.GetType().Name obj_name = getattr(obj, 'Name', '<No Name>') self._update_status(f"Object {i}: {obj_type} - {obj_name}") # Try each layer property layer_found = False layer_props = ['Layer', 'LayerName', 'LayerId', 'LayerKey'] for prop in layer_props: if hasattr(obj, prop): try: layer_value = getattr(obj, prop) if layer_value: # Determine layer value type and content if hasattr(layer_value, 'Name'): layer_display = f"{layer_value.Name} (via {prop}.Name)" elif hasattr(layer_value, 'Key'): layer_display = f"{layer_value.Key} (via {prop}.Key)" else: layer_display = f"{layer_value} (via {prop})" self._update_status(f" ✅ Layer: {layer_display}") layer_found = True break except Exception as e: self._update_status(f" ❌ Error accessing {prop}: {e}") if not layer_found: self._update_status(" ⚠ No layer information found") # Try reflection-based discovery try: obj_type_obj = obj.GetType() if hasattr(obj_type_obj, 'GetProperties'): layer_related_props = [] for prop in obj_type_obj.GetProperties(): prop_name = prop.Name.lower() if 'layer' in prop_name: layer_related_props.append(prop.Name) if layer_related_props: self._update_status(f" 📋 Available layer-related properties: {', '.join(layer_related_props)}") else: self._update_status(" 📋 No layer-related properties found via reflection") except Exception as e: self._update_status(f" ❌ Reflection analysis failed: {e}") except Exception as e: self._update_status(f"Object {i}: Error analyzing - {e}") # Summary of found layers with details self._update_status("") self._update_status("Layer Summary:") if self.layers_found: for layer in sorted(self.layers_found): # Count how many objects are on this layer objects_on_layer = 0 for obj in self.initial_selection: obj_layers = self._get_layers_from_objects([obj]) if layer in obj_layers: objects_on_layer += 1 self._update_status(f" 📁 '{layer}' - {objects_on_layer} object(s)") else: self._update_status(" ❌ No layers identified") self._update_status("=== END LAYER EXTRACTION DEBUG ===") self._update_status("") self._update_status("✅ Step 3 complete: Layers extracted") def _step4_find_objects(self): """Step 4: Find all objects on the identified layers""" self._update_status("Searching for objects on identified layers...") # Try TBC native command first if self._try_native_select_by_layer(): self.objects_on_layers = self._get_selected_objects_multiple_methods() self._update_status(f"✅ Used TBC native command, found {len(self.objects_on_layers)} objects") else: # Use custom implementation self._update_status("Using custom layer search...") self.objects_on_layers = self._find_objects_on_layers(self.layers_found) if not self.objects_on_layers: self._update_status("❌ No objects found on target layers") raise Exception("No objects found on the identified layers") self._update_status(f"✅ Found {len(self.objects_on_layers)} objects on target layers") self._update_status("✅ Step 4 complete: Objects found") def _step5_select_objects(self): """Step 5: Select all found objects""" self._update_status("Selecting all objects on target layers...") try: # Use multiple methods to select objects selected_count = self._select_objects_multiple_methods(self.objects_on_layers) if selected_count > 0: self._update_status(f"✅ Successfully selected {selected_count} objects") self._update_status("✅ Step 5 complete: Objects selected") else: self._update_status("❌ No objects were successfully selected") raise Exception("Failed to select any objects") except Exception as e: self._update_status(f"❌ Error selecting objects: {e}") raise def _try_native_select_by_layer(self): """Try to use TBC's native Select by Layer command""" if not hasattr(self, 'cmdManager') or not self.cmdManager: return False try: mgr = getattr(self.cmdManager, 'CommandManager', None) if mgr: command_variants = ["SelectByLayer", "Select by Layer", "SelectSimilarByLayer"] for cmd_name in command_variants: try: if hasattr(mgr, 'ExecuteCommand'): result = mgr.ExecuteCommand(cmd_name) if result: self._update_status(f"✅ Used TBC command: {cmd_name}") return True except: continue except: pass return False def _show_results(self): """Show the results of the wizard""" try: # Show results section if hasattr(self, 'ResultsHeader'): from System.Windows import Visibility self.ResultsHeader.Visibility = Visibility.Visible self.ObjectsList.Visibility = Visibility.Visible # Populate results list self.ObjectsList.Items.Clear() for obj in self.objects_on_layers[:50]: # Show first 50 results obj_info = self._get_object_info(obj) self.ObjectsList.Items.Add(obj_info) if len(self.objects_on_layers) > 50: self.ObjectsList.Items.Add(f"... and {len(self.objects_on_layers) - 50} more objects") except Exception as e: print(f"Error showing results: {e}") # Include all the helper methods from the original implementation def _get_selected_objects(self): """Get currently selected objects - legacy method for compatibility""" return self._get_selected_objects_multiple_methods() def _get_layers_from_objects(self, objects): """Extract layer names/IDs from the given objects""" layers = set() for obj in objects: try: layer_props = ['Layer', 'LayerName', 'LayerId', 'LayerKey'] for prop in layer_props: if hasattr(obj, prop): layer_value = getattr(obj, prop) if layer_value: if hasattr(layer_value, 'Name'): layers.add(layer_value.Name) elif hasattr(layer_value, 'Key'): layers.add(str(layer_value.Key)) else: layers.add(str(layer_value)) break except Exception as e: continue return layers def _find_objects_on_layers(self, target_layers): """Find all objects in the project that are on the specified layers""" objects_on_layers = [] try: all_objects = self._get_all_project_objects() for obj in all_objects: try: obj_layers = self._get_layers_from_objects([obj]) if obj_layers.intersection(target_layers): objects_on_layers.append(obj) except: continue except Exception as e: print(f"Error finding objects on layers: {e}") return objects_on_layers def _get_all_project_objects(self): """Get all objects in the current project""" all_objects = [] try: if hasattr(self.currentProject, 'Members'): for member in self.currentProject.Members: all_objects.append(member) elif hasattr(self.currentProject, 'Objects'): for obj in self.currentProject.Objects: all_objects.append(obj) elif hasattr(self.currentProject, 'Items'): for item in self.currentProject.Items: all_objects.append(item) except Exception as e: print(f"Error getting project objects: {e}") return all_objects def _get_object_info(self, obj): """Get descriptive information about an object""" if obj is None: return "<None>" parts = [] try: type_name = obj.GetType().Name parts.append(type_name) except: parts.append("<Unknown Type>") try: name = getattr(obj, 'Name', None) if name: parts.append(f"Name='{name}'") except: pass try: layers = self._get_layers_from_objects([obj]) if layers: parts.append(f"Layer={list(layers)[0]}") except: pass return " | ".join(parts) if parts else "<No Info>" def _update_status(self, message): """Update status display""" print(message) # Always print to console try: if hasattr(self, 'StatusText'): # Append to existing status (keep log) current_text = getattr(self.StatusText, 'Text', '') if current_text: self.StatusText.Text = current_text + "\n" + message else: self.StatusText.Text = message except: pass def _debug_components(self): """Debug helper method to inspect selection access and currentProject""" self._update_status("=== COMPONENT DEBUGGING ===") # Debug selection access methods self._update_status("Selection Access Analysis:") if GlobalSelection is not None: try: self._update_status(f"GlobalSelection Type: {GlobalSelection.GetType()}") import System.Reflection as Reflection members = GlobalSelection.GetType().GetMembers(Reflection.BindingFlags.Public | Reflection.BindingFlags.Static | Reflection.BindingFlags.Instance) member_names = [m.Name for m in members if not m.Name.startswith('_')] self._update_status(f"GlobalSelection Members: {', '.join(sorted(set(member_names)))}") except Exception as e: self._update_status(f"Error analyzing GlobalSelection: {e}") else: self._update_status("GlobalSelection is None") if self.selection_accessor is not None: try: self._update_status(f"Selection Accessor Type: {self.selection_accessor.GetType()}") except Exception as e: self._update_status(f"Error analyzing selection accessor: {e}") else: self._update_status("No selection accessor established") # Debug currentProject in detail self._update_status("currentProject Analysis:") if self.currentProject is None: self._update_status("currentProject is None") else: try: self._update_status(f"currentProject Type: {self.currentProject.GetType()}") import System.Reflection as Reflection members = self.currentProject.GetType().GetMembers(Reflection.BindingFlags.Public | Reflection.BindingFlags.Instance) member_names = [m.Name for m in members if not m.Name.startswith('_')] self._update_status(f"currentProject Members: {', '.join(sorted(set(member_names)))}") except Exception as e: self._update_status(f"Error analyzing currentProject: {e}") # Debug current wizard state and found layers self._update_status("") self._update_status("Wizard State Analysis:") self._update_status(f"Current Step: {self.current_step} of {self.total_steps}") self._update_status(f"Wizard Completed: {self.wizard_completed}") self._update_status(f"Initial Selection Count: {len(self.initial_selection)}") # Debug layers if we've reached step 3 or beyond if self.current_step >= 3 and self.layers_found: self._update_status("") self._update_status("Found Layers Debug:") self._update_status(f"Total Unique Layers: {len(self.layers_found)}") for i, layer in enumerate(sorted(self.layers_found), 1): self._update_status(f" {i}. '{layer}' (Type: {type(layer).__name__})") elif self.current_step >= 3: self._update_status("No layers found yet (may indicate extraction issue)") # Debug objects on layers if we've reached step 4 or beyond if self.current_step >= 4 and self.objects_on_layers: self._update_status("") self._update_status("Objects on Layers Debug:") self._update_status(f"Total Objects Found: {len(self.objects_on_layers)}") # Show first few objects as examples for i, obj in enumerate(self.objects_on_layers[:3], 1): obj_info = self._get_object_info(obj) self._update_status(f" {i}. {obj_info}") if len(self.objects_on_layers) > 3: self._update_status(f" ... and {len(self.objects_on_layers) - 3} more objects") elif self.current_step >= 4: self._update_status("No objects on layers found yet") self._update_status("=== END COMPONENT DEBUGGING ===") def DebugClicked(self, sender, e): """Debug button handler""" self._debug_components() def CloseClicked(self, sender, e): """Close button handler""" closer = getattr(self, 'CloseUICommand', None) if closer: try: closer() except: pass
Selection.xaml
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <StackPanel Margin="10"> <!-- Header with step indicator --> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBlock Text="Layer Selection Wizard" FontWeight="Bold" FontSize="14" VerticalAlignment="Center"/> <TextBlock x:Name="StepIndicator" Text="Step 1 of 5" FontSize="12" Foreground="Gray" Margin="10,0,0,0" VerticalAlignment="Center"/> </StackPanel> <!-- Progress bar --> <ProgressBar x:Name="ProgressBar" Height="4" Margin="0,0,0,10" Minimum="0" Maximum="5" Value="1"/> <!-- Step description --> <TextBlock x:Name="StepDescription" Text="Initializing wizard..." FontWeight="SemiBold" Margin="0,0,0,10" TextWrapping="Wrap"/> <!-- Status display --> <TextBlock x:Name="StatusText" Text="Ready to start..." Margin="0,0,0,10" TextWrapping="Wrap" Background="LightGray" Padding="5"/> <!-- Results display --> <TextBlock x:Name="ResultsHeader" Text="Results:" FontWeight="SemiBold" Margin="0,5,0,5" Visibility="Collapsed"/> <ListBox x:Name="ObjectsList" Height="150" Margin="0,0,0,10" Visibility="Collapsed"/> <!-- Action buttons --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Button x:Name="BackButton" Content="Back" Width="60" Margin="0,0,5,0" Click="BackClicked" IsEnabled="False" ToolTip="Go to previous step"/> <Button x:Name="NextButton" Content="Next" Width="60" Margin="0,0,5,0" Click="NextClicked" ToolTip="Proceed to next step"/> <Button x:Name="DebugButton" Content="Debug" Width="60" Margin="0,0,5,0" Click="DebugClicked" ToolTip="Show debugging information" Visibility="Collapsed"/> <Button Content="Close" Width="60" Click="CloseClicked"/> </StackPanel> </StackPanel></UserControl>
I feel like I am poking in the dark trying to find the proper attribute name by sheer luck.
Any help is appreciated.,
------------------------------
Eero Isola
Original Message:
Sent: 09-14-2025 01:26
From: Ronny Schneider
Subject: Using Select by Layer macro by API
From my understanding you can't start a TBC function from within a macro.
If you use the "MemberSelection" as suggested in my previous post
In the UI XAML
<Wpf:MemberSelection x:Name="objs" Height="30" Margin="0"/>
You can activate the options menu there, as shown in the TBC sample macros.
in the macro in OnLoad
optionMenu = SelectionContextMenuHandler() # remove options that don't apply here optionMenu.ExcludedCommands = "SelectObservations | SelectPoints | SelectDuplicatePoints" self.objs.ButtonContextMenu = optionMenu # set what is visible when clicking the option button
Screenshot from an old 4.xx TBC version, just as example, don't have a dongle currently

Includes more mouse clicking. You weren't clear on how automated you want the process.
------------------------------
Ronny Schneider
Original Message:
Sent: 09-13-2025 03:35
From: Eero Isola
Subject: Using Select by Layer macro by API
Hi,
I am trying to use a native TBC Macro (Select by Layer, in this case) in my custom macro, but I can't access it. And it seems there is no documentation.
Can someone help with the proper way to access TBC tools in macros?
Sincerely:
Eero Isola
------------------------------
Eero Isola
------------------------------