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

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

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

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

Q&A

3回答

449閲覧

Excelマクロで条件に沿って2次元配列を作成し、結果を別シートで統合したい

shallow104

総合スコア0

VBA

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

0グッド

0クリップ

投稿2022/06/06 11:38

編集2022/06/06 11:50

マクロ初心者です。研究で画像処理をしています。

■やりたいこと
以下の構成のエクセルでMainシートから結果シートの結果を条件式で判定し、
該当する結果を下記「理想の出力」のようにまとめたい。

■エクセルの構成
・Main(結果を統合するシート)
・Result1.csv(結果1)
・Result2.csv(結果2)
(結果のシートは多数あり)

※ResultX.csvは下記のような構成

フレーム番号フラグ(0or1)
00
10
20
31
41
50
61
70
......
(フレーム数は10000前後)

■条件式
フラグが0→1に変わったフレームの番号を取得する

■理想の出力
Mainシートに以下のようにまとめたい

シート名フレーム番号
Result1.csv3
Result1.csv6
Result1.csv20
Result2.csv2
......

■現状
条件式の判定はできるようになりましたが、判定結果をMainシートに反映する方法がわからない

■現状のコード
条件に該当するフレームがいくつあるのかわからないため、可変長の配列にすべきと思うのですが、複数のFor分の設定、配列の作成がわからず、手が止まってしまいました。。

VBA

1Sub sample1() 2 Dim i,j As Long '条件式による判定用 3 Dim RowNum As Integer '結果のフレーム数 4 Dim FlagFrame As() Long 5 ReDim Preserve FlagFrame(1) 6 7 Worksheets("Result1.csv").Activate 8 RowNum = Cells(Rows.count,1).End(xlUp).Row 9 10 For i = 1 To RowNum 11 j = Cells(i,"B") 12 k = Cells(i+1,"B") 13 If j = 0 And k = 1 Then '条件式 14 FlagFrame(l)= i 15 Debug.Print i-1 & "フレームでフラグ切替検知" 16 End If 17 Next 18End Sub

不明点や不足している情報などありましたらご指摘お願いします。

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

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

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

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

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

tatsu99

2022/06/06 12:40

Excelのシート構成は、Main以外は全てResultX.csvと理解して良いですか。 フレーム番号=0のフラグが1の場合は、Mainシートに登録対象になりますか。それともなりませんか?
shallow104

2022/06/06 12:44

①Excelのシート構成は、Main以外は全てResultX.csvと理解して良いですか。 →はい、認識の通りです。 ②フレーム番号=0のフラグが1の場合は、Mainシートに登録対象になりますか。それともなりませんか? →フレーム番号=0のフラグが1になることはないものと思って頂いて大丈夫です。
guest

回答3

0

特に2次元配列は不要かと思います。
配列を使わない方法です。
前の値が0で今回の値が1なら、その行をMainに取り込みます。
Main,resultX.csvともに1行目は見出し行である前提です。

VBA

1Option Explicit 2Public Sub Main収納() 3 Dim ms As Worksheet 4 Dim ws As Worksheet 5 Dim msRow As Long 'Mainシート行番号 6 Set ms = Worksheets("Main") 7 ms.Cells.ClearContents 8 ms.Range("A1:B1").Value = Array("シート名", "フレーム番号") 9 msRow = 2 10 '全シート分設定 11 For Each ws In Worksheets 12 If ws.Name <> ms.Name Then 'Mainシートでないなら、シートの設定を行う 13 Call Set1Sheet(ms, msRow, ws) 14 End If 15 Next 16 MsgBox ("完了") 17End Sub 18'1シート分設定 19Private Sub Set1Sheet(ByVal ms As Worksheet, ByRef msRow As Long, ByVal ws As Worksheet) 20 Dim maxrow As Long 21 Dim pval As Variant 22 Dim wrow As Long 23 maxrow = ws.Cells(Rows.Count, 1).End(xlUp).Row 'A列最終行取得 24 pval = 1 25 For wrow = 2 To maxrow 26 If ws.Cells(wrow, "B").Value = 1 And pval = 0 Then '前行が0でかつ現在行が1の場合 27 ms.Cells(msRow, "A").Value = ws.Name 'シート名 28 ms.Cells(msRow, "B").Value = ws.Cells(wrow, "A").Value 'フレーム番号 29 msRow = msRow + 1 30 End If 31 pval = ws.Cells(wrow, "B").Value '前行を記憶 32 Next 33End Sub 34

投稿2022/06/06 23:51

tatsu99

総合スコア5462

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

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

0

配列を使うなら、セル範囲をそのまま二次元配列に代入できるので、それを使うといいでしょう。
出力結果も2列なので、その配列に結果を上書きしていくと無駄がないです。

とりあえず Result1.csv の結果をMainに出力するサンプル。

vba

1Sub sample1() 2 Dim ws As Worksheet 3 Set ws = Worksheets("Result1.csv") 4 5 Dim FlagFrame() 6 FlagFrame = ws.Range("A1").CurrentRegion.Value 7 8 Dim i As Long, j As Long 9 j = 1 10 For i = 1 To UBound(FlagFrame) - 1 11 If FlagFrame(i, 2) = 0 And FlagFrame(i + 1, 2) = 1 Then 12 FlagFrame(j, 2) = FlagFrame(i + 1, 1) '2列目にフレーム番号を代入 13 FlagFrame(j, 1) = ws.Name '1列目にシート名を代入 14 j = j + 1 15 End If 16 Next 17 18 Worksheets("Main").Cells(1, 1).Resize(j - 1, 2).Value = FlagFrame '配列をセル範囲に出力 19End Sub

追記

ブックと同じフォルダーにCSVファイルがあり、それを読み込む場合のコード例

vba

1Public Sub sample() 2 Dim outputCell As Range 3 With Worksheets("Main") 4 .Cells(1, 1).CurrentRegion.ClearContents 5 .Range("A1:B1").Value = Array("シート名", "フレーム番号") 6 Set outputCell = .Cells(2, 1) '出力セル 7 End With 8 9 Application.ScreenUpdating = False 10 Dim fn As String 11 fn = Dir(ThisWorkbook.Path & "\result*.csv") 12 Do Until fn = "" 13 With Workbooks.Open(fn) 14 outputMain .Worksheets(1), outputCell 15 .Close False 16 End With 17 fn = Dir() 18 Loop 19 Application.ScreenUpdating = True 20End Sub 21 22Sub outputMain(ws As Worksheet, ByRef outputCell As Range) 23 Dim FlagFrame() 24 FlagFrame = ws.Range("A1").CurrentRegion.Value 25 Dim i As Long, j As Long 26 For i = 1 To UBound(FlagFrame) - 1 27 If FlagFrame(i, 2) = 0 And FlagFrame(i + 1, 2) = 1 Then 28 j = j + 1 29 FlagFrame(j, 2) = FlagFrame(i + 1, 1) 30 FlagFrame(j, 1) = ws.Name 31 End If 32 Next 33 outputCell.Resize(j, 2).Value = FlagFrame 34 Set outputCell = outputCell.Offset(j) '出力セルを次のセルに設定 35End Sub

投稿2022/06/06 13:22

編集2022/06/07 02:25
hatena19

総合スコア33782

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

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

shallow104

2022/06/06 13:43

回答ありがとうございます! 参考にさせていただきます!
guest

0

2次元配列に入れてませんが、こんな感じで考えてみました。

Option Explicit Sub Sample() ReadCSV "result1.csv" ReadCSV "result2.csv" End Sub Sub ReadCSV(fn As String) Dim main As Worksheet Dim r As Long Set main = ThisWorkbook.Worksheets("Main") main.Range("A1:B1").Value = Array("シート名", "フレーム番号") r = main.Cells(main.Rows.Count, 1).End(xlUp).Row + 1 Dim wb As Workbook, ws As Worksheet Set wb = Workbooks.Open(fn) Set ws = wb.Worksheets(1) Dim i For i = 2 To ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If ws.Cells(i, 2).Value = 1 And ws.Cells(i - 1, 2).Value = 0 Then main.Cells(r, 1).Resize(, 2).Value = Array(fn, i) r = r + 1 End If Next wb.Close False End Sub Sub Sample2() Dim f With CreateObject("Scripting.FileSystemObject") For Each f In .GetFolder(ThisWorkbook.Path).Files If LCase(f.Name) Like "result*.csv" Then ReadCSV f.Name Next End With End Sub

投稿2022/06/06 13:12

編集2022/06/06 13:49
jinoji

総合スコア4585

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

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

shallow104

2022/06/06 13:41

回答ありがとうございます! ちなみに、 csvもfor文で読み込ませようとなると、どのようにすればよいでしょうか?
jinoji

2022/06/06 13:51

Sample2 として追記してみました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問