工作表更改事件不会在控制台应用程序

时间:2016-02-11 20:01:28

标签: vb.net excel console-application

我一直在尝试开发一个控制台应用程序,它将打开现有的Excel工作簿并将数据写入工作表。它收集的数据来自另一个名为NX的应用程序,即CAD程序。我使用Framework 4.5和Office 2010在VB.NET中编写了控制台应用程序。除了基于事件的代码之外,代码可以正常工作。我包含了一些在选择更改事件发生时应该触发的功能。我花了几周时间做研究,并试图发现为什么我的基于事件的代码不会被激活。我似乎唯一得出的结论是控制台应用程序立即关闭/完成,并没有为事件处理程序提供“足够的时间”。

这是我的代码:

Option Strict Off
Option Infer Off

Imports System.IO
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Text
Imports System.Diagnostics
Imports System.Collections
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.Assemblies
Imports NXOpen.Utilities
Imports NXOpen.UF


Imports Microsoft.Office.Interop ' import Excel Interop Namespace
Imports System.Runtime.InteropServices.Marshal
Imports Microsoft.Office.Interop.Excel
Imports System.Windows.Forms


Module remoting_client_test

    Public theSession As Session = DirectCast(Activator.GetObject(GetType(Session), "http://localhost:4567/NXOpenSession"), Session)
    Public ufs As UFSession = DirectCast(Activator.GetObject(GetType(UFSession), "http://localhost:4567/UFSession"), UFSession)
    Public workPart As Part = theSession.Parts.Work
    Public displayPart As Part = theSession.Parts.Display
    Public TagIdentifier As Long
    Public row As Long = 3

    Sub Main()

        Dim myForm As New Form1

        'need to initialize value of excel object variables

        myForm.OpenWorkBook("C:\Path File")

        myForm.ProcessNXData()

    End Sub

    Public Sub DoLog(s As [String])
        Session.GetSession().LogFile.WriteLine(s)
        Console.WriteLine(s)
    End Sub

    Sub Echo(ByVal output As String)

        theSession.ListingWindow.Open()
        theSession.ListingWindow.WriteLine(output)
        theSession.LogFile.WriteLine(output)

    End Sub

    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        Return Session.LibraryUnloadOption.Immediately
    End Function


End Module

Public Class Form1

    Private WithEvents excel As Excel.Application
    Private WithEvents workbook As Excel.Workbook
    Private WithEvents myWorksheet As Excel.Worksheet


    Public Sub OpenWorkBook(path As String)
        If excel Is Nothing Then
            excel = New Excel.Application
            excel.Visible = True ' user is responsible for closing Excel
            excel.UserControl = True
            excel.EnableEvents = True
        End If
        If workbook IsNot Nothing Then
            FreeCOM(workbook)
        End If
        Dim workbooks As Excel.Workbooks = excel.Workbooks
        workbook = workbooks.Open(path)
        FreeCOM(workbooks)

        If myWorksheet IsNot Nothing Then
            FreeCOM(myWorksheet)
        End If
        Dim Worksheets As Excel.Sheets = workbook.Worksheets

        myWorksheet = CType(Worksheets.Item(1), Microsoft.Office.Interop.Excel.Worksheet) ' 1 based indexing
        Worksheets("NX Data").Activate()
        myWorksheet = Worksheets("NX Data")

    End Sub

    Public Shared Sub FreeCOM(ByVal COMObj As Object, Optional ByVal GCCollect As Boolean = False)
        Try
            If COMObj IsNot Nothing Then
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(COMObj)
            End If
        Finally
            COMObj = Nothing
            If GCCollect Then
                GC.Collect()
                GC.WaitForPendingFinalizers()
            End If
        End Try
    End Sub


    Public Sub ProcessNXData()
        ' This assumes the assembly is loaded.

        Dim dp As Part = theSession.Parts.Display
        Dim row As Long = 3

        theSession.EnableRedo(False)

        Dim nextBody As NXOpen.Tag = NXOpen.Tag.Null

        Do
            Dim t As Integer, st As Integer
            Dim isOcc As Boolean = False
            Dim theProtoTag As NXOpen.Tag = NXOpen.Tag.Null
            Dim owningPart As NXOpen.Tag = nextBody
            Dim partName As String = ""

            ufs.Obj.CycleTypedObjsInPart(dp.Tag, UFConstants.UF_solid_type, nextBody)
            If nextBody.Equals(NXOpen.Tag.Null) Then
                Exit Do
            End If
            ufs.Obj.AskTypeAndSubtype(nextBody, t, st)
            If st <> UFConstants.UF_solid_body_subtype Then
                Continue Do
            End If
            isOcc = ufs.Assem.IsOccurrence(nextBody)
            If isOcc.Equals(True) Then
                'Echo("Found occurrence body: " & nextBody.ToString())
                theProtoTag = ufs.Assem.AskPrototypeOfOcc(nextBody)
                ufs.Obj.AskOwningPart(theProtoTag, owningPart)
                ufs.Part.AskPartName(owningPart, partName)
                Echo("Owning Part: " & partName)
            End If

            Dim theNXOM As NXObjectManager = theSession.GetObjectManager
            Dim theObj As NXObject = theNXOM.GetTaggedObject(nextBody)
            Dim theBody As Body = CType(theObj, Body)


            Dim myMeasure As MeasureManager = theSession.Parts.Display.MeasureManager()
            Dim massUnits(4) As Unit

            massUnits(0) = theSession.Parts.Display.UnitCollection.GetBase("Area")
            massUnits(1) = theSession.Parts.Display.UnitCollection.GetBase("Volume")
            massUnits(2) = theSession.Parts.Display.UnitCollection.GetBase("Mass")
            massUnits(3) = theSession.Parts.Display.UnitCollection.GetBase("Length")

            Dim singleBodyArray() As Body = {theBody}
            Dim mb As MeasureBodies = myMeasure.NewMassProperties(massUnits, 1, singleBodyArray)
            mb.InformationUnit = MeasureBodies.AnalysisUnit.PoundFoot

            Dim centroidalPoint As Point3d = mb.Centroid()
            Echo("Centroid: " & centroidalPoint.X & "  " & centroidalPoint.Y & "  " & centroidalPoint.Z)
            Echo("  ")

            'get parent tag
            Dim parentTag As Tag
            ufs.Assem.AskParentComponent(theBody.Tag, parentTag)
            Dim bodyComp As Component = theSession.GetObjectManager.GetTaggedObject(parentTag)
            'get root name
            Dim c As ComponentAssembly = workPart.ComponentAssembly

            excel.Cells(2, 2) = theBody.OwningPart.Leaf

            excel.Cells(2, 3).value = c.RootComponent.GetStringAttribute("DB_PART_NAME")

            'find attribute data
            If bodyComp.HasUserAttribute("DB_PART_NAME", NXObject.AttributeType.String, -1) = True Then
                excel.Cells(row, 3) = bodyComp.GetStringAttribute("DB_PART_NAME")
            End If

            If bodyComp.HasUserAttribute("MF Material", NXObject.AttributeType.String, -1) = True Then
                excel.Cells(row, 7) = bodyComp.GetStringAttribute("MF Material")
            End If

            If bodyComp.HasUserAttribute("MF NN", NXObject.AttributeType.String, -1) = True Then
                excel.Cells(row, 9) = bodyComp.GetStringAttribute("MF NN")
            End If

            If bodyComp.HasUserAttribute("MF Modifier", NXObject.AttributeType.String, -1) = True Then
                excel.Cells(row, 8) = bodyComp.GetStringAttribute("MF Modifier")
            End If

            If bodyComp.HasUserAttribute("MF Type", NXObject.AttributeType.String, -1) = True Then
                excel.Cells(row, 10) = bodyComp.GetStringAttribute("MF Type")
            End If

            'bounding box 
            Dim bodyLengths(2) As Double
            bodyLengths = GetBoundingBox(theBody)

            'Measures Min/Max of all model parts in assembly 
            Dim bbox(5) As Double
            Dim tagList(0) As NXOpen.Tag
            ufs.Modl.AskBoundingBox(theBody.Tag, bbox)

            'write data to cells
            excel.Cells(row, 2).value = bodyComp.Parent.Prototype.OwningPart.Leaf
            excel.Cells(row, 4).value = bodyComp.Prototype.OwningPart.Leaf
            excel.Cells(row, 11).value = mb.Volume.ToString
            excel.Cells(row, 14).value = centroidalPoint.Z
            excel.Cells(row, 16).value = centroidalPoint.X
            excel.Cells(row, 18).value = centroidalPoint.Y
            excel.Cells(row, 21) = (bbox(0) / 12) 'LCG
            excel.Cells(row, 22) = (bbox(3) / 12)
            excel.Cells(row, 23) = (bbox(2) / 12) 'VCG
            excel.Cells(row, 24) = (bbox(5) / 12)
            excel.Cells(row, 25) = (bbox(1) / 12) 'TCG
            excel.Cells(row, 26) = (bbox(4) / 12)
            excel.Cells(row, 50).value = nextBody.ToString

            row = row + 1

        Loop Until nextBody.Equals(NXOpen.Tag.Null)

    End Sub

    Private Function GetBoundingBox(ByVal solidBody As NXOpen.Body) As Double()

        'AskBoundingBox returns min and max coordinates
        'this function will simply return the box lengths (x, y, z)
        Dim bboxCoordinates(5) As Double
        Dim bboxLengths(2) As Double

        Try
            'get solid body bounding box extents
            ufs.Modl.AskBoundingBox(solidBody.Tag, bboxCoordinates)
            bboxLengths(0) = bboxCoordinates(3) - bboxCoordinates(0)
            bboxLengths(1) = bboxCoordinates(4) - bboxCoordinates(1)
            bboxLengths(2) = bboxCoordinates(5) - bboxCoordinates(2)

            Return bboxLengths

        Catch ex As NXException
            MsgBox(ex.GetType.ToString & " : " & ex.Message, MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "Solid Body Bounds Error!")
            bboxLengths(0) = 0
            bboxLengths(1) = 0
            bboxLengths(2) = 0
            Return bboxLengths
        End Try

    End Function


    Sub Echo(ByVal output As String)
        theSession.ListingWindow.Open()
        theSession.ListingWindow.WriteLine(output)
        theSession.LogFile.WriteLine(output)
    End Sub

    Public Function GetUnloadOption(ByVal arg As String) As Integer
        Return Session.LibraryUnloadOption.Immediately
    End Function
    Public Sub myWorksheet_SelectionChange(ByVal Target As Excel.Range) Handles myWorksheet.SelectionChange

        MsgBox("its firing")

        Dim theSession As Session = DirectCast(Activator.GetObject(GetType(Session), "http://localhost:4567/NXOpenSession"), Session)
        Dim ufs As UFSession = DirectCast(Activator.GetObject(GetType(UFSession), "http://localhost:4567/UFSession"), UFSession)

        Dim workPart As Part = theSession.Parts.Work
        Dim dp As Part = theSession.Parts.Display

        'Dim theCompName As String
        Dim theCompTag As NXOpen.Tag = NXOpen.Tag.Null
        Dim RowNum As Long

        RowNum = Target.Row
        TagIdentifier = excel.Cells(RowNum, 50).value()
        ufs.Disp.SetHighlight(TagIdentifier, 1)

        ReleaseComObject(Target)
    End Sub

    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed

        If myWorksheet IsNot Nothing Then
            FreeCOM(myWorksheet)
        End If
        If workbook IsNot Nothing Then
            FreeCOM(myWorksheet)
        End If
        If excel IsNot Nothing Then
            FreeCOM(excel, True)
        End If
    End Sub

End Class

有人可以告诉我他们认为这个问题是什么吗?

0 个答案:

没有答案