2017-03-22 4 views
0

テキストに格納されている数値を複数のワークシートの数値に変換しようとしています。私の問題は、私が一緒に手錠をかけたコードが過度の時間を費やしているようだということです。私は必要なワークシートと範囲をループするFor Eachステートメントを使用しています。それはExcelをクラッシュさせない、それはちょうど永遠に一見を走り続ける。For Eachステートメントで数値としてテキストとして格納された数値を変換する

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 

スクリプトの実行を停止して[デバッグ]をクリックすると、最初の[次へ]ステートメントに巻き込まれているようです。私は、値を変換するために使用しているメソッドは、必要以上に時間がかかりすぎるため、複数のシート上で実行する方がさらに悪いと思います。

私は、このプロセスをより速く実行するために、すべての提案には公開されています。前もって感謝します!

+0

最後に使用された行と列を探し、配列にすべてをロードして、変更を加えてから値を戻します。スピードアップします。それはあなたがテストしているすべてのセルをサイクリングして変更することです。それは長い時間がかかります。配列は指数関数的に高速化します。 –

+0

これは間違いなく私が想像するのを助けるでしょう。私のデータが特定のポイントを超えないことを知っているので、私の更新は私のために働く。しかし、私が時間を見つけたら、最後の行と列を見つけてここに投稿するようにコードを更新します。ありがとう!質問に入れる代わりに –

+0

のように新しいコードを答えとして入れてください。 –

答えて

1

以下のコードを試してみてください。バリアントを使用して配列をループするのではなく、インデックス番号を使用しました。私は間違っている可能性がありますが、For Eachはコレクションでしか動作しないと思います。私が間違っていると誰かが私を修正してください。 (編集:私は確かに間違っています。それぞれについてはうまく動作します)

いずれにしても、配列のインデックス番号がベストプラクティスです。

私はまたあなたの履歴書を削除し、正しく処理しました。 Resume Nextを使わないことを強くお勧めします。 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

私は計算を手作業にしたり、イベントを無効にしたりせずに試してみましたが、それと同じくらい時間がかかりましたが、それらの2つを追加すると約30秒で実行されます。ご協力いただきありがとうございます!また、私はDebug.Printオプションを保持しました。私は通常それを使用しませんが、これはエンドユーザのためのものですので、問題についてのダイアログを与えることは大きなアドバイスです。 –

+1

それを聞いてうれしい!計算イベントは主なパフォーマンスの向上の可能性が高いです。ただし、VBAも記述していない限り、エンドユーザーはdebug.printを見ることはできません。あなたはメッセージボックスを使ってこれを克服することができますが、あなたのシートネームはハードコーディングされているので理想的ではありません。 –

0

これは、ループが文字通りすべてのセルを通過しているためです。空白値のチェックを行うのに最適

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

""とvbNullstringが同じであるため、 'If r.Value <> vbNullString then'を使用するのが最善です。 –

+0

@BrandonBarney実際にはそうではありません。 null値と空白は2つの異なるもので、処理方法が異なります。これは特に優れています。 –

+0

空白と ""は2つの異なるものです。 vbNullStringは ""の定数式です。イミディエイトウィンドウを使用して、2つの間の等しいかどうかをチェックすることもできます(Debug.Print "" = vbNullString Trueを返します)。さて、空白文字はまったく別の話ですが、確かに異なって扱われますが、空白文字ではありません。これに興味があるかもしれません:http://stackoverflow.com/questions/32435320/is-there-any-difference-between-vbnullstring-and。 –

1

私は当初、Brandonの答えを使用しましたが、私の提案では、値を格納してメモリを変更するために配列を使用しました。以下は、私が今使用しています更新されたコードです:

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秒に短縮されました。みんなの入力と幸せなコーディングに感謝します!

関連する問題