エクセルマクロで質問です。
マクロを学びたいため、例のマクロを教えていただきたいです。
マンションのデータをまとめたいため、スーモのサイトからエクセルにコピペしました。
元データ
やりたい条件としては、
・A列を「チェック」で検索→ヒットしたセルの3個下のセルの内容をマンション名列に入れる
・販売価格で検索→ヒットしたセルのひとつ下のセルの内容を販売価格列に入れる
・・・・くりかえしです。
必要な項目だけを抜き出して整理するマクロを作りたいです。
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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
総合スコア294
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
総合スコア294
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/04 09:18
2015/09/04 11:04