[[20140310115833]] 『ユーザーフォームからの検索・修正』(ぶっちゃん) ページの最後に飛ぶ

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

 

『ユーザーフォームからの検索・修正』(ぶっちゃん)

初めて質問させて頂きますので宜しくお願いいたします。

ユーザーフォームからデータを入力しするように作成しました。
追加で検索・修正を出来るようにしたいです。

色々とサイトを検索し下記のコードで検索までは出来ました。
検索したデータをユーザーフォーム上で修正した後の上書きが出来ずに困っています。
更新ボタンをクリックしたら、上書きされるという風にしたいのですが・・・

何が間違っているのかお教え頂けないでしょうか?

Private Sub 検索_Click()

    Dim SerchKey As String
    Dim SerchArea As Range

    '検索語入力
    SearchKey = Application.InputBox( _
    Prompt:="注文?s?力", Type:=2)
    If SearchKey = "" Or SearchKey = "False" Then
        Exit Sub
    End If

'検索範囲(シート名も指定)

    Set SearchArea = Sheets("DSK(鳥取)").Range(Range("b6"), Range("b6").End(xlDown))

    '検索処理(引数:LookAt に xlWhole で完全一致
    Set FoundCell = SearchArea.Find( _
        What:=SearchKey, _
        SearchOrder:=xlByRows, _
        LookAt:=xlWhole, _
        MatchCase:=False)
    '商品コードが無い場合の処理
    If FoundCell Is Nothing Then
        MsgBox "見つかりません", vbCritical
        GoTo ExitHandler
    End If
    '見つかった場合の処理
    With FoundCell
        Me.注文??.Value = .Value
        Me.発注日.Value = .Offset(0, -1).Value
        Me.管理??.Value = .Offset(0, 1).Value
        Me.仕様.Value = .Offset(0, 2).Value
        Me.数量.Value = .Offset(0, 3).Value
        Me.単価.Value = .Offset(0, 4).Value
        Me.納期.Value = .Offset(0, 6).Value
        Me.備考.Value = .Offset(0, 10).Value
        Me.納入日.Value = .Offset(0, 7).Value
        Me.検収日.Value = .Offset(0, 8).Value
        Me.受領印日.Value = .Offset(0, 9).Value

    End With

ExitHandler:

    Set SearchArea = Nothing
    Exit Sub
End Sub

Private Sub 更新_Click()

  With FoundCell
        .Value = Me.注文??.Value
        .Offset(0, -1).Value = Me.発注日.Value
        .Offset(0, 1).Value = Me.管理??.Value
        .Offset(0, 2).Value = Me.仕様.Value
        .Offset(0, 3).Value = Me.数量.Value
        .Offset(0, 4).Value = Me.単価.Value
        .Offset(0, 6).Value = Me.納期.Value
        .Offset(0, 10).Value = Me.備考.Value
        .Offset(0, 7).Value = Me.納入日.Value
        .Offset(0, 8).Value = Me.検収日.Value
        .Offset(0, 9).Value = Me.受領印日.Value
    End With
    MsgBox "更新しました", vbInformation

End Sub

Private Sub 終了_Click()

    Unload 明細入力

    Range("A1").Select

End Sub

< 使用 Excel:Excel2003、使用 OS:WindowsXP >


 更新のプロシージャでは「FoundCell」が定義されていないためです。
 標準モジュールにFoundCellをPublicで定義すれば、このままのコードで問題ないとは思います・・・

 標準モジュール直下に(Subとか置かずに)
Public FoundCell As Range

 その後、更新のプロシージャでは
    If FoundCell Is Nothing Then
        MsgBox "検索を実行してください"
        Exit Sub
    If MsgBox(FoundCell.Value & "に上書きします。よろしいですか?", vbYesNo) = vbNo Then Exit Sub
    '処理〜〜〜〜    

 としてはいかがでしょうか?

(稲葉) 2014/03/10(月) 13:23


 変数の有効期間というタイトルで分かりやすい説明が有りますので、ご一読ください。
http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_200_050.html
(稲葉) 2014/03/10(月) 13:24

ありがとうございます。
上手く処理できました。

まだまだ勉強不足ですが、こちらで勉強させていただきます。

(ぶっちゃん) 2014/03/10(月) 13:30


 一応解決したようですが、学校ですので少し雑学の追加まで。

 Public 変数で「たいていの場合」は、期待する動作はすると思いますが、
http://support.microsoft.com/kb/408871/ja 「[VBA] Public 宣言された変数の有効期間」
 という話もあります。
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
ほとんどの場合、プロシージャ終了後も値は保持されますが、意図しない
タイミングで保持されていた Public 変数の値が破棄され、使えていた変数の
値が突然使えなくなる場合があります。 そのため、Public 変数がアプリケー
ション終了時まで有効であることを期待する VBA マクロの実装は、
推奨されません。
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

 実際ネットの質問掲示板には
 「あるとき Public 変数の中身が消えることがあったのだけれどなぜか」
 という質問も散見しているようです。

 変数に関する一般的な説明は下記あたりが参考になるでしょうか。
http://support.microsoft.com/kb/843144/ja 「Visual Basic for Applications で Excel の Sub プロシージャに変数を使用する方法」

 文法的に、保持を目的とした宣言は Static かと思います。
 こちらは一応アプリケーション終了か「プロジェクトのリセット」まで保持を
 すると説明されています。

 下記、田中さんの解説ページです。
http://officetanaka.net/excel/vba/variable/10.htm 「値が消えない静的変数」

 より強固な保持を期待するのであれば、セルに書くなどの方が確実な気はし
 ますが、そのあたりを理解してそれぞれを利用してはと思います。

 蛇足でした。
(Mook) 2014/03/10(月) 17:58

 勉強になりました。
 Staticを使う機会がなかったので紹介できませんでした。勉強不足です。
 今回はRangeオブジェクトの保持でしたが、Addressで文字列としてセルに書き込んでおいても
 よさそうですね!

 Staticで色々試します。
 ありがとうございました。
(稲葉) 2014/03/10(月) 18:05

 この変数の保持は、厄介な話ですよね!!
 数値や文字列ならば、セルやCustomProperty辺りに保存しておけば良いのですが、
 保持したいデータがオブジェクト変数の場合は、どうすればよいのでしょうねえ??

 自作クラスのプロパティは、殆ど私は、Private宣言したそのクラスのモジュールレベルの変数に
 値をおきますが(殆どの方がそうだと思っています)、変数のデータ保持力が
 モジュールレベルの変数<静的変数(Static宣言)というならば、

 データの書き込み、読み込み専用プロシジャー内にStatic変数を配置し、そのI/Oでデータのやり取り
 を行った方が安全という事になりますよね?
 Static変数は、値を時間的に短時間の保持を目的にしか使ったことはありません。

 例えば VBAのDir関数

 sub test()
    dim flnm as string
  flnm=dir("d:\aaa\*.xlsx")
    do until flnm=""
       '処理
       flnm=dir
    loop
 end sub

 こんな手法で使いますが、Dir関数を作ることを考えた場合、
 この最初の呼び出しにパラメータとして与えた検索文字列は、
 2回目以降、省略できるのは、どこかに値が保持されていると考えると、このデータをStatic変数で保持する
 なんて想像ができますよね?
 この場合、値の保持は時間的にそう長くないですよね?

 私は、こんな場面にしか使ったことがないのですが、    

 モジュールレベルの変数<静的変数(Static宣言)

 が本当ならば、これは助かりますね もっとも、Static変数では、イベントの展開ができませんが。

 私もこの問題にExcel2000の時に悩まされました。顧客に納品後に起きた現象で
 再現手順があいまいで再現ができない。原因がわからなくモジュールレベルの変数が初期化されてしまって・・・。

 結局、他のブック(アドインブック)に長く値の保持を期待するデータは、宣言し、それを参照する
 という手法をとりました(アドインには 参照設定は、しない)。
 この手法で、その後変数が初期化されるというエラーは出なくなりました。

 静的変数の効力には興味深いものがありますね!!

 ただ、Mookさんご紹介の本店サイトの

http://support.microsoft.com/kb/408871/ja

 の捕捉に

 >この文書で説明する Public 変数とは、すべてのモジュール レベル変数および静的変数を指します。

 とあります。静的変数も含んでいるという主旨の記述もあります。

 これが気になりますけど・・・。

(ichinose) 2014/03/13(木) 08:07


コメント返信:

[ 一覧(最新更新順) ]


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