『VBA 入力したデータを別シートに反映させたい』(1250)
お世話になっております。
[[20240329112223]]で質問をしたものです。
その節は教えていただきありがとうございました。この場を借りてお礼申し上げます。
本題ですが、入力シートにて新たに入力したデータのみを反映させる方法を教えていただきましたが
入力後にマクロ実行をし忘れたまま新たにデータ入力⇒マクロ実行すると
し忘れたデータ(前回入力したデータ)が反映されない問題が発生しました。
また入力シートが一部変更いたしました。
<旧入力>シート
A B C D E F G
1 日付 種類1 種類2 種類3 名前1 名前2 名前3
2 4/1 ○○ ▲▼ □ S藤 Y田
3 4/1 ▲▼ S藤
4 4/3 □◆ ○○ ☆☆ Y田 S木 K島
↓
<新入力>シート
A B C D E F G H …
1 日付 種類1 種類2 種類3 グループ 名前1 グループ 名前2
2 4/1 ○○ ▲▼ □ A S藤 C Y田
3 4/1 ▲▼ A S藤
4 4/3 □◆ ○○ ☆☆ C Y田 B S木
グループ名(列)が追加になりました。
5 4/4 ☆☆ ○○ B S木 C K島
5行目に新たにデータを入力しマクロを実行すると
<データ一覧>シート
A B C
1 日付 名前 種類 2 4/1 S藤 ○○ 3 4/1 S藤 ▲▼ 4 4/1 S藤 □ 5 4/1 Y田 ○○ 6 4/1 Y田 ▲▼ 7 4/1 Y田 □ 8 4/1 S藤 ▲▼ 9 4/3 Y田 □◆ 10 4/3 Y田 ○○ 11 4/3 Y田 ☆☆ 12 4/3 S木 □◆ 10 4/3 S木 ○○ 11 4/3 S木 ☆☆ 12 4/3 K島 □◆ 13 4/3 K島 ○○ 14 4/3 K島 ☆☆ 15 4/4 S木 ☆☆ 16 4/4 S木 ○○ 17 4/4 K島 ☆☆ 18 4/4 K島 ○○ 19 4/5 S木 ☆☆ 20 4/5 S木 ○○ 21 4/5 K島 ☆☆ 22 4/5 K島 ○○
新たにデータを入力した4/5のみを反映ではなく全てのデータを更新しデータ一覧シートに反映したいです。
今、hatena様に教えていただいたVBAを使用しています。
Public Sub Test()
Dim InputWS As Worksheet, ListWS As Worksheet Set InputWS = Worksheets("入力") Set ListWS = Worksheets("データ一覧") Dim InputNewRow As Long, OutputRow As Long InputNewRow = InputWS.Cells(Rows.Count, 1).End(xlUp).Row OutputRow = ListWS.Cells(Rows.Count, 1).End(xlUp).Row + 1 Dim KCol As Long, NCol As Long, i As Long For KCol = 2 To 4 If InputWS.Cells(InputNewRow, KCol).Value = "" Then Exit For For NCol = 5 To 7 If InputWS.Cells(InputNewRow, NCol).Value = "" Then Exit For ListWS.Cells(OutputRow, 1) = InputWS.Cells(InputNewRow, "A").Value ListWS.Cells(OutputRow, 2) = InputWS.Cells(InputNewRow, KCol).Value ListWS.Cells(OutputRow, 3) = InputWS.Cells(InputNewRow, NCol).Value OutputRow = OutputRow + 1 Next Next End Sub
一気に書き込む方法を教えていただいた、もこな2様の
.Range("A2:C2").Resize(UBound(配列) + 1).Value = 配列
を使えばいいのかな?と思いましたが、まずグループ名を追加したことによって
For NCol = 5 To 7 が使用できないことに気付き自分なりに検索して
.Range("F, H, J")にしてみたのですがうまくできません。
勉強不足で申し訳ございません。ご教示のほどお願いいたします。
< 使用 Excel:Excel2013、使用 OS:Windows10 >
↑ こちらからの ご継続案件のようなので。。。リンクだけでもと。^^ m(__)m (隠居Z) 2024/04/15(月) 14:42:56
はい。入力シートで検索する時に使用するので反映シートでは使用しません。
名前3はあります。プレビューで改行になってしまい見えづらくなってしまったので消しました。
そのことをきちんと書かず申し訳ございません。ご指摘ありがとうございます。
(1250) 2024/04/15(月) 15:37:39
For NCol = 5 To 7
たとえば↑を丁寧に書くと↓のようになります。
For NCol = 5 To 7 Step 1
では、今回であれば【】の部分がどうなればよいか考えてみてはどうでしょうか?
For NCol = 【】 To 【】 Step 【】
■2
上記とも関連しますが↓だけで解決させてるわけじゃないですよ?
.Range("A2:C2").Resize(UBound(配列) + 1).Value = 配列
配列を使うならば、大きさを決めている部分や格納する部分をきちんと理解しないとダメです。
(もこな2 ) 2024/04/15(月) 15:43:27
はい、エラーになってしまいました。
■1
For NCol = 5 To 10 Step 2
であっていますでしょうか?
■2
本当そうですよね。ご指摘ありがとうございます。
(1250) 2024/04/15(月) 16:47:57
(もこな2 ) 2024/04/15(月) 17:50:02
6
ですよ
6
5 はグループ名なので。。。多分。。。^^;
m(__)m
(隠居Z) 2024/04/15(月) 18:06:47
Sub 研究用2() Dim buf As Long, 行 As Long, i As Long, 種類列 As Long, 名前列 As Long Dim 配列() As Variant Dim 最終行 As Long
With Worksheets("入力") 最終行 = .Cells(.Rows.Count, "A").End(xlUp).Row
ReDim 配列(最終行 - 1 * 3 * 3, 2)
For 行 = 2 To 最終行 Step 1 For 種類列 = 2 To 4 Step 1 For 名前列 = 5 To 7 '←ここをかえればOK If .Cells(行, 種類列).Value <> "" And .Cells(行, 名前列).Value <> "" Then 配列(i, 0) = .Cells(行, "A").Value 配列(i, 1) = .Cells(行, 種類列).Value 配列(i, 2) = .Cells(行, 名前列).Value i = i + 1 End If Next 名前列 Next 種類列 Next 行 End With
With Worksheets("データ一覧") .Range("A2:C" & .Rows.Count).ClearContents .Range("A2:C2").Resize(UBound(配列) + 1).Value = 配列 End With End Sub
(もこな2) 2024/04/16(火) 07:33:09
誤 ReDim 配列(最終行 - 1 * 3 * 3, 2) 正 ReDim 配列((最終行 - 1) * 3 * 3, 2)
(もこな2 ) 2024/04/16(火) 08:41:05
ありがとうございます。実行してみたら確かにグループ名でした;
もこな2様
返信が遅くなり申し訳ありません。
ReDim 配列((最終行 - 1) * 3 * 3, 2)の解読に時間がかかってしまいました。
教えていただいたので実行できました。ありがとうございます。
実は、入力データのA列に番号が入っていたのを忘れていました(-_-;)
どこを変更すればいいのか頑張ってみようと思います。
(1250) 2024/04/16(火) 17:02:55
どの辺がわかりづらかったのでしょうか? 今後の回答の参考にしたいので教えてください。
■6
>実は、入力データのA列に番号が入っていたのを忘れていました(-_-;)
↓がそれぞれズレればいいのですから難しい話じゃないですよね?
最終行 = .Cells(.Rows.Count, "A").End(xlUp).Row ~~~ For 種類列 = 2 To 4 Step 1 ~~~ ~~~ For 名前列 = ● To ● Step ● ~~~~ ~~~~ 配列(i, 0) = .Cells(行, "A").Value ~~~
(もこな2 ) 2024/04/16(火) 18:07:13
■5
■6
はい、一つずつずらしてみたのですが、インデックスが有効範囲にありません。
とエラーになってしまい苦戦しております。
(1250) 2024/04/17(水) 13:47:31
追加で質問よろしいでしょうか。
For 行 = 2 To 最終行 Step 1
の行とはどこをさしているのでしょうか?
2 To 最終行 とありますが、最終行は日付の最終行を取得しているのですよね?
となると 2 は何なのでしょうか…
(1250) 2024/04/17(水) 14:08:14
で
めでたく、二次元の[縦、若しくは行?]最大必要保管場所がメモリーに確保されます。
1次元[横、若しくは列?]の方は日付、名前、種類の三項目なので3で固定なので 0,1,2
の三個 指定値は2で固定です。
と
想像致します。真意のほどは先生にお伺いしなければなりませんが。。。^^;
m(__)m
ついでに
2 to 最終行は
見出し、項目行は抜かすので2行目から〜最終行では?。。。これも想像ですが^^;
一緒に先生のお出ましをお待ちいたしませうm(__)m
(隠居Z) 2024/04/17(水) 14:19:49
With Worksheets("入力") For 行 = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row buf = buf _ + WorksheetFunction.CountA(Intersect(.Rows(行), .Range("B:D"))) _ * WorksheetFunction.CountA(Intersect(.Rows(行), .Range("E:G"))) Next 行 ReDim 配列(buf - 1, 2) End With
要は、【行ごと】に【データが入力されている種類列】×【データが入力されている名前列】を調べて足し上げれば【必要なデータ数】がわかるという話をしてますよね?
で、こちらにトピックでは「配列の大きさを決めるほうは、最大数用意しておけばよいでしょう。」とコメントしましたよね?
ということは、【データ行数】×【種類の数(3)】×【名前の数(3)】がMAXですよね。
さらに、データは2行目から始まっているのですから、仮にデータが2行目で終わっていれば【2-1=1行分】という単純な算数の結果です。
なので、例示のように最終行が5行目であれば↓になりませんか?
【データ行数(4)】×【種類の数(3)】×【名前の数(3)】=最大36行分の枠を用意しておけばよい
列数のほうは、既にコメントがあるように「日付、名前、種類」の3列分ですから、3-1=2(配列が0から始まるため)です。
※配列が0から始まる話はしてませんが、聞くなら前のトピックの段階で聞くべき話です。 ※そういった追加質問がなかったので、こちらとしては別途調べて理解したのだと解釈しています。
なお、厳密にいうと(配列が0から始まるので)↓にすべきですところですが横着してしまったので、そちらが原因で混乱させてしまったのであればごめんなさい。
ReDim 配列(((最終行 - 1) * 3 * 3) -1, 2)
■8
>行とはどこをさしているのでしょうか?
質問の意図が理解できかねますが、提示したものを展開すると↓ですよね。
For 行 = 2 To Worksheets("入力").Cells(.Rows.Count, "A").End(xlUp).Row Step 1
(「■7」でも書きましたが)、既にコメントがあるように【2】行目からデータが始まってるのだから【2】〜データの最終行まで見ればよいということになりませんか?
■9
>はい、一つずつずらしてみたのですが、インデックスが有効範囲にありません。
>とエラーになってしまい苦戦しております。
こちらにはあなたの画面は見えませんので、実際のコードと行列を踏まえたレイアウトを提示して、どこでエラーが発生して困っているのか教えてください。
(もこな2 ) 2024/04/17(水) 18:32:18
ReDim 配列(((最終行 - 1) * 3 * 3) -1, 2)について
詳しい説明有難うございます。やっと理解いたしました。
ノートに写して覚えておきますm(__)m
■9
すみません、コードを保存せず再度Excelを開き入力したらうまく実行できました。
数日にわたり教えていただきありがとうございました。本当に助かりました。
隠居Z様
いろいろと教えていただきありがとうございましたm(__)m
(1250) 2024/04/19(金) 11:09:02
■11
>やっと理解いたしました。
口が悪い書き方になりますが嘘くさいです。
>ノートに写して覚えておきますm(__)m
上記に関連して、ちゃんと理解できたなら覚えておくのは↓じゃないですか?
・【データ行数】×【種類の最大数】×【名前の最大数】=組み替えたときの【最大行数】 ・ExcelVBAの配列は、基本的に0から始まるのでその分ずらす必要がある (1から始める方法もあるので気になったらご自身で深堀調査してください)
■12
>すみません、コードを保存せず再度Excelを開き入力したらうまく実行できました。
こちらからのボールを投げ返してもらってないことを含めて、↑も正直嘘くさいと感じてしまいますが言ってもしょうがないので割愛します。
ただ、最後に【現状(実は〜が反映された版)のコード】を提示してもらえませんか?
(ここまで関わったので、せめてちゃんと理解できたのかは確認しておきたいです。)
動作不良のコードは保存して無いから提示できないという理屈ですから、動作不良じゃないコードは提示できますよね?
(もこな2 ) 2024/04/19(金) 12:53:52
■10
確かにその通りです。申し訳ありませんでした。
■12
Sub 研究用2() Dim buf As Long, 行 As Long, i As Long, 種類列 As Long, 名前列 As Long Dim 配列() As Variant Dim 最終行 As Long With Worksheets("入力") 最終行 = .Cells(.Rows.Count, "B").End(xlUp).Row ReDim 配列((最終行 - 1) * 3 * 3, 2) For 行 = 2 To 最終行 Step 1 For 種類列 = 3 To 5 Step 1 For 名前列 = 7 To 11 Step 2 If .Cells(行, 種類列).Value <> "" And .Cells(行, 名前列).Value <> "" Then 配列(i, 0) = .Cells(行, "B").Value 配列(i, 1) = .Cells(行, 種類列).Value 配列(i, 2) = .Cells(行, 名前列).Value i = i + 1 End If Next 名前列 Next 種類列 Next 行 End With With Worksheets("データ一覧") .Range("A2:C" & .Rows.Count).ClearContents .Range("A2:C2").Resize(UBound(配列) + 1).Value = 配列 End With End Sub
(1250) 2024/04/19(金) 17:24:27
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.