Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


212 / 13645 ツリー ←次へ | 前へ→

【81504】For nextの二重ループ文 きんもくせい 20/10/6(火) 21:20 質問[未読]
【81506】追記します きんもくせい 20/10/6(火) 21:36 質問[未読]
【81507】Re:追記します マナ 20/10/6(火) 21:39 発言[未読]
【81508】Re:追記します マナ 20/10/6(火) 21:55 発言[未読]
【81509】再度、ご質問です きんもくせい 20/10/7(水) 8:27 質問[未読]
【81510】Re:再度、ご質問です γ 20/10/7(水) 11:09 発言[未読]
【81511】Re:再度、ご質問です きんもくせい 20/10/7(水) 12:57 質問[未読]
【81512】Re:再度、ご質問です γ 20/10/7(水) 13:17 発言[未読]
【81514】Re:再度、ご質問です マナ 20/10/7(水) 17:49 発言[未読]
【81515】ありがとうございます。 きんもくせい 20/10/7(水) 18:50 お礼[未読]
【81516】Re:ありがとうございます。 マナ 20/10/7(水) 20:12 発言[未読]
【81517】Re:ありがとうございます。 マナ 20/10/7(水) 20:25 発言[未読]
【81519】Re:ありがとうございます。 きんもくせい 20/10/7(水) 20:42 お礼[未読]
【81520】Re:ありがとうございます。 マナ 20/10/7(水) 21:17 発言[未読]
【81521】Re:ありがとうございます。 きんもくせい 20/10/7(水) 22:12 お礼[未読]
【81518】Re:ありがとうございます。 きんもくせい 20/10/7(水) 20:39 お礼[未読]

【81504】For nextの二重ループ文
質問  きんもくせい  - 20/10/6(火) 21:20 -

引用なし
パスワード
   はじめまして。VBAを学び始めて間もないものです。
配列とFor next文の二重ループで悩んでいます。
教えていただけないでしょうか。

◆設定
A,B,E,J列の1行目に項目(商品名、単価など)が入っている
その下にデータが100行ある
静的変数の宣言で0〜3までのインデックスを確保する
インデックスに項目名を格納
変数i、jを使ってfor nextの二重ループで
100行に適用し、隣のSheet2に転記したいです。

変数iが変化することで縦に値が入り、jが変化することで
横に値が入ることは分かるのですが。。。
下のコードのように、未完成で悩んでいます。
どのようにかいたらよいでしょうか?


Sub 練習1()

Dim arr(3) As String
Dim i As Long
Dim j As Long

arr(0) = Cells(1, 1).Value
arr(1) = Cells(1, 2).Value
arr(2) = Cells(1, 5).Value
arr(3) = Cells(1, 10).Value

  For i = 1 To 100

  Worksheets("sheet2").Cells(i).Value = arr(i)

    For j = 1 To 4
  
  
    Next j 


  Next i

End Sub

【81506】追記します
質問  きんもくせい  - 20/10/6(火) 21:36 -

引用なし
パスワード
   分かりにくかったら申し訳ありませんので、追記します。
下のコードで、ひとまず項目名であるセルA1、B1、E1、J1を
転記することはできました。
それを、100行に適用する形に改良したいと思っています。

Sub 演習1()

Dim arr(4) As String
Dim i As Long

arr(1) = Cells(1, 1).Value
arr(2) = Cells(1, 2).Value
arr(3) = Cells(1, 5).Value
arr(4) = Cells(1, 10).Value

For i = 1 To 4

  Worksheets("sheet2").Cells(1, i).Value = arr(i)


Next i

End Sub

【81507】Re:追記します
発言  マナ  - 20/10/6(火) 21:39 -

引用なし
パスワード
   ▼きんもくせい さん:

どのようなものをイメージしているかわかりませんが
こんなことでしょうか。

Sub 練習1()
  Dim arr(3) As String
  Dim i As Long
  Dim j As Long
  
  arr(0) = 1
  arr(1) = 2
  arr(2) = 5
  arr(3) = 10

  For j = 0 To 3
    For i = 2 To 100
      Worksheets("sheet2").Cells(i, j).Value = Worksheets("sheet1").Cells(i, arr(i)).Value
    Next i
  Next j

End Sub

【81508】Re:追記します
発言  マナ  - 20/10/6(火) 21:55 -

引用なし
パスワード
   間違いだらけでした。

Sub 練習1()
  Dim arr(3) As String
  Dim i As Long
  Dim j As Long
  
  arr(0) = 1
  arr(1) = 2
  arr(2) = 5
  arr(3) = 10

  For j = 0 To 3
    For i = 1 To 100
      Worksheets("sheet2").Cells(i, j + 1).Value = Worksheets("sheet1").Cells(i, arr(j)).Value
    Next i
  Next j

End Sub

【81509】再度、ご質問です
質問  きんもくせい  - 20/10/7(水) 8:27 -

引用なし
パスワード
   マナさん、お返事ありがとうございます。
画像を貼れるとよいのですが、できないので書いてみます


  A    B   C   D  E ・・・ J
1 商品  番号  数量 単価 合計   棟番号
2 ...
3 ...
4 ...
5 ...

このようなデータが100行あり、移行先のSheet2に商品、番号、合計、棟番号の
列にあるデータ100行分を抜き出して転記したいのです。
1行目の項目名A,B,D,Jだけを転記することはできました。
これを2重ループを使って100行分に適用したいのですが、、((+_+))

ひょっとして、
arr(1) = Cells(1, 1).Value
arr(2) = Cells(1, 2).Value
arr(3) = Cells(1, 5).Value
arr(4) = Cells(1, 10).Value

こういうやり方でのループ適用は無理があるのでしょうか??

【81510】Re:再度、ご質問です
発言  γ  - 20/10/7(水) 11:09 -

引用なし
パスワード
   横からすみません。
見出しの名前は一行目の転記には使えますが、
2行目以降の転記にあたってはは殆ど無用の情報です。

既に指摘があるように、
何列目を転記対象とするかの情報が重要です。

思いつきに過ぎないものは
ひょっとしません。

フィルタオプションの利用と混同されているのでは?

【81511】Re:再度、ご質問です
質問  きんもくせい  - 20/10/7(水) 12:57 -

引用なし
パスワード
   Yさん
こんにちは。お返事ありがとうございます。

実はこれは私が考えた例題などではなく、昔の就業先の勉強会資料
に載っているものなのです。

>既に指摘があるように、
>何列目を転記対象とするかの情報が重要です。

やはり、この配列宣言をしてしまうなら
「何列目か」という特定の列を転記することしかできないと
考えてよいでしょうか?

考え方としてヒントを書いてある箇所ではどうも、
一行目を転記したようにExcelの横方向に向かって順に
ループする形を書くよう指示されているみたいなのですが・・

私も、一行目の項目の文字列を配列に入れてしまったら、
ループするといってもどうするのか。。とわかりませんでした。

【81512】Re:再度、ご質問です
発言  γ  - 20/10/7(水) 13:17 -

引用なし
パスワード
   ▼きんもくせい さん:
>考え方としてヒントを書いてある箇所ではどうも、
>一行目を転記したようにExcelの横方向に向かって順に
>ループする形を書くよう指示されているみたいなのですが・・

そのような、貴方しか持っていない文書を前提にされても困ります。

推測するなら、
見出しを与えて、それをもとにMatch関数かなにかで何列目かを判定して、
その後、その列を転記をしているんじゃないですか?

余り生産的な話でも無いです。
すでに実行可能なコードは提示されているわけですし、
貴方の持っている文書に合わせるなら、そちらで工夫してください。

【81514】Re:再度、ご質問です
発言  マナ  - 20/10/7(水) 17:49 -

引用なし
パスワード
   ▼きんもくせい さん:

>見出しを与えて、それをもとにMatch関数かなにかで何列目かを判定して、

Sub 練習1()
  Dim ws1 As Worksheet, ws2 As Worksheet
  Dim arr(3) As String
  Dim m As Long
  Dim i As Long
  Dim j As Long
  
  Set ws1 = Worksheets("sheet1")
  Set ws2 = Worksheets("sheet2")
  
  arr(0) = "商品"
  arr(1) = "番号"
  arr(2) = "合計"
  arr(3) = "棟番号"
  
  For j = 0 To UBound(arr)
    m = Application.Match(arr(j), ws1.Rows(1), 0)
    For i = 1 To 100
      ws2.Cells(i, j + 1).Value = ws1.Cells(i, m).Value
    Next i
  Next j

End Sub

【81515】ありがとうございます。
お礼  きんもくせい  - 20/10/7(水) 18:50 -

引用なし
パスワード
   マナさん:
ありがとうございます。このコードが、私がやってみたかったことでした。
ちゃんと選択した項目の全列が転記されました。

資料を作ったらしい方はもういらっしゃらず、解答例も載っていない
ので、これは例題の作成ミスなのか何なのかはわからないのですが、
もし本当に一行目の項目名を配列に入れて、二重ループさせて
全列転記するという方法があるのであれば、どうやるのだろう?
という気持ちと、なぜそうなるのかを理解したかったのです。

私がVBAを勉強し始めて2か月という初心者なのですが、マナさんが
書いてくださったコードを、ひとつづつ解釈してみました。
何か間違って読んでいるところはあるでしょうか?
特にROWS関数の使い方の解釈と、一番最後の
ws2.Cells(i, j + 1).Value = ws1.Cells(i, m).Value
                    ↑このコードの部分が不安です。

1、ws1,ws2 というオブジェクト変数を宣言する
2、インデックス0〜3までの 4要素が入る配列arrを宣言する
3、m,i,jという変数を宣言する
4、ws1はこのシートの"sheet1" ws2は"sheet2"です。
5、配列arrの各要素に転記したい項目名を入れる
6、jという(列方向に動く)変数で0から配列の最大値まで繰り返す

7、m = Application.Match(arr(j), ws1.Rows(1), 0)

 arr(j)がMatch関数を使うときの検索値になる
 ※Match(検索値 , 検索範囲 , 検索方法)だから、

 ※ROWS(配列)検索範囲はA列?
 ※完全一致で検索

変数mには検索値である項目名が合致した列数が入る

8、変数iで1〜100行まで繰り返す

ws2.Cells(i, j + 1).Value = ws1.Cells(i, m).Value

Sheet2に転記するときにセルA1、B1、C1、D1 の次はA2、B2・・になるので
行であるiは1から始まっているが、jは配列に合わせて0始まりになって
いるので+1してあげる。

Sheet2のCells(行i,列j)に繰り返しているiの行数とSheet1のarr(j)と
いう検索値でヒットした列数の値を転記する

【81516】Re:ありがとうございます。
発言  マナ  - 20/10/7(水) 20:12 -

引用なし
パスワード
   ▼きんもくせい さん:

> ※ROWS(配列)検索範囲はA列?

A列ではなく、1行目です。

【81517】Re:ありがとうございます。
発言  マナ  - 20/10/7(水) 20:25 -

引用なし
パスワード
   今回は、For〜nextの勉強なのかもしれませんが、

γさんのコメントにでてきたフォルタオプションを使うと
ループなしでも転記可能です。
覚えておくとよいと思います。

Sub test()
  Dim 転記先 As Range
  
  Set 転記先 = Worksheets("sheet2").Range("A1:D1")
  転記先.Value = Array("商品", "番号", "合計", "棟番号")
  
  Worksheets("sheet1").Range("A1").CurrentRegion.AdvancedFilter _
    Action:=xlFilterCopy, CopyToRange:=転記先

End Sub

【81518】Re:ありがとうございます。
お礼  きんもくせい  - 20/10/7(水) 20:39 -

引用なし
パスワード
   ▼マナ さん:
>A列ではなく、1行目です。

すみません、Rowsだから行でしたね。
読みにくく書いてしまいましたが、やっと、わかりました!<(_ _)>

arr(j)にはまずインデックス0の「商品」が入る。
sheet1の1行目の範囲で完全一致で検索するとA列なので列数1を
Rows関数が返して、その1が変数mに入る

次に内側のループに入り、jは0のままiが1から100まで変化する
以下を繰り返します。
Sheet1のセル(1,1)の値がSheet2のセル(1,0+1)つまりA1に入る

次にiが2になる
Sheet1のセル(2,1)の値がSheet2のセル(2,0+1)つまりA2に入る・・・A100まで繰り返し

iが100行分終わったら今度は外側のループに戻ってjが1になる
arr(j)には「番号」が入る。
sheet1の1行目の範囲で完全一致で検索するとB列なので列数2を
Rows関数が返して、その2が変数mに入る

また内側のループに入り、jは1のままiが1から100まで変化する

Sheet1のセル(1,2)の値がSheet2のセル(1,1+1)つまりB1に入る
次にiが2になる
Sheet1のセル(2,2)の値がSheet2のセル(2,1+1)つまりB2に入る・・・B100まで繰り返し

ここまで、書いてみないと理解できないのですが
これから頑張って勉強します。ありがとうございました。

【81519】Re:ありがとうございます。
お礼  きんもくせい  - 20/10/7(水) 20:42 -

引用なし
パスワード
   ▼マナ さん:
>今回は、For〜nextの勉強なのかもしれませんが、
>
>γさんのコメントにでてきたフォルタオプションを使うと
>ループなしでも転記可能です。
>覚えておくとよいと思います。

これも今、わからないので調べて使えるようにします(^▽^;)
本当にありがとうございました、、

【81520】Re:ありがとうございます。
発言  マナ  - 20/10/7(水) 21:17 -

引用なし
パスワード
   ▼きんもくせい さん:

もうひとつ、よく使う技

Resizeを使うと、100セルを一括で転記できます。
このケースでは、二重ループは不要ということです。


Sub 練習1()
  Dim ws1 As Worksheet, ws2 As Worksheet
  Dim arr(3) As String
  Dim m As Long
  Dim j As Long
 
  Set ws1 = Worksheets("sheet1")
  Set ws2 = Worksheets("sheet2")
 
  arr(0) = "商品"
  arr(1) = "番号"
  arr(2) = "合計"
  arr(3) = "棟番号"
 
  For j = 0 To UBound(arr)
    m = Application.Match(arr(j), ws1.Rows(1), 0)
    ws2.Cells(1, j + 1).Resize(100).Value = ws1.Cells(1, m).Resize(100).Value
  Next j

End Sub

【81521】Re:ありがとうございます。
お礼  きんもくせい  - 20/10/7(水) 22:12 -

引用なし
パスワード
   二重ループを無理に使うよりフィルタオプションやResizeを使う方がスッキリしてすごく分かりやすい
コードになるんですね。
凄すぎる、、というのが感想で、
ResizeもMatch関数も、テキストで習いはしたのです。でもそれを実務的な場面でどう使うのかまでは
まだわからなかったです。
色々教えてくださって、目からウロコ状態でした!

212 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free