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

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

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

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

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

Q&A

解決済

2回答

1329閲覧

VBA マクロを使った指定の文字列の抽出方法

icecleam

総合スコア46

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

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

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

0グッド

0クリップ

投稿2020/09/21 08:33

以下のマクロを実行すると以下の「転記先」のように転記が実行されます。
現在のソースでは、転記元の「開発A」、「開発B」というのは以下の「該当箇所」で抽出しているのですが、
それだと、「転記元」のB29,B30、B39、B40のようなセルが同じ列に含まれているときに、そちらも抽出してしまい、予期せぬ動きをしてしまいます。

今回だと、B14,B32の「開発A」、「開発B」のセルの内容のみをピンポイントで検索して、抽出する方法があれば教えていただきたいです。
「開発A」、「開発B」というのは担当者の数が可変なので、行が変わる可能性があり、そのセルの内容を例えばCell(14,3)のように一定の場所で指定することはできません。

該当箇所

Macro

1'① 2If Left(.Cells(i, 2).Value, 2) = "開発" Then 3

転記先
イメージ説明

転記元
イメージ説明

現状のソース

Macro

1Sub sample1() 2 3 Dim lngRowsNo As Long ' 書きこむ位置 4 Dim lngSheetIndex As Long ' シートの番号 5 Dim strFile As String ' Excelファイルの場所 6 Dim xlsAcq As New Excel.Application ' 取得側Excel 7 Dim wbAcq As Workbook ' 取得側Excelブック 8 Dim wsAcq As Worksheet ' 取得側Excelシート 9 Dim wsSet As Worksheet ' 設定側Excelシート 10 Const strPath As String = "パスを指定する" 11 Set wsSet = ActiveSheet 12 Dim i As Long 13 14 strFile = Dir(strPath & "*.xls") 15 lngRowsNo = 3 16 Do Until strFile = "" 17 '----- Excelブックを開く 18 Set wbAcq = Workbooks.Open(strPath & strFile) 19 20 '----- シートを検索 21 For lngSheetIndex = 1 To wbAcq.Worksheets.Count 22 '----- 「更新」シートを検索 23 If wbAcq.Worksheets(lngSheetIndex).Name = "更新" Then 24 '----- 「更新」シートを変数へ登録 25 Set wsAcq = wbAcq.Worksheets(lngSheetIndex) 26 '----- 「更新」シートの内容を現在のシートにコピー(自由に変更して下さい) 27 With wsAcq 28 Dim fname As String 'ファイル名 29 Dim n As Long 'ループで使用します。 30 Dim m As Long 'ループで使用します。 31 Dim ec1 As Long '各開発の一番下の担当者のセルを取得 32 Dim ec2 As Long '各開発の 月の一番右(最後)のセルを取得 33 Dim ColumnNo As Long ' 転記先の列番号(初期値4) 34 Dim ColumnNo2 As Long ' 転記元の列番号(初期値5)+3されていく 35 36 ColumnNo = 4 37 ColumnNo2 = 5 38 39 For i = 1 To .UsedRange.Rows.Count 40            '① 41 If Left(.Cells(i, 2).Value, 2) = "開発" Then 42 '月を取得して転記 43 ec2 = .Cells(i + 1, 5).End(xlToRight).Column + 1 44 For col = 5 To ec2 45 46 wsSet.Cells(2, ColumnNo).Value = .Cells(i + 1, ColumnNo2).Value 47 48 ColumnNo = ColumnNo + 1 49 ColumnNo2 = ColumnNo2 + 3 50 51 Next col 52 53 ' ------ 開発〇から一番上の担当者のセル位置を相対的にCells(i + 3, 3)として取得し 54 'データの入っているところまでループさせる (その時、開発名を転記) 55 ec1 = .Cells(i + 3, 2).End(xlDown).Row 56 For n = i + 3 To ec1 57 58 '担当者が空白の時スキップする 59 If Cells(n, 3) = "" Then 60 GoTo NEXT99 61 End If 62 63 'ファイル名 64 fname = ActiveWorkbook.Name 65 wsSet.Cells(lngRowsNo, 1).Value = fname 66 67 '開発 68 wsSet.Cells(lngRowsNo, 2).Value = .Cells(i, 2).Value 69 70 '担当者 71 wsSet.Cells(lngRowsNo, 3).Value = .Cells(n, 3).Value 72 73 '工数 74 wsSet.Cells(lngRowsNo, 4).Value = .Cells(n, 5).Value 75 76 wsSet.Cells(lngRowsNo, 5).Value = .Cells(n, 8).Value 77 78 wsSet.Cells(lngRowsNo, 6).Value = .Cells(n, 11).Value 79 80 wsSet.Cells(lngRowsNo, 7).Value = .Cells(n, 14).Value 81 82 wsSet.Cells(lngRowsNo, 8).Value = .Cells(n, 17).Value 83 84 wsSet.Cells(lngRowsNo, 9).Value = .Cells(n, 20).Value 85 86 wsSet.Cells(lngRowsNo, 10).Value = .Cells(n, 23).Value 87 88 wsSet.Cells(lngRowsNo, 11).Value = .Cells(n, 26).Value 89 90 wsSet.Cells(lngRowsNo, 12).Value = .Cells(n, 29).Value 91 92 wsSet.Cells(lngRowsNo, 13).Value = .Cells(n, 32).Value 93 94 '1行下へ 95 lngRowsNo = lngRowsNo + 1 96 97NEXT99: 98 Next n 99 End If 100 Next i 101 End With 102 103 '----- 検索の終了 104 Exit For 105 End If 106 Next lngSheetIndex 107 108 '----- シート参照の解放 109 Set wsAcq = Nothing 110 '----- ブックを閉じる 111 wbAcq.Close Savechanges:=False 112 '----- 次のファイルへ 113 strFile = Dir() 114 Loop 115 116 '----- Excelへの参照の解放 117 Set xlsAcq = Nothing 118 119End Sub 120 121 122

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

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

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

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

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

guest

回答2

0

転記元のシート画像を見ると「No」の上のセルを参照すればいいはずなので、
Find/FindNextメソッドで「No」を完全一致で検索して見つかったセルの一つ上を参照するようにすればいいかと。
(その方が高速なはず。)

条件に当てはまるセルを検索する(Find/FindNext/FindPreviousメソッド) :Excel VBA|即効テクニック|Excel VBAを学ぶならmoug

あるいは、Match関数で検索してもいいでしょう。(こちらの方かさらに高速。)

【ExcelVBA入門】MATCH関数を使ったセル範囲を検索する方法を徹底解説! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト


+を付けてくれた人のために、
MATCH関数を使った場合のコード例

vba

1Public Sub sample1() 2'前略 3 With wsAcq 4 Dim LastRow As Long 5 LastRow = .Cells(.Rows.Count, 2).End(xlUp).Row 6 Dim TargetRow As Long 7 TargetRow = 1 8 9 Dim MatchRow As Long 10 MatchRow = 1 11 12 Do 13 With Application 14 MatchRow = .IfError(.Match("No", .Range("B" & TargetRow & ":B" & LastRow), 0), 0) 15 End With 16 TargetRow = TargetRow + MatchRow - 2 17 If MatchRow <> 0 Then 18 Dim 開発 As String 19 開発 = .Cells(TargetRow, 2).Value 20 21 '転記処理省略 22 23 24 End If 25 TargetRow = TargetRow + 3 26 Loop Until MatchRow = 0 27 28 End With 29 30'後略 31End Sub

投稿2020/09/21 09:54

編集2020/09/22 00:51
hatena19

総合スコア34075

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

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

0

ベストアンサー

対策は2つあります。

1案 
最初の2文字が"開発"かどうかで判断しているので、
「開発A質問」 ではなく 「☆開発A質問」 のように頭に適当な1文字を追加して、最初の2文字が開発
にならないようにする。これだと、ソースの変更は不要です。

2案
「開発A質問」の文字があるのが、結合セルであることに注目して
最初の2文字が開発かつそのセルが結合セルでないなら処理をおこなうようにする。
具体的には
If Left(.Cells(i, 2).Value, 2) = "開発" Then を
If Left(.Cells(i, 2).Value, 2) = "開発" And .Cells(i, 2).MergeCells = False Then
に変更する。
但し、この方法は、今後、開発A、開発Bのセルを結合セルにしないことが条件となります。

投稿2020/09/21 09:03

tatsu99

総合スコア5493

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

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

icecleam

2020/09/21 15:35 編集

ありがとうございます。 上記の第2案で無事にやりたいことを実行できました! 余談なのですが、例えば今回「開発A」、「開発B」のように「開発」という共通の文字列で検索をかけましたが、これが「マクロ」、「ジャバ」であった時のように全く違う文字列であった時の検索方法は以下のようになるのでしょうか。 ちょっと以下のコードで試しに動かして見たのですが、うまく動いてくれなかったので。。 If Left(.Cells(i, 2).Value, 3) = "マクロ " And Left(.Cells(i, 2).Value, 3) = "ジャバ" And .Cells(i, 2).MergeCells = False Then
tatsu99

2020/09/21 22:33

If (Left(.Cells(i, 2).Value, 3) = "マクロ " Or Left(.Cells(i, 2).Value, 3) = "ジャバ") And .Cells(i, 2).MergeCells = False Then にしてください。 あなたの書いたマクロは、日本語では そのセルが「マクロ」かつ「ジャバ」であり、かつそのセルが結合セルでないなら になります。1つのセルの内容が「マクロ」と「ジャバ」の両方の値をとることはあり得ません。よってその式が成立することは、絶対にありません。 正しい日本語では、 そのセルが「マクロ」又は「ジャバ」であり、かつそのセルが結合セルでないこと になります。マクロで記述した場合は、OrよりもAndの方が強いので、 (Left(.Cells(i, 2).Value, 3) = "マクロ " Or Left(.Cells(i, 2).Value, 3) = "ジャバ") のようにOrの部分をカッコでくくり、こちらを優先させます。
icecleam

2020/09/22 01:36

ありがとうございます! とても勉強になりました。 日本語に直してみたら確かに一目瞭然ですね。 ご対応いただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問