ExcelVBAにて、同じフォルダ内における複数ブックの特定項目(名前、住所)の集計しようと考えて、以下のように作成しましたが、シートの一行目しか取得できません。2行目以降も取得したいのですが、やり方についてご存じの方がいたら、ご教示ください。
'ボタンをクリックした時の処理
Public Sub sample()
Dim wFile As String
Dim wFilePath As String
Dim i As Long
'Excelファイルが存在していたらファイル名を返す
wFile = Dir(ActiveWorkbook.Path & "\*.xlsx")
'先頭行を指定
i = 2
'カレントディレクトリに存在するExcelファイルを全て読み込む
Do While wFile <> ""
'開くExcelファイルのフルパスを取得
wFilePath = ActiveWorkbook.Path & "\" & wFile
'名前・住所を取得し配列に格納する(区切り文字:|)
strData = Split(File_Load(wFilePath), "|")
'名前
Cells(i, 1) = strData(0)
'住所
Cells(i, 2) = strData(1)
'ファイル名
Cells(i, 3) = wFile
'次のExcelファイルを取得
wFile = Dir()
'行数をカウント
i = i + 1
Loop
End Sub
'Excelファイルを開いてデータを取得
'戻り値:名前|住所 ( | で区切る)
Function File_Load(ByVal wFilePath As String) As String
Dim CurBookName As Variant
Dim ColNo As Long
Dim RowNo As Long
Dim strValue As String
Dim FoundCell As Range
Dim i As Long
'ファイルを開く
Workbooks.Open wFilePath
'開いたExcelのファイル名を取得
CurBookName = Application.ActiveWorkbook.Name
'検索する項目を配列に格納
wItem = Array("名前", "住所")
Dim s As Long
'検索する
For i = LBound(wItem) To UBound(wItem)
Set FoundCell = Cells.Find(What:=wItem(i))
If FoundCell Is Nothing Then
'検索出来なかった場合
If i = 0 Then
strValue = ""
Else
strValue = strValue & "|"
End If
Else
'検索したセルに移動
FoundCell.Select
ColNo = ActiveCell.Column '列番号を取得
RowNo = ActiveCell.Row '行番号を取得
'住所を取得する
If i = 0 Then
'最初の項目
strValue = Cells(RowNo + 1, ColNo).Value
Else
'2番目以降の項目は|で区切る
strValue = strValue & "|" & Cells(RowNo + 1, ColNo).Value
End If
End If
Next i
'結果を返す
File_Load = strValue
'開いたExcelファイルを閉じる
Application.DisplayAlerts = False '確認メッセージの非表示
Workbooks(CurBookName).Close
Application.DisplayAlerts = True '確認メッセージの表示
End Function
A 回答 (11件中1~10件)
- 最新から表示
- 回答順に表示
No.11
- 回答日時:
すいませんが、あとは常連さんにお任せする事になりそうです。
No.9の方法では1つのブックで複数のシートに対してやるにもそのシート名を取得し処理するってのはややこしそうですので、普通にブックを開いてやった方が良いでしょうね。
確か2013でしたね。
2016以降ならパワークエリでいけたかもですが、ここは仕方ないですよね。
でも今回課題を解決できたなら今後もドンドン指示されそうですね。
私個人はそれが嫌なのであくまで自分の業務でしか使わず・見せずでした。
仮に解決できるにしてもそんな評価はいらないって事と後々めんどくさいって理由で。
No.10
- 回答日時:
「各ブックのシート1だけではなく、全てのシートに項目がちらばっているため」とは、次のうちどれでしょうか?
① それぞれのシートに全ての項目が存在するものだけを集計する
② たとえば「シート1」には、「受付日」「氏名」「郵便番号」「住所」「電話番号」、「シート2」には、「氏名」「金額」「用途」「入金日」「公表名」「公表金額」「納入方法」「個数」「品物」のように分散されていてキーになる物が有りそれが同じ物は同じデータとして扱う。
⇒ キーとなる項目(例では「氏名」)は何ですか?(例のように「氏名」をキーにした場合に同姓同名がいたら成り立ちません)
③ たとえば「シート1」には、「受付日」「氏名」「郵便番号」「住所」「電話番号」、「シート2」には、「金額」「用途」「入金日」「公表名」「公表金額」「納入方法」「個数」「品物」のように分散されていてキーになる物は無く同じ行の物は同じデータとして扱う。(行削除や行挿入されるとデータとして成り立たないのであまりやらないと思います)
④ その他(具体的に説明して下さい)
返事遅れて申し訳ありません。
委託事業者と協議し、転記するデータは、一つのシートにまとめてもらうことになりました。
種々ご提案いただき誠にありがとうございます。
質問が締め切りになってしまいましたので、また改めて質問させていただきます。
No.9
- 回答日時:
色々書いててまともに回答もしてないので一案。
ただしOSとOfficeのBit数が違うとするとどうなるのかは経験がないです。
XP(32Bit)+Excel2002(32Bit)
10(64Bit)+Excel 365(64Bit)
なら経験してます。
あとAccessがインストールされてないと無理かも知れませんけど。
一応『Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント』と言うのを入れれば可能性があるのですが、
先のOSとOfficeのBit数が違った場合の対処法については未経験です。
動かなかったらごめんなさい。
Sub megu()
Dim objCn As Object '★参照設定なし版
Dim objRS As Object '★参照設定なし版
Dim r1 As Range
Dim strSQL As String
Dim f_Path As String, f_Name As String
Set objCn = CreateObject("ADODB.Connection") '★参照設定なし版
Set objRS = CreateObject("ADODB.Recordset") '★参照設定なし版
f_Path = ThisWorkbook.Path & "\"
With Worksheets("Sheet1") '★纏めるBookのシート
If .Range("A1").Value = "" Then _
.Range("A1:C1").Value = Array("名前", "住所", "ブック名")
Set r1 = .Cells(Rows.Count, "A").End(xlUp).Offset(1)
End With
strSQL = ""
strSQL = strSQL & " SELECT 名前 , 住所" '★1行目は必ず項目名がある事。存在する場所(列)や順序等には左右されない
strSQL = strSQL & " FROM [Sheet1$]" '★それぞれのシート名が同じである事に注意!
f_Name = Dir(f_Path & "*.xlsx")
Do Until f_Name = ""
With objCn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Properties("Extended Properties") = "Excel 12.0;HDR=YES;"
.Open f_Path & f_Name
End With
objRS.Open strSQL, objCn, 1 '★ 1 : adOpenKeyset がないと参照設定なしの場合レコード数が取れない
r1.Offset(, 2).Resize(objRS.RecordCount).Value = f_Name
r1.CopyFromRecordset objRS
Set r1 = r1.Offset(objRS.RecordCount)
objRS.Close
objCn.Close
f_Name = Dir()
Loop
Set r1 = Nothing
Set objCn = Nothing
Set objRS = Nothing
End Sub
No.8
- 回答日時:
日付って点でいくと『複数の業者』にばら撒いている事から、ファイルの更新日での順序なのかなって考えちゃいましたね。
簡単にいけば『登録した当日の日付』とも思ったのですが、特に返信もないので動きようもなく・・・
他のサイト等で解決したのかな?
めぐみんさん、素人同然の私に的確なアドバイスをまことにありがとうございます。
ご指摘のとおり、私もファイルの更新日での順序も候補して考えておりましたが、ブック名の前の数字や日付で管理したほうが他の職員にもわかりやすいかなと考えたため、当内容で順序を管理するとした次第でございます。
素人同然の私の考えたことなのでお許しください。
なお、他の方からも、いくつかアドバイスをいただておりますので、作成向けて現在 再チャレンジしているところです。
No.7
- 回答日時:
こんばんは、
すでに、他のやり方、回答はあるようですが、、
Do While wFile <> ""
strData = Split(File_Load(wFilePath), "|") これは、ファイルのDoで一回しか呼ばれないかと思いますが、
なので書き出しまでを繰り返す必要があります。その場合、File_Loadの引数も変える必要があるかと。
Do(For) データが無くなるまで(データがある範囲)
strData = Split(File_Load(ブック、シート、行、列などの情報), "|") ’ほとんどFunctionぽく無くなりそう。
Cells(i, 1) = strData(0)'名前
Cells(i, 2) = strData(1)'住所
Cells(i, 3) = wFile'ファイル名
Next
Function File_Load 側
もし、1ファイル1回の呼び出しの場合は、
For i = LBound(wItem) To UBound(wItem)・・・?
これ、wItem = Array("名前", "住所") なので LBound(wItem)=? UBound(wItem)=?
そうです。0と1ですね。すると、
'2番目以降の項目は|で区切る
strValue = strValue & "|" & Cells(RowNo + 1, ColNo).Value
のコード何回通りますか?
やはり、データの(この場合対象シート行数の)ある数だけ繰り返す必要がありますね。
また、Set FoundCell = Cells.Find(What:=wItem(i))
これは、シート全体を検索しています。
1行目が見出し行であるなら、、Range(Cells(1, 1),Cells(1, Cells(1, Columns.Count).End(xlToLeft).Column)).Find(wItem(i)).Column
まあまあ、、範囲が未定なら良いですが、、
例えば、
Dim Maxrow As Long
ColNo = ActiveCell.Column '列番号を取得
RowNo = ActiveCell.Row '行番号を取得
Maxrow = ActiveSheet.Cells(Rows.Count, ColNo).End(xlUp).Row
For j = RowNo+1 to Maxrow '見出し行の下から(RowNoが見出し行とした場合)
'住所を取得する
’If j = 1 Then 上で見出し行の下からなので要らない
'最初の項目
’strValue = Cells(RowNo + 1, ColNo).Value
’Else
'2番目以降の項目は|で区切る
strValue = strValue & "|" & Cells(j, ColNo).Value ’strValueの初めに空文字が入らない工夫を、、又は最後に左一文字を消す?
’End If
Next j
End If
Next i
しかし、Splitすると困ったことにこれだとstrData(0)....strData(20)...みたいに増えますね。
また、Cells(i, 1) = strData(0)'名前 Cells(i, 2) = strData(1)'住所 Cells(i, 3) = wFile'ファイル名 が出力となると
ColNo = ActiveCell.Column '列番号を取得部分を増やす必要がありますね。
(Function File_Loadの渡す前にwItem = Array("名前", "住所")で配列ループが必要かな)
いっそのこと、strData()を配列にしてstrData(j,ColNo)=strValue strData(j,ColNo1)=strValue1 strData(j,ColNo2)=strValue2 みたいに、、
なんとなく、、直して使えそうですが、、、やってられない感出てきました。。
先の事を考えると、ロジックを検討する余地がありそうですが、、事情もお在りかと。。
#4GooUserラックさんの回答にあるように、Copyを使えるならその方がExcelらしいと言うか、簡単ですよ。
処理的な問題があるなら、仕方ありませんが。。
時間があったので、当たり前の事に纏めず、あ~だこうだと長文を書いてみました。
下記は、お詫びを兼ねて。
ファイルの処理順、、について、
strData = Split(File_Load(wFilePath), "|")のような使い方でファイルの昇順(タイムスタンプ)のソートを作ったので参考にする機会があれば、、、です。
4,5列にそれぞれ書き出すので、新規のシートか何かで試してみてください。
ファイルを順次 処理ルーチンに投げれば、昇順タイムスタンプでファイルが処理できます。
タイムスタンプ取得部分をファイル名にすれば、ファイル名の昇順で実行できるかと思います。
Sub fileSort()
Dim f As Object, i As Long, j As Long
Dim ArrFile() As String, tmp As Variant
Dim FName As String
'----------フォルダ内ファイル抽出(配列作成)
With CreateObject("Scripting.FileSystemObject")
For Each f In .GetFolder(ThisWorkbook.Path).Files 'ThisWorkbook.Pathフォルダパス
If LCase(.GetExtensionName(f)) = "xlsx" _
Or LCase(.GetExtensionName(f)) = "xlsm" Then
i = i + 1
ReDim Preserve ArrFile(i)
ArrFile(i) = f.DateCreated & "|" & f.Name '昇順ファイル名なら入れ替える
End If
Next f
End With
For i = 1 To UBound(ArrFile)
For j = UBound(ArrFile) To i Step -1
If ArrFile(i) > ArrFile(j) Then
tmp = ArrFile(i)
ArrFile(i) = ArrFile(j)
ArrFile(j) = tmp
End If
Next j
Next i
tmp = ""
For i = 1 To UBound(ArrFile)
tmp = Split(ArrFile(i), "|")
Cells(i, 4) = tmp(1) '昇順タイムスタンプ (ファイル名)
Cells(i, 5) = tmp(0) ' (タイムスタンプ)
' FName = tmp(1)
' Call Sample1(FName)
Next
End Sub
最後まで読んで頂いたなら、時間を使い申し訳ありませんでした。^;
No.6
- 回答日時:
>③のせる順番は、前に日付か番号をつけ、その順序。
まずデータを取得するBookの順序も気にはなりますが、『前に日付か順番をつけ、その順序』の『前』って何を差しているのでしょう?
ブック名の事?
取り込んだデータに日付かインデックスを付ける?
こう言った場合なら求める結果の例題を載せて貰えるとわかりやすいのかと。
めぐみんさん、種々のご指摘ありがとうございます。
ご指摘のとおり、私の質問の仕方が悪いです。
前⇒同じフォルダ内にあるブック名の名前の前に日付か順番をつけるという意味でございました。
No.5
- 回答日時:
お礼を拝見しましたが、各ブックのシートにあるデータが1行目から始まってるのなら、
『名前・住所』の項目を検索するのは不可能です
仮に1行目に項目があるけどそれぞれがどの列にあるのか不明と言うのなら、
複数の業者となってましたので名称を変えられてる可能性はないのでしょうか?
個人的には項目名に変更がなければ、どこにあるのか?と探すのも面倒なので、
ADO等を使ってブックに接続し取り出すデータ群を指定して抽出しますね
ただ2013は不所持(Bitも不明)なので書いてもそちらで動く保証はないです
No.4
- 回答日時:
それでしたら以下のような物はいかがですか?
Sub Sample()
Dim ファイル名 As String
Dim シート番号 As Long
Dim 列番号 As Long
Dim 名前列 As Long
Dim 住所列 As Long
Dim 一覧行 As Long
Dim 終 As Long
一覧行 = Cells(Rows.Count, 1).End(xlUp).Row + 1
ファイル名 = Dir(ThisWorkbook.Path & "\*.xlsx")
Do While ファイル名 <> ""
Workbooks.Open Filename:=ThisWorkbook.Path & "\" & ファイル名
Sheets(1).Select
名前列 = 0
住所列 = 0
For 列番号 = 1 To Cells(1, Columns.Count).End(xlToLeft).Column
If Cells(1, 列番号).Value = "名前" Then 名前列 = 列番号
If Cells(1, 列番号).Value = "住所" Then 住所列 = 列番号
Next
If 名前列 <> 0 Then
If 住所列 <> 0 Then
終 = Cells(Rows.Count, 名前列).End(xlUp).Row
Range(Cells(2, 名前列), Cells(終, 名前列)).Copy
Windows("一覧.xlsm").Activate
Cells(一覧行, 1).Select
ActiveSheet.Paste
Windows(ファイル名).Activate
Range(Cells(2, 住所列), Cells(終, 住所列)).Copy
Windows("一覧.xlsm").Activate
Cells(一覧行, 2).Select
ActiveSheet.Paste
Range(Cells(一覧行, 3), Cells(一覧行 + 終 - 2, 3)).Value = ファイル名
一覧行 = 一覧行 + 終 - 1
Windows(ファイル名).Activate
End If
End If
Application.CutCopyMode = False
ActiveWindow.Close
ファイル名 = Dir()
Loop
End Sub
No.3
- 回答日時:
念のため確認させていただきます。
①「一覧.xlsm」と同じフォルダにある「○○○.xlsx」の「名前」と「住所」の列データとその「ファイル名」を「一覧.xlsm」にまとめるだけのような感じですが間違いありませんか?
② 重複データはどうするのでしょうか?
ⓐ そのまま全て載せる
ⓑ どれか1つだけ載せる
ⓒ その他(具体的に説明して下さい)
③ 載せる順番になにかルールはありますか?
④ 実行ごとに1度データはクリアした方が良いですか?
ⓓ 毎回クリアする
ⓔ クリアせず追加していく
ⓕ その他(具体的に説明して下さい)
⑤ シートに関して
ⓖ 一番左のシートのみ処理する
ⓗ「○○○.xlsx」は全てのシートから1行目に「名前」と「住所」が有る物を使う
ⓘ その他(具体的に説明して下さい)
⑥ Excel のバージョンは何ですか?
大変わかりにくくて申し訳ありません。
最終的には、集計用の一覧.xlsx(xlsm)ブックに集計ボタンを置いて、それをクリックすると各ブック(名前.住所 1.xlsx,名前 住所 2 xlsx)のシート1のデータが、一覧.xlsx(xlsm)ブックに転記されるようにしたいのです。
添付画像でいうと、名前.住所 1.xlsx シート1から、1行目 氏名 岡島 博・住所 東京都、2行目 山田 隆・堺市を転記するようにしたいのですが、一行目の氏名 岡島 博・住所 東京都しか上記のVBAでは転記されません。なお、岡田 敦 大阪狭山市は、名前 住所 2 xlsx シート1の一行目となります。
なお、名前.住所 .xlsxのブックは画像では1~2しかないですが、今後増えていきます。
①お見込みのとおりです。
②重複データはそのままのせる形です。
③のせる順番は、前に日付か番号をつけ、その順序。
④クリアせずに追加していく。
⑤シートに関しては、一番左のシートのみで構いません。
⑥Excel 職場のものは2013なので、2013を使用します。
No.2
- 回答日時:
画像がよくわかりませんが、1つのブックについて取得する『名前・住所』はその項目の1つ下の1対だけなのでしょうか?
何が、
>シートの一行目しか取得できません。2行目以降も取得したいのですが、
と伝え解決したいのかが・・・・?
大変わかりにくくて申し訳ありません。
最終的には、集計用の一覧.xlsx(xlsm)ブックに集計ボタンを置いて、それをクリックすると各ブック(名前.住所 1.xlsx,名前 住所 2 xlsx)のシート1のデータが、一覧.xlsx(xlsm)ブックに転記されるようにしたいのです。
添付画像でいうと、名前.住所 1.xlsx シート1から、1行目 氏名 岡島 博・住所 東京都、2行目 山田 隆・堺市を転記するようにしたいのですが、一行目の氏名 岡島 博・住所 東京都しか上記のVBAでは転記されません。なお、岡田 敦 大阪狭山市は、名前 住所 2 xlsx シート1の一行目となります。
なお、名前.住所 .xlsxのブックは画像では1~2しかないですが、今後増えていきます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) Excel VBAどこが間違ってますか? 4 2023/07/17 10:04
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
- Visual Basic(VBA) 貼り付けた値が消えていく 以下はソースファイルの2番目のシートのB6から最終行を取得 ターゲットファ 2 2023/07/27 12:23
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- Visual Basic(VBA) 【ご教示ください】VBAの記述方法がわかりません。 2 2022/08/12 21:28
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたい 6 2023/01/23 12:00
- Visual Basic(VBA) 【前回の続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/16 16:44
- Excel(エクセル) フォルダ内のワードファイルをPDFに一括変換するVBA 3 2023/06/09 16:51
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA シートをコピーする際に Co...
-
ワイルドカード「*」を使うとう...
-
ACCESSでExcelにデータ出力、高...
-
vbaで他のブックに転記したい。...
-
【Excel VBA】書き込み先ブック...
-
エクセルVBAが途中で止まります
-
[Excel]ADODBでNull変換されて...
-
VBA 実行時エラー 2147024893
-
VBA コードを実行すると画面が...
-
エクセルのマクロについて教え...
-
VBAで別のブックにシートをコピ...
-
ExcelのVBAです。フォルダ内の...
-
VBS Bookを閉じるコード
-
vbaでvbaProjectのパスワード解...
-
シートをコピーする下記記述で...
-
別ブックをダイアログボックス...
-
エクセルマクロで任意のファイ...
-
【ExcelVBA】インデックスが有...
-
新しく開いたブックをアクティ...
-
転記先VBA 一致しているセルが...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA シートをコピーする際に Co...
-
エクセルVBAが途中で止まります
-
別ブックをダイアログボックス...
-
【ExcelVBA】インデックスが有...
-
ワイルドカード「*」を使うとう...
-
【ExcelVBA】VBA実行でダイアロ...
-
ExcelのVBAです。フォルダ内の...
-
フォルダ内の全てのファイルに...
-
VBA コードを実行すると画面が...
-
VBA 別ブックからコピペしたい...
-
VBAで別ブックのシートを指定し...
-
VBS Bookを閉じるコード
-
vbaでvbaProjectのパスワード解...
-
【VBA】全シートの計算式を全て...
-
VBA シート名が一致した場合の...
-
【ExcelVBA】zip圧縮されたCSV...
-
複数のエクセルブックをひとつ...
-
VBSでExcelのオープン確認
-
VBAで別のブックにシートをコピ...
-
【Excel VBA】書き込み先ブック...
おすすめ情報
申し訳ありません。
各ブックのシート1の名前、住所を一覧ブックに集計するのは、上記のマクロで問題なく処理できたのですが、また上から新たなものを作成して欲しいと依頼があり、困っております。
今度は、集計する項目が、受付日、氏名、郵便番号、住所、電話番号、金額、用途、入金日、公表名、公表金額、納入方法、個数、品物と増えたうえ、各ブックのシート1だけではなく、全てのシートに項目がちらばっているため、全てのシートから集計するようにしなければなりません。
種々試しているのですが、私のスキルが未熟すぎてうまくいきません。
お忙しいところ、大変恐縮ですが、またご指導、ご鞭撻いただければ幸いでございます。
ご丁寧にありがとうございます。
別の用事で、会社から出てしまっておりますので再度確認して連絡いたします。