I am excited to present my latest journal to you all. This time infused with a touch of Lord Voldemort's unique style.
The tool automates the process of analyzing and annotating the dimensions and material thicknesses of parts in a Siemens NX assembly. It is designed specifically to aid engineers and CAD designers like myself in efficiently processing and documenting crucial measurements directly within the NX framework.
Features:
- Component Analysis: The script iterates through all components in the main assembly, including subassemblies, calculating the dimensions of each component. It intelligently handles duplicated components by skipping them.
Based on this sub, created by NXJournaling on 2012.
https://www.nxjournaling.com/content/creating-subroutine-process-all-com...
- Bounding Box Calculation: For the designated body, the script creates a non-aligned bounding box to determine its width, depth, and height. The body doesn't have to be aligned with the absolute coordinate system. The process involves generating a non-aligned minimum bounding box, selecting the first vertex on it, iterating through the edges that share a common point with this vertex, and then measuring these three edges.
Solid Body Requirements:
If the body is on Layer 1, it will be processed.
If on any layer other than Layer 1, it will be skipped.
If multiple bodies are on Layer 1, the script will skip the component.
Dimensions are in millimeters.
- Material Thickness Identification: The script determines the material thickness from a pre-set range of valid thicknesses, adjusting the value according to specific criteria. Refer to the code comments for customization to your environment.
- Dimension Sorting: The script sorts the calculated dimensions to identify the length, width, and material thickness of each component. If the material thickness is indeterminable, the script designates the smallest dimension as the thickness.
- User Interaction: The script includes a form interface for user adjustments to dimensions (additional length and width) and to modify grain direction as required.
- Attribute Assignment: Attributes for length, width, and material thickness are added to each associated component / Part. Refer to the code comments for customization to your environment.
Use Case:
Ideal for mechanical engineers and designers using Siemens NX who need a fast, automated method to document and review dimensions and material thicknesses of components in complex assemblies. This tool is particularly valuable in large-scale projects where manual measurement is impractical.
The code has been tested on versions 2212 and 2306 with Teamcenter 13.
Happy Holidays :)
Enjoy!
' created by Tamas Woller at 27.12.2023 Option Strict Off Imports System Imports System.Collections.Generic Imports NXOpen Imports NXOpen.UF Imports NXOpen.Utilities Imports NXOpen.Assemblies Imports System.Drawing Imports System.Windows.Forms Module NXJournal Dim theSession As Session = Session.GetSession() Dim lw As ListingWindow = theSession.ListingWindow Dim theUFSession As UFSession = UFSession.GetUFSession() Dim theUI As UI = UI.GetUI() Dim workPart As Part = theSession.Parts.Work Dim Length As Double Dim Width As Double Dim winFormLocationX As Integer = 317 ' Default X position for Winforms Dim winFormLocationY As Integer = 317 ' Default Y position for Winforms ' Use a Dictionary to track processed components Private ProcessedComponents As New Dictionary(Of String, Boolean) Sub Main() Dim markId1 As NXOpen.Session.UndoMarkId markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Dimensions Tool") lw.Open() ' Make all components visible Dim showhide As Integer = theSession.DisplayManager.ShowByType(DisplayManager.ShowHideType.All, DisplayManager.ShowHideScope.AnyInAssembly) workPart.ModelingViews.WorkView.FitAfterShowOrHide(NXOpen.View.ShowOrHideType.ShowOnly) Try Dim workPart As Part = theSession.Parts.Work Dim dispPart As Part = theSession.Parts.Display Dim ca As ComponentAssembly = dispPart.ComponentAssembly If Not IsNothing(dispPart) Then lw.WriteLine("---------------------------------------------- ") lw.WriteLine("Lord Voldemort's Dimensions Tool") lw.WriteLine(" ") lw.WriteLine("The ritual of dimensions begins.") lw.WriteLine("Behold, Width, Height, and Material Thickness.") lw.WriteLine(" ") lw.WriteLine("The Main Assembly reveals itself as: " & dispPart.Name) lw.WriteLine(" ") ReportComponentChildren(ca.RootComponent) Else lw.WriteLine("This part is devoid of any components, much like a soul without magic.") End If Catch e As Exception theSession.ListingWindow.WriteLine("Failure? Impossible! " & e.ToString) Finally ' Reset to main assembly lw.WriteLine(" ") lw.WriteLine("Returning home to the main assembly, like a serpent to its lair.") ResetToMainAssembly() End Try End Sub Sub ReportComponentChildren(ByVal comp As Component) ' List to keep track of components along with their suppressed status Dim componentsWithStatus As New List(Of Tuple(Of Component, Boolean)) ' List to keep track of processed component display names for duplicate check Dim NameList As New List(Of String) ' Collect components and their suppressed status For Each child As Component In comp.GetChildren() ' Add component and its suppressed status to the list componentsWithStatus.Add(New Tuple(Of Component, Boolean)(child, child.IsSuppressed)) Next ' Sort the list so that suppressed components come first componentsWithStatus.Sort(Function(x, y) y.Item2.CompareTo(x.Item2)) ' Process sorted components For Each tuple As Tuple(Of Component, Boolean) In componentsWithStatus Dim child As Component = tuple.Item1 Dim isSuppressed As Boolean = tuple.Item2 ' Check for duplicate part If NameList.Contains(child.DisplayName()) Then ' Logic for handling duplicate parts lw.WriteLine("Another duplicate, unworthy of my attention: " & child.DisplayName()) Continue For Else NameList.Add(child.DisplayName()) ' Add new component display name to the list End If If isSuppressed Then lw.WriteLine("A suppressed component hides in the shadows: " & child.DisplayName()) Else lw.WriteLine("-----------------") ' Retrieve and process the part associated with the child component Dim childPart As Part = LoadComponentAndGetPart(child) If childPart IsNot Nothing AndAlso childPart.IsFullyLoaded Then ' Display the part name instead of the component name lw.WriteLine("Now, gaze upon the Part: " & childPart.Name) ProcessBodies(childPart, child) ' Pass the Part and Component objects Else lw.WriteLine("This part lacks the magic it needs, it is not fully conjured.") End If If child.GetChildren.Length <> 0 Then ' Continue processing subassemblies ReportComponentChildren(child) End If End If Next End Sub ' Method to load a component and return the associated part Function LoadComponentAndGetPart(ByVal component As Component) As Part Dim partLoadStatus As PartLoadStatus = Nothing Try ' Set the work component to load the component theSession.Parts.SetWorkComponent(component, PartCollection.RefsetOption.Current, PartCollection.WorkComponentOption.Visible, partLoadStatus) ' Get the part associated with the component If TypeOf component.Prototype Is Part Then Return CType(component.Prototype, Part) End If Catch ex As Exception lw.WriteLine("An unexpected disturbance in the dark arts: " & ex.Message) Return Nothing Finally ' Dispose of the part load status If partLoadStatus IsNot Nothing Then partLoadStatus.Dispose() End If End Try Return Nothing End Function Sub ProcessBodies(ByVal part As Part, ByVal comp As Component) Dim lw As ListingWindow = theSession.ListingWindow Dim nXObject1 As NXOpen.NXObject Dim bbWidth, bbDepth, bbHeight, Length, Width, MaterialThickness As Double Dim lengthDisplay As String = "" ' Declare lengthDisplay Dim widthDisplay As String = "" ' Declare widthDisplay ' Set the measure manager to consistent unit Dim myMeasure As MeasureManager = part.MeasureManager() Dim wIconMOseT (0) As Unit wIconMOseT (0) = part.UnitCollection.GetBase("Mass") ' Create a mass properties measurement for the entire part Dim mb As MeasureBodies = myMeasure.NewMassProperties(wIconMOseT , 0.99, part.Bodies.ToArray()) mb.InformationUnit = MeasureBodies.AnalysisUnit.KilogramMilliMeter ' Check if the part is valid and loaded If Not part Is Nothing AndAlso part.IsFullyLoaded Then ' Get the list of solid bodies in the part Dim bodies As Body() = part.Bodies.ToArray() ' Lists to track bodies on Layer 1 Dim bodiesOnLayer1 As New List(Of Body) ' Check bodies and categorize based on layer For Each body As Body In bodies Dim bodyLayer As Integer = body.Layer Dim bodyName As String = If(String.IsNullOrEmpty(body.Name), "Unnamed Body", body.Name) If bodyLayer = 1 Then bodiesOnLayer1.Add(body) lw.WriteLine("Found Solid Body: " & bodyName & " on Layer 1") lw.WriteLine(" ") Else lw.WriteLine("A mere illusion: " & bodyName & " on Layer " & bodyLayer.ToString()) lw.WriteLine("I shall disregard it.") lw.WriteLine(" ") End If Next ' Check the number of bodies on Layer 1 If bodiesOnLayer1.Count > 1 Then lw.WriteLine("Too many forms vie for attention on Layer 1") lw.WriteLine("I shall choose none.") lw.WriteLine(" ") Exit Sub ElseIf bodiesOnLayer1.Count = 1 Then ' Process the single body found on Layer 1 Dim bodyToProcess As Body = bodiesOnLayer1(0) lw.WriteLine("Processing Body: " & bodyToProcess.Name) Try ' Calculate and display the center of mass Dim accValue(10) As Double accValue(0) = 0.999 Dim massProps(46) As Double Dim stats(12) As Double theUFSession.Modl.AskMassProps3d(New Tag() {bodyToProcess.Tag}, 1, 1, 4, 0.03, 1, accValue, massProps, stats) ' Convert the center of mass coordinates to Double Dim com_x As Double = massProps(3) Dim com_y As Double = massProps(4) Dim com_z As Double = massProps(5) Dim toolingBoxBuilder1 As NXOpen.Features.ToolingBoxBuilder = workPart.Features.ToolingFeatureCollection.CreateToolingBoxBuilder(Nothing) toolingBoxBuilder1.Type = NXOpen.Features.ToolingBoxBuilder.Types.BoundedBlock toolingBoxBuilder1.ReferenceCsysType = NXOpen.Features.ToolingBoxBuilder.RefCsysType.SelectedCsys toolingBoxBuilder1.XValue.SetFormula("10") toolingBoxBuilder1.YValue.SetFormula("10") toolingBoxBuilder1.ZValue.SetFormula("10") toolingBoxBuilder1.OffsetPositiveX.SetFormula("0") toolingBoxBuilder1.OffsetNegativeX.SetFormula("0") toolingBoxBuilder1.OffsetPositiveY.SetFormula("0") toolingBoxBuilder1.OffsetNegativeY.SetFormula("0") toolingBoxBuilder1.OffsetPositiveZ.SetFormula("0") toolingBoxBuilder1.OffsetNegativeZ.SetFormula("0") toolingBoxBuilder1.RadialOffset.SetFormula("0") toolingBoxBuilder1.Clearance.SetFormula("0") toolingBoxBuilder1.CsysAssociative = True toolingBoxBuilder1.NonAlignedMinimumBox = True toolingBoxBuilder1.SingleOffset = False Dim selectionIntentRuleOptions1 As NXOpen.SelectionIntentRuleOptions = Nothing selectionIntentRuleOptions1 = workPart.ScRuleFactory.CreateRuleOptions() selectionIntentRuleOptions1.SetSelectedFromInactive(False) Dim selectedBody As NXOpen.Body = TryCast(NXOpen.Utilities.NXObjectManager.Get(bodyToProcess.Tag), NXOpen.Body) If selectedBody Is Nothing Then lw.WriteLine("The tag you dare present does not match any corporeal form.") Return End If ' Use the selectedBody for creating the dumb rule Dim bodyDumbRule1 As NXOpen.BodyDumbRule = workPart.ScRuleFactory.CreateRuleBodyDumb(New Body() {selectedBody}, True, selectionIntentRuleOptions1) selectionIntentRuleOptions1.Dispose() Dim scCollector1 As NXOpen.ScCollector = toolingBoxBuilder1.BoundedObject Dim rules1(0) As NXOpen.SelectionIntentRule rules1(0) = bodyDumbRule1 scCollector1.ReplaceRules(rules1, False) ' Use the selectedBody in SetSelectedOccurrences Dim selections1(0) As NXOpen.NXObject selections1(0) = selectedBody Dim deselections1(-1) As NXOpen.NXObject toolingBoxBuilder1.SetSelectedOccurrences(selections1, deselections1) Dim selectNXObjectList1 As NXOpen.SelectNXObjectList = Nothing selectNXObjectList1 = toolingBoxBuilder1.FacetBodies Dim objects1(-1) As NXOpen.NXObject Dim added1 As Boolean = Nothing added1 = selectNXObjectList1.Add(objects1) toolingBoxBuilder1.CalculateBoxSize() ' Set the box position using the center of mass coordinates Dim csysorigin1 As NXOpen.Point3d = New NXOpen.Point3d(com_x, com_y, com_z) toolingBoxBuilder1.BoxPosition = csysorigin1 ' Commit the tooling box to create the feature nXObject1 = toolingBoxBuilder1.Commit() ' Destroy the tooling box builder If toolingBoxBuilder1 IsNot Nothing Then toolingBoxBuilder1.Destroy() End If ' Access the body of the bounding box feature Dim bboxFeature As Features.Feature = TryCast(nXObject1, Features.Feature) Dim bboxBody As Body = Nothing Dim innerBboxBody As Body = Nothing If bboxFeature IsNot Nothing Then For Each innerBboxBody In bboxFeature.GetBodies() 'bboxBody = body Exit For Next End If If innerBboxBody IsNot Nothing Then ' Initialize directions and distances arrays Dim minCorner(2) As Double Dim directions(,) As Double = New Double(2, 2) {} Dim distances(2) As Double ' Get the bounding box of the body theUFSession.Modl.AskBoundingBoxExact(innerBboxBody.Tag, Tag.Null, minCorner, directions, distances) ' Define the minimum corner point and print it Dim cornerPoint As Point3d = New Point3d(minCorner(0), minCorner(1), minCorner(2)) ' Initialize a List to store unique vertices Dim vertices As New List(Of Point3d)() ' Iterate through all edges in the body and get vertices For Each edge As Edge In innerBboxBody.GetEdges() Dim vertex1 As Point3d, vertex2 As Point3d edge.GetVertices(vertex1, vertex2) If Not vertices.Contains(vertex1) Then vertices.Add(vertex1) If Not vertices.Contains(vertex2) Then vertices.Add(vertex2) Next ' Select the first vertex as the starting vertex Dim startingVertex As Point3d = vertices(0) ' Initialize a List to store lengths of edges connected to the starting vertex Dim edgeLengths As New List(Of Double) Dim edgesAtStartingVertex As Integer = 0 ' Iterate through all edges in the body For Each edge As Edge In innerBboxBody.GetEdges() Dim vertex1 As Point3d, vertex2 As Point3d edge.GetVertices(vertex1, vertex2) If IsPointEqual(startingVertex, vertex1) OrElse IsPointEqual(startingVertex, vertex2) Then edgesAtStartingVertex += 1 edgeLengths.Add(edge.GetLength()) End If Next ' Check if we have at least three edges before accessing the list If edgeLengths.Count >= 3 Then ' Sort the edge lengths edgeLengths.Sort() ' Assign the sorted values bbWidth = Math.Round(edgeLengths(0)) bbDepth = Math.Round(edgeLengths(1)) bbHeight = Math.Round(edgeLengths(2)) ' Output the dimensions lw.WriteLine("Bounding Box Dimensions:") lw.WriteLine("Width: " & bbWidth.ToString("F0") & " mm") lw.WriteLine("Depth: " & bbDepth.ToString("F0") & " mm") lw.WriteLine("Height: " & bbHeight.ToString("F0") & " mm") lw.WriteLine(" ") Else lw.WriteLine("Not enough edges found, like a spell half-cast.") End If ' Valid material thicknesses Dim validThicknesses As Double() = {2, 5, 7, 8, 8.5, 12, 12.5, 13, 22, 24, 25} ' Change here to suit your environment Dim materialThicknessIdentified As Boolean = False ' Identify Material Thickness If Array.IndexOf(validThicknesses, bbWidth) >= 0 Then MaterialThickness = bbWidth materialThicknessIdentified = True ElseIf Array.IndexOf(validThicknesses, bbDepth) >= 0 Then MaterialThickness = bbDepth materialThicknessIdentified = True ElseIf Array.IndexOf(validThicknesses, bbHeight) >= 0 Then MaterialThickness = bbHeight materialThicknessIdentified = True End If If Not materialThicknessIdentified Then ' Handle case where material thickness is not identified MaterialThickness = Math.Min(bbWidth, Math.Min(bbDepth, bbHeight)) lw.WriteLine("Cannot identify material thickness. Using the smallest dimension instead.") End If ' Determine Length and Width from the remaining dimensions Dim remainingDimensions As New List(Of Double) From {bbWidth, bbDepth, bbHeight} remainingDimensions.Remove(MaterialThickness) ' Ensure there are two dimensions left If remainingDimensions.Count = 2 Then ' Assign the larger value to Length and the smaller to Width Length = Math.Max(remainingDimensions(0), remainingDimensions(1)) Width = Math.Min(remainingDimensions(0), remainingDimensions(1)) Else lw.WriteLine("Unable to determine Length and Width accurately.") End If ' Delete the bounding box feature Dim featureTags(0) As NXOpen.Tag featureTags(0) = bboxFeature.Tag theUFSession.Modl.DeleteFeature(featureTags) Dim myForm As New Form1() If myForm.ShowDialog() = DialogResult.OK Then ' Check the IsGrainDirectionChanged property If myForm.IsGrainDirectionChanged Then ' Flip Length and Width Dim temp As Double = Length Length = Width Width = temp lw.WriteLine("Grain direction changed") End If ' Update Length and Width based on LengthExtra and WidthExtra lengthDisplay = Length.ToString("F0") If myForm.LengthExtra > 0 Then Length += myForm.LengthExtra lengthDisplay = Length.ToString("F0") & " (" & myForm.LengthExtra.ToString("F0") & ")" Else 'lw.WriteLine("No Extra added to Length") End If widthDisplay = Width.ToString("F0") If myForm.WidthExtra > 0 Then Width += myForm.WidthExtra widthDisplay = Width.ToString("F0") & " (" & myForm.WidthExtra.ToString("F0") & ")" Else 'lw.WriteLine("No Extra added to Width") End If ' Write the updated dimensions to the listing window If Length > 0 And Width > 0 Then lw.WriteLine("Length: " & lengthDisplay & " mm") lw.WriteLine("Width: " & widthDisplay & " mm") Else lw.WriteLine("The dimensions evade my grasp.") End If End If ' Adjust Material Thickness if necessary - Change here to suit your environment Select Case MaterialThickness Case 8.5 MaterialThickness = 8 lw.WriteLine("Material thickness identified: 8.5mm. Changed to 8mm.") Case 12.5 MaterialThickness = 12 lw.WriteLine("Material thickness identified: 12.5mm. Changed to 12mm.") Case 22 MaterialThickness = 20 lw.WriteLine("Material thickness identified: 22mm. Changed to 20mm.") Case 25 MaterialThickness = 24 lw.WriteLine("Material thickness identified: 25mm. Changed to 24mm.") End Select lw.WriteLine("Material Thickness: " & MaterialThickness.ToString("F0") & " mm") lw.WriteLine(" ") ' Adding Attributes to the Component as Part - Change here to suit your environment AddPartAttribute(comp, "VLength", lengthDisplay) lw.WriteLine("Length attribute added") AddPartAttribute(comp, "VWidth", widthDisplay) lw.WriteLine("Width attribute added") AddPartAttribute(comp, "VMaterialThickness", MaterialThickness) lw.WriteLine("Material Thickness attribute added") Else lw.WriteLine("The bounding box, a ghost, it eludes me.") End If Catch ex As Exception lw.WriteLine("An error? A mere setback in my grand design: " & ex.Message) Finally End Try Else lw.WriteLine("No solid bodies found on Layer 1") End If Else lw.WriteLine("The part before me is flawed, incomplete in its essence.") End If End Sub Function IsPointEqual(point1 As Point3d, point2 As Point3d) As Boolean Const Tolerance As Double = 0.001 Return (Math.Abs(point1.X - point2.X) < Tolerance AndAlso Math.Abs(point1.Y - point2.Y) < Tolerance AndAlso Math.Abs(point1.Z - point2.Z) < Tolerance) End Function ' Method to reset to the main assembly Sub ResetToMainAssembly() Dim partLoadStatus2 As PartLoadStatus = Nothing Try ' Reset to main assembly theSession.Parts.SetWorkComponent(Nothing, PartCollection.RefsetOption.Current, PartCollection.WorkComponentOption.Visible, partLoadStatus2) lw.WriteLine(" ") lw.WriteLine("As shadows gather and night befalls, our paths now diverge in silent halls.") lw.WriteLine("Remember, the Dark Lord's gaze, ever so watchful, in mystery's maze. ") lw.WriteLine("Until we meet in destiny's corridors, obscure and deep,") lw.WriteLine("our dark voyage concludes, in secrets we keep.") lw.WriteLine(" ") Catch ex As Exception lw.WriteLine("Failed to return to my dominion: " & ex.Message) Finally ' Dispose the PartLoadStatus object if it's not null If partLoadStatus2 IsNot Nothing Then partLoadStatus2.Dispose() End If End Try End Sub <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ Partial Class Form1 Inherits System.Windows.Forms.Form Public Property LengthExtra As Double Public Property WidthExtra As Double Public Property IsGrainDirectionChanged As Boolean ' Form designer variables Private components As System.ComponentModel.IContainer Friend WithEvents chkChangeGrainDirection As System.Windows.Forms.CheckBox Friend WithEvents txtExtraLength As System.Windows.Forms.TextBox Friend WithEvents txtExtraWidth As System.Windows.Forms.TextBox Friend WithEvents btnOK As System.Windows.Forms.Button 'Friend WithEvents btnCancel As System.Windows.Forms.Button Friend WithEvents lblExtraLength As System.Windows.Forms.Label Friend WithEvents lblExtraWidth As System.Windows.Forms.Label <System.Diagnostics.DebuggerNonUserCode()> _ Protected Overrides Sub Dispose(ByVal disposing As Boolean) If disposing AndAlso components IsNot Nothing Then components.Dispose() End If MyBase.Dispose(disposing) End Sub <System.Diagnostics.DebuggerStepThrough()> _ Private Sub Form1_Load(sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.StartPosition = FormStartPosition.Manual Me.Location = New System.Drawing.Point(winFormLocationX, winFormLocationY) ' Setting the color properties of the form and its controls Me.BackColor = Color.FromArgb(55, 55, 55) ' Set form background color ' Set colors for buttons btnOK.BackColor = Color.FromArgb(50, 50, 50) 'btnCancel.BackColor = Color.FromArgb(50, 50, 50) ' Setting the font colors to white txtExtraLength.ForeColor = Color.Black txtExtraWidth.ForeColor = Color.Black btnOK.ForeColor = Color.White 'btnCancel.ForeColor = Color.White lblExtraLength.ForeColor = Color.White lblExtraWidth.ForeColor = Color.White chkChangeGrainDirection.ForeColor = Color.White End Sub Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing ' Save the location of the form winFormLocationX = Me.Location.X winFormLocationY = Me.Location.Y End Sub Private Sub InitializeComponent() Me.chkChangeGrainDirection = New System.Windows.Forms.CheckBox() Me.txtExtraLength = New System.Windows.Forms.TextBox() Me.txtExtraWidth = New System.Windows.Forms.TextBox() Me.btnOK = New System.Windows.Forms.Button() 'Me.btnCancel = New System.Windows.Forms.Button() Me.lblExtraLength = New System.Windows.Forms.Label() Me.lblExtraWidth = New System.Windows.Forms.Label() Me.SuspendLayout() ''chkChangeGrainDirection ' Me.chkChangeGrainDirection.AutoSize = True Me.chkChangeGrainDirection.Location = New System.Drawing.Point(30, 17) Me.chkChangeGrainDirection.Name = "chkChangeGrainDirection" Me.chkChangeGrainDirection.Size = New System.Drawing.Size(200, 17) Me.chkChangeGrainDirection.TabIndex = 0 Me.chkChangeGrainDirection.Text = "Would you like to change Grain Direction?" Me.chkChangeGrainDirection.UseVisualStyleBackColor = True ''lblExtraLength ' Me.lblExtraLength.AutoSize = True Me.lblExtraLength.Location = New System.Drawing.Point(30, 55) Me.lblExtraLength.Name = "lblExtraLength" Me.lblExtraLength.Size = New System.Drawing.Size(100, 13) Me.lblExtraLength.Text = "Enter Extra Length:" ''txtExtraLength ' Me.txtExtraLength.Location = New System.Drawing.Point(220, 50) Me.txtExtraLength.Name = "txtExtraLength" Me.txtExtraLength.Size = New System.Drawing.Size(100, 20) Me.txtExtraLength.TabIndex = 1 ''lblExtraWidth ' Me.lblExtraWidth.AutoSize = True Me.lblExtraWidth.Location = New System.Drawing.Point(30, 85) Me.lblExtraWidth.Name = "lblExtraWidth" Me.lblExtraWidth.Size = New System.Drawing.Size(100, 13) Me.lblExtraWidth.Text = "Enter Extra Width:" ''txtExtraWidth ' Me.txtExtraWidth.Location = New System.Drawing.Point(220, 80) Me.txtExtraWidth.Name = "txtExtraWidth" Me.txtExtraWidth.Size = New System.Drawing.Size(100, 20) Me.txtExtraWidth.TabIndex = 2 ''btnOK ' Me.btnOK.Location = New System.Drawing.Point(152, 130) Me.btnOK.Name = "btnOK" Me.btnOK.Size = New System.Drawing.Size(75, 23) Me.btnOK.TabIndex = 3 Me.btnOK.Text = "OK" Me.btnOK.UseVisualStyleBackColor = True ''btnCancel ''Me.btnCancel.Location = New System.Drawing.Point(220, 130) 'Me.btnCancel.Name = "btnCancel" 'Me.btnCancel.Size = New System.Drawing.Size(75, 23) 'Me.btnCancel.TabIndex = 4 'Me.btnCancel.Text = "Quit" 'Me.btnCancel.UseVisualStyleBackColor = True ''Form1 ' Me.AcceptButton = Me.btnOK 'Me.CancelButton = Me.btnCancel Me.ClientSize = New System.Drawing.Size(380, 170) Me.Controls.Add(Me.chkChangeGrainDirection) Me.Controls.Add(Me.lblExtraLength) Me.Controls.Add(Me.txtExtraLength) Me.Controls.Add(Me.lblExtraWidth) Me.Controls.Add(Me.txtExtraWidth) Me.Controls.Add(Me.btnOK) 'Me.Controls.Add(Me.btnCancel) Me.Name = "Form1" Me.Text = "Dimensions" Me.ResumeLayout(False) Me.PerformLayout() End Sub Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click ' Set the IsGrainDirectionChanged based on the checkbox Me.IsGrainDirectionChanged = chkChangeGrainDirection.Checked ' Set the properties based on user input If chkChangeGrainDirection.Checked Then Me.IsGrainDirectionChanged = True End If Dim lengthExtraValue As Double Dim widthExtraValue As Double ' Validate and set LengthExtra If Not String.IsNullOrWhiteSpace(txtExtraLength.Text) AndAlso Double.TryParse(txtExtraLength.Text, lengthExtraValue) Then Me.LengthExtra = lengthExtraValue ElseIf Not String.IsNullOrWhiteSpace(txtExtraLength.Text) Then MessageBox.Show("Enter a proper lenght number worthy of my time. ", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If ' Validate and set WidthExtra If Not String.IsNullOrWhiteSpace(txtExtraWidth.Text) AndAlso Double.TryParse(txtExtraWidth.Text, widthExtraValue) Then Me.WidthExtra = widthExtraValue ElseIf Not String.IsNullOrWhiteSpace(txtExtraWidth.Text) Then MessageBox.Show("Enter a proper width number worthy of my time. ", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If Me.DialogResult = DialogResult.OK Me.Close() End Sub End Class Sub AddPartAttribute(ByVal comp As Component, ByVal attTitle As String, ByVal attValue As String) If comp Is Nothing Then lw.WriteLine("A null component? Unacceptable!") Exit Sub End If Try Dim objects1(0) As NXObject objects1(0) = comp Dim attributePropertiesBuilder1 As AttributePropertiesBuilder attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, objects1, AttributePropertiesBuilder.OperationType.None) attributePropertiesBuilder1.IsArray = False attributePropertiesBuilder1.DataType = AttributePropertiesBaseBuilder.DataTypeOptions.String attributePropertiesBuilder1.ObjectPicker = AttributePropertiesBaseBuilder.ObjectOptions.ComponentAsPartAttribute attributePropertiesBuilder1.Title = attTitle attributePropertiesBuilder1.StringValue = attValue Dim nXObject1 As NXObject nXObject1 = attributePropertiesBuilder1.Commit() attributePropertiesBuilder1.Destroy() Catch ex As Exception lw.WriteLine("A flaw in the enchantment: " & ex.Message) End Try End Sub Public Function GetUnloadOption(dummy As String) As Integer GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination End Function End Module