9

私はマクロを書いた経験があまりないので、次の問題が発生した場合はこのコミュニティの助けが必要です:

私のマクロは、1 つのワークシートの縦方向の範囲に入力された値の範囲をコピーし、別のワークシートに値を横方向 (転置) に貼り付けます。理論的には、最初のシートの値を、内容のない 2 番目のワークシートの最初の行に貼り付けます。最初の 5 行にはコンテンツがあるため、値を 6 行目に貼り付けます。マクロの実行に関して私が抱えている問題は、マクロが遅すぎると感じているため、より速く実行したいということです。

同じことを行う同じマクロがありますが、代わりに値を別のワークシートの最初の行に貼り付け、完全に実行されます。

したがって、2 番目のマクロは 6 行目から貼り付けを開始する必要があり、最初の 5 行にはマクロの実行に時間がかかるコンテンツが含まれている可能性があるため、実行速度が遅いと推測されます (多くの他のワークブックへのセル参照) を使用して、貼り付ける次の行の場所を決定します。それは私の最善の推測ですが、私はマクロについてほとんど何も知らないので、何が問題なのかはっきりとは言えません.

ここに私のマクロのコードを提供します。誰かが私のマクロを遅くしている原因を教えて、それをより速く実行する方法についての解決策を提供してくれることを心から願っています. 解決策は、マクロがデータの最初の 5 行を考慮せず、最初のエントリの 6 行目にすぐに貼り付けを開始することである可能性があると考えています。次回は7行目など。これは解決策かもしれませんが、それを行う方法でコードを書く方法がわかりません。

時間を割いて解決策を見つけるのを手伝ってくれてありがとう、コードは次のとおりです。

Sub Macro1()
Application.ScreenUpdating = False

    Dim historyWks As Worksheet
    Dim inputWks As Worksheet

    Dim nextRow As Long
    Dim oCol As Long

    Dim myCopy As Range
    Dim myTest As Range

    Dim lRsp As Long

    Set inputWks = wksPartsDataEntry
    Set historyWks = Sheet11

      'cells to copy from Input sheet - some contain formulas
      Set myCopy = inputWks.Range("OrderEntry2")

      With historyWks
          nextRow = .Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Row
      End With

      With inputWks
          Set myTest = myCopy.Offset(0, 2)

          If Application.Count(myTest) > 0 Then
              MsgBox "Please fill in all the cells!"
              Exit Sub
          End If
      End With

      With historyWks
          With .Cells(nextRow, "A")
              .Value = Now
              .NumberFormat = "mm/dd/yyyy hh:mm:ss"
          End With
          .Cells(nextRow, "B").Value = Application.UserName
          oCol = 3
          myCopy.Copy
          .Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True
          Application.CutCopyMode = False
      End With

      'clear input cells that contain constants
      With inputWks
        On Error Resume Next
           With myCopy.Cells.SpecialCells(xlCellTypeConstants)
                .ClearContents
                Application.GoTo .Cells(1) ', Scroll:=True
           End With
        On Error GoTo 0
      End With

Application.ScreenUpdating = True
End Sub
4

7 に答える 7

7

すでに述べたことを繰り返すだけです:

Option Explicit

Sub Macro1()

'turn off as much background processes as possible
With Excel.Application
        .ScreenUpdating = False
        .Calculation = Excel.xlCalculationManual
        .EnableEvents = False
End With

    Dim historyWks As Excel.Worksheet
    Dim inputWks As Excel.Worksheet

    Dim nextRow As Long
    Dim oCol As Long

    Dim myCopy As Excel.Range
    Dim myTest As Excel.Range

    Dim lRsp As Long

    Set inputWks = wksPartsDataEntry
    Set historyWks = Sheet11

      'cells to copy from Input sheet - some contain formulas
      Set myCopy = inputWks.Range("OrderEntry2")

      With historyWks
          nextRow = .Cells(.Rows.Count, 1).End(Excel.xlUp).Offset(1, 0).Row
      End With

      With inputWks
          Set myTest = myCopy.Offset(0, 2)

          If Excel.Application.Count(myTest) > 0 Then
              MsgBox "Please fill in all the cells!"
              GoTo QuickExit
          End If
      End With

      With historyWks
          With .Cells(nextRow, 1)
              .Value = Now
              .NumberFormat = "mm/dd/yyyy hh:mm:ss"
          End With
          .Cells(nextRow, 2).Value = Excel.Application.UserName
          oCol = 3
          myCopy.Copy
          .Cells(nextRow, 3).PasteSpecial Paste:=Excel.xlPasteValues, Transpose:=True
          Excel.Application.CutCopyMode = False
      End With

      'clear input cells that contain constants
      With inputWks
        On Error Resume Next
           With myCopy.Cells.SpecialCells(Excel.xlCellTypeConstants)
                .ClearContents
                Excel.Application.Goto .Cells(1) ', Scroll:=True
           End With
        On Error GoTo 0
      End With

    Calculate

QuickExit

With Excel.Application
        .ScreenUpdating = True
        .Calculation = Excel.xlAutomatic
        .EnableEvents = True
End With

End Sub

マクロを 1 行ずつ実行して、どの行が遅いかを突き止めようとします。

別の代替手段 - 速度が上がるかどうかはわかりませんが - クリップボードを避けてを失うcopy/pasteことです。そのため、次のような方法を適用してデータを移動します。

Option Explicit

Sub WithoutPastespecial()

'WORKING EXAMPLE

Dim firstRange As Range
Dim secondRange As Range

Set firstRange = ThisWorkbook.Worksheets("Cut Sheet").Range("S4:S2000")
With ThisWorkbook.Worksheets("Cutsheets")
    Set secondRange = .Range("A" & .Rows.Count).End(Excel.xlUp).Offset(1)
End With

With firstRange
      Set secondRange = secondRange.Resize(.Rows.Count, .Columns.Count)
End With
secondRange.Value = firstRange.Value

End Sub
于 2013-01-02T17:27:30.177 に答える
7

私の経験に基づいてパフォーマンスを向上させる最善の方法は、値を検索するたびにスプレッドシートにアクセスするのではなく、コード内の変数を操作することです。作業したい範囲を変数 (バリアント) に保存してから、それがシートであるかのように反復処理します。

    dim maxRows as double
    dim maxCols as integer.
    dim data as variant
with someSheet
    maxRows = .Cells(rows.count, 1).end(xlUp).row             'Max rows in sheet
    maxCols = .Cells(1, columns.count).end(xlToLeft).column   'max columns in sheet
    data = .Range(.Cells(1,1), .Cells(maxRows, maxCols))      'copy range in a variable
end with

ここから、スプレッドシートのようなデータ変数にアクセスできます-データ(行、列)の読み取り速度がはるかに高速です。

于 2013-03-08T11:18:57.167 に答える
5

こちらの記事も合わせてご覧ください。 計算を高速化し、パフォーマンスを向上させる方法...

どうしても、 Application.calculation= xlCalculationManual が通常犯人です。しかし、揮発性の Excel シート関数は、大規模なデータ処理と機能面でアプリケーションをほとんど停止させる可能性があることに気付くことができます。

また、現在のコードでは、次の投稿は直接関係ない場合があります。全体的な Excel/VBA パフォーマンスの最適化に関するヒントとして役立つと思います。

75 Excel 高速化のヒント

PS: あなたの投稿にコメントするほどの評判はありません。だから答えとして追加..

于 2012-11-07T06:06:12.467 に答える
1

コメントで他の数人が示唆しているように、Application.CalculationをxlCalculationManualに変更し、最後にxlcalculationAutomaticに戻すように覚えておく必要があります。また、Application.Screenupdating = Falseを設定してみてください(そして、それを再びオンに戻します)。また、.Copyはセル値をコピーする非常に非効率的な方法であることに注意してください。本当に値が必要な場合は、範囲設定.Valueを古い範囲の.Valuesにループします。すべてのフォーマットが必要な場合は、おそらく.Copyで立ち往生しています。

計算/画面更新フラグをオフにするときは、すべての状況で(プログラムが別の時点で終了したり、ランタイムエラーが発生した場合でも)必ずオンに戻すことを忘れないでください。そうでなければ、あらゆる種類の悪いことが起こります。:)

于 2012-11-30T01:20:16.163 に答える
1

いくつかの提案(コメントとして投稿したはずですが、担当者がいないと思います):

  1. 名前付き範囲の代わりにセル アドレスを参照してみてください (これが原因であることに疑いはありませんが、パフォーマンスに影響を与えている可能性があります)。

  2. ワークブックの数式に他のワークブックへのリンクが含まれていますか? リンクが壊れているファイルでコードをテストして、パフォーマンスが向上するかどうかを確認してください。

  3. これらのいずれも問題でない場合、私の推測では、数式が過度に複雑な場合は、処理のオーバーヘッドが追加されている可能性があります。値のみを含むファイルでコードを試して、パフォーマンスが向上するかどうかを確認してください。

于 2013-01-02T17:53:50.230 に答える
0

.Cells(nextRow, 3).PasteSpecial Paste:=xlPasteValues, Transpose:=True Application.CutCopyMode = False

私はそれをしません。切り取り、コピー、貼り付けの操作は、プロセッサの使用率という点で、オペレーティング システムで最もコストのかかる操作です。

代わりに、次のように、あるセル/範囲から別のセル/範囲に値を割り当てることができます。

    Cells(1,1) = Cells(1,2)  or Range("A1") = Range("B1")

あなたが私の要点を理解してくれることを願っています..

于 2016-09-09T10:31:33.777 に答える
0

セル値の変更中に計算を停止することで速度を改善でき、その後有効にすることができます。リンクをたどってください。 http://webtech-training.blogspot.in/2013/10/how-to-stop-heavy-formula-calculation.html

于 2013-12-20T16:51:42.253 に答える