• 締切済み

[VBAマクロ] Private Sub

以下のコードは、ある任意のテーブルの最終行に何か入力すると自動的に新しい行を追加します。(例えば、TotalVal をセルR5に名前定義して、4行目に何か入力するとマクロが走って5行目に新規の行が挿入されます。) 新規の行を入力するだけでなく、直前行の計算式とフォーマット形式もコピーして行の挿入をするにはどうしたらよいか、どなたかご教示していただけませんでしょうか。よろしくお願います。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row = [TotalVal].Row - 1 Then Application.EnableEvents = False [TotalVal].EntireRow.Insert Application.EnableEvents = True End If End Sub

みんなの回答

回答No.3

こんにちは。 すみません。今の内容だけでは、何か足らない気がしています。 本日は、完成しませんし、明日はお応えできるか分かりません。 >4行目にいろんな式や入力規制とかあってそれをそのまま5行目にコピーして、 >それ以降は新規行が挿入されるたびにその直前一行前をコピーして新規行に貼り付けというのをやりたいのです…… これまでに、分かったことをまとめますと、 ---------------------------------- 表の計算は、テーブル内で行われていること。 「TotalVa」 の名前登録の「R5」というのは、R1C1型の5行目ということ。 4行目に数式(SUM関数)や入力規則があること。 「計算式を含む行とそれ以前を挿入する」と、R1からR4の合計のSUM関数の計算がずれること。 SUM関数の後の新規の行が挿入されたら、直前一行前をコピーして新規行に貼り付けすること。 (つまり、SUM関数はコピーはしないから、SUM関数の次の次の行からイベント・ドリブン型のマクロが起動する) ----------------------------------------- ここまでは、良ろしいのでしょうか? 最大の問題点は、Worksheet_Changeのイベント・ドリブン型ですから、入力のたびにマクロが走ってしまうこと。 4行目に挿入したら、数式等は、5行目に移ります。 行が挿入されたら、数式などが下に移動するだけです。それ自体をコピーをする必要などはありません。 実際、SUM関数などをコピーしたら、二重の計算になって意味を持ちません。 >それ以降は もう一つは、名前定義の「TotalVal」の存在です。これ自体は、ワークシートに属するものですから、マクロでは確実な把握はできません。 挿入はともかく、削除したりすれば、マクロがエラーになってしまいます。 ------------------------ 試験段階としては、Calculate イベントで考えてみました。ただ、Calculateイベントは、ワークブック全体に走るイベントですから、シートのみにするために、施してあります。実用度はかなり低いものだと思っています。また、名前定義はなくなる可能性があるので、そのチェック項目を付けました。もともと、何かの値を入れて、挿入を繰り返すというのは、そのテーブルをいじることが出来ないのではないか、と思いました。本日は、ここまでといたします。 少し、日にちが空くかもしれませんが、ご容赦のほどをお願いします。できたら、私の疑問点にお応えください。 '// Private Sub Worksheet_Calculate()  Dim rng As Range  Dim i As Long  Dim num As Long  On Error Resume Next  i = Range("TotalVal").Row '名前登録のチェック  num = Err.Number  On Error GoTo 0  If ActiveCell.Parent.Parent.Name <> ThisWorkbook.Name Then Exit Sub  If Intersect(ActiveCell, Me.ListObjects(1).Range) Is Nothing Then Exit Sub  Set rng = Intersect(ActiveCell.EntireRow, Me.ListObjects(1).Range)  If rng.Cells(1).Offset(1).HasFormula = True Then   With rng.Cells(1).Offset(1)    If InStr(1, .FormulaLocal, "=SUM", vbTextCompare) > 0 Then     Application.EnableEvents = False     For Each c In .Rows.Cells      c.FormulaLocal = "=SUM(R1C:R[-1]C)"     Next    End If   End With   On Error Resume Next    With Me.ListObjects(1).Range    Application.EnableEvents = False     .Rows(rng.Row - 1).Copy     .Rows(rng.Row).PasteSpecial Paste:=11    End With    Application.CutCopyMode = False    On Error GoTo 0  ElseIf num = 0 Then   If rng.Row > i And _    rng.Rows.Cells(1).Value = "" Then    Application.EnableEvents = False    On Error Resume Next    With Me.ListObjects(1).Range     .Rows(rng.Row - 1).Copy     .Rows(rng.Row).PasteSpecial Paste:=11    End With    Application.CutCopyMode = False    On Error GoTo 0    Application.EnableEvents = True   End If   Else    If num > 0 Then     MsgBox "名前登録'TotalVal' は壊れています。", 16    ElseIf Intersect(Range("TotalVal"), Me.ListObjects(1).Range) Is Nothing Then     MsgBox "名前登録'TotalVal' はテーブルの範囲外にあります。", 16    End If  End If  i = 0  Application.EnableEvents = True End Sub '//

回答No.2

こんにちは。 また、もしかしてなのですが、 >R5にはsum計算式があり、R1からR4の合計 それは、R1C1方式なのではありませんか? その場合は、R5の数式は、=SUM(R1C:R5C)ではなく、相対参照式で、 =SUM(R[-5]C:R[-1]C) にすれば、数式は、挿入しても、そのまま生きているはずです。 (R[-5]は、R1の部分に、項目名が入っていない場合です。)

sdguy1973
質問者

補足

ありがとうございます。 4行目にいろんな式や入力規制とかあってそれをそのまま5行目にコピーして、それ以降は新規行が挿入されるたびにその直前一行前をコ ピーして新規行に貼り付けというのをやりたいのですが、どうしたらよいのでしょうか? よろしくお願います。

回答No.1

こんにちは。 もしかしてですが、 >任意のテーブルの最終行に何か入力すると自動的に新しい行を追加します。 この仕様をテーブル全体にしたいということでしょうか?それとも、4行目に対してのみですか? >TotalVal をセルR5に名前定義して これ自体、なぜ名前定義をしているのかよく分からないのですが、今のコードですと、4行目の対象セルが下にズレていくようです。

sdguy1973
質問者

補足

お返事ありがとうございます。 R5にはsum計算式があり、R1からR4の合計が計算されています。行を挿入する度にsum計算式がズレて常にR1から直前行の合計が見えるようにしたいのです。

関連するQ&A

  • エクセル マクロ 初心者です

    エクセルマクロ初心者です。 以下の2つの Private Sub Worksheet_Change(ByVal Target As Range)を1つのシートで実行させたいのですが、 当方、初心者なので組み合わせ方が分かりません。 よろしくお願いします。 ===No1=== Private Sub Worksheet_Change(ByVal Target As Range) Application.EnableEvents = False Target = StrConv(Target, vbUpperCase) Application.EnableEvents = True End Sub ===No2=== Private Sub Worksheet_Change(ByVal Target As Range) Dim Ans As Integer If Target.Count = 1 Then Ans = MsgBox("コピーは禁止!!", vbCritical) MsgBox "データを消去します。" With Application .EnableEvents = False .Undo .EnableEvents = True End With End If If Target.Count = 1 Then Exit Sub Else MsgBox “複数セルのコピー禁止!" With Application .EnableEvents = False .Undo .EnableEvents = True End With End If End Sub ------------ 上記の2つを1つのシートで動作させたいのですが、うまくいきません。 単体では、動作します。

  • 2つのVBAを組み合わせる方法

    お世話になります、2つのVBAを組み合わせる方法で迷っています。 1つ目が Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Intersect(Target, Range("C1,B9:B39")) Is Nothing Or Target.Count > 1 Then Exit Sub Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True End Sub です。 2つめが Private Sub Worksheet_Change(ByVal Target As Range)  Application.EnableEvents = True If Intersect(Target, Range("R8:R38")) Is Nothing Then Exit Sub Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End Sub です。2つのPrivate Sub Worksheet_Change(ByVal Target As Range)イベントのVBAですが、どのようにして組み合わせれば良いのでしょうか?

  • (少数点、第三位で切り捨て)をしたいんですが、このマクロに何を足せばいいですか??

    四捨五入を切捨て(第三位)するにはどうしたらいいのでしょうか?? VBAをちゃんと理解できていないので、誰か分かる人助けてください!! ついでにROUNDDOWNとかの関数はVBAに入力するコードとしては、 まったく別物なんでしょうか??初心者が生意気言ってすいません・・・。 Private Sub Worksheet_Change(ByVal Target As Range) On Error Resume Next Application.EnableEvents = False If Range(Target.Address).Column = 2 And _ Range(Target.Address).Row >= 5 And _ Range(Target.Address).Row <= 10 Then Range(Target.Address).Value = _ Range(Target.Address).Value / 19 End If Application.EnableEvents = True End Sub よろしくおねがいします。

  • (少数点、第三位から切り捨て)をこのマクロにどう入力すればいいですか??

    四捨五入を切捨て(第三位)するにはどうしたらいいのでしょうか?? VBAをちゃんと理解できていないので、誰か分かる人助けてください!! ついでにROUNDDOWNとかの関数はVBAに入力するコードとしては、 まったく別物なんでしょうか??初心者が生意気言ってすいません・・・。 Private Sub Worksheet_Change(ByVal Target As Range) On Error Resume Next Application.EnableEvents = False If Range(Target.Address).Column = 2 And _ Range(Target.Address).Row >= 5 And _ Range(Target.Address).Row <= 10 Then Range(Target.Address).Value = _ Range(Target.Address).Value / 19 End If Application.EnableEvents = True End Sub よろしくおねがいします・・。 カテゴリー間違えて入れなおしました。すみません・・。

  • excel 2007 VBA コードの記述

    Excel 2007 を使用しています。 TEST.xlsm というブック内に テスト01 というシートを作成し、そのタブを右クリックして コードの表示 を選択。 表示されたVBAコード入力シートに下記のコードを記述して使用してます。 Private Sub Worksheet_Change(ByVal Target As Range) 'この行から If Intersect(Target, Range("E3:E33,G3:G33,AH3:AH33,AJ3:AJ33,BK3:BK33,BM3:BM33")) Is Nothing Or Selection.Count <> 1 Then Exit Sub Application.EnableEvents = False If Target <> "" Then If IsNumeric(Target) Then Target = Target - 23 End If End If Application.EnableEvents = True End Sub 'この行まで この条件に新たに下記のコードを追加したいと思い ネット検索しながらあれこれ試行錯誤してますが まだまだVBA初心者のため上手く機能してくれません。 ※上のコードだけなら思った通りに機能します。 Private Sub Worksheet_Change(ByVal Target As Range) 'この行から If Intersect(Target, Range("Y3:Y33,BB3:BB33,CE3:CE33")) Is Nothing Or Selection.Count <> 1 Then Exit Sub Application.EnableEvents = False If Target <> "" Then If IsNumeric(Target) Then Target = Target - 30 End If End If Application.EnableEvents = True End Sub 'この行まで どなたかこれら二種のコードを一つにまとめた記述方法を 教えて頂けますでしょうか?

  • エクセルでデータ入力された日付と時間を自動入力する

    前回ご質問にて 1行目に何か入力したら2行目に日付と時間を自動入力する というVBAを教えて頂きました。 ------------------------ Private Sub Worksheet_Change(ByVal Target As Excel.Range) Application.EnableEvents = False If Target.Row = 1 Then Target.Offset(1, 0).Value = Format(Now, "yyyy/mm/dd"" ""hh:mm:ss") End If Application.EnableEvents = True End Sub ------------------------ これを1行目に何か入力したら2行目に日付と時間ではなく セル指定を行いたいのです。 例)F13~P13に何か入力したら、その下のセルの F14~P14に日付と時間が自動入力される という作りです。 よろしくお願いします。

  • VBAの日付チェックでオーバーフローを回避したい。

    VBAの日付チェックでオーバーフローを回避したい。 ExcelのG列のセルに入力されたものが日付型であるかどうかのチェックかけたいと思います。 以下のコードだと、数字2958466以上の入力でオーバーフローが発生します。 これを回避する方法はありますか? セルを日付型に設定しているため、2958465(2999/12/31)までしか判別できないのでしょうが、 利用者が2958466以上を入力してしまう可能性はあります。 オーバーフローではなく、エラーメッセージが出せたら・・・と思います。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 8 Then Application.EnableEvents = False If Target <> "" And Not IsDate(Target) Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select End If Application.EnableEvents = True End If End Sub こんなコードも試しましたが、結果は同じでした。 ↓ Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 8 Then Application.EnableEvents = False If Target > 2958466 Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select Else If Target <> "" And Not IsDate(Target) Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select End If End If Application.EnableEvents = True End If End Sub On Error Resume Next や On Error GoTo ... での対処も考えましたが、同じ結果でした。 何か良い方法がありましたら、お願いいたします。

  • エクセル:シート内に入力があった場合のマクロの書き方

    シート内に入力があった時の処理を作作りたいです。 現状の作り方は、シートのコードにWorksheet_Changeを用意し、 その中に「Target.Addressを取得し、そのアドレスに応じて処理をする」と書き込んでいます。 例えば以下は、入力があったら3列離れた同じ行に同じ内容入力をする、というコードです。 Private Sub Worksheet_Change(ByVal Target As Range)   Dim T_row As Integer, T_col As Integer   T_row = Target.Row   T_col = Target.Column + 3   Application.EnableEvents = False   Cells(T_row, T_col).Value = Target   Application.EnableEvents = True End Sub このコードの作り方だと、1つのセルへの入力にしか対応しないというか、 ドラッグやコピー&ペースト等、複数のセルにまたがった操作をすると動きません。 そういった通常可能な操作にも対応できるように作っていきたいのですが、 その場合どのように書き始めていけばよいでしょうか。 面倒な質問となってしまいましたが、 お時間あればよろしくお願いします。

  • エクセル VBAマクロ if文 はどうすれば?

    先ほど質問したのですが、さらにわからなくなったのでお願いします 先ほどの質問 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ http://okwave.jp/qa/q7236338.html >変数と式の両立は難しいでしょうからどうすればよいのでしょう?  ⇒関数では出来無いのはエクセルの常識ですのでマクロ(VBA)組込みになります。 一例です。 対象シートタブ上で右クリック→コードの表示→以下のコード貼り付けてA1に枚数を入力して お試しください。 サンプルコード Private Sub Worksheet_Change(ByVal Target As Range) 単価 = 5 If Intersect(Target, Range("A1")) Is Nothing Then Exit Sub If IsNumeric(Target.Value) And Target.Value > 0 Then  Application.EnableEvents = False  Target.Value = Target.Value * 単価  Application.EnableEvents = True End If End Sub ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ↓変更&応用したのですが、、、、 EX:(セル)    セル番号  用紙種類1~3       用紙種類    C12   A3モノクロ1     D12  A3カラー1    C13   A3モノクロ2     D13  A3カラー2    C14   A3モノクロ3     D14  A3カラー3 ※金額の違いは、モノクロとカラーの値段が違うだけ  1~3は金額的な違いはない とあった場合、 ためしに先ほどのを応用して用いたのですが 変更点は、用紙サイズ、カラーの有無による金額        出力先セルの番号 Private Sub Worksheet_Change(ByVal Target As Range) を Private Sub A4_mono_1(ByVal Target As Range) Private Sub A4_mono_2(ByVal Target As Range) ・             ・            ・ と変更したのですがうまく動作しなかったのですが、 どういった点が悪かったのでしょうか? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 最終的な質問↓ 上記のものはVBAマクロ文は基本1つのみなので、if文で作らなくてはいけないということが分かったのですが、そこでさらに疑問が浮かびました、 Private Sub Worksheet_Change(ByVal Target As Range) If or(target.columns = C12:C14) Then 単価1 = 7.6 If Intersect(Target, Range("C12:C14")) Is Nothing Then Exit Sub If IsNumeric(Target.Value) And Target.Value > 0 Then Application.EnableEvents = False Target.Value = Target.Value * 単価1 Application.EnableEvents = True単価1 = 7.6 elseif or(target.columns = D12:D14) Then 単価2 = 30.6 If Intersect(Target, Range("D12:D14")) Is Nothing Then Exit Sub If IsNumeric(Target.Value) And Target.Value > 0 Then Application.EnableEvents = False Target.Value = Target.Value * 単価2 Application.EnableEvents = True End If End Sub としたっ場合全く式になっていません どのようにすればよいのでしょう?

  • このマクロあっていますでしょうか?よろしくお願いいたします。

    ★sheetA Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$C$14" And Target.Address <> "$C$19" _ And Target.Address <> "$F$19" Then Exit Sub If Target.Address <> "$R$14" And Target.Address <> "$S$14" _ And Target.Address <> "$T$19" Then Exit Sub Application.EnableEvents = False With Sheets("B") .Range("F14").Value = Range("C14").Value .Range("F17").Value = Range("C19").Value .Range("F20").Value = Range("F14").Value .Range("F23").Value = Range("F19").Value End With With Sheets("C") .Range("F13").Value = Range("R14").Value .Range("F14").Value = Range("S14").Value .Range("F18").Value = Range("T19").Value End With Application.EnableEvents = True End Sub ★sheetB Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$F$14" And Target.Address <> "$F$17" _ And Target.Address <> "$F$23" Then Exit Sub Application.EnableEvents = False With Sheets("A") .Range("C14").Value = Range("F14").Value .Range("C19").Value = Range("F17").Value .Range("F19").Value = Range("F23").Value End With Application.EnableEvents = True End Sub ★sheetC Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$F$13" And Target.Address <> "$F$14" _ And Target.Address <> "$F$18" Then Exit Sub Application.EnableEvents = False With Sheets("A") .Range("R14").Value = Range("F13").Value .Range("S14").Value = Range("F14").Value .Range("T19").Value = Range("F18").Value End With Application.EnableEvents = True End Sub

専門家に質問してみよう