• 締切済み

「プロシージャの分け方について」助けてください…

現在WorkSheet_changeプロシージャ内にかなりの記述量があり プロシージャが大きすぎますとエラーが出てしまいました。 For文で回して少し削ってはいるのですが、どうしていいのかわかりません。。。 WorkSheet_changeプロシージャをまるまるコピーしてWorkSheet1_changeにしても反応してくれません。。

みんなの回答

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

#7 の訂正です。 他のマクロを使っていて、Sh1 のオブジェクトが壊れることがありますから、その場合を想定して、以下のように、ErrHandler: の中を書き換えてください。 ErrHandler:   If Err.Number = 91 Then     Set Sh1 = Worksheets("Sheet1")     Resume   End If   Application.EnableEvents = True End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.7

こんばんは。 >'(1) > If lngTargetRow = 46 And lngTargetCol = 4 Then >  >  If Target.Cells(1, 1).Value <> "" _ >  And ActiveSheet.Cells(lngTargetRow + 1, lngTargetCol) <> "" _ >  And ActiveSheet.Cells(lngTargetRow + 2, lngTargetCol) <> "" Then 今、一通り、読めました。難しい書き方をしていますね。すぐに読めませんでした。コメントでも付けたほうがよいです。 その部分は、 n = Target.Row - ((rw + 2) Mod 3) のようにして、先頭行を取り、3行を取ります。 ただし、まだ、ActiveSheet と Sh1 の区別があるのか分かりません。 それから、それが、別のシートだとすると、別のシートから、シートプロテクトの制御がうまく行きません。Protectの UserInterfaceOnly を使ってください。 '------------------------------------------------ '  ** 標準モジュール ** '------------------------------------------------ Public Sh1 As Worksheet Sub Auto_Open() Set Sh1 = Worksheets("Sheet1") 'Sh1 のシートを設定 Sh1.Protect UserInterfaceOnly:=True End Sub '------------------------------------------------ '  ** シートモジュール ** '------------------------------------------------ Private Sub Worksheet_Change(ByVal Target As Range)   Dim rw As Long   Dim i As Long, n As Long   Dim iColor As Integer   Dim LockFlg As Boolean      '入力が2個以上の場合は、無効   If Target.Count > 1 Then Exit Sub   'D列以外は、無効   If Target.Column <> 4 Then Exit Sub      On Error GoTo ErrHandler   Application.EnableEvents = False      rw = Target.Row   '180セット分   If rw >= 46 And rw <= 585 Then     '3行を1セットとする     n = Target.Row - ((rw + 2) Mod 3)     '3行が、1セットになるか判定     If WorksheetFunction.Count(Cells(n, 4).Resize(3)) = 3 Then       iColor = xlNone       LockFlg = False     Else       iColor = 15       LockFlg = True     End If     For i = 10 To 64 Step 6       With Sh1.Cells(i, 10).Resize(3)         .Interior.ColorIndex = iColor         .Locked = LockFlg       End With     Next i   End If ErrHandler:   Application.EnableEvents = True End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

こんにちは。 今のところは、私は、単なるアドバイスしか出来ません。 最初に、イベント・ドリブン型に入れること自体が無理がありますね。 64kb の壁という話も出てくるかもしれませんが、#1 のコードが読めないですね。 これは、基になっている本体自体は、一通り分かっている人のコードだと思います。それを、単につなげただけのようです。 それは、改めてコードを書き直したほうがよいです。内容は、非常に簡単で単純なもののようです。それを公式化が出来ていないので、個別のコードになっているのだと思います。 それに、コードの中の、ActiveSheet とSh1 の関係性が見えてこないのです。 イベント・ドリブン型マクロには、ActiveSheet というものはありません。Sh1 と出てくる場所はどこかも分かりません。 それから、lngTargetRow というのは、単に、Target.Row か、Target.Cells(1).Row のことだと思います。 それに、これは、みんな場所が同じところを繰り返しているだけですね。 ----------------------------------------------- それに、これ自体(2)、ループが必要なほどの量でもなさそうです。 --------------------------------------------------- '(2)  For i = 10 To 64 Step 6         Sh1.Range(Sh1.Cells(i, 10), Sh1.Cells(i + 2, 10)).Locked = False         Sh1.Range(Sh1.Cells(i, 10), Sh1.Cells(i + 2, 10)).Interior.ColorIndex = xlNone       Next i -------------------------------------------------       (1)の意味が良く分からないです。 この(1)の意味さえ、解ければ、後は、すべて統一できるはずです。 行によって、lngTargetRow (+1,+2,-1...) の周辺の位置が変わっているようですが、そこの説明を受けないと分かりません。 何か、囲碁のような連想をさせます。しかし、(2)の色塗りとLock の位置は、皆、定位置同じだから、あまり意味がありません。 --------------------------------------------------- '(1)  If lngTargetRow = 46 And lngTargetCol = 4 Then     If Target.Cells(1, 1).Value <> "" _   And ActiveSheet.Cells(lngTargetRow + 1, lngTargetCol) <> "" _   And ActiveSheet.Cells(lngTargetRow + 2, lngTargetCol) <> "" Then --------------------------------------------------- 何か、入力したセルの周りが、"" だったら実行しろというようなコードのようですね。 それに、lngTargetRow = 46 の同じようなものがいくつもあるようだけれども、 単に、lngTargetRow >=46 ということのような気がします。 今、やろうとしている詳しい説明を請けて、新たにコードを書き直したほうが良いと思います。そんなに難しいことをしているようには思えません。数列の公式を見つければ可能だと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • lark_0925
  • ベストアンサー率63% (37/58)
回答No.5

ちょっと訂正 Private Sub Worksheet_Change(ByVal Target As Range)   Call chk_and_set_data(46, 47, 4, 48, 4,target)   Call chk_and_set_data(47, 46, 4, 48, 4,target)   Call chk_and_set_data(48, 47, 4, 46, 4,target) End Sub '=============================================================== Sub chk_and_set_data(rw As Long, crw1 As Long, ccol1 As Long, crw2 As Long, ccol2 As Long,target as range)   Dim i As Long   Dim sht1 As Worksheet   dim lngTargetRow as long   dim lngTargetCol as long   lngTargetRow=target.row   lngTargetCol=target.column   Set sht1 = Worksheets(1) '適切なシートをセット   sht1.Unprotect   If lngTargetRow = rw And lngTargetCol = 4 Then    vntCellValue = Target.Cells(1, 1).Value    If vntCellValue <> "" And _       ActiveSheet.Cells(crw1, ccol1) <> "" And _       ActiveSheet.Cells(crw2, ccol2) <> "" Then      For i = 10 To 64 Step 6       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = False       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = xlNone       Next i    Else      For i = 10 To 64 Step 6       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = 15       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = True       Next i      End If    End If   sht1.Protect End Sub

全文を見る
すると、全ての回答が全文表示されます。
  • lark_0925
  • ベストアンサー率63% (37/58)
回答No.4

まだ全体像がわかりません。 コードしか掲載してもらえないからです(勿論、コードは必要ですが)。 やりたいことを仕様書として掲載が本来は必要です。 提示されたコードだけを見ると(これも省略掲載なので、この変数が何か 等不明な点がありますが)、 '=============================================================== Private Sub Worksheet_Change(ByVal Target As Range)   Call chk_and_set_data(46, 47, 4, 48, 4)   Call chk_and_set_data(47, 46, 4, 48, 4)   Call chk_and_set_data(48, 47, 4, 46, 4) End Sub '=============================================================== Sub chk_and_set_data(rw As Long, crw1 As Long, ccol1 As Long, crw2 As Long, ccol2 As Long)   Dim i As Long   Dim sht1 As Worksheet   Set sht1 = Worksheets(1) '適切なシートをセット   sht1.Unprotect   If lngTargetRow = rw And lngTargetCol = 4 Then    vntCellValue = Target.Cells(1, 1).Value    If vntCellValue <> "" And _       ActiveSheet.Cells(crw1, ccol1) <> "" And _       ActiveSheet.Cells(crw2, ccol2) <> "" Then      For i = 10 To 64 Step 6       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = False       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = xlNone       Next i    Else      For i = 10 To 64 Step 6       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = 15       SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = True       Next i      End If    End If   sht1.Protect End Sub はっきり内容を把握していないので 正しく機能分割されていないかもしれません。

全文を見る
すると、全ての回答が全文表示されます。
noname#79209
noname#79209
回答No.3

> 下記記述コードをそのままSub Sub1()とし、 > 標準モジュールに突っ込んでみましたが、 > Call Sub1で呼び出すことができません。。 プロシージャの頭は Public Sub となっていますか? 別モジュール置いて呼び出すプロシージャは、 パブリックでないと呼び出せません。

全文を見る
すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

内容的にまとまった部分をSuBプロシージャーに分けて(どちらかというと無理やりに)(引数で変数データを渡さなくて良い単位にできればなお良い) Private Sub Worksheet_Change(ByVal Target As Range) ここにある程度主要な部分は今のまま温存しておき Call SUB1 Call Sub2 ・・・・ End Sub のようにしてみましたか。Callは不要。 Sub Sub1() 切り分けたコード End Sub Sub Sub2() 切り分けたコード End Sub

sdlabxx2
質問者

補足

下記記述コードをそのままSub Sub1()とし、標準モジュールに突っ込んでみましたが、Call Sub1で呼び出すことができません。。 プログラム自体まだまだ不慣れなもので。。。 下記記述コードをそのままSub Sub1()とすること自体が間違っているのでしょうか…

全文を見る
すると、全ての回答が全文表示されます。
  • lark_0925
  • ベストアンサー率63% (37/58)
回答No.1

どんなコードなのか見なければはっきりしたことは言えません。 が、プログラムの基本形は、   前処理    |    |  一回以上のループ処理    |    |   後処理 私は、この基本形にコードを整えることを考えます。 まずは、前処理や後処理が別のプロシジャーに分割できるか 検討してください。 プロシジャー分割と言うのは、 トップダウンとボトムアップに仕様を検討して、後々メンテしやすい ようにコードを分割していくものです。 慣れないと難しいところもあるかもしれませんね!!

sdlabxx2
質問者

補足

プログラムコードとしては、 下記のようなものになります。 下記を1セットとし、180セット記述します。。。 If lngTargetRow = 46 And lngTargetCol = 4 Then vntCellValue = Target.Cells(1, 1).Value If vntCellValue <> "" And ActiveSheet.Cells(lngTargetRow + 1, lngTargetCol) <> "" And ActiveSheet.Cells(lngTargetRow + 2, lngTargetCol) <> "" Then SH1.Unprotect For i = 10 To 64 Step 6 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = False SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = xlNone Next i SH1.Protect Else SH1.Unprotect For i = 10 To 64 Step 6 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = 15 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = True Next i SH1.Protect End If End If If lngTargetRow = 47 And lngTargetCol = 4 Then vntCellValue = Target.Cells(1, 1).Value If vntCellValue <> "" And ActiveSheet.Cells(lngTargetRow - 1, lngTargetCol) <> "" And ActiveSheet.Cells(lngTargetRow + 1, lngTargetCol) <> "" Then SH1.Unprotect For i = 10 To 64 Step 6 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = False SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = xlNone Next i SH1.Protect Else SH1.Unprotect For i = 10 To 64 Step 6 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = 15 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = True Next i SH1.Protect End If End If If lngTargetRow = 48 And lngTargetCol = 4 Then vntCellValue = Target.Cells(1, 1).Value If vntCellValue <> "" And ActiveSheet.Cells(lngTargetRow - 1, lngTargetCol) <> "" And ActiveSheet.Cells(lngTargetRow - 2, lngTargetCol) <> "" Then SH1.Unprotect For i = 10 To 64 Step 6 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = False SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = xlNone Next i SH1.Protect Else SH1.Unprotect For i = 10 To 64 Step 6 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Interior.ColorIndex = 15 SH1.Range(SH1.Cells(i, 10), SH1.Cells(i + 2, 10)).Locked = True Next i SH1.Protect End If End If

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Excel VBA イベントプロシージャを2つ記述する(基本です)

    基本的な事なのですが、Excelのイベントプロシージャで2つプログラムを作るにはどうやって記述すればよいのでしょうか? 具体的には、worksheetのchangeイベントで、セルC5の値を変えた時と、セルG7の値を変えた時の2通りのマクロを作成したいのです。 Private Sub Worksheet_Change(ByVal Target As Range) C5を変えた時の処理 End Sub Private Sub Worksheet_Change(ByVal Target As Range) G7を変えた時の処理 End Sub このように書けばよいのでしょうか?そうするとTargetがかぶっておかしくなる気がします。。 お願いします。

  • ExcelにおけるDDEデータのイベントプロシージャについて

    DEEをつかって、Excelのセルにデータを出力しています。 そのセルのデータが変更された時に、自動でそのデータをコピーし別のシートにペーストしたいのですが、よろしければ助言をお願い致します。 イベントプロシージャの(worksheet_change)で試してみたのですが、任意でセルの値を変えないとプロシージャが動かず行き詰りました。 VBAも超初心者なのですが、よろしくお願い致します。

  • EXCEL VBA イベントプロシージャを

    一枚のシートにWorkseet Changeプロシージャを複数入れたいと思いますがこれは可能でしょうか? やってみると「名前が適当ではありません」というエラーがでてしまうのですが。 よろしくお願いします。

  • イベントプロシージャ『 Worksheet_Change 』の対象セル

    イベントプロシージャ『 Worksheet_Change 』の対象セルを『 コピー貼付 』の際 どんな方法で貼り付けてもマクロがフリーズすることがなくなる方法をご存知の方が いらっしゃいましたら、是非その方法を教えて下さい。 『 Worksheet_Change 』対象セルの『 コピー貼付 』の際、ツールの『 編集 』から 『 貼り付け 』の手順で『 Worksheet_Change 』対象セル宛に情報を貼り付けてみた 場合は特に問題なく情報が貼り付いてくれます。 『 Ctrl+V 』で貼り付けた場合も問題なく情報が貼り付いてくれます。 しかし、コピー後に貼り付け先のセルを右クリックして『 形式を選択して貼り付け 』の手順での 貼り付けをしようとすると、必ず決まってマクロがフリーズしてしまいます。 そのため、その度にウィンドウ右上の閉じるボタン『 X 』をクリックして『 保存しますか? 』を 『 キャンセル 』してマクロのフリーズを解除している状況です。 コピー元のセルと貼り付け先のセルは共にセル結合されている状態ですが、この『 セル結合 』は マクロのフリーズとは無関係のことと思われます。 何か良い解決策をご存知の方、どうか宜しくお願いします。

  • プロシージャをコンパイルするとフリーズ

    プロシージャを.sqlファイルに記述し、sql*plusより.sqlファイルを実行すると途中で反応がなくなります。別端末よりsvrmgrlからshutdown immediateを行おうとしてもレスポンスがかえってこなくなります。abortは受け付けてます。 CreateTableでも同じことが起きてますが、こちらは一定の長さまでのCreate文は受理し、途中で止まってしまいます。その後はプロシージャのときと同じです。 どうもスクリプトが長いと途中で止まっているみたいなのですが、なんで止まるのかがわかりません。 なにか対処方法がありましたら教えてください。使用しているのはOracle8i サーバはSolaris です。(バージョンはわかりません)

  • Excel2010 イベントプロシージャが動かない

    VBAはほとんどいじったことのない初心者です。 イベントプロシージャをインターネットから探してきて、コピペして使おうとしてます。 Private Sub Worksheet_Change(ByVal Target As Range) On Error GoTo ERR_HANDLER If Target.Address(False, False) = "E2" Then ActiveSheet.Name = Range("E2").Value End If Exit Sub ERR_HANDLER: MsgBox "現在のE2セルの値はシート名にできません。" End Sub やりたいのは、セルE2の値に変更があったら、そのセルの値をシート名にしたいということです。 初心者には難しいでしょうか? ご教示いただけると幸いです。 よろしくお願いします。

  • ストアドプロシージャのbegin、end

    下記の様なストアドプロシージャを作成し、VB側から実行させています。 どうしても、★SQL文2★の後のreturn文を実行してくれません。 (VB側ではreturn値が0と判断します。) このreturn文を★SQL文2★の前に移動すると、return値が-1として正常に取得できます。 begin、endのブロックの記述に何か間違いがあるのでしょうか? 環境:sqlserver2000,windows2000,vb6 よろしくお願いします。 CREATE PROCEDURE [sp_AAA] @PARAM1 varchar(16) AS begin if (~) begin ★SQL文1★ if (@@ERROR <> 0) begin return @@ERROR end end ★SQL文2★ return -1 ←ココ end

  • worksheet_changeがループする

    worksheet_change イベントでの質問です。シートに文字が入力された時に、他のセルに値をコピーしたいのですが、一つ目の値を代入した時点で、再びchangeイベントが発生して、この関数の頭に戻ってしまいます。実行中は、changeイベントを発生しないようにできないのでしょうか。 Private Sub Worksheet_Change(ByVal Target As Range) Dim i, j As Integer j

  • マクロのプロシージャーが大きすぎる・・

    自動マクロで作成した二つのマクロをコピーして結合させました・・そして実行しようとするとプロシージャーが大きすぎるために実行できません、のエラーが出ました。マクロの余分なところを削除して軽くするしか方法がないでしょうか?他に方法があればご教授ください。よろしくお願いします。

  • プロシージャ作成がしたい

    SQL*Plusに下記のコードを記述したところ 「警告~」という内容のエラーが起こってしまいました。 どうしてコンパイルがうまくいかないのでしょうか? 初めてPL/SQLを勉強しているのでひとりで長いこと悩んでます。。。 どなたかご協力お願いします! SQL> CREATE OR REPLACE PROCEDURE ProcA( 2 i1 IN NUMBER, 3 i2 IN NUMBER, 4 o1 OUT NUMBER) IS 5 BEGIN 6 o1 = i1 + i2; 7 RETURN; 8 END; 9 / 警告: プロシージャが作成されましたが、コンパイル・エラーがあります。

このQ&Aのポイント
  • フリーウェイ給与計算の年末調整データ入力システムが利用できない問題について
  • フリーウェイ給与計算の年末調整データ入力システムの利用方法と有料かどうかについて
  • フリーウェイ給与計算の年末調整データ入力システムに関する初歩的な質問
回答を見る

専門家に質問してみよう