- ベストアンサー
VBAで内容を抽出させてコピーする方法
- VBAを使用して、エクセルの特定の条件に基づいてデータを抽出し、別のシートにコピーする方法を教えてください。
- 質問者はプログラムやコピーの方法について困っており、シート1の勤務体制とシート2の特定の条件に基づいてデータをコピーする方法が欲しいとしています。
- また、シート3にも同じようなコピーをする必要がある場合、その方法についても知りたいとしています。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
kopepeです。 13個ずつですと 1番 2番から14番 15番から27番 28番から40番となるかと思いますので、それで記載します。 iCnt = 0 iGyo = 1 iCol = 2 ' 2列目に固定 Do While Sheet1.Cells(iRow, 2) <> "" If Sheet1.Cells(iRow, 2) = sData Then Select Case iCnt Case 1 ' 1番がおわった後ということで2番になったら Sheet3.Activate ' シートを変える iGyo = 1 ' 複写する行をリセットします Case 14 ' 14番のあと、つまり15になったら(繰り返し) Sheet4.Activate iGyo = 1 Case 27 Sheet5.Activate iGyo = 1 End Select iGyo = iGyo + 1 ' ここでインクリメントすると、初期値が1なので2行目から始まる Cells(iGyo, iCol) = Sheet1.Cells(iRow, 1) iCnt = iCnt + 1 End If iRow = iRow + 1 Loop これなら、15個ずつでも29個ずつでも対応できると思います。 Case の数値を何番の後かという事に設定すればよいからです。 最初が0なのでわかりにくいかも知れませんが、当初は余りを使用していたためこのようになりました。 また、シート数が増えても少しの変更で可能です。 今回はテストしてないので、もしかしたら記載ミスがあるかも知れませんが、エラーの内容で判断すれば解決できると思います。
その他の回答 (6)
- kopepe
- ベストアンサー率50% (1/2)
kopepeです。 最初の1個だけはF4かも知れないしAA5かも知れないと言うことでしたので#5のような記述になったのですが、意味が図りかねています。 つまり、 1番はシート2のB2、 2番から10番までがシート3のB2からB10 11番から20番はシート4のB2からB11 21番から30番はシート5のB2からB11 という意味でしょうか。 もしそうなら Do While Sheet1.Cells(iRow, 2) <> "" If Sheet1.Cells(iRow, 2) = sData Then If iCnt = 1 Then Sheet3.Activate '2番目からシートをかえる If iCnt = 10 Then Sheet4.Activate ' 10になったら更にシートを変える ' 先ほどよりシートが繰り越されている iGyo = iCnt Mod 10 + 2 '-------------------------- B2の場合。 '------------------------------F4なら4,6 AA5なら5,27 If iCnt = 0 Then iGyo = 2 iCol = 2 End if '------------------------------ Cells(iGyo, iCol) = Sheet1.Cells(iRow, 1) iCnt = iCnt + 1 End If iRow = iRow + 1 Loop もし最初の1個をAA5にして、1から10まではシート2のまま 11からシート3に移るというのでしたら、 2番目からシートをかえるという行は削除し、 10になったらSheet3として、 iGyo = 5 iCol = 27 とします。 私の理解が正しかったでしょうか。
補足
本当にすべてが参考になります。一気に知識が上がったような期がします。 こういうことです。 つまり、 1番はシート2のB2 それから以降はふつうに13個筒(最後の変更ですm(__)m)ですので 2番から14番までがシート3のB2からB14 15番から28番はシート4のB2からB14 29番から41番はシート5のB2からB14 という意味です。 間違いなくシート5以上は存在しません。
- kopepe
- ベストアンサー率50% (1/2)
kopepeです 変動する条件がわかっていれば対処は出来ますが、 あらかじめ分かっていないとファジーな対処は私には出来ません。 このような方法はいかがでしょうか Dim iCol As Integer と宣言しておく事にします。 ここからが条件分岐 Select case (条件) Case (ケース1) iCol = (列番号) iGyo = (行番号) Case (ケース2) iCol = (列番号) iGyo = (行番号) Case (ケース3) iCol = (列番号) iGyo = (行番号) ....... Case Else iCol = (列番号) iGyo = (行番号) End select Cells(iGyo, iCol) = Sheet1.Cells(iRow, 1) とする方法です。 (条件)は、状況を表す文字なり数値を格納したセル等を指定します。 たとえばシート1のD1あたりに、「緊急招集」とか「お花見」とかの条件を入れます。 (ケース)は、それらの分岐内容です。 たとえば、「ほろ酔い」とか「弁当がまずい」とかです。 2つ3つの条件が複合して有る場合は、更にケースの中でIFやSelectCaseを入れ子にして作成します。 変動する条件がわかりませんので具体的ではないのですが、 SelectCaseのヘルプを参考にしてみて下さい。
補足
お早い回答うれしいです。では変動する条件としてこうしました? シート2には (シート2) A B C D E 1 夜勤務 2 佐藤 3 という風に一個だけ入れることにしました。 それでシート3、シート4以降は固定の (シート3) A B C D E 1 2 小林 3 松田 4 という風にB2~10個分をいれるようにしました。 これではどうでしょうか?また十個を超えればシート4に行くという感じです。 最初の1個だけはシート2のB2にいれるということはできないでしょうか? お願いいたします。m(_ _)m 何度も何度もすいません。本当にすいません。
- kopepe
- ベストアンサー率50% (1/2)
kopepeです。 複写開始行が1行目になったと理解して回答します。 iGyo = iCnt Mod 10 + 2 ' 対象の数を10で割った余りを出し、行数を指定 の行は iGyo = iCnt Mod 10 + 1 とします。これで1行目から開始します。 次に1行目の時だけE列、あとはB列にする方法です。 If iGyo = 1 Then Cells(iGyo, 5) = Sheet1.Cells(iRow, 1) Else Cells(iGyo, 2) = Sheet1.Cells(iRow, 1) End if 他には Dim iCol As Integer と宣言しておき If iGyo = 1 Then iCol = 5 Else iCol = 2 Cells(iGyo, iCol) = Sheet1.Cells(iRow, 1) とする方法もあります。 もしシート3以降は2行目から始まるのでしたら If iGyo = 1 Then iCol = 5 Else iCol = 2 If iCnt >= 20 Then iGyo = iGyo + 1 Cells(iGyo, iCol) = Sheet1.Cells(iRow, 1) と間に1行入れてください。 これなら20以降、つまりシート3以降なら2行目から開始します。
補足
なんどもすいません。先ほどいったE1というのは場合によって変動するかもしれないので、複写開始行が1行目になったというわけではないのです。なのでF4かもしれませんしAA5になるかもしれないのです。2個目以降は先ほどいった固定なのですが・・・。 なので1個に現れたのだけ特定位置にコピーできれば幸いなのですが・・ kopepeさんに何度も回答いただいてうれしく思っていますが、 もうkopepeさんしか解決お願いできる人がいないので なんとかならないでしょうか? 助けてください。 期限がせまっていまして・・。
- kopepe
- ベストアンサー率50% (1/2)
#2のkopepeです。 Sheet1と記載されているシート名は、タブの名前と同じでない可能性があります。 VisualBasicEditorで Sheet1(Sheet1) Sheet2(Sheet2) Sheet3(Sheet3) となっているか確認してください。 場合によっては Sheet2(Sheet1) Sheet1(Sheet2) Sheet3(Sheet3) となっていたりするケースもあります。 タブの名前を変更すると、たとえば Sheet1(たぶ1) Sheet2(みみたぶ2) Sheet3(たぶん3) のように括弧内がタブ名になりますが、シート名は変わりません。 ですからアクティブにするシートを括弧の前のシート名にするか、 あるいは Sheets("みみたぶ2").Activate のようにタブ名を指定するかして、そのワークブックのシート構成にあうように変更してみてください。
補足
kopepeさん謎が解決しました。いわれた通りシート名が違っていました。 なんといったらよいかkapopoさんのおかげで、悩みが一気にとれていき 感動しています。なんとお礼をいったらよいか。。 それとkopepeさん本当に申し訳ないのですが、たとえば 夜勤務 と指定していくつかでてきますが、でてきたらシート2では (シート2) A B C D E 1 夜勤務 佐藤 2 小林 3 松田 4 という風にでてきた1個目だけ E1 に。 以下にでてきたものはさっきいった通りのB2~10個だけ、 10個以上はシート3へ。 これはできないでしょうか? 急きょやるないようが1個だけかわってしまったので。 1行目にでてきたのだけ E1にいれなければいけない状態になってしまいまして・・・・
- kopepe
- ベストアンサー率50% (1/2)
こんにちは。 いつもいろいろな人に助けてもらってますので、今回は恩返しに投稿します。 こんなので試してみてください。 Public Sub Sabori() Dim sData As String ' 対象とする勤務態勢用 Dim iRow As Integer ' シート1で検索するためのカウンタ Dim iCnt As Integer ' 対象が見つかったときのカウンタ Dim iGyo As Integer ' コピーするための行数を格納するため ' ------------------------------- sData = Sheet2.Cells(1, 1) ' シート1のA1にある文字列(対象とする勤務態勢) iRow = 2 ' 検索を始める行番号 iCnt = 0 ' VBAでは無意味だけど初期化 iGyo = 0 ' 同上 ' ------------------------------- Sheet2.Activate ' 複写する先をアクティブにする(この方法でシートを変えてゆくため) ' 別のもっとスマートな方法もありますが... ' ------------------------------- Do While Sheet1.Cells(iRow, 2) <> "" ' シート1に社員がいるだけ検索する If Sheet1.Cells(iRow, 2) = sData Then ' 勤務態勢が同じ人が見つかった場合 ===== ここから If iCnt = 10 Then Sheet3.Activate ' 10になったらシートを変える 'If iCnt = 20 Then Sheet4.Activate ' 20になったら更に次のシートに行く ' シートがあるだけ繰り返して入れておく ' 0から始まっているので、10は11人目になる iGyo = iCnt Mod 10 + 2 ' 対象の数を10で割った余りを出し、行数を指定 Cells(iGyo, 2) = Sheet1.Cells(iRow, 1) ' カレントシートのセルにデータを入れる iCnt = iCnt + 1 ' みつかった数をインクリメントする End If ' ====================================== ここまで iRow = iRow + 1 ' 検索する行をインクリメントし、次の行に移る Loop End Sub
補足
kopepeさん本当にご回答うれしい限りで泣きそうです。何日も頭を悩ませてたことが解決しそうなので! 一つだけ質問させていただいてもよろしいでしょうか? 実行するとシート2のマージセルにコピーされないでシート1にコピーされてしまうのですが、どこを変更すればシート2にコピーされるのでしょうか・・?
- porilin
- ベストアンサー率22% (142/631)
可能かと言えば可能ですというか簡単です。 ちゃんとコーディングしても良いのですが、誰かが先に答えたら労力無駄なのでコ-ディングのヒントだけ。 VBAですよね? シート2のA1に入力でキックする様にしてA1の内容を変数に入れ 参照値=cells(1,1).value シート1のB1から順番に見てゆきます。 sheets("シート1").select 縦位置 = 1 while cells(2,i)value > "" if 参照値 = cells(2,i)value then ****ここにシート2に転機するコーディング******* end if i = i + 1 wend if文の中にカウンタをつけて、10個書いたら次のシートに書く等を記述すれば 「シート3にも」も対応できます。 解答欄にベタ入力なので、細かい部分間違いがあるかもしれませんが流れはイメージしていただけますか? ちなみにシート2のA1はセレクトBOXにした方が入力楽です。
補足
本当にご回答うれしく思います!!m(_ _)m porilinさんご足労ありがとうございます。 私もこのイメージは自分の中でも考えついたのですが(カウンタをつける等勉強になりました)、実際のコーディングがやはりわからないところが多々あるため、できたらプログラムをお教え頂けると幸いなのですが;; もしporilinさんにお時間があればでいいのでお願いいたします。無理なお願いを少しでも聞いていただきまして本当にうれしい限りです。
お礼
何回も大変ありがとうございました。なぞが解決しましたのでkopepeさんには数え切れないほどに感謝をしております。本当にありがとうございました。
補足
ご回等いただいてから返事が遅れてしまいすいませんでした。あれかたずっと徹夜でヒントをもとにプログラムを書いたりしてたのですが、どうしても解決できませんでした。kopepeさんのを上のプログラムで総合すると、以下のとおりになるのでしょうか? Public Sub Sabori() Dim sData As String ' 対象とする勤務態勢用 Dim iRow As Integer ' シート1で検索するためのカウンタ Dim iCnt As Integer ' 対象が見つかったときのカウンタ Dim iGyo As Integer ' コピーするための行数を格納するため ' ------------------------------- sData = Sheet2.Cells(1, 1) ' シート1のA1にある文字列(対象とする勤務態勢) iRow = 2 ' 検索を始める行番号 iCnt = 0 ' VBAでは無意味だけど初期化 iGyo = 0 ' 同上 ' ------------------------------- 'Sheet2.Activate iCnt = 0 iGyo = 1 iCol = 2 ' 2列目に固定 Do While Sheet1.Cells(iRow, 2) <> "" If Sheet1.Cells(iRow, 2) = sData Then Select Case iCnt Case 1 ' 1番がおわった後ということで2番になったら Sheet3.Activate ' シートを変える iGyo = 1 ' 複写する行をリセットします Case 14 ' 14番のあと、つまり15になったら(繰り返し) Sheet4.Activate iGyo = 1 Case 27 Sheet5.Activate iGyo = 1 End Select iGyo = iGyo + 1 ' ここでインクリメントすると、初期値が1なので2行目から始まる Cells(iGyo, iCol) = Sheet1.Cells(iRow, 1) iCnt = iCnt + 1 End If iRow = iRow + 1 Loop End Sub これで実行するとなぜかシート2のB2に1個、シート3からは13個づつとなるはずが、 シート2に13個張り付き、シート3以降に複写されません。 それでやはり、kopepeさんのお力をお借りしたく思い、もう一度 お願いしたいです。本当に何度もすいません。 助けていただけないでしょうか? 参考書を買ってきて、勉強中なのですが、わたしの知識がおいついてないのかもしれません。すいません。