• ベストアンサー

VBAでおしえてください

お世話になっております。 今、5個のエクセルファイルがあり、それぞれ複数のシートで構成されていますが、シート名、並び順は、5個のファイルとも共通です。 シート名は、sheet1から、A,B,C,D,・・・・と割り振っております。 ここで、同じシート名のdataを同じシート内に集めたいです。。 (元DATAの形式) ファイル1 SheetA SheetB セル DATA セル DATA B2 2 B2 8 B3 3 B3 5 B4 4 B4 6 ファイル2 SheetA SheetB セル DATA セル DATA B2 6 B2 2 B3 5 B3 3 B4 1 B4 4 VBA変換後 ファイル1 SheetA セル DATA セル DATA B2 2 C2 6 B3 3 C3 5 B4 4 C4 1 よろしくお願いいたします

質問者が選んだベストアンサー

  • ベストアンサー
  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.10

前質問からの乗りかかった船ですので、横からで失礼します。 こちらの認識にあやまりがあるかも知れませんが、こんな処理だと判断しました。 処理対象となる5個のブックと「同じシート数がある」新規ブックを作り、サンプルマクロ(Test3)を標準モジュールにコピペします。 マクロを実行すると、一緒に開いていて非表示になっていない全てのブックに対して、マクロのあるブックの各シートに各ブックのB列を転記して行きます。 Sub Test3() Dim wb As Workbook, i As Integer For Each wb In Workbooks  If Not wb Is ThisWorkbook And Windows(wb.Name).Visible Then    For i = 1 To wb.Worksheets.Count      wb.Worksheets(i).Columns(2).Copy _       ThisWorkbook.Worksheets(i).Range("IV2"). _        End(xlToLeft).Offset(0, 1).EntireColumn    Next i  End If Next wb End Sub 変数の使い方とループ処理と条件分岐、この3つを覚える事で応用の幅が広がります。 前質問の回答を読んで急いでいるのは解りましたが、丸投げばかりではいつまでも身につきませんよ。

towa2005
質問者

お礼

できました^^ >前質問の回答を読んで急いでいるのは解りましたが、丸投げばかりで>はいつまでも身につきませんよ。 →おっしゃるとおりです。 身にしみました。本当にありがとうございました。

その他の回答 (9)

  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.9

VBAでは無くて、VBSですが。 以下のソースをメモ帳などに貼り付けて拡張子をvbsとして保存します。 C:\新規Microsoft Excel ワークシート(?).xlsの各シートのB列をC:\Target.xlsの同名のシートに集めるようになっています。 ファイル名は環境にあわせて適当に変えてください。 Const DstFileName = "C:\Target.xls" Dim SrcFileName Dim objXlsApp Dim objDstXls Dim objSrcXls Dim objDstSht Dim objSrcSht Dim DstXlsList(4) DstXlsList(0) = "C:\新規Microsoft Excel ワークシート.xls" DstXlsList(1) = "C:\新規Microsoft Excel ワークシート (2).xls" DstXlsList(2) = "C:\新規Microsoft Excel ワークシート (3).xls" DstXlsList(3) = "C:\新規Microsoft Excel ワークシート (4).xls" DstXlsList(4) = "C:\新規Microsoft Excel ワークシート (5).xls" Set objXlsApp = CreateObject("Excel.Application") Set objDstXls = objXlsApp.Workbooks.Open(DstFileName) For Each SrcFileName In DstXlsList Set objSrcXls = objXlsApp.Workbooks.Open(SrcFileName) For Each objSrcSht In objSrcXls.Worksheets Set objDstSht = FindSheet(objDstXls, objSrcSht) If objDstSht Is Nothing Then Set objDstSht = objDstXls.Worksheets.Add objDstSht.Name = objSrcSht.Name End If CopyDataColumn objSrcSht, objDstSht Next objSrcXls.Close Next objDstXls.Close True, objDstXls.FullName objXlsApp.Quit Private Function FindSheet(objDstXls, objSrcSht) Dim objDstSht For Each objDstSht In objDstXls.Worksheets If objDstSht.Name = objSrcSht.Name Then Set FindSheet = objDstSht Exit Function End If Next Set FindSheet = Nothing End Function Private Sub CopyDataColumn(objSrcSht, objDstSht) Dim objDstCell Dim objSrcCell Set objDstCell= objDstSht.Range("B2") While objDstCell.Value <> "" Set objDstCell = objDstCell.Offset(0, 1) Wend Set objSrcCell = objSrcSht.Range("B2") While objSrcCell <> "" objDstCell.Value = objSrcCell.Value Set objSrcCell = objSrcCell.Offset(1, 0) Set objDstCell = objDstCell.Offset(1, 0) Wend End Sub 蛇足ですがイミディエイトウインドウはVBAでは基本の分野にあたります。 インターネット等で調べてみるだけでなく、初期のうちは本を読むなどしたほうが理解がスムーズに行くと思います。

towa2005
質問者

お礼

ご丁寧にありがとうございます やってみます

  • yokomaya
  • ベストアンサー率40% (147/366)
回答No.8

○ファイル1に戻り の部分は Windows("ファイル1").Activate みたいな記録かと思いますが 内側のループにするとコピーの前に Windows("ファイル2").Activate で戻す必要があることを忘れてました。 勿論ファイル2と直接かくのではなく Range("J"&j)です。 あれ?さっきはRange("J"&i)って書いちまった。間違いです。Range("J"&j)ね。 このjを用いて貼り付け位置をずらすには Range("C2").select が記録された内容なら Cells(2,2+j).select と変更すればjの変化に応じて右にひとつずつ ずれていきます。 まだ説明足りないとは思うけどとりあえず試してみていただけます?

towa2005
質問者

お礼

イミディトのところに、、?thisworkbook.worksheets(1).name と記入しましたが。・そのあと、どうすればよいのです??

  • yokomaya
  • ベストアンサー率40% (147/366)
回答No.7

初めて聞きましたか。なるほど。僕は直接確かめるのによく使います。プログラム中もデバッグの途中でブレークポイントを指定して止めて色々な状態を確認したり出来ますし。それはさておき、?thisworkbook.worksheets(1).nameで一番目のシート名がでますよね。()の中の数字を変えるとその他のシート名も得られます。 ということは、最初の目的のシートを選択の前にループの為に for i=1 to 5 として最後のファイル2を閉じる前に next を置くと5回ループしますから、 その間でシートを選ぶときに、直接シート名をうつ代わりに thisworkbook.worksheets(i).name を使うとiが自動的に1から5まで変わっていくのでシート名も期待通りに変化してくれるのです。 ところで手作業ではコピーに際してシートを選択してセルを選択してそれをコピーしますがプログラムの場合は全部くっつけちゃう方が合理的で無駄がありません。 例えば Sheets("Sheet3").Select Range("B2:B4").Select Selection.Copy ならば Sheets("Sheet3").Range("B2:B4").Copy みたいにです。 (勿論この"Sheet3"の処は前述の().nameを使うんですよ。) 貼り付けのほうはそうは行きませんので。 selectのままでいいです。 ただ貼り付け場所がずれていかなければなりませんよね。それにはブックで用いるループの変数に応じてひとつずつ右にずれるということでよいのかな、多分。 ブックで用いるループは全体の外側に つまり先頭に for j=1 to 4 と最終行に next を入れます。 ファイル2からファイル5までのブックの名前を 4個シートの使わない部分に並べます。 例えば J1からJ4に並べたとすればファイル2を開いたマクロの記録部分で"ファイル2"の代わりにRange("J"&i)を使うと順次ブック名が割り当てられます。

towa2005
質問者

お礼

難しいですね。。 ちょっとついてけそうにないです・・

  • yokomaya
  • ベストアンサー率40% (147/366)
回答No.6

全てのブックのシート名が共通との事ですからファイル1のシート名をそのまま使う事で実現します。VBEを開いてイミディエイトに?thisworkbook.worksheets(1).nameと打ってみて下さい。今携帯からなので続きは家から打ちます。

towa2005
質問者

お礼

お世話になります.イミディエイトウィンドウは初めて聞く単語でしたので、ネットで調べておりました・。・。・ 続きをどうかよろしくお願いいたします

  • yokomaya
  • ベストアンサー率40% (147/366)
回答No.5

これくらいは知っているというのはループ処理とかのことで良いですか。僕が示したのは1箇所分だけなので後の4回×ファイル5本分はループ処理で行う様に記述していく予定で考えているのですが、説明についてこれるという意味と考えてよろしいでしょうか?ソースは示しませんので変更すべき点を説明したいとおもいますが。

towa2005
質問者

お礼

ループ処理は以前組んだことがありますので、分かるのですが。。 複数のブックから、同じシート名のDATAを集めるというのが、どうしたらいいか??です・・ お教え願いたら幸いです

  • yokomaya
  • ベストアンサー率40% (147/366)
回答No.4

貴方はVBAをどれくらい理解されているでしょう?けして難しい話しではなくマクロの記録とそれの構文が読めれば、数箇所の記述と変更で実現は出来ます。 ファイル1にまとめるのですからまずファイル1だけを開いた状態でマクロの記録を開始します。 ○ファイル2を開き ○目的のシートを選択 ○コピーしたい範囲を選択 ○コピー ○ファイル1に戻り ○目的のシートを選択 ○貼付け位置を選択して ○貼付け ○ファイル2を閉じます。 マクロの記録を終了します。 これを修正していくのですが、変数、ループ処理、配列が理解できないと以下説明しても意味がないのでとりあえずここまで。

towa2005
質問者

お礼

これくらいは知っています、数が多いので、マクロの記録は時間がかかるのと思っています、 同じシート名のデータを集めるということで苦労しています。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.3

#01です。 =[Book3.xls]Sheet1!$B$5 のようにすれば他のブックのセル参照式になります。 先の質問も拝見しましたが、今回の質問は「各ブック、各シートのB列の値をそっくりコピーしたい」という意味なら、先の回答を少し直せば可能ですよ。

towa2005
質問者

お礼

>ブック、各シートのB列の値をそっくりコピーしたい 同じシート毎に、B列を集めたいのですが。。

noname#22222
noname#22222
回答No.2

ウーン!質問の都度、やりたい事が変化しているようで・・・。 データをCSVファイルで吐き出すとして・・・。 1,2,3,4 1,2,3,4 1,2,3,4 という<datas.csv>ファイルを仮定します。 これを、1列目をb1.xlsに、2列目をc1.xlsに、4列目をe1.xlsに書き込むコードは次のようです。 回答のコードを多少いじれば、複数のブックにデータを振り分けることが可能でしょう。 注意1: datas.csv は、カレントディレクトリに置いて下さい。 注意2: microsft runtime script を参照するように設定して下さい。 一応、テスト済みです。 Private Sub CommandButton1_Click()   Dim bkName   Dim I     As Integer   Dim J     As Integer   Dim K     As Integer   Dim N     As Integer   Dim xlApp   As Object   Dim xlBook(3) As Object   Dim Datas()  As String   Dim Data()  As String      ' -----------------------------   ' bkName() にブック名をセット   ' -----------------------------   bkName = Array("C:\Temp\b1.xls", "C:\Temp\c1.xls", "C:\Temp\d1.xls", "C:\Temp\e1.xls")   ' ---------------------------------   ' Datas() に datas.csv を読み込む   ' ---------------------------------   ' 注意: datas.csv はカレントディレクトリに存在すること   '   Datas() = FileReadArray("datas.csv")   N = UBound(Datas())   ' ------------------   ' ブックをオープン   ' ------------------   Set xlApp = CreateObject("Excel.Application")   Set xlBook(0) = xlApp.Workbooks.Open(bkName(0))   Set xlBook(1) = xlApp.Workbooks.Open(bkName(1))   Set xlBook(2) = xlApp.Workbooks.Open(bkName(2))   Set xlBook(3) = xlApp.Workbooks.Open(bkName(3))   ' --------------   ' ブックを更新   ' --------------   For J = 0 To N     Data() = Split(Datas(J), ",")     If UBound(Data()) = 3 Then       K = J + 1       xlBook(0).Sheets(1).Cells(K, 1) = Data(0)       xlBook(1).Sheets(1).Cells(K, 1) = Data(1)       xlBook(2).Sheets(1).Cells(K, 1) = Data(2)       xlBook(3).Sheets(1).Cells(K, 1) = Data(3)     End If   Next J   ' --------------   ' ブックを保存   ' --------------   xlBook(0).Close True, bkName(0)   xlBook(1).Close True, bkName(1)   xlBook(2).Close True, bkName(2)   xlBook(3).Close True, bkName(3)   ' --------------   ' xlApp を破棄   ' --------------   Set xlApp = Nothing End Sub Public Function FileReadArray(ByVal FileName As String) As String() On Error GoTo Err_FileReadArray    Dim fso    As FileSystemObject    Dim fil    As File    Dim txs    As TextStream    Dim strText  As String    Dim strTexts() As String       Set fso = New FileSystemObject    Set fil = fso.GetFile(FileName)    Set txs = fil.OpenAsTextStream(ForReading, TristateUseDefault)    strText = txs.ReadAll    strTexts = Split(strText, Chr$(13) & Chr$(10)) Exit_FileReadArray:    FileReadArray = strTexts()    Exit Function Err_FileReadArray:    MsgBox Err.Description & "(FileReadArray)", vbExclamation, " 関数エラーメッセージ"    strTexts() = Split("")    Resume Exit_FileReadArray End Function ※Excelは操作したことがない単なるスーツのデザイナーです。 ※VBA を使えば簡単ですが、私の回答を読めないと少しシンドイです。 ※Excelの機能を駆使して手作業が早いような気もします。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.1

VBAを書いてくださいという依頼ですか? でも集めてくるセルの範囲、マクロを実行するときの前提(BOOKは開いているかどうか)、BOOK名、BOOKのパス、などが明記されていないので、コードも書きようがありません。 それらをあれこれ想像して作っても質問者さまが修正しなければ使い物にならないでしょう。質問者さまがマクロを掲載して「どう直せばよいか?」お聞きになるのであれば、お答えもできますが… 代替案ですが、エクセルでは複数のBOOKにまたがってセル参照が可能ですから、その方法を用いる方が簡単ではありませんか?

towa2005
質問者

お礼

すいません、VBAをイメージしていおりました。 VBAを使わなくともできる方法として、セル参照というのがあるのですね?教えてくだされば幸いです。

関連するQ&A

  • Excel VBA シート間のコピー・ペースト

    いつもお世話になります。 「sheetA」「sheetB」の二つのシートがあります。 このシート間でのコピー・ペーストをしたいのです。 (1)「sheetA」の『R1C4』を「sheetB」の『R1C2』に、  「sheetA」の『R1C9』を「sheetB」の『R1C7』に、コピー・ペースト。  尚、最終行は、毎回違います。 (2)「sheetB」の『R1C1』には、先程、ペーストした、『R1C2』に値があるだけ、  ≪○≫印を入れたいのです。 以上、よろしくお願いします。

  • excelのオートフィル

    すいません、いろいろと調べてみましたがわからなかったので質問させてください。 あるシート(sheetA)に集計データがあり、それを別シート(sheetB)に表示したいとき、 シート名を固定し、参照するセル番号を10刻みで増やしたい場合、オートフィルで可能でしょうか? 具体的には、sheetAのAE4~AE242およびにランダムな数値データがあった際に、 ・sheetBのB3~B26にsheetAのAE4,AE14,AE24・・・と十刻みでコピー ・sheetBのC3~C26にsheetAのAE5,AE15,AE25・・・と十刻みでコピー ・sheetBのD3~D26にsheetAのAE6,AE16,AE26・・・と十刻みでコピー ということをしたいと思っています。 拙い文章で恐縮ですが、どなたか教えていただけると幸いです。 よろしくお願いいたします。

  • sheet1セルA1のデータ切り替えについて

    Excel2010に3つのシートsheetA、sheetB、sheetC があります。 それぞれセルA1のデータは,sheetAのA1=ブランク、sheetBのA1=b、sheetCのA1=c とします。 この状態で、 sheetBがActiveの時に、sheetAのA1=b sheetCがActiveの時に、sheetAのA1=c になるような関数、もしくはマクロを組み込みたいと思います。 どのようにしたら実現できますでしょうか? よろしくお願いします。

  • エクセルで自動的に範囲選択させるには?

    職場のエクセルの表を壊してしまいました。チカラを貸してください。 SHEETaに表があります。 常に表の最終行にデータを入力しています。  A10     B10    C10    D10   E10 3月3日   りんご   8個   みかん  5個 この一部を同じブックのSHEETbの表の最終行に =IF(SHEETa!A10="","",SHEETa!A10)といったふうに返しています。  A15     B15    C15 3月3日   みかん   5個 ちなみにSHEETaとSHEETbのデータの並び順は違います。 行の番号も違います。 作業としては、SHEETaを入力したあと、SHEETbの最終行を1行だけ 印刷します。 SHEETaを入力すると自動的にSHEETbの最終行が選択されるようにするにはどうしたらいいのでしょうか?    

  • エクセルのデータ移動(マクロ使用)

    エクセルのSheetAを使用して入力画面を作成し、そのデータをSheetBやSheetCへリンクさせて印刷を行っています。1件ごとの入力になるので、データが残りません。このSheetAのデータを別のSheetDか別のファイルへ行ごとの横一直線という形式で残したいのですが、どうすればよろしいでしょうか? また、反対に移動したデータを戻す場合などどうしたらいいのでしょうか? マクロを利用すればいいように思うのですが、マクロは印刷程度の簡単なマクロの知識しかありません。 もしも、何か方法があるようでしたら、いろんな応用が利きそうなので、今後に向かって幅が広がりそうなので、是非詳しい方お願いします。 <例> 1つめのデータをSheetAへ入力 SheetA セルA1 h16.12.1                  B2 ○○商事                           C3 △△-□□          ↓(データー移行) SheetD セルA1 h16.12.1 B1 ○○商事 C1 △△-□□  (この間にSheetAのデータはすべて削除) 2つめのデータをSheetAへ入力 SheetA セルA1 h16.12.3                 B2 ●●販売                            C3 ▲▲-■■          ↓(データー移行) SheetD セルA1 h16.12.1 B1 ○○商事 C1 △△-□□       A2 h16.12.3 B2 ●●販売 C2 ▲▲-■■

  • エクセル2003(VBA)で複数条件の合計を出したい

    エクセル2003(VBA)で日別個人集計表を作っています。が 配列関数を使うとほぼ動かない量のデータがあり、ユーザー関数等 を作って処理すべきなのかなと思い、ご質問させて頂きました。 一括処理してくれるようなVBAを希望しております。 下記に具体的なデータを記載しますので、どうかお知恵をお貸し下さい。 よろしくお願い致します。 ○元の参照データ(SheetA) ※レジのデータです A1: (日時)   B2: (担当) C2: (売上額) A2: 09/03/03 08:26 B2: 伊藤 C2: 1,000 A3: 09/03/04 18:12 B3: 武田 C2: 1,000 A4: 09/03/05 15:48 B4: 甲斐 C4: 1,000 A5: 09/03/05 09:24 B5: 迫田 C5: 1,000 A6: 09/03/04 03:23 B6: 武田 C6: 2,000 ・ ・ 以下30000行ぐらいあります。 ○日別個人集計表(SheetB) A1: (日付)   B2: (担当) C2: (売上額) A2: 09/03/03 B2: 伊藤 C2: 1,000 ←下記参照 A3: 09/03/04 B3: 武田 C2: 3,000 A4: 09/03/05 B4: 甲斐 C4: 1,000 A5: 09/03/05 B5: 迫田 C5: 1,000  ※C列には現在配列関数を入れ、オートフィルしていますが30行(人)を超えるともう動きません   C列は現在、下記の通りです。   例){=SUMPRODUCT(TEXT(SheetA!$A$2:$A$65536,"yy/mm/dd")=A2)*      (SheetA!$B$2:$B$65536=B2),SheetA!$C$2:$C$65536)}

  • 【Excel】印刷前の設定に戻す

    Excel2003を使用しています。 4シート(9ページ)を作業グループにして、印刷前にセルの塗りつぶしを解除して印刷。印刷終了後、セルの塗りつぶしを元の設定に戻す。 というマクロを作りたく、とりあえず、「新しいマクロの記録」でやってみました。 Sheets(Array("SheetA", "SheetB", "SheetC", "SheetD")).Select Sheets("SheetA").Activate で、コードが始まっていました。(SheetA,B,C,Dはシート名とします) このシート名の部分をシート名ではなく、シート番号で指定したいのですが、どのようにすればいいでしょうか?(単にシート番号に変更しても、エラーが出てしまいましたので。。。) マクロ勉強中でして、『Array』というのも今回初めて目にしました。よろしくお願いします。

  • 【エクセル】結合したセルからのリンクについて

    教えてください! エクセルのワークシート間のリンクについてです。 ワークシート(SheetA)内に結合したセルを作ってその中で計算式を作っているのですが、その計算された値を他の作業ワークシート(ここでは仮にSheetBとします)にリンクさせようとすると、SheetBのセル内に ='SheetA'!C1301:I1304 というように表示され、確定すると#VALUEとなってしまいます。また、リンク先のセルを選択するだけで固定された状態('SheetA'!$C$1301:$I$1304)になってしまいます。 毎回、:以降を消去して値をリンクさせているのですが、そのようなわずらわしい作業を行わずにリンクをさせたいのですがどのようにすればいいのでしょうか?設定で変更ができるようであればその方法を教えて下さい。 よろしくお願いします!

  • エクセルVBAで困ってます。

    エクセルVBAで困っています。 データ入力済みのシートが2つあります。 シート名を「Sheet1」「Sheet2」とします。 「Sheet1」のA列のデータが「Sheet2」のA列のデータと一致した時に それぞれのシートのセル番地を取得したいのですが出来ません。 教えて下さい。 データの並び順は「Sheet1」と「Sheet2」で異なります。

  • エクセルで入力済みのセルのみ見つけて・・

    エクセルで入力済みのセルだけを見つけ出して、 指定した場所に並べる作業をマクロで1発で出来るようにしたいのですが、その方法を教えてください。 シートが37シートあります。(sheetA1~sheetA12,sheetB1~sheetB12,sheetC1~sheetC12,sheet37) それぞれセルC5からC20まで数値が入っていますが、 最終行はC20とは限りません。(sheet37はまとめるためのシートで空白) C15が最終行の場合もあれば、C18が最終行の場合もあります。 各シートそれぞれ最終行が違います。(列は同じですスタートもC5です) 各シートのC列の入力済みのセルの数値をsheet37のB1セルから順番に縦に並べたいのです。 A,B,Cのシート順にC列に入力された数値を縦に並べます。 空白は無しで詰めて並べます。 これを1回の作業でできるマクロを教えてください。 それから入力済みの最終行を見つけ出すマクロの部分を表示して頂けるとありがたいです。 宜しくお願いします。

専門家に質問してみよう