vb.net excel 互操作的 IsDate 用户定义函数

IsDate user defined function for vb.net excel interop

以下代码是 TnTinMn 代码的简化版本。

我也明白这是干什么的:values(i, 1) = DateTime.TryParse(CStr(obj).Trim, dt)

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    Dim app As New Excel.Application
    app.Visible = True
    Dim wb As Excel.Workbook = app.Workbooks.Add()
    Dim ws As Excel.Worksheet = CType(wb.Worksheets(1), Excel.Worksheet)

    ws.Range("A1:A10000").Value2 = "Hello"
    ws.Range("A1").Value2 = "1/1/2000"
    ws.Range("A2").Value2 = "I am not a date"
    ws.Range("A3").Value2 = 100.123

    Dim values As Object(,) = CType(ws.Range("A1:A10000").Value, Object(,))

    For i As Integer = 1 To values.GetUpperBound(0)

        Dim typDate As Type = GetType(DateTime)
        Dim typString As Type = GetType(String)

        Dim obj As Object = values(i, 1)
        Dim typeOfObj As Type = obj.GetType

        Dim dt As DateTime

        If typeOfObj Is typDate Then
            values(i, 1) = True
        ElseIf typeOfObj Is typString Then
            values(i, 1) = DateTime.TryParse(CStr(obj).Trim, dt)
        Else
            values(i, 1) = False
        End If
    Next

    ws.Range("B1:B10000").Value = values
End Sub

另一个版本;

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    Dim app As New Excel.Application
    app.Visible = True
    Dim wb As Excel.Workbook = app.Workbooks.Add()
    Dim ws As Excel.Worksheet = CType(wb.Worksheets(1), Excel.Worksheet)

    ws.Range("A1:A10000").Value2 = "Hello"
    ws.Range("A1").Value2 = "1/1/2000"
    ws.Range("A2").Value2 = "I am not a date"
    ws.Range("A3").Value2 = 100.123

    Dim values As Object(,) = CType(ws.Range("A1:A10000").Value, Object(,))

    For i = 1 To values.GetUpperBound(0)
        If IsDate(values(i, 1)) Then
            values(i, 1) = True
        Else
            values(i, 1) = False
        End If
    Next

    ws.Range("B1:B10000").Value = values
End Sub

使用DateTime.TryParse():

Public Function IsDate(ByVal Input As String) As Boolean
    Return DateTime.TryParse(Input, Nothing)
End Function

I dont want to use following code because following code is very slow.

   For i = 1 To 10000
        If Not IsDate(WorkSheet1.Range("A" & i).Value.ToString) Then
            WorkSheet1.Range("B" & i).Value = "FALSE"
        End If
   Next

根据此声明,我假设工作簿无法使用 IsDate 函数。

当处理连续的 Excel 范围时,最好将值拉入数组并进行处理。您还可以将数组写入相同大小的范围。这样读写会比较快

下面的示例创建了一个新工作簿并将一些数据写入列 A。GetColumnA_SetColumnB 方法是您应该关注的。它检索列 A 中的值,然后处理它们。代码重用通过读取值创建的数组来保存确定值是否为有效 DateTime 的结果。请注意,由于 VBA IsDate 函数会将包含有效日期的字符串计算为 True,因此在所示方法中复制了此类函数。

Private Const lastRow As Int32 = 10000

Private Sub demo()
    Dim app As New Excel.Application
    Dim wb As Excel.Workbook = app.Workbooks.Add()
    Dim ws As Excel.Worksheet = CType(wb.Worksheets(1), Excel.Worksheet)
    CreateColumnA(ws)   ' creates some values to work with
    GetColumnA_SetColumnB(ws)
    ' leave excel open and in user control
    app.Visible = True
    app.UserControl = True
End Sub


Private Sub CreateColumnA(ws As Excel.Worksheet)
    Dim values As Object(,) = CType(Array.CreateInstance(GetType(Object), New Int32() {lastRow, 1}, New Int32() {1, 1}), Object(,))
    For i As Int32 = 1 To lastRow
        values(i, 1) = DateTime.Now()
    Next
    ws.Range("A1:A" & lastRow.ToString).Value = values  ' set formatted values
    ws.Range("A1").Value2 = "  1/1/2000"    ' set a string that Vba.IsDate interprets as a Date
    ws.Range("A2").Value2 = "I am not a date"
    ws.Range("A3").Value2 = 100.123
    ws.Range("A3").ClearFormats()   ' make sure its formatted as a number
End Sub

Private Sub GetColumnA_SetColumnB(ws As Excel.Worksheet)
    Dim rngA As Excel.Range = ws.Range("A1:A" & lastRow.ToString)
    Dim rngB As Excel.Range = rngA.Offset(0, 1)

    Dim values As Object(,) = CType(rngA.Value, Object(,)) ' retrieve the formatted values

    Dim typDate As Type = GetType(DateTime)
    Dim typString As Type = GetType(String)

    For i As Int32 = 1 To values.GetUpperBound(0)
        Dim obj As Object = values(i, 1)
        Dim typeOfObj As Type = obj.GetType

        If typeOfObj Is typDate Then
            values(i, 1) = True
        ElseIf typeOfObj Is typString Then
            ' it still may be a Date
            Dim dt As DateTime
            values(i, 1) = DateTime.TryParse(CStr(obj).Trim, dt)
        Else
            values(i, 1) = False
        End If
    Next
    ' write Column B
    rngB.Value = values
End Sub