- ベストアンサー
ExcellVBAのFindに関する質問です。
お世話になります。 VBA超初心者です。 同じSheetに二つのテーブル 性別テーブル(名前を付けてます) 顧客ID 性別 SA081 男 SA083 男 SA010 女 SA013 女 顧客テーブル(名前を付けてます) ID 氏名 顧客ID 性別 1 山田 太郎 SA081 2 斉藤 清 SA082 3 山本 花子 SA061 です。 顧客テーブルの顧客IDを上から性別テーブルを検索して、あれば顧客テーブルの性別フィールドにその人の性別を記入するには、どうすればいいのでしょうか。 一生懸命考えて作ってはいるのですが、デバックばっかり出て、全然進みません。 Sub Chck() Dim k As Range, s, i Set k = Range("顧客テーブル").Range(2, 3).Value For i = 2 To myTbl.Rows.Count Set s = Range("性別テーブル").Cells.Find(what:=i, lookat:=xlPart, MatchCase:=False) If s Is Nothing Then k.Range("g2").Value 'ここに性別を書きます(ここは顧客テーブル外です。) Exit Sub End If Next End Sub 宜しくお願いします
- sofut_me3
- お礼率46% (6/13)
- オフィス系ソフト
- 回答数4
- ありがとう数4
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>それとも全部おかしいのでしょうか? yes・・・。 簡単な動作から覚えましょうw 最初のエラーがk.Range("g2").Valueですよね。 このままだと、k の内容はシートが指定されないといけませんが、 >Set k = Range("顧客テーブル").Range(2, 3).Value では全く別の値をオブジェクトに設定しています。 この設定にも誤りがあります。 おそらく、"顧客テーブル"と言う範囲を設定したいのでしょう。 この場合、シートのどこかに顧客テーブルという名前の範囲が設定されていれば、Set k = Range("顧客テーブル") と書けますが、Range(2, 3).Valueは余計です。 でも、書かれたソースでは役立たない値です。 >For i = 2 To myTbl.Rows.Count myTblが何処にも定義されていないので、参照不可でエラー。 >Set s = Range("性別テーブル").Cells.Find(what:=i, lookat:=xlPart, MatchCase:=False) If s Is Nothing Then Set s = Range("性別テーブル").Find(・・・・という書き方が良いでしょう。 でも、検査値が what:=i ではFor文が動かないので、検索しようが無いですね。 動いたとしても数値なので、顧客IDは入っていません。 >k.Range("g2").Value 一巡して、(仮に)Range("g2").Value = 検索値 では、毎回同じ位置に入ってしまいます。 個々の文を正しくしても、目的の通りに動作させることは不可能です。 >Exit Sub も、うまく動作したとしても1回目の検索で記入が終了してしまいます。 他の方法もあると思いますが下記のような物を書いて見ました。 'Find版 Sub ChckFind() Dim k As Range Dim Ct As Integer Dim s As Range For Each k In Range("顧客テーブル") '顧客テーブルの全ての値を取得 If InStr(k.Value, "顧客ID") = 1 Then Ct = k.Column '顧客IDが何列目にあるかを記録 If k.Column = Ct And k <> "" Then '顧客テーブルの列で、値が空白以外なら検索を行う Set s = Range("性別テーブル").Find(what:=k.Value, lookat:=xlPart, MatchCase:=False) If Not s Is Nothing Then '見つかった場合 '顧客IDの隣のセルに、性別テーブルで見つけた顧客IDの '隣のセルの値を記入。 k.Offset(0, 1) = s.Offset(0, 1) End If End If Next End Sub 'Vlookup版 Sub ChckVlookup() Dim k As Range Dim Ct As Integer Dim s As Variant On Error Resume Next 'エラーがあっても止まらないで実行 For Each k In Range("顧客テーブル") If InStr(k.Value, "顧客ID") = 1 Then Ct = k.Column If k.Column = Ct And k <> "" Then 'VLOOKUPを使って性別テーブルの値を取得 s = WorksheetFunction.VLookup(k.Value, Range("性別テーブル"), 2, False) If s <> "" Then '値が見つかったら記入する。 k.Offset(0, 1) = s End If End If Next On Error GoTo 0 'エラーが有ったら止まるように設定する。 End Sub 頑張ってくださいね。
その他の回答 (3)
- papayuka
- ベストアンサー率45% (1388/3066)
#2です。 書き忘れましたが、元のコードが lookat:=xlPart になってたので、そのままサンプルも書きましたが、xlWhole にしないと部分的に一致する値があった場合、先に見つけた方を拾ってしまいます。
お礼
有難うございます。 本を見て勉強しているんですが、難しくって… 又質問すると思いますので、その時も宜しくお願いします。
- papayuka
- ベストアンサー率45% (1388/3066)
変数の型などを理解されていないようで、かなりの部分がおかしいと思います。 ↓kはRange型ですから代入するのであれば Set k = Range("顧客テーブル").Range(2, 3).Value ↓ Set k = Range("顧客テーブル") のようにしないと成り立ちません。 ↓myTblってどこから出てきたのでしょう? For i = 2 To myTbl.Rows.Count ↓最初の i は For の指定だと 2 です。つまり 2 を含むものを探してます。 ~.Find(what:=i, lookat:=xlPart, MatchCase:=False) ↓逆です。見つからなかった場合になっています。 If s Is Nothing Then ↓文法的に変です。 k.Range("g2").Value '-------------------------------------------------------------------------- 上手く動くか解りませんがサンプルです。 試すならテスト環境で。 Sub Test() Dim tRange As Range, r As Range, fr Set tRange = Range("顧客テーブル").Offset(, 2).Resize(, 1) For Each r In tRange Set fr = Range("性別テーブル").Resize(, 1).Find(what:=r, lookat:=xlPart) If Not fr Is Nothing Then r.Offset(, 1).Value = fr.Offset(, 1).Value Next r End Sub
- hana-hana3
- ベストアンサー率31% (4940/15541)
VBAの問題以前に、データベースの作り方に誤りがあるような気がします。 顧客IDというのは一意なもので普遍ですから、これを顧客テーブルのIDに割り当てるべきかと思います。 そうすれば、単純にVLOOKUP関数で処理できます。 顧客ID 氏名 性別 SA081 山田 太郎 =VLOOKUP(~) VBAで処理する必要は何でしょうか?
補足
早速の回答有難うございます。 確かにそうですね。 何を一生懸命悩んでたんだろう。 ですが、一応勉強の為にマクロでの書き方を教えていただけますか。 k.Range("g2").Value の記述の仕方が間違っているんだと思うんですが。。。 それとも全部おかしいのでしょうか? 宜しくおねがいします。
関連するQ&A
- For~Nextについて
VBA勉強中です。 For~Nextについて、いまいちわからないので、教えてほしいのですが、 下記の表を作り、テーブルと言う名前を付けました。 C列に上からA.Bの値を入れようと思います。 | A | B |C 1| AA| 11| 2| AB| 12| Sub Macro1() Dim AA As Range, BB As Range, AB As Variant Dim myTbl As Range, myFld As Integer, i As Integer Set AA = Range("A1") 'AAの箱にA1の値を Set BB = Range("B1") 'BBの箱にB1の値を Set myTbl = Range("テーブル") 'myTblの箱にテーブルを myFld = 3 'myFldの箱に3列目 AB = AA & "." & BB 'A1とB1の値を入れる For i = 1 To myTbl.Rows.Count 'iはテーブルの1行目から最後の行まで If myTbl.Cells(i, myFld).Value = AB Then 'テーブルの1行目のCのセルにA1とB1の値を入れる Exit Sub End If Next End Sub と思うのですが、やはり動きません。 アドバイスをお願いします。
- ベストアンサー
- オフィス系ソフト
- マクロで質問します。
初心者です。 下記のようなマクロの式があるのですが、条件を一つ増やしたいのですが、 イロイロ試してみたのですが、うまくゆきませんので教えてください! Sub 給与支払一覧() Application.ScreenUpdating = False Dim Sh As Worksheet For Each Sh In Worksheets If Sh.Name <> "給与支払一覧" And Sh.Name Like "Sheet*" Then With Worksheets("給与支払一覧") If Sh.Range("D14").Value > 0 Then With .Cells(.Rows.Count, 1).End(xlUp).Offset(1) Sh.Range("O2:X14").Copy .Cells(1) .Resize(13, 10).Value = Sh.Range("O2:X14").Value End With End If End With End If Next Sh Set Sh = Nothing End Sub この中で If Sh.Range("D14").Value > 0 Then とありますが、 同じ条件で I14も 0より大きいな時としたいのですが、 うまくゆきませんでした。 たぶん基本できな簡単な事と思いますが 分かりません。 If Sh.Range("D14").Value > 0 Then If Sh.Range("I14").Value > 0 Then 並べてみたり If Sh.Range("D14、I14").Value > 0 Then こんなのや If Sh.Range("D14、I14").).Value > 0 Then このような事も 他にも笑われるようなことも・・・・・ よろしくお願いします。
- ベストアンサー
- オフィス系ソフト
- ExcelからAccess2013DBを更新する時
Excel2013 vba-> Access2013 mdbファイル 問題点:以下のソースを実行すると、エラーが発生します。このエラーをなくしてアクセスデータベースのテーブルの情報の更新、新規追加、削除を行いたいです。 エラー内容:実行時エラー'3251' 現在のRecordsetは更新をサポートしていません。プロバイダーか、選択されたロックタイプの限界の可能性があります。 ソース: Sub 登録処理() Dim Rst As adodb.Recordset Dim SQL As String Dim Rg As Range Dim RgData As Range Dim lngLastRow As Long Dim RgDel As Range On Error GoTo errH Set RgData = mySh.Range("B2") lngLastRow = RgData.End(xlDown).Row Set RgData = mySh.Range(RgData, mySh.Range("AB" & lngLastRow)) SQL = "Select * from [会社管理テーブル]" Call DBconection2 Set Rst = New adodb.Recordset With Rst .ActiveConnection = Cn 'SQL文でテーブル名と抽出条件を指定する .Source = SQL .CursorLocation = 3 ' クライアントサイドカーソルに変更 .Open End With Dim y As Long Sheets("会社管理").Select If Rst.EOF = False And Rst.BOF = False Then For i = 1 To RgData.Rows.Count If Cells(i + 1, 1).Value = "変更" Then Rst.MoveFirst Rst.Find "[施工会社ID]=" & RgData(i, 1).Value If Rst.EOF Then Else Rst.Fields("会社ID").Value = RgData(i, 2).Value Rst.Fields("会社名").Value = RgData(i, 3).Value Rst.Fields("フリガナ").Value = RgData(i, 4).Value Rst.Update End If Cells(i + 1, 1).Value = "" ElseIf Range(i, 1).Value = "削除" Then Rst.MoveFirst Rst.Find "[会社ID]=" & RgData.Cells(i, 1).Value If Rst.EOF Then Else Rst.Delete End If Set RgDel = Rows(i + 1 & ":" & i + 1) RgDel.Select RgDel.Delete ElseIf Range(i, 1).Value = "新規" Then Rst.AddNew Rst.Fields("会社ID").Value = RgData(i, 2).Value Rst.Fields("会社名").Value = RgData(i, 3).Value Rst.Fields("フリガナ").Value = RgData(i, 4).Value Rst.Update Cells(i + 1, 1).Value = "" End If Next i End If exitH: Rst.Close: Set Rst = Nothing Call DBclose2 Exit Sub errH: MsgBox Err.Number & "(" & Err.Description & ")" GoTo exitH End Sub Sub DBconection2() Set Cn = New adodb.Connection Cn.Provider = "Microsoft.Jet.OLEDB.4.0" Cn.Open modPublic.DBPATH End Sub Function MakeDBconection() As adodb.Connection Set Cn = New adodb.Connection Cn.Provider = "Microsoft.Jet.OLEDB.4.0" Cn.Open modPublic.DBPATH Set MakeDBconection = Cn End Function Sub DBclose2() Cn.Close Set Cn = Nothing End Sub Sub EraseContents(s_Rg As Range) s_Rg.ClearContents End Sub 誰か、解決方法がおわかりの方がいましたら、アドバイスをよろしくお願いします。
- 締切済み
- その他(データベース)
- 2つのVBAを組み合わせる方法
お世話になります、2つのVBAを組み合わせる方法で迷っています。 1つ目が Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Intersect(Target, Range("C1,B9:B39")) Is Nothing Or Target.Count > 1 Then Exit Sub Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True End Sub です。 2つめが Private Sub Worksheet_Change(ByVal Target As Range) Application.EnableEvents = True If Intersect(Target, Range("R8:R38")) Is Nothing Then Exit Sub Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End Sub です。2つのPrivate Sub Worksheet_Change(ByVal Target As Range)イベントのVBAですが、どのようにして組み合わせれば良いのでしょうか?
- ベストアンサー
- Excel(エクセル)
- Find,Offsetを使ってセルを指定する方法
エクセルVBAのことで伺います。 以下の記述は、「D3からQ3までのセルの中で「年」と入ったセルの左横のセルを探し、 その中の値(西暦の年が入っています)を、G4からI100までの範囲に入力される月日 の年として置き換える」といったものなのですが、エラーが出てしまいます。 「実行時エラー424、オブジェクトが必要です。」とのメッセージが表示され、デバックを クリックすると、「Set FoundCell = Range("D3:Q3").Find("年").Offset(0, -1).Select」 が黄色く強調表示されています。 プログラムの記述をどのように修正すれば良いか、どなたかお教えください。 よろしくお願いいたします。 Private Sub Worksheet_Change(ByVal Target As Range) Dim FoundCell As Range Set FoundCell = Range("D3:Q3").Find("年").Offset(0, -1).Select With Target If Intersect(Target, Range("G4:I100)) Is Nothing Or Target.Count <> 1 Then Exit Sub If IsDate(.Value) Then If Year(.Value) <> FoundCell Then Application.EnableEvents = False .Value = DateSerial(FoundCell, Month(.Value), Day(.Value)) Application.EnableEvents = True End If End If End With End Sub
- ベストアンサー
- Excel(エクセル)
- マクロのFINDメソッドで質問です。
マクロの初心者で、いつもお世話になっております。 FINDメソッドを使って別々のシートから同じIDを探す処理をしたいのですが、IDが片方にしか無い場合に検索2rangeが"nothing"になってしまい止まってしまいます。 抜粋ですか以下の様にコーディングしました。 解る方がいましたらアドバイスをお願いします。 IDはIDがセットされている列です。 シート2を上から1つずつ見ていき、 シート1から該当するIDを探す処理をします。 最終的には該当したIDの行数を記憶して、 シート1とシート2をマッチングさせたいのですが。 Dim 検索range As Range Dim 検索2range As Range ID = Sheet2.Cells(LOOP_C1, 検索列).Value Set 検索Range = Range(Sheet1.Cells(F2TOP,検索列),Sheet1.Cells(LASTRow, 検索列)) Set 検索2range = 検索Range.Find(What:=ID, LookAt:=xlWhole, SearchOrder:=xlByRows, searchformat:=True).Row ※ If 検索2range Is Nothing Then Else 検索2range.Activate End If ・ ・ ・ ※の箇所で止まってしまいます。
- ベストアンサー
- オフィス系ソフト
- すべてのシートでマクロを実行したい
以下のプログラムでは、選択したシートのみマクロが動作しています。ネット検索で見よう見まねで作ったため何がまちがっているのかわかりません。ご教示いただけるとありがたいです。 ・月の予定表で利用者が休みの日に斜線を引くマクロ ・入力ミスを防ぐためシート保護をしている Sub すべてのシート() Dim s As Worksheet For Each s In Worksheets s.Select Call 斜線 Next End Sub Sub 斜線() ActiveSheet.Unprotect Password:="1234" For i = 1 To Range("E10").End(xlDown).Row Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlNone If Range("E10").Value = 0 Then Exit Sub If Cells(i, "E").Value = "日" And Range("BP9").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "E").Value = "月" And Range("BP10").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "E").Value = "火" And Range("BP11").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "E").Value = "水" And Range("BP12").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "E").Value = "木" And Range("BP13").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "E").Value = "金" And Range("BP14").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "E").Value = "土" And Range("BP15").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If If Cells(i, "AY").Value = "祝日" And Range("BP16").Value = 0 Then Range("AS" & i).Borders(xlDiagonalUp).LineStyle = xlContinuous End If Next i ActiveSheet.Protect Password:="1234" End Sub
- ベストアンサー
- Excel(エクセル)
- comboboxで任意の行列を削除する
comboboxで選択したデーターを探して、その行の 2列目から45列までを、削除する方法をお教えください。 下のように記述したのですが、1行全てが削除されてしまいます。 どのように記述したらよいのでしょうか。 よろしくお願いします。 Private Sub 保存データー削除_Click() Dim i As Long For i = 2 To 199 If Cells(i, 2).Value = combobox1.Value Then Range(i & ":" & i).Delete End If Next i Dim k As Long, s As Long k = 1 For s = 1 To 31 Cells(s, 1).Value = k k = k + 1 Next s End Sub
- ベストアンサー
- その他(プログラミング・開発)
- エクセルのデータの変更
今マクロでSheet1にあるデーターをSheet2・3・4・5・6・7それぞれにそれぞれの抽出条件で抽出できるよう設定してあるのですが、このSheet1を他のBookに変更した場合のマクロの変更の仕方を教えてください。 ちなみにいまは 標準モジュールに Sub 定義() Dim myTbl As Range, myQry As Range, sakiRng As Range End Sub と各シートの[Worksheet Activate] に Private Sub Worksheet_Activate() Set myTbl = Sheets(1).Range("myTbl") Set myQry = Sheets(8).Range("A_抽出条件") Set sakiRng = Sheets(2).Range("A3:AR3") myTbl.AdvancedFilter xlFilterCopy, myQry, sakiRng Dim rw As Long '入力最終行 rw = Range("I65536").End(xlUp).Row With Application Range("I" & rw + 1) = .Sum(Range("I1:I" & rw)) Range("AO" & rw + 1) = .SumIf(Range("AP1:AP" & rw), "済", Range("AO1:AO" & rw)) Range("AQ" & rw + 1) = .Sum(Range("AQ1:AQ" & rw)) End With End Sub となっています。
- 締切済み
- オフィス系ソフト
- 再質問 長いIF文を短くしたい
お世話になっております 先日1/24に、条件を示さずに「長いIF文を短くしたい」という質問をしてしまいました こちらの手抜きをお詫びします 前回keithinさんにアドバイスいただいた方法で書き直しましたので これをさらに簡単に書く方法があれば教えてください 以下は、Private Sub Worksheet_Change(ByVal Target As Range)内のマクロです If Target.Row >= 15 And Target.Row <= 100 And Target.Column = 9 Then If Range("I" & Target.Row).Value < Range("J" & Target.Row).Value Then If Range("G" & Target.Row).Value >= 1 Then If Range("I" & Target.Row).Value >= Range("G" & Target.Row).Value Then If Range("I" & Target.Row).Value Mod Range("G" & Target.Row).Value = 0 Then 処理 End If End If End If End If End If
- 締切済み
- Excel(エクセル)
お礼
有難うございます。 本当に私のと全然違いますね。 For EachステートメントやInStr関数っていうのがあるなんて知りませんでした。 又色々質問すると思いますので、その時も宜しくお願いします。