質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

412閲覧

VBAの配列についての質問

cd987456

総合スコア33

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2018/06/05 00:50

エクセル2007を使用しています。
VBAを使って以下の事がやりたいです。

「シート1」に以下の表があります。
イメージ説明

A列に商品、B列にロットNoとあります。
CD列、EF列、GH列にそぞぞれ日付、出荷台数とあります。

VBAを実行すると、「シート2」に以下のような表を作成したいです。

イメージ説明

A列に商品、B列にロットNoとあります。
「シート1」のCD列、EF列、GH列に記載されている日付、出荷台数を
商品、ロットに合わせて、シート2のC列日付、D列出荷台数に転記したいです。

商品数が1000を超えるくらいあり高速処理したいです。

途中までコードを考えてみました。

Public Sub リスト化() Dim myDic As Object Dim i As Long, j As Long Dim ary1() Dim ary2() Dim maxrow As Long Application.ScreenUpdating = False Application.EnableEvents = False Set myDic = CreateObject("Scripting.Dictionary") With Sheets("シート1") maxrow = .Cells(.Rows.Count, 1).End(xlUp).Row ary1 = .Range(.Cells(2, 1), .Cells(maxrow, 2)).Value For i = LBound(ary1) To UBound(ary1) myDic.Item(ary1(i, 1) & "," & ary1(i, 2)) = .Range(.Cells(i + 1, 3), .Cells(i + 1, 8)).Value Next i End With With Sheets("シート2") maxrow = .Cells(.Rows.Count, 1).End(xlUp).Row Erase ary1 '配列の初期化 ary1 = .Range(.Cells(2, 1), .Cells(maxrow, 2)).Value 'ここにどのようなコードを書けばいいのか分かりません。 ' For i = LBound(ary1) To UBound(ary1) ' ' ' Next End With Set myDic = Nothing Application.EnableEvents = True Application.ScreenUpdating = True End Sub

データを配列から書き出す時のコードが分かりません。
教えて下さい。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自分であれば、C列以降を2列毎にシート2へコピペする方針で考えます。
最初にA,B列をコピペし、C列以降を縦方向にコピペしていき、
最後に、A,B列を埋める。

配列を使いたいのはやまやまですが、
初心者には難しい処理です。
1.シート1の1行分のデータを配列に格納
2.C列以降のセット数をカウント
3.加工配列を用意(Redim)
4.1の配列からを加工配列にデータを埋めておく
5.シート2に貼り付ける
6.シート1の次の行へ続く

Dictionaryは自分でもよく使いますが、今回のケースではあまりメリットがありません。
同じロットの行が他にもあるからまとめたい、という気持ちがあるのかもですが、
シート2のA,B列でソートをかければいいかと。

投稿2018/06/05 02:11

ExcelVBAer

総合スコア1175

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

重複排除や突き合わせをするわけではないので、Dictonary を使う意味はないですね。

現状のロジックだと、行毎にセル範囲にアクセスして格納してますので、
出力も行毎に縦変換してセルに代入することになりますので、
それほど高速化はしません。

単純にシート1の表全体を配列に格納して、
出力用の配列にレイアウト変換しつつ代入して、
それをシート2に出力する、
というロジックでいいと思います。
これなら、一括読み込み、一括出力になりますので、
重い処理になるシートのレンジへのアクセスが2回ですみます。

サンプルコード

vba

1Public Sub リスト化() 2 3 Dim i As Long, j As Long, c As Long 4 Dim ary1() 5 Dim ary2() 6 Dim maxrow As Long 7 8 Application.ScreenUpdating = False 9 Application.EnableEvents = False 10 11 With Sheets("シート1") 12 maxrow = .Cells(.Rows.Count, 1).End(xlUp).Row 13 ary1 = .Range(.Cells(2, 1), .Cells(maxrow, 8)).Value 14 maxrow = WorksheetFunction.CountA(.Range(.Cells(2, 3), .Cells(maxrow, 8))) \ 2 '出力行数 15 End With 16 17 ReDim ary2(1 To maxrow, 1 To 4) '出力用配列のサイズ確保 18 19 For i = LBound(ary1) To UBound(ary1) 20 For j = 3 To 8 Step 2 21 If ary1(i, j) <> "" Then 22 c = c + 1 23 ary2(c, 1) = ary1(i, 1) 24 ary2(c, 2) = ary1(i, 2) 25 ary2(c, 3) = ary1(i, j) 26 ary2(c, 4) = ary1(i, j + 1) 27 Else 28 Exit For 29 End If 30 Next 31 Next 32 33 With Sheets("シート2") 34 .Cells(.Rows.Count, 1).End(xlUp).Offset(1).Resize(UBound(ary2), 4).Value = ary2 35 End With 36 37 Application.EnableEvents = True 38 Application.ScreenUpdating = True 39End Sub

出力用配列にレイアウト変換して代入する部分のロジックが初心者には難しいかな?
コードを読んでもらえれば、それほど難しいことはしてないことがわかると思います。

あとは、CountA で空白以外のセル件数を取得して、2で割って出力行数を取得するというのを思いつくかですね。

投稿2018/06/05 01:46

編集2018/06/05 02:44
hatena19

総合スコア33620

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cd987456

2018/06/05 05:15

回答ありがとうございます。 丁寧な説明もありがとうございます。 CountAの部分、日付、出荷台数を丸ごと取得して・・教えてもらって初めて気付きました。 配列は高速処理できて便利ですが、理解するのに時間が掛かりますね。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問