• ベストアンサー

Excel整形処理:列ごと&12行おきに「行列を入れ替えて貼り付け」

ExcelデータをVBAで次のように処理したいのですが、ご助力いただけますでしょうか。 Sheet1のD列とE列に4万行ほどの数値データがあります(行数は必ず12で割り切れます)。 このデータを、列ごと&12行おきに「行列を入れ替えて貼り付け」みたいなことをSheet2に 施したいです。具体的なイメージとしては、 【処理前】 D列 E列 ---------- D1 E1 D2 E2 D3 E3 :(略) D35 E35 D36 E36 :(略) 【処理後】 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12■ここで改行 D13 D14 D15 D16 D17 D18 D19 D20 D21 D22 D23 D24 E13 E14 E15 E16 E17 E18 E19 E20 E21 E22 E23 E24■ここで改行 D25 D26 D27 D28 D29 D30 D31 D32 D33 D34 D35 D36 E25 E26 E27 E28 E29 E30 E31 E32 E33 E34 E35 E36■ここで改行 :(略) なお、テキストエディタを介することによってなら、解決策が見つかりました。 (1) E列の右(=F列)に12行ごとに@などの目印をつけます。 (2) E列、F列を選択・コピーし、テキストエディタに貼りつけます。 (3) 置換でまず\nを全て除去し、次にもう一度置換で\t@を\nに。 (4) D列も同様の手順です。

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

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

SHEET1のD1~E48000を入れ替えながら、SHEET2のA1から 始まる縦2000x横24のデータへ変換するマクロです。 エクセルマクロの基本として、一度配列に落としてから シートに流し込む方が効率がよいです。 配列は0から始まりますがCELLSは1から始まるため、 若干混乱するかもしれません。 max_col = 24 max_row = 2000 Dim a() ReDim a(max_row - 1, max_col - 1) For i = 0 To max_col - 1 For j = 0 To max_row - 1 a(j, i) = Sheets("Sheet1").Range("D1").Offset((i Mod 12) + 12 * j, i \ 12) Next Next Sheets("Sheet2").Range(Cells(1, 1), Cells(max_row, max_col)).Value = a

litton101
質問者

補足

yamabejpさん、いつもお世話になります。 例示いただいたものは、Sheet1にあったデータを、 Sheet2のA1から(24列目である)X2000セルまで見事に転記してくれます。 ありがとうございます。 さて、もう1回戦追加で、 Sheet1にあるデータ ===> Sheet3!A1:X2000に、 Sheet2にあるデータ ===> Sheet3!Y1:AV2000にと、 それぞれ転記する場合、元回答のスクリプトを以下のように改造しましたが、 どうもうまくいきません。何か、変数を上書きしたりしているのでしょうか? あるいは、Offsetの扱いがよくわかっていないので、そこかもしれません、 以下、何が誤りでしょうか? (aというのは、昨日のご回答で使っているので、意味ないかもしれませんが  避けてます) max_col = 24 max_row = 2000 Dim c() ReDim c(max_row - 1, max_col - 1) For o = 0 To max_col - 1 For p = 0 To max_row - 1 c(p, o) = Sheets("Sheet1").Range("D1").Offset((o Mod 12) + 12 * p, o \ 12) Next Next Sheets("Sheet3").Range(Cells(1, 1), Cells(max_row, max_col)).Value = c Dim d() ReDim d(max_row - 1, max_col - 1) For q = 0 To max_col - 1 For r = 0 To max_row - 1 d(r, q) = Sheets("Sheet2").Range("D1").Offset((q Mod 12) + 12 * r, q \ 12) Next Next Sheets("Sheet3").Range(Cells(1, 25), Cells(max_row, max_col)).Value = d

その他の回答 (5)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.6

こういうループの表現の方がすっきりするのでは。 500行でテスト済み。40000行なら If i > 40000 Then Exit Sub にしてください。 7列を主体に繰り回し、行はそれについていく。 Sheet2の出力行は繰り返し回数で捉えられる。 ーーー Sub test01() Dim sh1 As Worksheet Dim sh2 As Worksheet Set sh1 = Worksheets("Sheet1") Set sh2 = Worksheets("Sheet2") k = 1 i = 0 While 1 = 1 For j = 1 To 12 i = i + 1 If i > 500 Then Exit Sub sh2.Cells(k, j) = sh1.Cells(i, "D") sh2.Cells(k, j + 12) = sh1.Cells(i, "E") Next j k = k + 1 Wend End Sub

litton101
質問者

お礼

imogasiさん、ほかのみなさんとは 異なるアプローチ、ありがとうございました。 また、御礼が遅れて失礼いたしました。 40000行でも、使わせていただいたのですが、 結構な早さで処理できました。 コード自体も大変短く、完結ですね。 ありがとうございました。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.5

すみません。a()は単純にarrayの頭文字がaなので 使ってます。深い意味はありません。 さて#2のバグの件、失礼しました。 エラーの原因はわかりました。 cellに対してSheets("hoge")が利いていないですね。 これも以下のようにoffsetでやるとよいかもしれません。 そうでなければcellをSheet("hoge").cellなど 明示すればよいでしょう。 offset自体はいわゆるオフセットをとるつまり 右や下にずれた値をとるときにつかいます。 いろいろテストしてみていただくとわかります。 ちなみにFORで使うカウンタはなるべくI~Nを使う 因習があります。(一説にはINTをもじって、 未定義でもI~Nを変数に使うとINT型になるから とききます by fortran) これは汎用的につかうのでループごとに変更する 必要はありません。配列もredimすると初期化される ので、大きさが同じなら使いまわして問題ないでしょう。 以上をまとめるとこんな感じ。 ご不明の点はまたご質問ください。 max_col = 24 max_row = 2000 Dim a() ReDim a(max_row - 1, max_col - 1) For i = 0 To max_col - 1 For j = 0 To max_row - 1 a(j, i) = Sheets("Sheet1").Range("D1").Offset((i Mod 12) + 12 * j, i \ 12) Next Next Set c = Sheets("Sheet3").Range("A1") Range(c, c.Offset(max_row - 1, max_col - 1)).Value = a ReDim a(max_row - 1, max_col - 1) For i = 0 To max_col - 1 For j = 0 To max_row - 1 a(j, i) = Sheets("Sheet2").Range("D1").Offset((i Mod 12) + 12 * j, i \ 12) Next Next Set c = Sheets("Sheet3").Range("Y1") Range(c, c.Offset(max_row - 1, max_col - 1)).Value = a

litton101
質問者

補足

> cellに対してSheets("hoge")が利いていないですね。 文末のように本番環境に適用してみたのですがうまく動きません (先の御礼に書いたとおり、a()は他のところで使っているので 重複してるといわれるのでarray1に改名しています) プログラムでは、他にもごちゃごちゃした処理をして、 最後の方でこのマクロの出番があるのですが、 (1) マクロ全体を頭から実行するとSheet3に行列を入れ替えて貼り付け られるのですが、転記元であるSheet1とSheet2のA列も貼り付けられて しまい、意図したものと整形結果が異なっています。 (2) また、上記の「ごちゃごちゃした処理」を全部コメントにし、純粋に 本マクロだけを実行するとエラーなくマクロは実行されているようなの ですが、Sheet3には何も貼り付けられません。 以上から推察されるのは、何か変数が上書きされているとかが 起こっているようですが・・ >カウンタはなるべくI~Nを使う こちらの件は、とても勉強になりました。 PHPのプログラムを切り貼りしていて、iをカウンタとしたループ内で iを使ったループを入れ子にしてしまい、それがバグであることに なかなか気づかず、発見にえらい苦労した経験があったものですから、 初期化されることはなんとなく承知しているのですが、なんだか 重複させたくなかった次第です。 max_col = 24 max_row = 3500 Dim array1() ReDim array1(max_row - 1, max_col - 1) For i = 0 To max_col - 1 For j = 0 To max_row - 1 array1(j, i) = Sheets("Sheet1").Range("D1").Offset((i Mod 12) + 12 * j, i \ 12) Next Next Set c = Sheets("Sheet3").Range("A1") Range(c, c.Offset(max_row - 1, max_col - 1)).Value = a ReDim array1(max_row - 1, max_col - 1) For i = 0 To max_col - 1 For j = 0 To max_row - 1 array1(j, i) = Sheets("Sheet2").Range("D1").Offset((i Mod 12) + 12 * j, i \ 12) Next Next Set c = Sheets("Sheet3").Range("Y1") Range(c, c.Offset(max_row - 1, max_col - 1)).Value = a

  • hana-hana3
  • ベストアンサー率31% (4940/15541)
回答No.4

>ScreenUpdating = False とすると、目に見えなくなるのですね。 (そのほうが早いのかな?) その通りです。 画面の更新を抑止するので、実行速度をアップ出来ます。

litton101
質問者

お礼

hana-hana3さん、つぶやきへのご回答ありがとうございました。 わたしが画面の更新が頻繁な既存のマクロに 設定してみたら、確かに体感できるレベルで 早くなりました。 今後とも使わせていただきます。

  • hana-hana3
  • ベストアンサー率31% (4940/15541)
回答No.3

>こういう風にするのは難しいでしょうか。 すみませんm(__)m 読み間違えていたようです。 下記ではいかがですか? Sub tst2() Application.ScreenUpdating = False Dim ct As Long Dim ct2 As Long ct2 = 1 For ct = 1 To 40000 Step 12 Sheets("Sheet1").Range(Cells(ct, "D"), Cells(ct + 11, "D")).Copy Sheets("Sheet2").Cells(ct2, "A").PasteSpecial Paste:=xlPasteValues, Transpose:=True Sheets("Sheet1").Range(Cells(ct, "E"), Cells(ct + 11, "E")).Copy Sheets("Sheet2").Cells(ct2, "A").Offset(, 12).PasteSpecial Paste:=xlPasteValues, Transpose:=True ct2 = ct2 + 1 Next End Sub

litton101
質問者

お礼

たびたびのレス、本当に恐縮です。 早速組み込んでみました。今後は100%バッチリでした。 ScreenUpdating = False とすると、目に見えなくなるのですね。 (そのほうが早いのかな?) おかげさまで快適です。 #2さんのものと合わせて都合がよさそうなものを検討し、 今後とも活用させていただきます。ありがとうございました。

  • hana-hana3
  • ベストアンサー率31% (4940/15541)
回答No.1

>列ごと&12行おきに「行列を入れ替えて貼り付け」みたいなことを・・・ してみました。(Transpose:=True) Sub tst1() Application.ScreenUpdating = False Dim ct As Long Dim ct2 As Long ct2 = 1 For ct = 1 To 40000 Step 12 Sheets("Sheet1").Range(Cells(ct, "D"), Cells(ct + 11, "E")).Copy Sheets("Sheet2").Cells(ct2, "A").PasteSpecial Paste:=xlPasteValues, Transpose:=True ct2 = ct2 + 2 Next End Sub

litton101
質問者

補足

hana-hana3さん、連日お世話になります。 大変ありがとうございます。試しましたところ、 【処理後】 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12■ここで改行 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12■ここで改行 D13 D14 D15 D16 D17 D18 D19 D20 D21 D22 D23 D24■ここで改行 E13 E14 E15 E16 E17 E18 E19 E20 E21 E22 E23 E24■ここで改行 D25 D26 D27 D28 D29 D30 D31 D32 D33 D34 D35 D36■ここで改行 E25 E26 E27 E28 E29 E30 E31 E32 E33 E34 E35 E36■ここで改行 :(略) となってしまいますが、 【処理後】 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12■ここで改行 D13 D14 D15 D16 D17 D18 D19 D20 D21 D22 D23 D24 E13 E14 E15 E16 E17 E18 E19 E20 E21 E22 E23 E24■ここで改行 D25 D26 D27 D28 D29 D30 D31 D32 D33 D34 D35 D36 E25 E26 E27 E28 E29 E30 E31 E32 E33 E34 E35 E36■ここで改行 :(略) こういう風にするのは難しいでしょうか。

関連するQ&A

  • エクセルVBA 文字列複数行・列連続連結

    エクセルVBA 文字列複数行・列連続連結でお教え下さい A列に基本文字(縦順) B列~F列に複数行データー(文字・時間) 文字結合時に改行 例 A2&B2&改行&A3&C2&改行&A4&D2&改行・・・・・ 次のデーター行 A&B3&改行&A3&C3&改行&A4&D3&改行・・・・・ データーの最終行まで連続で このような複数行あるデーターの連続文字列連結をしたいのですが・・・ 文字列連結後は 1.指定セルに貼り付け 2.クリップボードに貼り付け 3.テキストファイルに保存 よろしくお願い致します

  • エクセルでの連番の処理

    お世話になります。 1行目に入力されたデータをルールに沿って2行目以下にどんどん追加していきたいと思っています。 まずD1、E1のセルに数字を入れます。 例:D1に3、E1に25 を入れてマクロを実行するとD列の2行目以下に3,4,5,6…25と連番で入力出来るようにしたいのです。 この例ではD列は24行目まで入力されています。そこで2行目から24行目までのA,B,C列にはそれぞれ1行目のA,B,C列と同じデータを入力します。なおA,B,C列は数字、文字列どちらもあります。空白の場合もあります。 この状態でA~E列の1行目のデータを変更し、仮にD1を2、E1を15としたとします。ここで再度マクロを実行すればD25に2、そして順に連番が入りD38に15が入るようにします。 同時に25行目から38行目までのA,B,C列にはそれぞれ1行目のA,B,C列と同じデータを入力します。 これの繰り返しです。 つまり2行目以下のD列で空白の行以下にどんどん連番を入れていく具合です。 前提としてD1、E1は整数しか入りません。またE1の数字はD1より大きいです。ただD1,E1に同じ数字が入った場合、その数字の1行分だけが入力されるようにします。 以上の処理が自動化できるマクロはできますか? アドバイス願います。

  • エクセルで長い行を5行ごとに1列にするには?

    エクセルで行列の入れ替えの応用(になるのでしょうか?)をお尋ねします。 A列に例えば100行のデータが入っているのを、5行ずつ横並べにして、20行にしたい時どうすればよいでしょうか? A列 ------- データ1 データ2 データ3 データ4 データ5 データ6 データ7 データ8 データ9 データ10 (続く…) -------- こうなっているのを、  A列  B列   C列  D列   E列 ------------------------------------------ データ1 データ2 データ3 データ4 データ5 データ6 データ7 データ8 データ9 データ10 (続く…) ---------------------------------------- このように、表示したいのです。 お尋ねしているのは、100行ですが、 実は1500行ほどの長い名簿データが元のものです。 宜しくお願い致します。

  • Excel 隣接しない列に値貼り付け

    Excel 隣接しない列に値貼り付け ※「Excel 隣接しない列に一発で値貼り付け」の書き直しです。 ある一定の書式にしたがって作成された20~30のシートのデータを1つのシートに集約しており(集約シートを含み全てのシートは同じデータ内です。)、データを集約した集約シートの「表A」は下記の添付画像左側のようになります。 やりたいことは、「表A」のB列、C列、D列、E列をある条件のもとに右側の「表B」のH列、J列、L列、N列に値の貼り付けを行いたいのです。 現在の作業工程は、C列の空白行は必要ないため(C列が空白=他の列も空白)C列に文字入力があるとチェックが入るA列のオートフィルターで、「○」のみ表示にし、B~E列を順にそれぞれ、2行目からデータが記載された最終行までコピーし 「表B」のそれぞれの箇所に値貼り付けを行っています。 この時の注意点として、A列のオートフィルタ利用のためC列には空白がありませんが、B、D、E列には空白が存在します。 データがある最終行以下の空白は必要ありませんが、データ間の空白には意味があります。(下記の図で示すと「B3、4」や「D3、4」) 現在の作業工程でも問題はないのですが、この作業は最初に記載した20~30のシートに記載されたデータの校正に使うため取りこぼしをしたくなく、不特定多数の方が簡単に使えるようにしたいので、どうにか作業工程を減らしたいと考えています。 よろしくお願いします。 ▼書式シート *シートの数は増減する。 *集約シートが参照するセルには、必ずデータが入力されているわけではない。 *入力データは全て数値ではなく文字である。 ▼集約シート *他のブックと共通使用なため、一部の式は他のブックへのコピーに対応する形である。 *空白セルを参照している場合に結果として返される「0」は、オプション設定で非表示にて対応 *「表A」の行長は増減する。 *貼り付け先「表B」の列は飛び飛びである。 ▼ちなみに「表A」に使われている計算式(実際とは一部変えています) ■A列  :C列に文字入力がある場合「○」が表示されます     {=IF(OR($C1>""),"○","")} ■B-E列:他のシートの任意のセルの値をコピー     {=IF(ISERROR(INDIRECT("'シート名'!セル")),"",INDIRECT("'シート名'!セル"))} PC環境:Win XP / Excel 2003

  • EXCELで特定の列を指定しての行と列を入れ替える方法がありますでしょうか?

    EXCELで特定のセルの行と列を入れ替える方法がありますでしょうか? 例えば、下記の様なデータがあったとします。 列1│列2 ──┼── D │3 ──┼── D │5 ──┼── D │7 ──┼── E │2 ──┼── E │4 ──┼── E │6 ──┼── E │8 これを関数を使って自動でこのように並べ替えたいのです。 関数のイメージとしては、”列1がDの時は、行と列を入れ替える”等といった内容です 結果としてこんなデータになって欲しいのです。 D│3│5│7│ ─┼─┼─┼─┼─ E│2│4│6│8 どなたか良い方法がありましたら是非教えて下さい。 どうか宜しくお願いします。

  • テキストエディターで置換の方法

    テキストエディターで置換をしたいのですが、初心者ですので方法が分かりません。 やりたいことは、既存の文書中で、「改行」と次行の「頭1文字」の組み合わせで、改行を無効にしたいのです。 たとえば、改行+”@”の場合、改行なしで@の行を継続行にしたいのです。 Wordでは、検索でTABの場合は[検索する文字列(N)]=「^t」とするらしいのですが、Word を使って、そのようなことでも結構です。 ボリュームが大きい文書なので、手作業は無理なのでよろしくお願いします。

  • エクセルで行を越えての貼り付け

    X1~X100に数値が入っていて これを5列で1行おきとか2行おきとかに 並べ替えたいのですがアドバイスお願いいたします データーが100くらいなら良いのですが もっと多いので簡単な方法をアドバイスください X1~X100に数値 A1~E1に X1~X5 A1=X1 B1=X2 C1=X3 D1=X4 E1=X5 A5~G5に X6~X10 A5=X6 B5=X7 C5=X8 D5=X9 E5=X10 と言う風にしたい A1:E1をコピーして間に3行挟んでA5:E5に貼り付け するとデーターが A5~G5に X5~X9とずれてしまいます 4行挟んでコピーすれば正しく貼り付けますが 1行挟んでも2行挟んでも3行挟んでも 何行挟んでも良いようにするには どうすれば良いでしょうか よろしくお願いいたします。

  • エクセル100行1列を2行50列にする方法

    エクセルで行列の入れ替えの応をお尋ねします。 A列に例えば100行1列のデータが入っているのを、2行ずつ横並べにして、50列にしたい時どうすればよいでしょうか? A列 ------- データ1 データ2 データ3 データ4 データ5 データ6 データ7 データ8 データ9 データ10 (続く…) -------- こうなっているのを、  A列  B列   C列  D列   E列 ------------------------------------------ データ1 データ3 データ5 データ7 データ9 データ2 データ4 データ6 データ8 データ10 (続く…) ---------------------------------------- このように、表示したいのです。 宜しくお願い致します。

  • 正規表現で特定文字列を含まない行を削除したいのですが

    テキストエディタ mi で正規表現のより「※補足」という文字列を含む行だけ残して他の行を削除しようとしています。 具体的には、 検索文字列 ^(?!.*\※補足).*$ 置換文字列            ← 空白 としてやっているんですが、例えば   なんとかかんとかで何やらが何として…   ※補足:よくわかりません   ※補足:質問します というテキストを上の方法で全置換すると何も起きません。 そこで試しに 検索文字列 ^(?!.*\※補足).*$ 置換文字列 ----- としてみました。 この場合、本当なら   -----   ※補足:よくわかりません   -----   ※補足:質問します となることを期待していたのですが、実際は   -----なんとかかんとかで何やらが何として…   ※補足:よくわかりません   -----   ※補足:質問します となってしまい、要するに「※補足」という文字列が含まれない行は正しく見つけてくれるものの、含まれていない行については、その行丸ごとを置き換えるのではなく行頭に置換文字列を付加するだけになってしまいます。 これは、何がどう悪いのでしょうか? ちなみに、こちらのサイトで「テキストで特定の文字列を含む行を削除」とQ&Aを検索すると、私の場合で言えば「^.*※補足.*\n」→「」(空白)という置換えで可能というご回答が見つかるのですが、miの場合、これでは「※補足」という文字列が含まている行も含まれていない行も見つけてくれませんでした。 どう直せば目的が達成されるか教えて頂けないでしょうか? どうかよろしくお願い致します。

    • ベストアンサー
    • Mac
  • Excelでキーを使って関数で列を行に変更したい

    Excelで下記の事を関数で行うことが出来るでしょうか?方法を知っている方がいましたらお教えください sheet1    A B   1 1 33  2 1 33  3 1 34  4 1 45  5 2 21  6 2 25  7 2 25  sheet2    A  B  C  D  E   1  1  33 33 34 45 2  2  21 25 25 Sheet1の状態のキーをA列とした場合に、 Sheet2でキーをA列に入力後 B1 C1 D1 E1 に 関数を使って列でまとまっているデーターを 行にする方法が分かる方、お教え願います。 (Sheet2の B1 C1 D1 E1に入れる関数の 組み方が分からないと言うことです。 また、マクロはわからないので><) よろしくお願い致します。

専門家に質問してみよう