[[20240415115253]] 『VBA 入力したデータを別シートに反映させたい』(1250) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『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 >


[[20240329112223]]

    ↑  こちらからの ご継続案件のようなので。。。リンクだけでもと。^^
m(__)m
(隠居Z) 2024/04/15(月) 14:42:56

ところで。。。新たに設置された グループ名
A B C  は何処にも反映しなくて、よいのでせうか。。。^^ ←素朴な疑問でした
それと、以前の 名前3 は無くなったのですか??;
m(__)m
(隠居Z) 2024/04/15(月) 14:51:17

隠居Z様

はい。入力シートで検索する時に使用するので反映シートでは使用しません。
名前3はあります。プレビューで改行になってしまい見えづらくなってしまったので消しました。

そのことをきちんと書かず申し訳ございません。ご指摘ありがとうございます。

(1250) 2024/04/15(月) 15:37:39


■1
For NCol = 5 To 7 が使用できないことに気付き自分なりに検索して
.Range("F, H, J")にしてみたのですがうまくできません。
それだとおそらくコンパイルエラーになるでしょう。
 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


もこな2様

はい、エラーになってしまいました。

■1
For NCol = 5 To 10 Step 2

であっていますでしょうか?

■2
本当そうですよね。ご指摘ありがとうございます。

(1250) 2024/04/15(月) 16:47:57


■3
>であっていますでしょうか?
聞く前に試してみてはどうですか?(ダメだったら、F列は何列目なのかよく考えましょう)

(もこな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


隠居Z様

ありがとうございます。実行してみたら確かにグループ名でした;

もこな2様

返信が遅くなり申し訳ありません。
ReDim 配列((最終行 - 1) * 3 * 3, 2)の解読に時間がかかってしまいました。
教えていただいたので実行できました。ありがとうございます。

実は、入力データのA列に番号が入っていたのを忘れていました(-_-;)
どこを変更すればいいのか頑張ってみようと思います。

(1250) 2024/04/16(火) 17:02:55


■5
>ReDim 配列((最終行 - 1) * 3 * 3, 2)の解読に時間がかかってしまいました。
 どの辺がわかりづらかったのでしょうか?
 今後の回答の参考にしたいので教えてください。

■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


もこな2様

■5

3 * 3, 2 がどういう意味なのか分かりませんでした…。

■6
はい、一つずつずらしてみたのですが、インデックスが有効範囲にありません。
とエラーになってしまい苦戦しております。

(1250) 2024/04/17(水) 13:47:31


もこな2様

追加で質問よろしいでしょうか。

For 行 = 2 To 最終行 Step 1

の行とはどこをさしているのでしょうか?
2 To 最終行 とありますが、最終行は日付の最終行を取得しているのですよね?
となると 2 は何なのでしょうか…

(1250) 2024/04/17(水) 14:08:14


1.種類の列数 3 × お名前の列数 3 ← 1行の最大必要格納場所の個数
2.1. × 項目名【見出し】を除く実データの行数


めでたく、二次元の[縦、若しくは行?]最大必要保管場所がメモリーに確保されます。
1次元[横、若しくは列?]の方は日付、名前、種類の三項目なので3で固定なので 0,1,2
の三個 指定値は2で固定です。

想像致します。真意のほどは先生にお伺いしなければなりませんが。。。^^;
m(__)m

ついでに

2 to 最終行は
見出し、項目行は抜かすので2行目から〜最終行では?。。。これも想像ですが^^;
一緒に先生のお出ましをお待ちいたしませうm(__)m
 
(隠居Z) 2024/04/17(水) 14:19:49


■7
>どういう意味なのか分かりませんでした…。
えっと・・・前のトピックで↓ように提示しましたがそちらは理解してますか?
        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


もこな2様
■7
+ と * が何の意味なのか分からずつまづいておりました。

ReDim 配列(((最終行 - 1) * 3 * 3) -1, 2)について
詳しい説明有難うございます。やっと理解いたしました。
ノートに写して覚えておきますm(__)m

■9
すみません、コードを保存せず再度Excelを開き入力したらうまく実行できました。

数日にわたり教えていただきありがとうございました。本当に助かりました。

隠居Z様
いろいろと教えていただきありがとうございましたm(__)m

(1250) 2024/04/19(金) 11:09:02


■10
>+ と * が何の意味なのか分からずつまづいておりました。
それなら、ちゃんと前のトピックで確認すべきでしょう・・・・

■11
>やっと理解いたしました。
口が悪い書き方になりますが嘘くさいです。

>ノートに写して覚えておきますm(__)m
上記に関連して、ちゃんと理解できたなら覚えておくのは↓じゃないですか?

 ・【データ行数】×【種類の最大数】×【名前の最大数】=組み替えたときの【最大行数】
 ・ExcelVBAの配列は、基本的に0から始まるのでその分ずらす必要がある
 (1から始める方法もあるので気になったらご自身で深堀調査してください)

■12
>すみません、コードを保存せず再度Excelを開き入力したらうまく実行できました。
こちらからのボールを投げ返してもらってないことを含めて、↑も正直嘘くさいと感じてしまいますが言ってもしょうがないので割愛します。

ただ、最後に【現状(実は〜が反映された版)のコード】を提示してもらえませんか?
(ここまで関わったので、せめてちゃんと理解できたのかは確認しておきたいです。)

 動作不良のコードは保存して無いから提示できないという理屈ですから、動作不良じゃないコードは提示できますよね?

(もこな2 ) 2024/04/19(金) 12:53:52


もこな2様

■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.