• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VBAで入力フォーム★入力&検索&修正登録)

VBAで入力フォーム★入力&検索&修正登録

このQ&Aのポイント
  • VBAを使用して、入力フォームを作成し、データの検索と修正登録する方法について教えてください。
  • 作成したフォームには新しくcomboboxを追加しましたが、エラーが発生しています。「Valueプロパティを設定できません。種類が一致しません。」
  • 参考にしたサイトではcomboboxが使用されていなかったため、エラーの原因がわかりません。ご教示いただけますか?

質問者が選んだベストアンサー

  • ベストアンサー
  • SI299792
  • ベストアンサー率47% (772/1616)
回答No.8

ワークシートを見て、構造とボタンが解りました。 やはり、ワークブックを見ないとだめですね。出ないと動くものは作れません。 シートの構造が変わっても、テーブルを変えるだけで済みます。 Option Explicit Const Table = "TTCTTTTTTTTTTTTTTTTTTTTCTTTTTCTTTTTCTTTTT" ' Private Sub UserForm_Initialize() '   ComboBox1.Style = fmStyleDropDownCombo   ComboBox1.RowSource = "クライアント一覧!B3:B50"   ComboBox1.ListIndex = -1 '   ComboBox2.Style = fmStyleDropDownCombo   ComboBox2.RowSource = "社名一覧!B3:B50"   ComboBox2.ListIndex = -1 '   ComboBox3.Style = fmStyleDropDownCombo   ComboBox3.RowSource = "社名一覧!B3:B50"   ComboBox3.ListIndex = -1 '   ComboBox4.Style = fmStyleDropDownCombo   ComboBox4.RowSource = "社名一覧!B3:B50"   ComboBox4.ListIndex = -1 '   Sheets("入力").Select End Sub ' Private Sub CommandButton1_Click() 'OK押すと入力フォームからシートに転記される '   Dim Row As Long   Dim Col As Long   Dim TCount As Integer   Dim CCount As Integer '   Row = Cells(Rows.Count, "B").End(xlUp).Row + 1   TCount = 1 '   For Col = 2 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Cells(Row, Col) = Controls("TextBox" & TCount)     Else       CCount = CCount + 1       Cells(Row, Col) = Controls("ComboBox" & CCount)     End If   Next Col   ClearForm End Sub ' Private Sub Search_Click() '   Display End Sub ' Private Sub 修正登録_Click() '   Dim Row As Long   Dim Col As Long   Dim TCount As Integer   Dim CCount As Integer '   If Userform1.Textbox1 = "" Then     MsgBox ("会員番号が未入力です")   Exit Sub   End If '   If MsgBox("修正登録しますか?", Buttons:=vbYesNo + vbExclamation) = vbNo Then     Exit Sub   End If '   Row = [A:A].Find(Textbox1, LookIn:=xlValues, LookAt:=xlWhole).Row   TCount = 1 '   For Col = 2 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Cells(Row, Col) = Controls("TextBox" & TCount)     Else       CCount = CCount + 1       Cells(Row, Col) = Controls("ComboBox" & CCount)     End If   Next Col   ClearForm End Sub ' Function Display() As Long '   Dim Col As Integer   Dim TCount As Integer   Dim CCount As Integer '   On Error Resume Next   Display = [A:A].Find(Textbox1, LookIn:=xlValues, LookAt:=xlWhole).Row   On Error GoTo 0 '   If Display = 0 Then     MsgBox "未登録番号です", vbCritical     Exit Function   End If   TCount = 1 '   For Col = 2 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Controls("TextBox" & TCount) = Cells(Display, Col)     Else       CCount = CCount + 1       Controls("ComboBox" & CCount) = Cells(Display, Col)     End If   Next Col End Function ' Function ClearForm() As Long '   Dim Col As Integer   Dim TCount As Integer   Dim CCount As Integer '   TCount = 1 '   For Col = 2 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Controls("TextBox" & TCount) = ""     Else       CCount = CCount + 1       Controls("ComboBox" & CCount) = ""     End If   Next Col End Function

参考URL:
https://25.gigafile.nu/1211-bca33cf6c284a8e0971235a515476feec
sayupero
質問者

お礼

ファイル確認させていただきました! やりたいことそのものです!! 何もわかってない私の意図をくみ取ってくださり またここまで仕上げていただいて・・ ありがとうございます!!

その他の回答 (8)

  • SI299792
  • ベストアンサー率47% (772/1616)
回答No.9

すみません。前プログラムは、Cancelの処理を入れていません。 また、プログラムが短くなりました。 プログラムを載せるとぐちゃぐちゃになるのでアドレスだけ乗せます。

参考URL:
https://29.gigafile.nu/1211-b5924ef1a7c4a9e2549df62089b5e585f
sayupero
質問者

お礼

SI299792様 ありがとうございます! 落ち着き次第またコードの確認させてもらいます! 取り急ぎお礼まで

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.7

#6です。 参考までに。 今設計したユーザーフォームの上に、どういうテキストボックスとコンボボックスがあるか、調べたいときには、 ユーザーフォームのクリックイベントに Private Sub UserForm_Click() ' Controls でコントロールの一覧を取得できる For Each o In UserForm1.Controls ' コントロールのタイプ名が TextBox であるか判定 If TypeName(o) = "TextBox" Then ' テキストの内容をクリアする o.Text = "" ' オブジェクト名を出力する MsgBox o.Name Debug.Print o.Name End If If TypeName(o) = "ComboBox" Then ' テキストの内容をクリアする o.Text = "" ' オブジェクト名を出力する MsgBox o.Name Debug.Print o.Name End If Next End Sub を作り、ユーザーフォームを表示して、ユーザーフォーム上をクリックすると 順次コントロールの名前が表示される。 Debug.Printだと一覧になる。 これで、VBAコードに書いた、コントロールの名前に漏れや抹消してしまった分がないか、チェックできるのではないか。

sayupero
質問者

お礼

imogasi様 色々ご教示いただいたりコードまでありがとうございます! 落ち着き次第またコードの確認させてもらいます! 取り急ぎお礼まで

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.6

状況がよくわからないので、小生の練習用に、久しぶりに、勝手な仕様で(質問と近い課題として)やってみました。 気が向けば参考のために、何をどうやっているか、見てください。 ーー ユーザーフォームに、TextBoxを4つ、Comboboxを2つ張り付けます。(簡略化少数化した例) コマンドボタンを2つ貼り付け、1つは検索用、1つは更新用とし、 Captionを「検索表示」と「更新」にしました。 ーー 各ComboBoxのアイテムは、 Private Sub UserForm_Initialize() UserForm1.ComboBox1.AddItem "AA" UserForm1.ComboBox1.AddItem "Ab" UserForm1.ComboBox1.AddItem "Ac" UserForm1.ComboBox1.AddItem "Ad" '--- UserForm1.ComboBox2.AddItem "BA" UserForm1.ComboBox2.AddItem "BB" UserForm1.ComboBox2.AddItem "Bc" End Sub で設定しました。 別方法として、セル範囲のデータと紐づける方法もありますが。 各コントロールのデータ内容を表すラベルは今回本例では省略。 ーーー シートのどこかの行に A-F列で cc 34 AA 160 Bc 99 のようなデータを、テストのため、入れて置きます。 コマンドボタン1(検索)のクリックイベントに Public mycellrow As Long Private Sub CommandButton1_Click() '検索とコントロールへ値設定 MsgBox TextBox1.Value Dim mycell As Range '--検索実行 Set mycell = Range("A4:A800").Find(What:=TextBox1.Value, LookAt:=xlWhole) '--見つかったら If Not mycell Is Nothing Then mycellrow = mycell.Row 'MsgBox mycellrow Else MsgBox "該当なし" Exit Sub End If '---各TextBoxと列の対応関係--- clm1 = Array(0, 0, 2, 4, 6) 'tb X,X,2,3,4 'cl X,X,2,4,6 'cl 3,5 列はCbへセット '---各ComboBoxと列の対応関係--- clm2 = Array(0, 3, 5) 'Cb X,1,2 'cl X,3,5 '=== mycellrow = mycell.Row With UserForm1 'MsgBox UBound(clm1) For i = 2 To UBound(clm1) 'i=1 はキー項目 'MsgBox "c=" & i & "=" & clm1(i) UserForm1.Controls("TextBox" & i).Value = Cells(mycellrow, clm1(i)).Value Next i '---各列データをComboBoxへ--- For i = 1 To UBound(clm2) UserForm1.Controls("combobox" & i).Value = Cells(mycellrow, clm2(i)).Value Next i End With End Sub ーーー コマンドボタン2(更新)のクリックイベントに Private Sub CommandButton2_Click() 'コントロールの値で各列を更新 clm1 = Array(0, 0, 2, 4, 6) clm2 = Array(0, 3, 5) With UserForm1 '---各TextBoxから各列へ For i = 2 To UBound(clm1) Cells(mycellrow, clm1(i)).Value = UserForm1.Controls("TextBox" & i).Value Next i '--- For i = 1 To UBound(clm2) Cells(mycellrow, clm2(i)).Value = UserForm1.Controls("Combobox" & i).Value Next i End With MsgBox "更新終了" End Sub と作ります。 == 作業(使い方) sub/UserFormの実行 ユーザーフォームが現れる。 その1番上のテキストボックスにA列の値の1つ(本例ではcc)を入れて、更新ボタンをクリック。 ユーザーフォームのコントロールに、各列のデータが表示される。 ーー 適当に項目データを変更したり、コンボで選択する。ただしキー項目以外。 コマンドボタンの更新をクリック。 シートの該当行の各列が、指定通り変わっていることを確認。 ーー 質問文のコードのように各コントロールと各列の代入や参照関係を個別に記述するのは、確実だか、気が乗らないので、対応配列で考えてみたが、判り育いかも。 === 回答でご指摘の、TextとValueの問題ではないと思った。 指定したIndex(TextBoxXXのXX)のコントロールが、思っているように、実際存在するか?が原因究明のカギではないかと思った。 作ったり消したりして混乱してないでしょうかね。

  • SI299792
  • ベストアンサー率47% (772/1616)
回答No.5

済みません、前のプログラムを流用したので、バグが      Cells(Row, "A").Resize(, 7).Delete xlUp       ↓      Rows(Row).Delete にして下さい。

  • SI299792
  • ベストアンサー率47% (772/1616)
回答No.4

皆さん見切り発車でコードを上げているので、私も上げます。 プログラムを短くするのと、変更に対応するため、テーブル方式にしました。 テーブルの意味は、左からA1から右を示していて、 T がTextBox C がComboBox です。項目の変更があっても、テーブルを変えるだけで済みます。 検索、登録、削除ともあります。 Search    検索 Registration 登録 Deletion   削除 です。ボタンを作り、オブジェクト名を変更して下さい。 但し、コンボボックスのリスト表示はありません。どこにデータがあるか判らないので。テキストボックスと同じ入力になります。 2行目への書き込みはしていません。 Option Explicit Const Table = "TTCTTTTTTTTTTTTTTTTTTTTCTTCTTCTTTTTCTTTTT" Private Sub Search_Click() '   Display End Sub Private Sub Registration_Click() '   Dim Row As Long   Dim Col As Long   Dim TCount As Integer   Dim CCount As Integer '   Row = Cells(Rows.Count, "A").End(xlUp).Row + 1   On Error Resume Next   Row = [A:A].Find(TextBox1, LookIn:=xlValues, LookAt:=xlWhole).Row   On Error GoTo 0 '   For Col = 1 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Cells(Row, Col) = Controls("TextBox" & TCount)     Else       CCount = CCount + 1       Cells(Row, Col) = Controls("ComboBox" & CCount)     End If   Next Col   ClearForm End Sub Private Sub Deletion_Click() '   Dim Row As Long '   Row = Display '   If Row = 0 Then     Exit Sub   End If '   If MsgBox("削除しますか", vbExclamation + vbOKCancel) = vbOK Then     Cells(Row, "A").Resize(, 7).Delete xlUp   End If   ClearForm End Sub Function Display() As Long '   Dim Col As Integer   Dim TCount As Integer   Dim CCount As Integer '   On Error Resume Next   Display = [A:A].Find(TextBox1, LookIn:=xlValues, LookAt:=xlWhole).Row   On Error GoTo 0 '   If Display = 0 Then     MsgBox "ありません", vbCritical     Exit Function   End If '   For Col = 1 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Controls("TextBox" & TCount) = Cells(Display, Col)     Else       CCount = CCount + 1       Controls("ComboBox" & CCount) = Cells(Display, Col)     End If   Next Col End Function Function ClearForm() As Long '   Dim Col As Integer   Dim TCount As Integer   Dim CCount As Integer '   For Col = 1 To Len(Table) '     If Mid(Table, Col, 1) = "T" Then       TCount = TCount + 1       Controls("TextBox" & TCount) = ""     Else       CCount = CCount + 1       Controls("ComboBox" & CCount) = ""     End If   Next Col End Function

  • nishi6
  • ベストアンサー率67% (869/1280)
回答No.3

コード全体が不明で、「下記エラーが発生するようになりました」がどのタイミングで出るのか分からないので明確な理由は分かりません。 また、コードと添付図(ユーザーフォーム)のコントロールの個数が不一致のように見えます。 >ご教示お願い致します 質問にあるコードに関して気づいたことです。 (1)コードを読むと、TextBox1に入力した値で、A列を検索し、見つかったら、その行のB列から横に連続した36個のセルの値を、TextBox2~TextBox37に入れています。その後、TextBoxとComboBoxの値を2行目のセルに書きこんでいる箇所はComboBoxの値も割り込ませて連続的に書き込んでいるのでComboBoxの値をクリアしていなければ、何が書き込まれるか分かりません。TextBoxの書き込み場所はComboBox分ずれていきます。わざとずらしているのかもしれませんがよく分かりません。2行目に書く必要性もよく分かりません。単にComboBoxの値を取り込んでいないだけでしょうか。 (2)Withステートメント  With Userform1   For i = 2 To 37    Userform1.Controls("TextBox" & i).Value = mycell.Offset(, i - 1).Value   Next i  End With このWithステートメントはほとんど意味がありません。下記のように書いた方がいいでしょう。  For i = 2 To 37   Userform1.Controls("TextBox" & i).Value = mycell.Offset(, i - 1).Value  Next i または、  With Userform1   For i = 2 To 37    .Controls("TextBox" & i).Value = mycell.Offset(, i - 1).Value   Next i  End With (3)「Option Explicit」を宣言していない コードを書くとき、一番大事なことは、「Option Explicit」を宣言することだと思っています。VBAの研修で行うことの最初がこれです。変数に野放図なベテランより、ちゃんと宣言する新人の方がより速く、より深くVBやVBAを理解しました。急がば回れでしょうか(経験談です) 何故それが分かるかというと、  Range("A2").Value = Textbox1.Value  Range("B2").Value = Textbox2.Value :  Range("I2").Value = Textbox8.Value  Range("J2").Value = TextBox9.Value TextboxとTextBoxの2種類があります。宣言していればTextBoxだけです。 もしかすると「i」も宣言されていないかもしれません。 また、  Range("AA2").Value = TextBo25.Value は入力ミスでしょう。宣言していれば、VBEが自動的に編集してくれたり、エラー表示が行われます。 (4)多数のコントロールの扱い VBAの研修で、ボタンやテキストボックスを10~20個作り、コーディングもさせ、最後に、これが100個や200個になったらどうする?と質問して考えさせます。コントロール名にボタンなら「cmd」やテキストボックスなら「txt」を先頭に付け、「txtShisya」、「txtName」などとして分かりやすくし、一括処理もできることを教えます。 (5) 検索値が見つからないときは、テキストボックスやコンボボックスの値を消すべきかもしれません。検索と保存の関係が分からないので、判断付きかねます。もしかすると、おかしな保存が起きる可能性があります。 質問にあるコード(検索して2行目に書く)を簡略化するために、テキストボックスとコンボボックスのTagプロパティを使ってみました。提示のコードと同じことをしているはずです。 TextBox1のTag = 「A_txt」 ~ TextBox37のTag = 「AO_txt」   値を書き込むセルの列名_txt ComboBox1のTag = 「C_cmb」 ~ ComboBox4のTag = 「AJ_cmb」   値を書き込むセルの列名_cmb コードでは「_」で左右に分解して使います。下記は、コンボボックスに対応するデータも4行目以下にある前提で、2行目と4行目以下は各列は対応しています。基本的にはテキストボックスやコンボボックスの数の増減に影響されません。(設定は必要です) Private Sub Search_Click() 'Searchを押すと検索結果を表示させる  Dim ctrl As Control  Dim ctCol As String  '// 書き込み列  Dim ctKind As String  '// コントロールの種類  Dim schRow As Integer '// Search結果の行    Range("A2").Value = TextBox1.Value  Dim myCell As Range   Set myCell = Range("A4:A800").Find( _      What:=Range("A2").Value, LookAt:=xlWhole)    If Not myCell Is Nothing Then   schRow = myCell.Row   For Each ctrl In UserForm1.Controls    ctKind = Right(ctrl.Tag, 3)    If ctKind = "txt" Or ctKind = "cmb" Then     ctCol = Left(ctrl.Tag, Len(ctrl.Tag) - 4)     ctrl.Value = Range(ctCol & schRow) '// 取り込み     Range(ctCol & 2) = ctrl.Value '// 2行目に書き出し    End If   Next  Else   MsgBox "未登録番号です"  End If End Sub

sayupero
質問者

補足

nishi6様 お世話になります。 無知なもので色々ご教示いただけて光栄です。 (1) ⇒2行目に表示させることには拘っておらず、検索結果として表示→引用して新しいデータ作成が出来ればいいかなというところです。 Textboxのみの反映になっててCombobox分ずれるのはわざとではなく、解決策が不明です…。 (2)Withステートメント ⇒ありがとうございます! (3)「Option Explicit」を宣言していない ちゃんと宣言して諸々書き込むのがいいようですね。軽くですが調べました。 大文字小文字でも差があるとは…ありがとうございます! (4)多数のコントロールの扱い ⇒これはほんとに大変ですしわけわからなくなりました!名前統一したほうがいいんですね。 知らないことばかりです。ありがとうございます。 (5) ⇒ここが難しいです…。作っていただけてありがたいです!!ありがとうございます。 ひとつずつ調べて覚えていきたいと思います! 現在のファイルがこちらになります。 https://28.gigafile.nu/1211-c30155165f041db6be9d7ce302d4f9f98 元も子もありませんが、コンボボックスでなくてもクライアント番号を検索してクライアント名を入力できる箇所と 過去データを検索してそのデータを引用して新規データを作成したり、その過去データを修正出来るようにしたい といった大まかなところです。 徐々に完成形に近づけていければなと思ってます!ありがとうございます。

  • SI299792
  • ベストアンサー率47% (772/1616)
回答No.2

コンポボックスは、当然リストが必要ですが、入れてありますか。 入れてなければ、当然エラーになります。 コンポボックスは5か所にあります。選択肢はどこかに入れてありますか。 これが解らない以上、アドバイスはできません。 あなた自身、このプログラム、意味が解ってますか。   For i = 2 To 37     Userform1.Controls("TextBox" & i).Value = mycell.Offset(, i - 1).Value   Next i の部分これは、指定行のデータをテキストボックスに入れるものです。 Textbox2にB列の値、Textbox3にC列の値…Textbox37にAK列の値を入れていくものです。 ComboBoxを追加したので、 Textbox3にはD列の値を入れなければなりません。 また、ComboBoxに値を入れていません。 ComboBoxを追加したのなら、ここも直さなければなりません。 ていうか、元のプログラムがひどすぎ。 シート→ユーザーフォームの処理は、ループを使っていて、 ユーザーフォーム→シートの処理は、ループを使っていません。 また、2行目にデータを転送するのも、何の為に行っているか判りません。 前に同じようなものを作ったことがあります。 できましたら、ワークブックそのものを、ギガファイル便等に上げていただけますか。 実際のワークブックを見ないと話になりません。 ダミーデータに置き換えて構いません。

参考URL:
https://gigafile.nu/
sayupero
質問者

補足

SI299792様 お世話になります。 コンポボックスは5か所にあります。選択肢はどこかに入れてありますか。 ⇒コンボボックスはcombobox1がひとつのリスト引用 combobox2-4でひとつの同じリストを引用しております。 ComboBoxを追加したのなら、ここも直さなければなりません。 ⇒直したいです!!   For i = 2 To 37     Userform1.Controls("TextBox" & i).Value = mycell.Offset(, i - 1).Value   Next i がテキストのみのループ作業だということは調べて分かりましたが、コンボボックスの組み込み方が調べられませんでした。 元も子もないかもしれませんが、コンボボックスでなくてもクライアントコードを叩いて出た結果を挿入するような形が理想かなとは思ってます・・! ご指示頂きました通りブックを上げさせていただきました。 宜しくお願い致します。 https://28.gigafile.nu/1211-c30155165f041db6be9d7ce302d4f9f98

  • kkkkkm
  • ベストアンサー率66% (1719/2589)
回答No.1

comboboxを追加してエラーになるということですので ComboBoxのプロパティをValueではなくTextにしてみてはいかがでしょう。 ComboBox1.Text のようにすべて変更する。

sayupero
質問者

お礼

ありがとうございます!VALUEのエラーが出なくなりました!