Excel 在大型数据集中将字符串转换为数字

Excel 在大型数据集中将字符串转换为数字,excel,vba,Excel,Vba,我目前正在使用此代码将大量包含以文本形式存储的十进制数的单元格转换为十进制数: For Each ws In Sheets On Error Resume Next For Each r In ws.UsedRange.SpecialCells(xlCellTypeConstants) If IsNumeric(r) Then r.Value = CDbl(r.Value) Next Next 这个操作运行得很慢,如果可能的话,我希望它运行得更快 我是这

我目前正在使用此代码将大量包含以文本形式存储的十进制数的单元格转换为十进制数:

For Each ws In Sheets
    On Error Resume Next
    For Each r In ws.UsedRange.SpecialCells(xlCellTypeConstants)
        If IsNumeric(r) Then r.Value = CDbl(r.Value)
    Next
Next
这个操作运行得很慢,如果可能的话,我希望它运行得更快


我是这方面的初学者,上面显示的代码是通过谷歌收集的。是否可以通过编辑代码或使用其他代码来加快此操作?

关闭和打开UI

'turn off UI
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
Application.Calculation = xlManual

--- your code here

'turn on UI
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
Application.Calculation = xlAutomatic

试试这个。这使用数组来完成整个操作。与在每个范围内循环相比,这是非常快的

逻辑:

循环浏览图纸,找到最后一行和最后一列 确定范围,而不是盲目使用UsedRange。你可能想看看 将该数据复制到数组中 清除工作表-将工作表的格式重置为常规格式。希望工作表中没有其他格式?如果您已经看到了第二段代码。 将数据粘贴回工作表。 代码

截图

编辑

如果工作表中有其他格式,请使用此

Sub Sample()
    Dim ws As Worksheet
    Dim usdRng As Range, rng as Range
    Dim lastrow As Long, lastcol As Long
    Dim myAr

    For Each ws In Sheets
        With ws
            '~~> Check if sheet has any data
            If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
                '~~> Find Last Row
                lastrow = .Cells.Find(What:="*", _
                              After:=.Range("A1"), _
                              Lookat:=xlPart, _
                              LookIn:=xlFormulas, _
                              SearchOrder:=xlByRows, _
                              SearchDirection:=xlPrevious, _
                              MatchCase:=False).Row

                '~~> Find last column
                lastcol = .Cells.Find(What:="*", _
                              After:=.Range("A1"), _
                              Lookat:=xlPart, _
                              LookIn:=xlFormulas, _
                              SearchOrder:=xlByColumns, _
                              SearchDirection:=xlPrevious, _
                              MatchCase:=False).Column

                '~~> Set your range here
                Set usdRng = .Range("A1:" & _
                Split(.Cells(, lastcol).Address, "$")(1) & lastrow)

                On Error Resume Next
                Set rng = usdRng.SpecialCells(xlCellTypeConstants)
                On Error GoTo 0

                If Not rng Is Nothing Then
                    '~~> Write to array
                    myAr = usdRng.Value

                    '~~> Clear the Range
                    rng.NumberFormat = "0.00"
                    Set rng = Nothing

                    '~~> Clear contents of the sheet
                    usdRng.ClearContents

                    '~~> Write back to the sheet
                    .Range("A1").Resize(lastrow, lastcol).Value = myAr
                End If
            End If
        End With
    Next
End Sub
截图


根据您的内容,您可以使用

For Each r In ws.UsedRange.SpecialCells(xlCellTypeConstants,xlTextValues)
或者,使用myArray=rangeb2:x200将范围或其一部分移动到一个数组中,然后处理该数组并立即重写它。这要快得多,因为在您的示例中,慢的部分实际上是VBA和单元格之间的交互

Sub test()
    Dim src As Range
    Dim ar As Variant
    Dim r As Long, c As Long

    Set src = Range("b2").CurrentRegion
    ar = src    'move ange into array
    For r = 1 To UBound(ar, 1)
        For c = 1 To UBound(ar, 2)
            If VarType(ar(r, c)) = 8 Then 'string
                If IsNumeric(ar(r, c)) Then
                    ar(r, c) = CDbl(ar(r, c))
                End If
            End If
        Next c
    Next r
    src = ar    'write array back to sheet
End Sub

其他两个选项,无VBA:

启用错误检查如果禁用,请选择适当的范围,然后单击!,单击“转换为数字”

在单元格中输入1,选择并复制它。选择合适的范围,粘贴特殊…,操作乘法。将空白单元格转换为0

我的版本- 使用您的首选选项设置范围-我在这里刚刚使用了UsedRange,但是使用FIND Siddharth更好,因为代码使用了这个选项

我把数字1放在一个空白单元格中,我使用了工作表上的最后一个单元格,复制该数字并粘贴特殊和乘法-任何数字都将乘以1并返回一个数字,任何文本保持不变

Sub TurnToNumbers()

    Dim rng As Range

    With Worksheets("Sheet1")
        Set rng = .UsedRange.SpecialCells(xlCellTypeConstants)

        'Place 1 into an empty cell, copy it and pastespecial and multiply.
        .Cells(Rows.Count, 1) = 1
        .Cells(Rows.Count, 1).Copy
        rng.PasteSpecial Operation:=xlPasteSpecialOperationMultiply
        .Cells(Rows.Count, 1).ClearContents
    End With

End Sub

我不是excel专家,但确实在一张工作表中找到了:ActiveSheet.UsedRange.Value=ActiveSheet.UsedRange。Value@racraman:不,那不会有什么不同:不,那不会有什么不同。代码仍然会在单元格中循环,这会使它变慢:我知道,但这是迄今为止我拥有的最快的解决方案;-我还使用了这段代码,在我的例子中,它大大提高了性能。在您的例子中,它可能会有所帮助,因为您的数据集非常小:尝试创建一个包含50k行和1k列的excel文件,然后告诉我需要多少时间。如果所有单元格都以文本形式存储了数字,则代码将循环通过50000 X 1000=50000000个单元格。不管怎样,我把决定权留给你;在某些情况下,将excel宏移动到数据库是很有用的;如果这是体力劳动,我会用它。我正在创建一个工作簿,该工作簿从另一个工作簿收集数据并处理这些数据,包括将文本转换为数字。这可能是一个愚蠢的问题,但这个问题会在工作簿中的每个工作表中循环,并将所有内容转换为数字,从而将公式转换为数字吗?如何将代码更改为仅在选定的工作表中运行,在本例中为导入?是,这将在每个工作表中循环,并将存储为文本的数字转换为数字。是,它还会将公式转换为文本/数字。要使其适用于导入工作表,请删除for循环,然后在With Ws之前添加行集Ws=thisworkbook.sheetsImportIt在我的示例中似乎不会将十进制文本转换为数字。我已经上传了一个文件到dropbox,所以你可以检查设置。它似乎已将单元格格式转换为数字,但在脚本运行后,数字本身仍保留为文本。是否有作为十进制运算符的逗号?是的,逗号是十进制运算符。尝试将0.00换成0.00,但没有效果。这一个也可以直接快速工作!干杯@iDevlop
Sub TurnToNumbers()

    Dim rng As Range

    With Worksheets("Sheet1")
        Set rng = .UsedRange.SpecialCells(xlCellTypeConstants)

        'Place 1 into an empty cell, copy it and pastespecial and multiply.
        .Cells(Rows.Count, 1) = 1
        .Cells(Rows.Count, 1).Copy
        rng.PasteSpecial Operation:=xlPasteSpecialOperationMultiply
        .Cells(Rows.Count, 1).ClearContents
    End With

End Sub