[[20120510105257]] 『ユーザーフォームの転記がうまくいきません・その』(peridot) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『ユーザーフォームの転記がうまくいきません・その後』(peridot)

[[20120410105511]]
[[20120411160743]]
[[20120413102254]]

 すみません、上の質問の関連で、どうしてもうまくいかない出来事があります。

 ユーザーフォームの内容を「箱サンプル」シートに転記するコードを作っています。

 ★「箱サンプル」シートレイアウト

   A   B   C   D  E   F   G  H  I  J   K   L
 1 作業簿_SK            日付      合計
 2 記号 媒体名 件数    記号 媒体名 件数     記号 媒体名 件数
 3 SK1  HY   82      SK2  KZ   2       SK  KZ   2
 4 SK1  FR   11      SK2  HY   4       SK  HY   86
 5                              SK  FR   11
  :
 19 
 20
 21 作業簿_KK
 22 記号 媒体名 件数    記号 媒体名 件数     記号 媒体名 件数
 23 VA1  KK   1516    VA2  KK   224      VA  KK   1740
 24 VE1  KK   9     VE2  KK   4       VE  KK   13
  :
 35 
 36
 37 作業簿_その他
 38 記号 媒体名 件数    記号 媒体名 件数     記号 媒体名 件数
 39 VS1  10P   6192    VS2  10P   672      VS  10P   7872
 40 VS3  10P   1008                   
  :
 49

 (最終行のA列) データ行終了

 上記のようなシートがあり、「作業簿_SK」「作業簿_KK」「作業簿_その他」の3つの表に分かれています。
 A〜G列に当日のデータを入力し、J〜L列にその値の合計を出します。
 「記号」の最後1文字(数字)は枝番で、合計の際は枝番を除外した「記号」で集計します。
 また、「合計」欄L列の各表の最後に、作業簿毎の件数の合計が関数で入力されています。

 前の質問で、
 ・ユーザーフォームからA〜G列を入力
 ・ユーザーフォームのコマンドボタンを押した時点で「合計」J〜L列の値を集計
 ・手入力でデータを変更した場合に備えて、シートモジュールのチェンジイベントで、
 A〜G列のセルの値が変更されるたびにJ〜L列の値を再集計

 という仕様にしました。

 「箱サンプル」シートモジュール

 Private Sub Worksheet_Change(ByVal Target As Range)
    Dim w As Variant
    Dim f As Long
    Dim e As Long
    Dim myCls As String

    If skipChange Then Exit Sub

    skipChange = True

    For Each w In dicSample
        If Right(w, 1) = "0" Then
            myCls = Left(w, Len(w) - 1)
            f = dicSample(w)(0)
            e = dicSample(w)(1)
            If Not Intersect(Target, Range("A" & f & ":G" & e)) Is Nothing Then
                Call getSample
                Call GetQtyInfo
                Call QtyTotal(myCls)
                Call getSample
                Call GetQtyInfo
                MsgBox myCls & " についての箱サンプルの合計処理を自動実行しました"
            End If
        End If
    Next

    skipChange = False

 End Sub

 それで、入力した後のA〜G列で、「作業_**」や見出しの「転送記号」「媒体名」「件数」が
 入っている行以外の、"SK1" "HY" "82" などの入力した値をクリアするコードを作っていたのですが、
 最初に書いたコードがこれでした

 Sub 件数クリア()

  With Sheets("箱サンプル")
    .Range("A3:C19").ClearContents
    .Range("A23:C35").ClearContents
    .Range("A39:C49").ClearContents
    .Range("E3:G19").ClearContents
    .Range("E23:G35").ClearContents
    .Range("E39:G49").ClearContents
    .Range("J3:L19").ClearContents
    .Range("J23:L35").ClearContents
    .Range("J39:L49").ClearContents

 End With

 End Sub

 この時は、「○○についての箱サンプルの合計処理を自動実行しました」のメッセージがClearContentsの回数分
 表示されますが、一応クリアできました。

 しかし、上記のコードは3つの表の行数が固定されていた場合で、先日「行が足りない」ということになったので「作業簿_KK」の行数を2行増やしました。
 それで

 Sub 件数クリア2()

  With Sheets("箱サンプル")
    .Range("A3:C19").ClearContents
    .Range("A23:C37").ClearContents
    .Range("A39:C49").ClearContents
    .Range("E3:G19").ClearContents
    .Range("E23:G37").ClearContents
    .Range("E39:G49").ClearContents
    .Range("J3:L19").ClearContents
    .Range("J23:L37").ClearContents
    .Range("J39:L49").ClearContents

 End With

 End Sub

 こうするとシートモジュールの
     For Each w In dicSample
 で「オブジェクトが必要です」のエラーになりました。

 そもそも行数が変わるたびにコードの書き換えをするというのは運用的にどうかと思い、
 下記のコードで試してみました。

 Sub 箱サンプルシートクリア()

 Dim i As Long
 Dim z As Long

 With Sheets("箱サンプル")
    z = .Cells(Rows.Count, 1).End(xlUp).Row - 1

    For i = 3 To z
        If .Cells(i, 1).Value <> "作業簿_KK" And .Cells(i, 1).Value <> "転送記号" And .Cells(i, 1).Value <> "作業簿_その他" Then
            .Range("A3:G" & z).ClearContents
        End If
    Next i
 End With

 End Sub

 こうすると「○○の合計処理を実行しました」のメッセージがセルの個数分出続ける上に、
 何故かL列の合計関数まで消えてしまいます。
 (G列までを指定したつもりなんですが…)

 「○○についての合計処理を実行しました」のメッセージが出るのは仕方ないとして、せめて1回だけにして、
 データの「値」(見出しや関数を除いて)をクリアするにはどうしたらいいでしょうか。

 前回(ぶらっと)様にお教えいただいたdictionaryのメモを見ながら試してもダメでした…

 申し訳ございません、よろしくお願いします。

 ちょっと、今日は眠いので明日、じっくり読んでみるけど、提供したコード自体は、
箱サンプルに各分類コードごとに用意してある行数は自動的に判断している。

 なので、
・マクロを無効にしてブックを開き
・箱サンプルシートをメンテ(マクロ無効なので、実行されず、結果としてメッセージもでない)
・閉じる

 これで、あらためて、マクロを有効にして開く。

 こうすればいいと思うんだけどな。

 (ぶらっと)


 あるいは、マクロが有効になって開かれたとしても
・VBE画面を表示
・表示->イミディエイトウィンドウ 
 ここで、Application.EnableEvents = False とタイプしてエンター
・で、箱サンプルシートをメンテ。(イベントが発生しないのでマクロも動かない)
・メンテ後、イミディエイトウィンドウ で Application.EnableEvents = True とタイプしてエンター。

 こうしてから、通常の処理を開始してもいい。

 (ぶらっと)

 (ぶらっと)様

 ありがとうございます。

 「マクロを無効にしてブックを開き〜」の状態で、下記のコードを書いて保存、再度ブックを開いて実行しました

 Sub 箱サンプルクリア()

 Dim i As Long
 Dim j As Long
 Dim x As Long
 Dim y As Long
 Dim z As Long
 Dim s1 As Long
 Dim s2 As Long
 Dim s3 As Long

 With Sheets("箱サンプル")

    z = .Cells(Rows.Count, 1).End(xlUp).Row - 1    '作業簿_その他最終行

    For i = 1 To z

        If .Cells(i, 1).Value = "作業簿_SK" Then
            s1 = i + 2                '作業簿_SK開始行
        ElseIf .Cells(i, 1).Value = "作業簿_KK" Then
            s2 = i + 2               '作業簿_KK開始行
            x = i - 2         '作業簿_SK最終行
        ElseIf .Cells(i, 1).Value = "作業簿_その他" Then
            s3 = i + 2               '作業簿_その他開始行
            y = i - 2         '作業簿_KK最終行
        End If

    Next i

    .Range("A" & s1 & ":G" & x).ClearContents
    .Range("A" & s2 & ":G" & y).ClearContents
    .Range("A" & s3 & ":G" & z).ClearContents

 End With

 End Sub

 「合計処理を〜」のメッセージが3回出ますが、これなら運用で大丈夫そうです。
 ありがとうございました!

 (peridot)

 解決ということだけど、まだまだ気になるところがあるので。

 あらためて今回の質問を読んでみた。

 まず、今までもそうだったけど、  
 >For Each w In dicSample で「オブジェクトが必要です」のエラーになりました。
 この種のコメントがたびたびでているね。
 説明しているけど、共通で使うDictionary他、ブックが開かれた時に、Preparation で
 変数をセットしている。なので、プロジェクトがリセットされた状況で再開するには
 ブックをとして開きなおす または 手動で Preparation を実行してから処理を継続する。
 これが必要。
 (なので、今回のようにシートをメンテナンスする場合、マクロ無効でメンテ->閉じて開きなおす
 これはいいんだけど、2番目に提示した、マクロ有効のままの処理の場合は、メンテ後、必ず
  Preparation を実行してね。(新レイアウト情報を取り込む必要があるので)

 次に、3回メッセージがでる件。これからの追加でもあるかもしれないので。
 手作業であれ、マクロからの更新であれ、該当の領域のセルが変更されれば合計処理が自動的に走り、メッセージもでる。
 コードからの変更時、これを「意図的に止める」ためには、変更前に skipChange = True、変更後に skipChange = False。
 こうしてね。

 で、そのクリアだけど、レイアウト情報はコード内に持っているので、以下のコードにしておけば、自動的にクリア
 されるよ。D列やF列も、一緒にクリアしていいなら 箱サンプルクリアA でOK。D,F列はさわりたくないなら
 箱サンプルクリアB を。(テストしてないけど、たぶん大丈夫)

 Sub 箱サンプルクリアA()
    Dim w As Variant
    Dim f As Long
    Dim e As Long

    skipChange = True

    For Each w In dicSample
        If Right(w, 1) = "0" Then
            f = dicSample(w)(0)
            e = dicSample(w)(1)
            Sheets("箱サンプル").Range("A" & f & ":L" & e).ClearContents
        End If
    Next

    skipChange = False

 End Sub

 Sub 箱サンプルクリアB()
    Dim w As Variant
    Dim f As Long
    Dim e As Long

    skipChange = True

    For Each w In dicSample
        If Right(w, 1) = "0" Then
            f = dicSample(w)(0)
            e = dicSample(w)(1)
            Sheets("箱サンプル").Range("A" & f & ":C" & e).ClearContents
            Sheets("箱サンプル").Range("E" & f & ":G" & e).ClearContents
            Sheets("箱サンプル").Range("J" & f & ":L" & e).ClearContents
        End If
    Next

    skipChange = False

 End Sub

 (ぶらっと)


 (ぶらっと)様

 引き続きのフォローありがとうございます。
 Preparation を実行する、今までも何度か言われていたのに理解していませんでした…申し訳ございません…

 ご提示いただいたコード、箱サンプルクリアAでほぼ良いのですが、L列の「作業簿_KK」の表の最後にある
 SUM関数が消えてしまいます…

 SUM関数はL列の「作業簿_SK」「作業簿_KK」「作業簿_その他」の表(最終行ではない)の下のセルにあります。
 あえて指定するなら、
 ・「作業簿_SK」のSUM関数の行=A列「作業簿_KK」の見出しがある1行上
 ・「作業簿_KK」のSUM関数の行=A列「作業簿_その他」の見出しがある1行上
 ・「作業簿_その他」のSUM関数の行=A列「データ最終行」の2行上

 になります。

 ★追加
 すみません、私の操作ミスでした…
 SUM関数ちゃんと残ります。
 ありがとうございました

 (peridot)

 >SUM関数ちゃんと残ります。

 それは祝着・・・・なんだけど、

 >「作業簿_その他」のSUM関数の行=A列「データ最終行」の2行上

 確か、ここはデータ行だった記憶が。少なくともコードとしては、そう理解して処理しているよ。
 もし、ここに計算式があるならクリアされるはず。
 計算式が「データ最終行」の【1行上】ならいいんだけど?

 もし、2行上ということなら、Preparation のロジックを直さなきゃいけないんだけど。

 (ぶらっと)


 (ぶらっと)様

 たびたび申し訳ございません…ご指摘の通り、「データ最終行」の1行上でした…
 (私の見間違えです…)

 本当に申し訳ございませんでした

 (peridot)

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.