[[20130322113443]] 『マクロで入力規則』(4949) ページの最後に飛ぶ

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

 

『マクロで入力規則』(4949)

 WindowsXP Excel2003

   B列  C列    D列   E列
 2  記号   品名	   単位	 単価
 3
 4
  
 B3セルにAと入力すると、C3にみかん D3に個 E3に100
 B4セルにBと入力すると、C4にりんご D4に個 E4に80
 B5セルにCと入力すると、C5にメロン D5に個 E5に800

 と入力出来るようにしたいのですがVLOOK関数を使用すれば可能なのですが、
 行数が2000行くらいまでありかつ20シート同じようなシートを作成しなければ
 ならないので容量が大きくなりすぎると思いまして、
 マクロを使用したいのですが単価が月単位で変更になるので別シートに

 記号   品名	   単位	 単価
 A   みかん    個   100
 B   りんご    個   80
 C   メロン    個   800
         ・
         ・
 と作成しそれを入力規則の名前の定義で作成し単価が変更になったらこちらを変更し
 入力規則を織り込んだマクロを作成したいのですがそのようなことは
 可能なのでしょうか?
 ご伝授お願いします。
 (4949)


 「入力規則」ということだけど「選択候補のリスト」が必要?
 それとも、許されたものだけの入力を受け入れ、それいがいははじくだけでいいの?

 それと、月ごとの単価を設定しているシートのシート名と、入力する20ぐらいのシートのシート名を
 区別するような、名前のルールを教えて。(対象シート名のルールであってもいいし、除外シート名のルールでもいい)

 (ぶらっと)

 とりあえずブック内のマスタのシート名は、先頭が"マスタ" ではじまっているものとして、
 そのほかのシートはすべて入力対象との前提。で、名前定義で登録してあるテーブル名を "PriceTable"としている。

 ThisWorkbookモジュールに

 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Dim r As Range
    Dim c As Range
    Dim a As Variant

    If Sh.Name Like "マスタ*" Then Exit Sub
    Set r = Intersect(Target, Sh.Columns("B"))
    If r Is Nothing Then Exit Sub

    Application.EnableEvents = False

    For Each c In r
        If c.Row >= 3 Then
            c.Offset(, 1).Resize(, 3).Value = "#N/A"
            a = Application.Match(c.Value, Range("PriceTable").Columns(1), 0)
            If IsNumeric(a) Then
                c.Offset(, 1).Resize(, 3).Value = Range("PriceTable").Rows(a).Range("B1:D1").Value
            End If
        End If
    Next

    Application.EnableEvents = True

 End Sub

 (ぶらっと)

 >「入力規則」ということだけど「選択候補のリスト」が必要?
 必要です。
 記号のところは入力規則でAからHくらいまで選択をします。

 >月ごとの単価を設定しているシートのシート名
 は仕様10という感じです。

 シート名は10号から始まり35号くらいまであります。

 入力規則は号ごとに記号A,Bとかは同じですが品名が”キャベツ”になったり”のり”になったりと違うので

 名前定義は記号10〜記号35という風に作成します。

 なのでThisWorkbookモジュールではなくシートモジュールに一つ一つマクロを組まないいけない
 様な気がします。
 (4949)

 >なのでThisWorkbookモジュールではなくシートモジュールに一つ一つマクロを組まないいけない
 >様な気がします。

 いやぁ、それってメンテナンスを考えても、避けたほうがいいね。シートごとに記述したとして
 所詮、このシートでは "名前35" とか このシートでは "名前10" とか、ハードコーディングするわけだから
 ThisWOrkbookモジュールで sh.Name から それぞれの名前を特定してやればいいと思う。

 それより、

 >必要です。
 >記号のところは入力規則でAからHくらいまで選択をします。

 この意味は、セルの入力規則は、あらかじめ設定してあって、入力まではあくまで、それを使う。
 単に、デコードのみをマクロで行うということ?

 (ぶらっと)

 勘違いがあるかもしれないけど。
 ThisWorkBookモジュールで。
 コード内のシートとそれようの名前の紐つけは実際のものをいくつでも。

 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Dim r As Range
    Dim c As Range
    Dim a As Variant
    Dim myName As String

    If Sh.Name Like "仕様*" Then Exit Sub
    Set r = Intersect(Target, Sh.Columns("B"))
    If r Is Nothing Then Exit Sub

    Select Case Sh.Name
        Case "データ10": myName = "記号10"
        Case "データ35": myName = "記号35"
    End Select

    If Len(myName) = 0 Then Exit Sub

    Application.EnableEvents = False

    For Each c In r
        If c.Row >= 3 Then
            c.Offset(, 1).Resize(, 3).ClearContents
            If Len(c.Value) > 0 Then
                a = Application.Match(c.Value, Range(myName).Columns(1), 0)
                If IsNumeric(a) Then
                    c.Offset(, 1).Resize(, 3).Value = Range(myName).Rows(a).Range("B1:D1").Value
                Else
                    c.Offset(, 1).Resize(, 3).Value = "#N/A"
                End If
            End If
        End If
    Next

    Application.EnableEvents = True

 End Sub

 (ぶらっと)

 ↑ 先頭の If Sh.Name Like "仕様*" Then Exit Sub は、なくてもいいね。(もちろん、あってもいいけど)

 (ぶらっと)

   B列  C列   D列   E列    F列
 2  記号   品名  個数    単位   単価
 3
 4

 という形でD列には入荷個数を手入力で入れる列が抜けてました。そのためB列にAと入れた場合
 CEF列は 入力されD列は空欄のままが理想なのです。
 削除の場合B列で削除行うと
 c.Offset(, 1).Resize(, 3).ClearContentsの3を4にしましたが手入力のD列まで
 消えてしまうので加工が必要と思うのですがマクロの内容が理解できないため解説をお願いします。

         If Len(c.Value) > 0 Then
                  a = Application.Match(c.Value, Range(myName).Columns(1), 0)
                  If IsNumeric(a) Then
                    c.Offset(, 1).Resize(, 3).Value = Range(myName).Rows(a).Range("B1:D1").Value
                Else
                    c.Offset(, 1).Resize(, 3).Value = "#N/A"
                End If
 上記の解説をお願いします。
 (4949)

 解説といっても、

 c.Offset(行,列) は 基準のセル(c)から下に何行、右に何列動かした場所という意味で
 c.Offset(, 1) は 同じ行の C 列 という意味。
 で、Resize(行,列)は、その領域(今回の場合は C● という1セル)の大きさを指定行数分、指定列数分に設定するということ。
 だから、Resize(, 3) は、右に列を3列にするということになり、c●:E● という領域になる。

 で、アップしたコードは、コード数を減少させる(のみならず、実行効率アップ)ため1行にしているんだけど、
 連続した領域ではないということであれば、分けざるを得ないね。

 c.Offset(, 1).Resize(, 3).ClearContents これを

c.Offset(, 1).ClearContents 'C列
c.Offset(, 3).Resize(, 2).ClearContents 'E,F列

 c.Offset(, 1).Resize(, 3).Value = Range(myName).Rows(a).Range("B1:D1").Value これを

c.Offset(, 1).Value = Range(myName).Rows(a).Range("B1").Value
c.Offset(, 3).Resize(, 2).Value = Range(myName).Rows(a).Range("C1:D1").Value

 c.Offset(, 1).Resize(, 3).Value = "#N/A" これを

c.Offset(, 1).Value = "#N/A"
c.Offset(, 3).Resize(, 2).Value = "#N/A"

 (ぶらっと)

 Set r = Intersect(Target, Sh.Columns("B"))

 For Each c In r
        If c.Row >= 3 Then

 これはB3から始まりという意味ですよね?
 E7から始めるとなると
 Set r = Intersect(Target, Sh.Columns("E"))

 For Each c In r
        If c.Row >= 7 Then

 と単純にはいかないのですか?

 理解が出来てないので・・・申し訳ないですけど教えてください。
 (4949)


 まず、D列に個数がはいったことによる対応をアップしたけど、それは確かめてくれた?
 1っ歩ずつやろうね。

 で、

 >と単純にはいかないのですか?

 ということだけど、その意図は? 直してみたけどうまくいかなかったということ?
 ただし、そちらがアップしたコードは、A とか B とか C といった入力を E列の 7行目以降に入力するように
 レイアウトをかえたということだけど、そうなの?
 どうも、唐突に E列がでてきても、困ってしまうんだけど?。

 それとも、D列に別のものが入るレイアウトになり、以前のD列がE列に、E列がF列になったことに対する
 対応を Set r = Intersect(Target, Sh.Columns("E")) 等でやろうとしている?
 もし、そうなら、勘違いだよ。それでは、できない。

 追記)あっ、もしかしたら、レイアウトとしては、入力欄が E列7行目以降になった。
    で、アップしたような改訂を行った。でも、なんだかうまくいかないということ?
    もしそうなら、それはそれで、具合悪いかもね。
    E列に入力するとして、マッチング結果をセットする場所はどこの列?
    そこも正しくしなきゃね。

 (ぶらっと)

 D列に個数が入ったマクロはきちんと起動しました。
 ありがとうございました。
 しかし、日付などを入れる枠を設け忘れてたのでA,B,C,Dに余裕を持たせて且つ、行にも余裕を持たせようと思いまして以前のB3始まりをE7から始めようと思いまして。。。
 自分なりに変更などをしてましたが理解してないのでうまくいかず質問させていただきました。
 E7から始まり
     E列  F列  G列   H列   I列 

 6  記号   品名  個数    単位   単価
 7
 8
 G列の個数は手入力です。
 (4949)

 自分なりにやってみましたがやはり無理でした。
 ご伝授ください。
 (4949)

 上のほうで連絡した修正(不連続セル対応)に加えて、入力領域のチェックをE列の7行目以降とすればいいんだけど。

 以下の2か所の★マークが入力領域チェックの場所変更対応。

 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Dim r As Range
    Dim c As Range
    Dim a As Variant
    Dim myName As String

    If Sh.Name Like "仕様*" Then Exit Sub
    Set r = Intersect(Target, Sh.Columns("E"))      '★
    If r Is Nothing Then Exit Sub

    Select Case Sh.Name
        Case "データ10": myName = "記号10"
        Case "データ35": myName = "記号35"
    End Select

    If Len(myName) = 0 Then Exit Sub

    Application.EnableEvents = False

    For Each c In r
        If c.Row >= 7 Then                          '★
            c.Offset(, 1).ClearContents 'F列
            c.Offset(, 3).Resize(, 2).ClearContents 'H,I列
            If Len(c.Value) > 0 Then
                a = Application.Match(c.Value, Range(myName).Columns(1), 0)
                If IsNumeric(a) Then
                    c.Offset(, 1).Value = Range(myName).Rows(a).Range("B1").Value
                    c.Offset(, 3).Resize(, 2).Value = Range(myName).Rows(a).Range("C1:D1").Value
                Else
                    c.Offset(, 1).Value = "#N/A"
                    c.Offset(, 3).Resize(, 2).Value = "#N/A"

                End If
            End If
        End If
    Next

    Application.EnableEvents = True

 End Sub

 (ぶらっと)

 出来ました。

 ぶらっとさんありがとうございました。
 (4949)


コメント返信:

[ 一覧(最新更新順) ]


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