2017-03-23 20 views
1

私は、3つのセルにヘッダーテキストを追加し、最後の行までずっと式を入力するVBAを作成しようとしています。私は、ヘッダーに何の問題を書き込みませんこれは、以下の書かれているが、それは私の最初の.Formulaへのを取得するときには、スローVBA式をセルに追加するには

アプリケーション定義またはオブジェクト定義のエラーこのように変更する必要は何

マクロは正常に実行されますか?問題は、あなたが式に引用符をエスケープされている可能性があり

Function Gre() 
    Range("E2").Select 
    ActiveCell.FormulaR1C1 = "Under" 
    Range("F2").Select 
    ActiveCell.FormulaR1C1 = "Over" 
    Range("G2").Select 
    ActiveCell.FormulaR1C1 = "Result" 

    With Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row) 
     .Formula = "=IF(C2<B2,B2-C2,"")" 
    End With 
    With Range("F2:F" & Cells(Rows.Count, "C").End(xlUp).Row) 
     .Formula = "=IF(C2>B2,C2-B2,0)" 
    End With 
    With Range("G2:G" & Cells(Rows.Count, "C").End(xlUp).Row) 
     .Formula = "=IF(F2>0,'Issue',"")" 
    End With 
End Function 
+0

1つのプロパティのみを割り当てるための利便性を活用している場合は、なぜあなたは 'WITH'ブロックを使用していますか? Formula = "= IF(C2 JamesFaix

答えて

2

(式は、セルの数式から直接引かれたので、私は、彼らは少なくとも、「フロントエンド」に有効な数式を知っているし、) 。

は何が必要です:最初の1のための

.Formula = "=IF(C2>B2,B2-C2,"""")" 

、例えば。他の見積もりも倍増する必要があります。これを行わない場合は、次のことができ

Dim ws as worksheet 
Set ws = Sheets("mySheet") 
ws.Range("E2").FormulaR1C1 = "Under" 

など

サイドノートとして、それはまたあなたのようなもので、作業中のシートを指定するのがベストだろうコードを実行中にエラーが発生することがあります。

+0

合意。 'Select'と' ActiveCell'を使うことは、シート名とセルアドレスを指定するだけでなく、はるかに遅く、あいまいです。 'ActiveCell'、' ActiveWorkbook'なども、特定のダイアログボックスが開いているときやフォーカスがあるときに値を持つことを止めます。 – JamesFaix

2
  1. OpiesDadが示唆しているように、あいまいさを最小限に抑えるために、ActiveCellなどを避けてください。
  2. Selectを使用すると、セルに直接割り当てるよりもパフォーマンスが大幅に低下します。
  3. 引用符を倍にすることでVBA内部のExcel式で引用符をエスケープする必要があるので、通常の空の文字列は""""になります。あなたはまた、式の中で一重引用符でIssueを持っています。それもエスケープされた二重引用符でなければなりません。
  4. Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row)が実際に何をしているのか分かりませんが、最後に使用したシートの行にE2を選択したようです。 Rows.Countを避けるか、シートの行を参照するだけで行10^31に移動します。 Worksheet.UsedRangeを使用して、コンテンツを含む最初の行と列からコンテンツを含む最後の行と列までの範囲を取得します。これには空文字列も含まれていますが、時には微妙なこともありますが、通常は何千もの余分な行を処理するよりも優れています。また

  1. あなたは一つだけの文を囲む場合、それは問題が発生することはありませんが、Withを使用する必要はありません。

  2. 理由がない限り、私はRange.FormulaRange.FormulaR1C1を混用しません。

    Function Gre() 
    
        Dim ws as Worksheet 
        Set ws = ActiveSheet 
    
        Dim used as Range 
        Set used = ws.UsedRange 
    
        Dim lastRow as Integer 
        lastRow = used.Row + used.Rows.Count - 1 
    
        ws.Range("E2").Formula = "Under" 
        ws.Range("F2").Formula = "Over" 
        ws.Range("G2").Formula = "Result" 
    
        ws.Range("E2:E" & lastRow).Formula = "IF(C2<B2, C2-B2, """")" 
        ws.Range("F2:F" & lastRow).Formula = "IF(C2<B2, C2-B2, 0)" 
        ws.Range("G2:G" & lastRow).Formula = "IF(F2>0, ""Issue"", """")" 
    
    End Function 
    
+1

これはすばらしい答えです。私はこれをすべて綴るにはあまりにも怠惰でした。 '.End(xlUp).Row'と組み合わせた 'Rows.Count'は、セルから値を削除した場合、' UsedRange'が問題を抱える可能性があるため、最後の行を見つける標準的な方法です。私は、式で設定しようとしている途中よりも、変数でこれを行うほうがはるかに良いということに同意します。他のすべてはスポットです。 – OpiesDad

-1

と同様に二重引用符を使用して、あなたはそれ以外の場合は、文字列を空に評価することが最初の二つの式に0を使用する必要があります。これにより、最後の数式に予期せぬ結果が生じることがあります。つまり、「Issue」が正しく返されません。あなたのデータと3つの新しい列の間の空白の列を持っていない場合は

あなたは、行の数を決定するためにCurrentRegionを使用することができます。

Range("E2:E" & Cells.CurrentRegion.Rows.Count).Formula = "=if(C2'<'B2,B2-C2,0)" 

Range("F2:F" & Cells.CurrentRegion.Rows.Count).Formula = "=if(C2>B2,C2-B2,0)" 

Range("G2:G" & Cells.CurrentRegion.Rows.Count).Formula = if(F2>0,""Issue"","""")" 
+0

数式のどれも「E列」を参照していないので、問題が発生するとは思われません。 – JamesFaix

0
  1. 最初の問題は、セルの選択です。これには、マクロを使用してセルを選択し、セルのアドレスを決定する必要があります。実際にセルを選択する必要がある場合は、Application.ScreenUpdating = Falseを使用してください。次に、マクロはセルのカーソル選択を表示する必要はありません。選択範囲を削除し、以下のような数式割り当てコード行に範囲を組み込むと、速度/効率がいくらか向上します。

    Range("E2").FormulaR1C1 = "Under"

  2. Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row)最小/最後使用するセルを決定するために、CTRLのキーストロークやアップキーを使用して、その後、ブランクカラム(行1048576)の最後のセルを選択するコードのバージョンです。これは、列が空白なので、毎回行数が1になります。最後の行を探しているからです。上からカウントダウンするほうが速いかもしれません。私のお気に入りの方法はループです。最後の行を探しながら、ループ内の変数をインクリメントします。次に、ボトムアップ戦略の代わりに変数を使用することができます。

    t = 0 
    Do Until Range("C2").Offset(t, 0).Value = "" 
    t = t + 1 
    Loop 
    
    With Range("E2:E" & t) 
    .Formula = "=IF(C2<B2,B2-C2,"""")" 
    End With` 
    
  3. TSQLと同じように、引用符文字には独自の引用符文字が必要です。

    .Formula = "=IF(C2<B2,B2-C2,"""")" 
    
  4. この場合、Range Fillup VBA関数を使用して、すべてのセルを下部からExcel式参照相対性を考慮した共通の式で満たすことができます。以下のコードは、ループカウンタから取得した範囲から始まります。次に、Excelの合計行からカウンター行に対応する行を差し引いた変数を設定します。次に、元の領域のサイズを必要な行のサイズに変更し、FillDown関数を使用して最初の数式をコピーします。
  5. 結果コードは次のとおりです。これはExcelの最後の行から始まる範囲を埋めるでしょう。

    Sub Gre() 
    Range("E2").FormulaR1C1 = "Under" 
    Range("F2").FormulaR1C1 = "Over" 
    Range("G2").FormulaR1C1 = "Result" 
    
    Do While Range("e2").Offset(t, 0).Value <> "" 
    t = t + 1 
    Loop 
    Range("E2").Offset(t, 0).Formula = "=IF(C2<B2,B2-C2,"""")" 
    r1 = Range("e2").EntireColumn.Rows.Count 
    r2 = Range("E2").Offset(t, 0).Row 
    Range("E2").Offset(t, 0).Resize(r1 - r2, 1).FillDown 
    Range("F2").Offset(t, 0).Formula = "=IF(C2>B2,C2-B2,0)" 
    Range("F2").Offset(t, 0).Resize(r1 - r2, 1).FillDown 
    Range("G2").Offset(t, 0).Formula = "=IF(F2>0,""Issue"","""")" 
    Range("G2").Offset(t, 0).Resize(r1 - r2, 1).FillDown 
    End Sub 
    
関連する問題