2017-03-22 18 views
0

我試圖將存儲在文本中的數字轉換爲多個工作表上的數字。我的問題是,我拼湊在一起的代碼似乎花費了過多的時間。我使用For Each語句循環遍歷必要的工作表和範圍。它不會使Excel崩潰,它只是看起來永遠運行。將存儲爲文本的數字轉換爲數字(對於每個語句)

Sub ConvertTextToNumber() 
    Application.ScreenUpdating = False 
    Dim WshtNames As Variant 
    Dim WshtNameCrnt As Variant 
    Dim r As Range 

    WshtNames = Array("Financial Data", "Site Data ", "Org Data", "Program Data") 

    For Each WshtNameCrnt In WshtNames 
    On Error Resume Next 
     For Each r In Worksheets(WshtNameCrnt).UsedRange.SpecialCells(xlCellTypeConstants) 
      If IsNumeric(r) Then r.Value = Val(r.Value) 
     Next 
    Next 
    Application.ScreenUpdating = False 
End Sub 

當我停止腳本運行並單擊調試時,它似乎在第一個Next語句中被捕獲。我認爲我用來轉換值的方法只是比必要的更多的時間密集型,因此在多張紙上運行它更糟糕。

我願意接受任何和所有建議,以使此過程更快運行。提前致謝!

+0

查看查找使用的最後一行和列,將所有內容加載到數組中,執行更改並將值返回。它會加快速度。就像你在循環測試每個單元並對其進行更改一樣。這將需要很長時間。數組會加速成倍增長。 –

+0

這絕對會幫助我想象。據我所知,我的數據不會超出某個特定點,我的更新適用於我。但是,如果我找到時間,我會更新代碼以找到最後一行和一列,並將其發佈到此處。謝謝! –

+0

而不是將其放在問題中,請將新代碼作爲答案,因爲它是這樣的。 –

回答

1

試試下面的代碼。我使用了一個索引號,而不是使用變體來循環訪問數組。我可能是錯的,但我認爲For Each只適用於集合。有人請糾正我,如果我錯了。 (編輯:我確實錯了,因爲每個作品都很好。)

無論如何,數組上的索引號是最佳實踐。

我也刪除了您的簡歷下一步並妥善處理它。我強烈建議不要使用繼續下一步。我不能想到Resume Next不能被好邏輯取代的任何事件。

Sub ConvertTextToNumber() 
    Application.ScreenUpdating = False 

    ' These two statements should further improve processing time. 
    ' The first prevents formulas from calculating. The second prevents 
    ' any background events from firing (mostly for Event triggered macros). 
    Application.Calculation = xlCalculationManual 
    Application.EnableEvents = False 
    Dim WshtNames As Variant 
    Dim i as Long 
    Dim r As Range 

    WshtNames = Array("Financial Data", "Site Data ", "Org Data", "Program Data") 

    ' When looping over an array use an index number. 
    ' I this case, 'i' will go from the lowest range of the array 
    ' all the way through to the highest range of the array. 
    For i = LBound(WshtNames) to Ubound(WshtNames) 
     'On Error Resume Next ' It is best to catch the errors, dont just skip them. 
     If Not Worksheets(WshtNames(i)) Is Nothing Then 
      For Each r In Worksheets(WshtNames(i)).UsedRange.SpecialCells(xlCellTypeConstants) 
       ' No need to check for an empty string here since 
       ' IsNumeric() will return false for non-numbers. 
       If IsNumeric(r) Then r.Value = Val(r.Value) 
      Next 
     Else 
      ' Put your error handling in here, or you can just skip it 
      ' I tend to use debug.print just to keep track. 
      Debug.Print WshtNames(i) & " doesn't exist." 
     End If 
    Next 
    Application.ScreenUpdating = True 

    Application.Calculation = xlCalculationAutomatic 
    Application.EnableEvents = True 
End Sub 
+1

我試了一下,沒有將計算放到手動和禁用事件上,而且花費了很長時間,但隨着這兩個的增加,它現在運行在大約30秒的光年更好。謝謝你的幫助!另外,我保留了Debug.Print選項。我通常不會使用它,但是這是給最終用戶的,所以給他們關於問題的對話是很好的建議。 –

+1

很高興聽到它!計算事件可能是主要性能提升。請記住,儘管您的最終用戶可能永遠也看不到debug.print,除非他們也在編寫VBA。你可以通過使用一個消息框來解決這個問題,但是你的表名是硬編碼的,所以這不太理想。 –

0

嗯,這是因爲你的循環逐字地經過每個單元格。最好對空白值進行一些檢查

IF r.Value <> "" or r.value <> vbnullstring then 
+0

「」和vbNullstring是相同的,所以最好使用'If r.Value <> vbNullString then'。 –

+0

@BrandonBarney其實他們不是。空值與空白是兩個不同的東西,得到不同的處理。 excel尤其如此。 –

+0

空格和「」是兩個不同的東西。 vbNullString是「」的常量表達式。你甚至可以使用即時窗口來檢查兩者之間的相等性(Debug.Print「」= vbNullString返回True)。現在,空白字符是一個完全不同的故事,當然處理方式不同,但「」不是空格。您可能對此感興趣:http://stackoverflow.com/questions/32435320/is-there-any-difference-between-vbnullstring-and。 –

1

我最初使用布蘭登的答案,但根據他的建議,我研究了使用數組來存儲值並在內存中進行更改。下面是我現在用更新的代碼:

Sub ConvertTextToNumber() 
    Application.ScreenUpdating = False 
    Application.Calculation = xlCalculationManual 
    Application.EnableEvents = False 
    Dim WshtNames As Variant 
    Dim DataRange As Variant 
    Dim r As Range 
    Dim i As Long 
    Dim lrow As Long 
    Dim lcol As Integer 
    Dim MyVar 

    WshtNames = Array("Financial Data", "Site Data ", "Org Data", "Program Data") 
    DataRange = Range("A1:FZ6000").Formula 

    For lrow = 1 To 6000 
     For lcol = 1 To 156 
     MyVar = DataRange(lrow, lcol) 
     If IsNumeric(MyVar) Then 
      MyVar = Val(MyVar) 
      DataRange(lrow, lcol) = MyVar 
     End If 
     Next lcol 
    Next lrow 
    Range("A1:FZ6000").Formula = DataRange 

    Application.ScreenUpdating = False 
    Application.Calculation = xlCalculationAutomatic 
    Application.EnableEvents = True 
End Sub 

這對我的作品,因爲我知道,我的牀單永遠不會超越我根據我的數據的性質選擇的範圍。這有效地將我的計算時間縮短到了2秒。感謝大家的意見和快樂編碼!

相關問題