エクセル2003でマクロを組んでいます

このQ&Aのポイント
  • エクセル2003でマクロを組んでいます。Sheet1,Sheet2の2つのシートがあり、片方のシートの指定範囲に値を書き込むと、もう片方の同じ位置に同じ値が書き込まれるようなマクロを組みたいです。
  • Sheet1とSheet2のモジュールに値を入力した場合、同じ行の別のセルの色を塗るマクロを組みたいです。
  • ThisWorkBookモジュールのマクロとSheetモジュールのマクロを同時に使いたいですが、エラーが出てうまく動作しません。
回答を見る
  • ベストアンサー

ThisWorkBookモジュールとSheetモジュールの両立

エクセル2003でマクロを組んでいます。 Sheet1,Sheet2の2つのシートがあり、 片方のシートの"A4:G10"の範囲に値を書き込むと、もう片方の同じ位置に同じ値が書き込まれるようなマクロを組みたいです。 以前ここで教えていただいたものを改変して以下を作りました(ThisWorkBookモジュールです)。 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) Dim r As Range Dim Num As Integer Dim S As String, Sh_name As String Sh_name = ActiveSheet.Name Set r = Intersect(Target, Range("A4:G10")) If Not (r Is Nothing) Then Application.EnableEvents = False For Num = 1 To 2 S = "Sheet" & Num If S <> Sh_name Then Worksheets(S).Range(r.Address).Value = r.Value End If Next Application.EnableEvents = True End If End Sub ここまでは正常に動作します。 また、 Sheet1とSheet2のモジュールに、 A列のセルに値が入力された場合、同じ行のC列のセルの色を塗るという記述をしています。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 1 Then Cells(Target.Row, 3).Interior.ColorIndex = 5 End If End Sub これらを同時に生かしたいのですが、 どのように書けばいいでしょうか。 EnableEvents = False/Trueを消してしまうと、 Worksheets(S).Range(r.Address).Value = r.Valueが実行されるたびにThisWorkBookモジュールが動いているようです。 そして2回目のSet r = Intersect(Target, Range("A4:G10"))でエラーが出ます。 (エラーは出ずとも延々と(無限ではない回数)ThisWorkBookモジュールを繰り返したコードもありました。) よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

補足: >今考えうる「全て」は、値、フォントの色、セル背景色、罫線です。 もし、フォントの色、セルの背景色、罫線のイベントで取ろうとしたら、インスタンスを作らないといけないので、かなり長いコードになるし、まったく発想が違います。今の延長上ではありませんから、これ以上の方法を願うのでしたら、「作業グループ」を取ってください。 例:  Worksheets(Array("Sheet1", "Sheet2")).Select そうでなかったら、Worksheet_Activate() などで、特定の範囲をコピーしたほうが楽です。 以前も、同じような質問が出ていましたが、同期と言っても、二つのWindowを開くなら別ですが、そうでなければ、見えないシートに対しては、開けるまでは、正確にはどうなっているかはわからないのですから。(値は、参照式があるので別ですが。) >(3)は、ThisWorkBookモジュールで(2)を行った時にSheet2のシートモジュールが動いて欲しかったのですが、 それをするなら、もともと、Sheet イベントは不必要です。 サブルーチン・マクロを呼び出せばよいのです。 'ThisWorkbook モジュール Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)  Application.EnableEvents = False  If StrComp(Sh.Name, "Sheet1") = 0 And Not Intersect(Target, Range("A4:G10")) Is Nothing Then    Worksheets("Sheet2").Range(Target.Address).Value = Target.Value    Call WorksheetsChange(Target.Address)  ElseIf StrComp(Sh.Name, "Sheet2") = 0 And Not Intersect(Target, Range("A4:G10")) Is Nothing Then    Worksheets("Sheet1").Range(Target.Address).Value = Target.Value    Call WorksheetsChange(Target.Address)  End If  Application.EnableEvents = True End Sub '標準モジュール 'プロシージャ名は、紛らわしい名前をあえてつけた Sub WorksheetsChange(myTarget As String) Dim Sh As Worksheet   For Each Sh In Worksheets(Array("Sheet1", "Sheet2"))   With Sh   If .Range(myTarget).Column = 1 Then     If .Range(myTarget).Cells(1).Value <> "" Then       .Range(myTarget).Offset(, 2).Interior.ColorIndex = 5     Else       .Range(myTarget).Offset(, 2).Interior.ColorIndex = xlColorIndexNone     End If   End If   End With   Next Sh End Sub

rem_1982
質問者

お礼

回答ありがとうございます。 返信が遅れて申し訳ありません。 挙げていただいたコードで満足のいく結果となりました。 シートイベントは要らなかったんですね。 これから標準モジュールに、背景色以外で同期を取りたい内容を加えていこうと思います。 今回は作業グループは使わないことにしましたが、使った方が処理速度は速いでしょうか。

その他の回答 (2)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんばんは。 >『Sheet1と2において指定した範囲の全ての同期を取る』です。 >今考えうる「全て」は、値、フォントの色、セル背景色、罫線です。 なるべく、最初から、そういうことは書いていただいたほうがよいですね。あまり後出しの条件が多いと、書いてきた全ての内容がひっくり返ってしまうことがあります。 最初に書かなかったけれども、最初から同期を取る目的なら、二つのシートを作業グループにしたほうが早いです。それで全てが済むはずです。最初、掲示する前に、そういうマクロを書いたけれども、趣旨が違うと思って載せませんでした。 マクロのマクロのような方法は、難しくなるだけだと思います。 >すみません、絶対の自信があるわけじゃないのですが、 >できればどうヘンなのか教えていただけないでしょうか。 >Sh_name = ActiveSheet.Name >Set r = Intersect(Target, Range("A4:G10")) そういうコードを回答者の中でも書く人がいますが、引数がきちんと捕らえられていないと思います。 引数、Sh は、ActiveSheet だからですし、 Intersect(Target, Range("A4:G10")) シートの指定がない前の確実性がない時に、Intersect の戻り値を Range オブジェクトを変数に代入しているけれど、単に、範囲のチェッカーだけに使えばよいと思います。それと、引数 Target で取得しているのだから、それを使えば済むわけです。

rem_1982
質問者

お礼

回答ありがとうございます。 返信が遅れて申し訳ありません。 >二つのシートを作業グループにしたほうが早いです。 「シートを作業グループにする」という記述があるのですね、「マクロの記録」でしっかり記録できました。 (Arrayを使ってシート数分やってるだけみたいですけど) これも使ってみようと思います。 >>できればどうヘンなのか教えていただけないでしょうか。 >引数がきちんと捕らえられていないと思います。 正直まだ理解できないようです、聞いておいて申し訳ありません。 Sh.nameで入力したシート名が手に入ることだけはわかりました。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.1

こんにちは。 ご質問者さんの、その Workbook_SheetChange のコードがちょっとヘンですね。前回のご質問で、これを出していただければすぐに分かりましたが。 >Sh_name = ActiveSheet.Name >Set r = Intersect(Target, Range("A4:G10")) この二行がヘンです。 >Worksheets(S).Range(r.Address).Value = r.Valueが実行されるたびにThisWorkBookモジュールが動いているようです。 Workbook_SheetChange 自体は、どこのシートのどの場所でも、入力すれば呼び出します。 ThisWorkbook モジュール Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)  Application.EnableEvents = False  If StrComp(Sh.Name, "Sheet1") = 0 And Not Intersect(Target, Range("A4:G10")) Is Nothing Then    Worksheets("Sheet2").Range(Target.Address).Value = Target.Value  ElseIf StrComp(Sh.Name, "Sheet2") = 0 And Not Intersect(Target, Range("A4:G10")) Is Nothing Then    Worksheets("Sheet1").Range(Target.Address).Value = Target.Value  End If  Application.EnableEvents = True End Sub なお、私なら、シートモジュールは、こんな感じに色消しも入れます。 これは、好みによります。こちらは、特に問題ありません。 Private Sub Worksheet_Change(ByVal Target As Range)   If Target.Column = 1 Then     If Target.Cells(1).Value <> "" Then       Target.Offset(, 2).Interior.ColorIndex = 5     Else       Target.Offset(, 2).Interior.ColorIndex = xlColorIndexNone     End If   End If End Sub      

rem_1982
質問者

補足

いつも回答ありがとうございます。 申し訳ありません、ちょっと説明不足でした。 「同時に生かしたい」と書いたのは、  ・各シートにおいてA4:G10の範囲の値について同期を取る  ・各シートのA列に値が入ったら同行のC列は青で塗る の2点です。 例えばSheet1のA1に"1"と入力した時の結果として、  (1)Sheet1のC1が青で塗られる。→Sheet1のシートモジュールの結果  (2)Sheet2のA1に"1"が入力される。→ThisWorkBookモジュールの結果  (3)Sheet2のC1が青で塗られる。→(ThisWorkBookモジュールの結果による)Sheet2のシートモジュールの結果 を行いたいです。 質問した時点で、 (1)は既にできており(問題無いと言ってもらえました)、 (2)も(ヘンと言われてしまいましたが結果的には)動いていました。 (3)は、ThisWorkBookモジュールで(2)を行った時にSheet2のシートモジュールが動いて欲しかったのですが、 Application.EnableEvents = Falseでイベントを止めているので動きません。 Application.EnableEvents = Falseを消すと、ループしてしまうのでNGです。 そこで、 (3)も実現するにはどのように組んだらよいでしょうか、というのが意図していた質問でした。 もしかして不可能でしょうか。 ちなみにコード中でSheet1と2にしか対応していないのにFor文で回している理由は、 Sheetが増えた時に対応しやすいかなと思ってのことです。 今回はこのようなコードしか思いつけなかったのでこれを質問しましたが、 目的としては、 『Sheet1と2において指定した範囲の全ての同期を取る』 です。 今考えうる「全て」は、値、フォントの色、セル背景色、罫線です。 例)  Sheet1に値の入力があった→Sheet2の同じ位置に入力。  Sheet2のセルの色を青に→Sheet1の同じ位置のセルの色を青に。 他にもっと確実な方法でもあれば教えていただきたいです。 >Workbook_SheetChange のコードがちょっとヘンですね。 すみません、絶対の自信があるわけじゃないのですが、 できればどうヘンなのか教えていただけないでしょうか。 よろしくお願いします。

関連するQ&A

  • エクセルVBAでシートモジュールでのパブリック変数

    エクセル2000です。 標準モジュールで取得したパブリック変数は他のシートモジュールで参照できますが、逆にシートモジュールで取得したパブリック変数は他のシートで参照できないのでしょうか? シートチェンジイベントで取得した文字列を変数nmに格納し、ワークブックモジュールで呼び出そうとしたら何もでてきませんでした。 どうやったらよいのでしょうか? 'シートモジュールの記述 Public nm As String Private Sub Worksheet_Change(ByVal Target As Range) Dim rw As Integer If Intersect(Target, Range("A1").CurrentRegion) Is Nothing Then Exit Sub If Selection.Count > 1 Then Exit Sub rw = Target.Row nm = IIf(Cells(rw, "A") = "", Cells(rw, "A").End(xlUp).Value, Cells(rw, "A").Value) 'MsgBox nm End Sub 'ThisWorkbookモジュールの記述 Private Sub Workbook_BeforeClose(Cancel As Boolean) If nm = "" Then Exit Sub MsgBox nm & "さん、ご苦労様でした。" End Sub

  • Excelでシート名と最終更新日を自動表示したい

    Excelを使って (1)セルA1に入れた名目をシート名にし (2)セルH1には、最終更新日を自動で入れたいです。 調べた結果、 シート名を右クリックして「コードの表示」から (1)は Private Sub Worksheet_Change(ByVal Target As Range) Sheets(1).Name = Range("B1") End Sub を入れてうまくいきましたが、 (2)は Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)  If ThisWorkbook.Saved = False Then   Worksheets("Sheet1").Range("H1").Value = Date  End If End Sub を入れてみましたが(←調べましたもの) うまくいきませんでした。 単純に、 Private Sub Worksheet_Change(ByVal Target As Range) Sheets(1).Name = Range("B1") End Sub Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)  If ThisWorkbook.Saved = False Then   Worksheets("Sheet1").Range("H1").Value = Date  End If End Sub とつなげて入れるのではだめなんでしょうか? それとも、(2)の何かが間違っていますか? ご教授願います。

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

    ★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

  • マクロでシート名を変更を変更したい

    A1セルの値をシート名にするマクロは以下のとおりだと思います。 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) If Target.Address = "$A$1" Then Sh.Name = Target.Range("A1").Value End Sub では、E6セルの値をシート名にすることは可能でしょうか? よろしくお願いします。

  • シート及びファイル名の付け方

    Windows XP EXCELL2003です。 いつもお世話になります。 すでに下記でご指導いただきました。 http://oshiete1.goo.ne.jp/qa5331087.html ご教授を仰ぎたいのは  マクロを実行 した時この場合は アクティブなシートに名前がつきますが これをアクティブなシートに関係なく、シート「FUKU」に名前が付くようにしたい野ですがご教授いただけないでしょうか。 マクロは下記のように入っています。 Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row = 1 And Target.Column = 1 Then ActiveSheet.Name = Target.Value ThisWorkbook.SaveAs ThisWorkbook.Path & "\" & Target.Value End If End Sub よろしく御願いします。

  • マクロで二つの構文を繋ぐには

    いつもお世話になります。 WIN7 EXCELL2010 です。 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) If Target.Address = "$A$1" Then Sh.Name = Target.Range("A1").Value End Sub ThisWorkbook に上記のマクロに下記のマクロを追加したいのですが、 End Sub の ところを End If End With などに変えたのですがうまくゆきません。 御指導お願いできませんでしょうか。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) Dim myRange As Range Set myRange = Intersect(Target, Range("M3:V27")) If Not myRange Is Nothing Then Select Case Target.Value Case "" Target.Value = "○" Case "○" Target.Value = "●" Case Else Target.ClearContents End Select Cancel = True End If End Sub 宜しくお願いいします。

  • ワークシートのChangeイベントについて

    シート1のA1セルの値を変更したらシート2のA1・A2・A3と変更内容を順に記録するような以下のようなコードがありますが、うまく動作しません。問題点を指摘していただければ大変助かります。 【Worksheet】 Private Sub Worksheet_Change(ByVal Target As Range) Static r Dim s As Range Set s = Sheets("sheet1").Range("$a$1").Value If s Is Nothing Then Else If r = "" Then r = 1 Sheets("sheet2").Cells(r, 1) = Sheets"sheet1").Range("$a$1").Value r = r + 1 End If End Sub

  • 特定の文字以外を入力すると別シートに表記する方法

    Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim StrRow As Long Dim TgtCol As Long Dim MaxRow As Long Dim ChgRow As Long Dim PutSh1 As Worksheet Dim PutSh2 As Worksheet Dim PutSh3 As Worksheet Dim PutCol As Long Dim PutRow As Long Dim ChgRng1 As Range Dim ChgRng2 As Range Dim ChgRng3 As Range StrRow = 5 MaxRow = 35 If Target.Count > 1 Then Exit Sub If Target.Value = "" Then Exit Sub Set PutSh1 = ThisWorkbook.Sheets("Sheet2") Set PutSh2 = ThisWorkbook.Sheets("Sheet3") Set PutSh3 = ThisWorkbook.Sheets("Sheet4") With ThisWorkbook.Sheets("Sheet1") Set ChgRng1 = Range(.Cells(StrRow, 3), .Cells(MaxRow, 3)) 'C列 Set ChgRng2 = Range(.Cells(StrRow, 5), .Cells(MaxRow, 5)) 'E列 Set ChgRng3 = Range(.Cells(StrRow, 7), .Cells(MaxRow, 7)) 'G列 End With ChgRow = Target.Row If Not Intersect(Target, ChgRng1) Is Nothing Then Target.Offset(0, -1).Value = Target.Offset(0, -1).Value + 1 DataPut PutSh1, ChgRow, Target.Value End If If Not Intersect(Target, ChgRng2) Is Nothing Then Target.Offset(0, -1).Value = Target.Offset(0, -1).Value + 1 DataPut PutSh2, ChgRow, Target.Value End If If Not Intersect(Target, ChgRng3) Is Nothing Then Target.Offset(0, -1).Value = Target.Offset(0, -1).Value + 1 DataPut PutSh3, ChgRow, Target.Value End If End Sub 以前質問させて頂いた内容で追加の質問です。 Sheet1の指定したセルに「ー(ハイフン)」の文字がある時は、Sheet2〜4に転送(表記)しない方法を追加する場合はどの様にすれば宜しいでしょうか?

  • 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ですが、どのようにして組み合わせれば良いのでしょうか?

  • セルの値をファイル名にするには

    現在下記のマクロを入力しています。 Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address = "$C$10" Then Target.Offset(-6, 2).Value = Date End If End Sub この時 ファイル名を SHEET1のA1 セルの値を利用してファイル名にするために下記の内容を入れてブックを保存したいと考えています。 上記のマクロが入っていないときは上手く行くのですが下記を追加するにはどうすればいいかご指導いただけませんでしょうか。 宜しく御願いします。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Row = 1 And Target.Column = 1 Then ActiveSheet.Name = Target.Value ThisWorkbook.SaveAs ThisWorkbook.Path & "\" & Target.Value End If End Sub

専門家に質問してみよう