質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

2回答

8580閲覧

【マクロ】検索に一致した条件とその下のセルを抽出

hirory

総合スコア42

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

2クリップ

投稿2015/09/03 09:04

エクセルマクロで質問です。
マクロを学びたいため、例のマクロを教えていただきたいです。

マンションのデータをまとめたいため、スーモのサイトからエクセルにコピペしました。
元データ
イメージ説明

この状態から
sheet3のこれに整理していく
イメージ説明

やりたい条件としては、
・A列を「チェック」で検索→ヒットしたセルの3個下のセルの内容をマンション名列に入れる
・販売価格で検索→ヒットしたセルのひとつ下のセルの内容を販売価格列に入れる

・・・・くりかえしです。

必要な項目だけを抜き出して整理するマクロを作りたいです。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

コメントではコードを貼り付けにくいので、新規でおこしました。

相対位置を指示する形式では期待する結果を得られないとの事でしたので、
検索をする方法に切り替えて書いてみました。

Sample()の中に全て書くとかなり冗長になってしまったので、一つ関数を作っています。
Sample()を実行して確認をしてもらえればと思います。

決め打ちの事項については、前回の物から「相対位置が同じ」と「データの1固まりが30行」を
除外したくらいです。

後、データの1固まり(「チェック」から次の「チェック」まで)で、取得する情報(販売価格など)が
ヒットしなかった場合は空""となります。(マンション名は除く)

VBA

1Option Explicit 2 3'keyword : 検索する項目名 4'rng : 検索範囲 5'offsetRow : 値が格納されている行(検索ヒット場所からの相対位置) 6'offsetCol : 値が格納されている列(検索ヒット場所からの相対位置) 7Function GetItemText(keyword As String, rng As Range, offsetRow As Long, offsetCol As Long) As String 8 On Error Resume Next 9 10 Dim MatchResult As Variant 11 Dim value As String 12 13 value = "" 14 15 '検索の実行 16 MatchResult = Application.Match(keyword, rng, 0) 17 18 If IsNumeric(MatchResult) Then 19 value = rng.Cells(CLng(MatchResult) + offsetRow, 1 + offsetCol).Text 'ヒットすれば結果をvalueへ 20 End If 21 22 GetItemText = value 23End Function 24 25 26Sub Sample() 27 28 Dim DataSht As Worksheet 29 Dim PutSht As Worksheet 30 Dim DataEndRow As Long 31 Dim BlockStartRow As Long 32 Dim BlockNextRow As Long 33 Dim PutRow As Long 34 Dim RngStr As String 35 Dim MatchResult As Variant 36 37 'データ出力開始位置 38 Const PUT_START = 4 39 40 'データ開始と取得情報のキーワード 41 Const KEYWORD_MANSION = "チェック" 42 Const KEYWORD_PRICE = "販売価格" 43 Const KEYWORD_LOCATION = "所在地" 44 Const KEYWORD_STATION = "沿線・駅" 45 Const KEYWORD_AREA = "占有面積" 46 Const KEYWORD_FLOOR = "間取り" 47 Const KEYWORD_BUILT = "築年月" 48 49 50 Set DataSht = Sheet2 '元のデータが入っているシート 51 Set PutSht = Sheet3 '取得した情報を出力するシート 52 53 54 ' データの入っている最終行を取得(A列) 55 DataEndRow = DataSht.Cells(Rows.Count, 1).End(xlUp).Row 56 57 '先頭の「チェック」位置を取得 58 RngStr = "A1:A" + CStr(DataEndRow) 59 MatchResult = Application.Match(KEYWORD_MANSION, DataSht.Range(RngStr), 0) 60 If IsError(MatchResult) Then 61 MsgBox "該当データが1つも存在しません" 62 Exit Sub 63 End If 64 BlockStartRow = CLng(MatchResult) 65 66 '出力開始位置で初期化 67 PutRow = PUT_START 68 69 70 Do While BlockStartRow < DataEndRow 71 72 '次の「チェック」を検索 73 RngStr = "A" + CStr(BlockStartRow + 1) + ":A" + CStr(DataEndRow) '検索範囲の文字列を生成 74 MatchResult = Application.Match(KEYWORD_MANSION, DataSht.Range(RngStr), 0) 75 If IsError(MatchResult) Then 76 BlockNextRow = DataEndRow + 1 '次の「チェック」が存在しない 77 Else 78 BlockNextRow = BlockStartRow + CLng(MatchResult) 79 End If 80 81 'マンション名が「チェック」の3行下なので、少なくともデータの1固まりは4行が必要 82 If BlockNextRow - BlockStartRow >= 4 Then 83 84 '----- A列に存在する情報の取得 ----- 85 RngStr = "A" + CStr(BlockStartRow) + ":A" + CStr(BlockNextRow - 1) '検索範囲 86 87 'マンション名の取得(A列) 88 PutSht.Cells(PutRow, 1) = DataSht.Cells(BlockStartRow + 3, 1).Text 89 90 '販売価格の取得(A列) 91 PutSht.Cells(PutRow, 2) = GetItemText(KEYWORD_PRICE, DataSht.Range(RngStr), 1, 0) 92 93 '所在地の取得(A列) 94 PutSht.Cells(PutRow, 3) = GetItemText(KEYWORD_LOCATION, DataSht.Range(RngStr), 1, 0) 95 96 '沿線・駅の取得(A列) 97 PutSht.Cells(PutRow, 4) = GetItemText(KEYWORD_STATION, DataSht.Range(RngStr), 1, 0) 98 99 '占有面積の取得(A列) 100 PutSht.Cells(PutRow, 5) = GetItemText(KEYWORD_AREA, DataSht.Range(RngStr), 1, 0) 101 102 103 '----- B列に存在する情報の取得 ----- 104 RngStr = "B" + CStr(BlockStartRow) + ":B" + CStr(BlockNextRow - 1) '検索範囲 105 106 '間取りの取得(B列) 107 PutSht.Cells(PutRow, 6) = GetItemText(KEYWORD_FLOOR, DataSht.Range(RngStr), 1, 0) 108 109 '築年月の取得(B列) 110 PutSht.Cells(PutRow, 7) = GetItemText(KEYWORD_BUILT, DataSht.Range(RngStr), 1, 0) 111 112 PutRow = PutRow + 1 113 End If 114 115 BlockStartRow = BlockNextRow 116 Loop 117 118 MsgBox "データの取得を完了しました" 119End Sub 120

投稿2015/09/04 05:41

sgr-2

総合スコア294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirory

2015/09/04 09:18

完璧でした!本当にありがとうございます! これをたたき台にして今後勉強していこうと思います。 お忙しい中本当にありがとうございました。
sgr-2

2015/09/04 11:04

上手くいったようで良かったです。 Excelは「マクロの記録」が とても強力なので、これを追うだけでもVBA(特にExcel固有の機能)など効率的に勉強できると思います。 # 私は「マクロの記録」に随分助けられました。
guest

0

こんばんは。
サンプルのコードを書くにあたり、かなり決め打ちしている部分があり
期待した方法と異なるかもしれませんが、以下のコードではいかがでしょうか。


決め打ちしている事
・データはSheet2に存在し、取得したデータはSheet3に出力する
・「チェック」が1固まりのデータの開始を示す(これは例の通りと思います)
・「チェック」は必ずA列に存在する
・取得対象の「間取り」と「築年月」はB列、それ以外はA列に存在する
・取得する情報(マンション名、販売価格など)はすべて「チェック」からの相対位置が同じ
→項目毎に検索しないで、チェックからの相対位置を使って取得
・スクリーンショットの通り、「チェック」から終端?「ロビー」までが30行なので
データの1固まりは30行あるとする
→コード中の「BLOCK_SIZE_ROW」がそれにあたります、30行より小さい可能性がある場合は
1固まりの最小となる行数を指定します

方法はいくらかあると思います。検索(Findコマンドなど)を使わないで、走査していく方が単純で
分かり易いと考えました。

データの固まりと固まりの間に多くの空行が存在するような形でなければ、走査する方法であっても

そんなに効率は悪くないと思います。

VBA

1Option Explicit 2 3Sub Sample() 4 5 Dim DataSht As Worksheet 6 Dim PutSht As Worksheet 7 Dim DataEndRow As Long 8 Dim ReadRow As Long 9 Dim ReadCol As Long 10 Dim PutRow As Long 11 12 'データ走査開始位置 13 Const START_ROW = 1 14 Const START_COL = 1 15 16 'データ出力開始位置 17 Const PUT_START = 4 18 19 Const KEYWORD = "チェック" 20 21 '各項目の「チェック」からの相対位置 22 Const MANSION_OFFSET_ROW = 3 'マンション名 23 Const MANSION_OFFSET_COL = 0 24 Const PRICE_OFFSET_ROW = 10 '販売価格 25 Const PRICE_OFFSET_COL = 0 26 Const LOCATION_OFFSET_ROW = 12 '所在地 27 Const LOCATION_OFFSET_COL = 0 28 Const STATION_OFFSET_ROW = 14 '沿線・駅 29 Const STATION_OFFSET_COL = 0 30 Const AREA_OFFSET_ROW = 16 '占有面積 31 Const AREA_OFFSET_COL = 0 32 Const FLOOR_OFFSET_ROW = 16 '間取り 33 Const FLOOR_OFFSET_COL = 1 34 Const BUILT_OFFSET_ROW = 18 '築年月 35 Const BUILT_OFFSET_COL = 1 36 37 Const BLOCK_SIZE_ROW = 30 'データ1固まりの行数 38 39 40 Set DataSht = Sheet2 '元のデータが入っているシート 41 Set PutSht = Sheet3 '取得した情報を出力するシート 42 43 ' データの入っている最終行を取得(A列) 44 DataEndRow = DataSht.Cells(Rows.Count, 1).End(xlUp).Row 45 46 '走査開始位置で初期化 47 ReadRow = START_ROW 48 ReadCol = START_COL 49 50 '出力開始位置で初期化 51 PutRow = PUT_START 52 53 Do While ReadRow < DataEndRow 54 If DataSht.Cells(ReadRow, ReadCol).Text = KEYWORD Then 55 56 With DataSht 57 'マンション名の取得 58 PutSht.Cells(PutRow, 1) = .Cells(ReadRow + MANSION_OFFSET_ROW, ReadCol + MANSION_OFFSET_COL).Text 59 60 '販売価格の取得 61 PutSht.Cells(PutRow, 2) = .Cells(ReadRow + PRICE_OFFSET_ROW, ReadCol + PRICE_OFFSET_COL).Text 62 63 '所在地の取得 64 PutSht.Cells(PutRow, 3) = .Cells(ReadRow + LOCATION_OFFSET_ROW, ReadCol + LOCATION_OFFSET_COL).Text 65 66 '沿線・駅の取得 67 PutSht.Cells(PutRow, 4) = .Cells(ReadRow + STATION_OFFSET_ROW, ReadCol + STATION_OFFSET_COL).Text 68 69 '占有面積の取得 70 PutSht.Cells(PutRow, 5) = .Cells(ReadRow + AREA_OFFSET_ROW, ReadCol + AREA_OFFSET_COL).Text 71 72 '間取りの取得 73 PutSht.Cells(PutRow, 6) = .Cells(ReadRow + FLOOR_OFFSET_ROW, ReadCol + FLOOR_OFFSET_COL).Text 74 75 '築年月の取得 76 PutSht.Cells(PutRow, 7) = .Cells(ReadRow + BUILT_OFFSET_ROW, ReadCol + BUILT_OFFSET_COL).Text 77 78 End With 79 ReadRow = ReadRow + BLOCK_SIZE_ROW 80 PutRow = PutRow + 1 81 82 Else 83 ReadRow = ReadRow + 1 84 End If 85 Loop 86End Sub

投稿2015/09/03 15:22

sgr-2

総合スコア294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirory

2015/09/04 02:34

うまくいきました!本当にありがとうございます!!! ただ、ところどころ空白行数が違い、チェックからの相対位置が異なります。 文字を検索して、その下を抽出するという方法はありますでしょうか? お手すきの時間にお教えいただきたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問