[[20140419145639]] 『ユーザーフォームへの転記』(アルバトロス) ページの最後に飛ぶ

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

 

『ユーザーフォームへの転記』(アルバトロス)

自分なりに調べたりしたのですが、どうにも上手くいかず、お力をお借りしに参りました。

ユーザーフォームにてコンボボックス1〜4でエクセルに入力(転記)しています。
転記先は
コンボボックス1がA列
コンボボックス2がC列
コンボボックス3がE列
コンボボックス4がG列
ユーザーフォーム上の入力ボタンで1行目に転記後コンボボックスの値は初期化。
これを繰り返して行数が増えていきます。

やりたいことは2つ。
1つ目は、この転記された行の中の1行のA列(例えるとA1)をアクティブセルに
すると、ユーザーフォーム上の該当コンボボックスに同行のA列C列E列G列の値
(例えでいくとA1,C1,E1,G1の値)が表示されるようにしたいです。
2つ目は、上記で表示されたボックスの値を変更後、ユーザーフォーム上の
変更ボタンを押すと、行の一番最後に転記されるのではなく、アクティブセルの行に
上書きされるようにしたいのです。

つたない説明でご理解いただけたか不安ですが、宜しくお願い致します。

< 使用 Excel:Excel2010、使用 OS:Windows7 >


 >ユーザーフォームにてコンボボックス1〜4でエクセルに入力(転記)しています。

 最低ここまでのコードを提示してください。でないと、

 「てっ、何でえ こりゃあ、どういうこんでえ 全部作ってくりょうっちゅう こんけえ!!」
 (花子とアン 風 甲州人は、あんなに てっ とは言いませんが・・・)

 ということになってしまいますので・・・。

 ユーザーフォームが表示されている状態でユーザーがセルにアクセスできる ということは、
 ユーザーフォームは、モーダレス表示 ということですか?

 >表示されたボックスの値を変更後、ユーザーフォーム上の変更ボタンを押すと、
 >行の一番最後に転記されるのではなく、アクティブセルの行に上書き
 新規入力と更新入力である ということを何かの動作で区別するという事ですね?

 さて、どこで区別するか? ですね!! 

(ichinose) 2014/04/19(土) 17:08


インフルで寝込んでいて会社お休みしていました...。

ichinose様
コメントありがとうございます。
1つのユーザーフォームで色々と作業していて、コードを載せるなら全部載せなきゃ駄目と
勝手に思い込み、載せるのに長すぎると思ってはしょっちゃってました。
駄目駄目ですね...。
コメントいただいた部分のコードです。

Private Sub cmdNyuuryoku_Click()

Dim lRow As Long

With Worksheets("Sheet1")

lRow = .Range("A" & Rows.Count).End(xlUp).Row

 '-----種類
  Range("A" & lRow + 1).Value = comboBox1.Value
  End With

 '-----特殊取扱1
 Range("C" & lRow + 1).Value = comboBox2.Value
 '-----特殊取扱2
 Range("E" & lRow + 1).Value = comboBox3.Value
 '-----数量
 Range("G" & lRow + 1).Value = NyuuryokuForm.txtSuuryou.Value

 '-----フォームの値をクリア
 Me.comboBox1.Value = ""
 Me.comboBox2.Value = ""
 Me.comboBox3.Value = ""
 Me.Suuryou.Value = 0

End Sub

G列に転記している数量はTextBoxにSpinButtonを連動(って言うんですかね?)させています。
コンボボックスではありませんでした。
すみません...。

ユーザーフォームはモーダレス表示です。

自分なりに調べてSheet1上にコードを

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If NyuuryokuForm.Visible Then

    NyuuryokuForm.comboBox1.Value = ActiveCell.Value
    End If
End Sub

として、アクティブセルの値のみをcomboBox1に表示させることまではできたのですが、
その後、Offsetをつかって他のボックスに値を表示させようとしても上手くいかず、
値を表示させることも出来ないでいるので、アクティブセルの行に上書きなんてことは
頭が真っ白な状態になり、こちらにお願いにお邪魔させていただきました。

どうにか出来ますでしょうか...?

(アルバトロス) 2014/04/23(水) 12:48


 >ユーザーフォームはモーダレス表示です。 
 モーダレスモードにする理由は、ユーザーフォーム表示中に、セルをユーザーに直接触ることを可能にするためですよね?

 しかもそのユーザーフォームは、後ろにあるシートの情報を登録・更新する機能を持っている ですね!!

 こういう条件で、ユーザーフォームをモーダレス表示で運用するのは、非常に厄介ですよね!!
 だって、ユーザーは、シートを触れるのですから、
 どのセルに何をしているのかを色々想像してそれに対応できるようにVBAコードを記述しなければ
 なりませんからねえ!!

 > NyuuryokuForm.comboBox1.Value = ActiveCell.Value

 とありますが、ユーザーは常にA列だけを選択するとは限りませんよね!!
 又、シートが複数あるなら、別のシートを選択してしまうかもしれません。

 Activecell.ValueをCombobox1に代入するでは、ダメな場合もありますよね!!

 更新するデータをシート上のセルを選択させる仕様にしたいから だけが、 
 モーダレス表示にする理由なら、モーダルモードで運用して、 アルバトロスさんが既に使われている
 SpinButton 等を利用して、更新する行を選択させる仕様の方が楽だと思いますが、いかがですか?
 検討してみてください。

 何かの理由でどうしてもというなら、

 ユーザーフォームのモジュールに

 Sub set_data(rng As Range)
    With rng.EntireRow
       ComboBox1.Value = .Cells(1, "a").Value
       ComboBox2.Value = .Cells(1, "c").Value
    End With
 End Sub

 等として、

 対象シートのモジュールに

 Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Call UserForm1.set_data(ActiveCell)
 End Sub

 このようなコードでよいと思います。

 実際には、アクティブセルが既に登録したデータ範囲内か否かのチェックが必要ですよ
 その際にその行が更新モードなのか 新規登録モードなのかの フラグを立てると良いと思います。

 そのフラグを基に再度シートに書き込む位置を判断する という方針でいかがですか?

(ichinose) 2014/04/24(木) 09:44


ichinose様
お返事ありがとうございます。

う〜ん...どうしてもという理由ではないのですが、今まで使っていたものが急に使え
ない状態になってしまいまして、それで同じような形態で作り直している状況です。
私程度で「エクセル使える」と矢が当たったので、他の同僚にしてみたら出来上がった
ものを「今までと同じく」使いたいということなのです。

ichinose様のコードでセルからの転記が理想通りに出来ました!
A、C、E、G、どこを選択しても同じ行のそれぞれがユーザーフォーム上に表示されて凄いです♪
ありがとうございました。
ichinose様のお時間があれば後学の為にコードの説明もお願いしたいのですが...無理でしたら無視して下さいませ!

 > 実際には、アクティブセルが既に登録したデータ範囲内か否かのチェックが必要ですよ
 > その際にその行が更新モードなのか 新規登録モードなのかの フラグを立てると良いと思います。
 > そのフラグを基に再度シートに書き込む位置を判断する という方針でいかがですか?

これは、ユーザーフォームのコマンドボタン「変更」を押すとアクティブセルへ上書きになるという
Private Sub cmdHenkou_Click()
End Sub
の間にコードを書き込む方法では駄目ということでしょうか?
間にどんなコードを書き込んだら良いのかも解ってないのですが(汗)

検索をして調べたコードをコピーしては貼付けている程度のレベルなので...。
やはり自分でユーザーフォームをつくるのはまだまだ無謀だったということですよね...orz
(アルバトロス) 2014/04/26(土) 15:25


 >後学の為にコードの説明

 Range("a1")とか Cells(1,1) を等で取得できるRangeオブジェクトを使ってセルを操作したり、
 必要な情報を取得したりすることができますよね。

 このRangeオブジェクトには、更に .rangeとか .Cells 等を使うことで、最初のRangeオブジェクトの
 相対位置にあたるRangeオブジェクトを取得することができます。

 例えば、

 Range("b3").Range("b2")  これは、セルB3をA1だと見立て場合、ここから B2の位置って・・・、
 C4に相当する事がわかります?

 同じようなことを

 Range("c5").Cells(1, "c") このような記述でも同じことを表すことができます。

 C5をA1だと見立てた場合、C1(Cells(1, "c")は、C1です)の位置は、E5になります。

 更に

 Range("7:7").Cells(1, "c")  これは、7行目を1行目と見立てて、C1の位置は、C7になります。

 このRangeオブジェクトの相対位置を取得する性質を使ってアクティブセルがどこであっても

 同じ行のA、C、E、G列のセルを特定できるのです。

 この相対位置のセルの取得って、もっと続けられます。

 range("a1").range("c3").range("a3")・・・・。
 もっとも、こんなに続けてしまうと、パズルになってしまいますから、使いませんけど・・・。

 方法は、他にもありますよ activecell.row  で行が取得できますから、

 dim rw as long
 rw=activecell.row

 cells(rw,"a").value  でA列が取得できます。

 >コマンドボタン「変更」を押すとアクティブセルへ上書きになるという

 そういう仕様でよいなら、それでもよいですよ!!

 新規にデータ登録するというのは、既にデータが入力されている行の次の行に登録しますよね?
 この仕様だと、新規のデータが既存データに詰めて追加されないで 飛び飛びに入力できてしまいます。

 これを防ぐために更新時と新規入力時を分けて考えてください と申し上げたのですが、
 アクティブセルの行に書きこむという仕様なら、それでいいのではないですか?
 もっともそれじゃあ、直接シートに書きこめばいいじゃん と思ってしまいますが・・・。

 >検索をして調べたコードをコピーしては貼付けている程度のレベルなので...。 
 >やはり自分でユーザーフォームをつくるのはまだまだ無謀だったということですよね...orz

 飽くなき探求心があれば、MS社は、VBAをエンドユーザープログラミングと命名しているくらいですから
 大丈夫いだと思いますよ!!
 まあ、ある程度の基礎勉強は必要ですね

 
 

(ichinose) 2014/04/27(日) 01:42


ichinose様
説明ありがとうございます。

 >直接シートに書き込めば〜
シートにはVLOOKUP関数が入力されていて、1文字でも違うとリストから反映されなくなってしまうので...。
私だけが入力するのでしたら直接変更で良かったのですけどね。

 Private Sub cmdHenkou_Click()

 Dim rw As Long

 With Worksheets("Sheet1")

 rw = ActiveCell.Row

  '-----種類
  Cells(rw, "A").Value = txtcomboBox1.Value
  End With

  '-----特殊取扱1
  Cells(rw, "C").Value = txtcomboBox2.Value
  '-----特殊取扱2
  Cells(rw, "E").Value = txtcomboBox3.Value
   '-----数量
  Cells(rw, "G").Value = NyuuryokuForm.txtSuuryou.Value

  '-----フォームの値をクリア
  Me.txtcomboBox1.Value = ""
  Me.txtcomboBox2.Value = ""
  Me.txtcomboBox3.Value = ""
  Me.txtSuuryou.Value = 0

  End Sub

として正常に動きました。
ありがとうございました。

ですが、アクティブセル行を反映したことで先に作成していたコードにエラーがでてしまいました...。

 Private Sub cmdSyokika_Click()

    Range("A1").Select
    Selection.ClearContents
    Range("A5:A162").Select
    Selection.ClearContents
    Range("C5:C162").Select
    Selection.ClearContents
    Range("E5:E162").Select
    Selection.ClearContents
    Range("G5:G162").Select
    Selection.ClearContents

    With Worksheets("Sheet1")

    ActiveCell.Activate

    Application.Goto Reference:=Range("A1"), Scroll:=True
    End With
 End Sub

このコードで転記シートを初期化した時にアクティブセルをA1へ持って行っています。
そして以下のコードでスピンボタンで数量を上限させているのですが...

 rivate Sub SpinButton1_SpinDown()
 If txtSuuryou.Value >= 1 Then
 txtSuuryou.Value = txtSuuryou.Value - 1
 End If
 End Sub

 Private Sub SpinButton1_SpinUp()
 txtSuuryou.Value = txtSuuryou.Value + 1
 End Sub

 Private Sub UserForm_Initialize()
 NyuuryokuForm.txtSuuryou.Value = 0
 End Sub

アクティブセル行のA、C,E,G列をユーザーフォーム上に表示することが出来たことにより、
G列のテキストボックスの値が空白になってスピンボタンが動きません。
テキストボックスに「0」を入力すれば動くのは解っていますが、私もまだまだなのに私より
エクセルに疎い方々に1クリック1入力のことですが説明するのも大変で(汗)
ユーザーフォーム上のテキストボックスの値を空白から0にする方法ってありますでしょうか?
最初の質問とは違う質問になってしまい申し訳ありません...。
(アルバトロス) 2014/04/29(火) 14:41


寝る前にふと、
「あれ?実は初期化の最後にフォームの値をクリアすれば良いだけじゃ...。」
と気が付き、実行。
どうやら正解だったようで動きました。

ichinose様
お付き合いくださりありがとうございました。

また何か行き詰ったらお邪魔させていただくかと思います。
ありがとうございました。
(アルバトロス) 2014/04/30(水) 08:24


 解決したようですが・・・。

 >Private Sub cmdHenkou_Click()
    >With Worksheets("Sheet1")
    '↑これを記述したなら、
       .Cells(rw, "C").Value = txtcomboBox2.Value   
       '↑. を付けてください そうしないと 意味がないので・・・。

 Private Sub cmdSyokika_Click()
    Application.EnableEvents = False
    Application.Goto Reference:=Worksheets("sheet1").Range("A1"), Scroll:=True
    Range("A5:A162,C5:C162,E5:E162,G5:G162").ClearContents
    Application.EnableEvents = True
 end sub

 ここは、こんな書き方ができます!! 
 元のコードは、マクロの記録からでしょうかねえ?
 マクロの記録は、便利な開発ツールですが、ここからコードを加工していくことを考えてみてください。

(ichinose) 2014/04/30(水) 08:37


コメント返信:

[ 一覧(最新更新順) ]


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