Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Excel 2016)
一致するデータの転記について
投稿日時: 23/09/28 12:06:01
投稿者: ひろまさ

アドバイスをお願いしたい事がございます。
商品CD、納期、数量が順に入力されたデータを、他のシートの
商品CD、納期が一致したセルに数量を横に転記したいのですが、
どのようにすればよいのか悩んでいます。
具体的には以下の形式です。
 
■元シート
商品CD  納期  数量
AAA   10/3   10
AAA   10/4   10
BBB   10/3   20
BBB   10/5   20
CCC   10/6   30
 
■転記先シート
   10/3  10/4  10/5  10/6
AAA  10   10
BBB  20       20
CCC              30
 
まだまだ、勉強の身で初めてのパターンですので、参考になるサイト等が
あればご教示お願い致します。
自身でも書籍、ネットで検索を行いましたが、参考になる情報がなくご質問を
させて頂きました。

回答
投稿日時: 23/09/28 12:21:51
投稿者: higejee

 元シート、転記先シートとも質問文の通りの形で A1 から書かれているとして、転記先シートの B2(商品CD=AAA、納期=10/3)に以下の数式を入力して、あとはコピーする。絶対参照/相対参照に注意。
 
=SUMIFS(元シート!$C:$C,元シート!$B:$B,転記先シート!B$1,元シート!$A:$A,転記先シート!$A2)

回答
投稿日時: 23/09/28 13:09:49
投稿者: WinArrow

SUMIFS関数以外の案
SUMPRODUCT関数
=SUMPRODUCT((Sheet1!$A$2:$A$10=$A2)*(Sheet1!$B$2:$B$10=B$1)*(Sheet1!$C$2:$C$10))

回答
投稿日時: 23/09/28 13:12:04
投稿者: WinArrow

VBAの板での質問ですが、一般機能として回答しています。

回答
投稿日時: 23/09/28 15:12:35
投稿者: higejee

 あ、そうかここは VBA 板だったのですね。^^;
 関数苦手なわたしでもできたもので、つい忘れてました。

投稿日時: 23/09/28 16:16:09
投稿者: ひろまさ

higejeeさん、 WinArrowさん アドバイスありがとうございます。
以前にもVBAだけではなく、関数を組み合わせた方がよいとアドバイスを、
他の方に頂きました。
今回もアドバイスを頂いた通りに関数を組み合わせて作成を行っています。
やはり、今回の仕組みは、VBAで作成する事は難しいでしょうか。
管理する日付が長くなると処理が重たくなってきますので今後、他の件でも
活用できたらと思いご質問をさせて頂いたのもあります。

回答
投稿日時: 23/09/28 22:57:31
投稿者: WinArrow

>今回の仕組みは、VBAで作成する事は難しいでしょうか。
  
VBAの場合は、
ループして、セル毎にSUMIFS関数を入れるのではなく、
セル範囲に、SUMIFS関数を一挙に入れて、計算する方法があります。
ループは、処理効率が悪い。
Excelで提供している関数と、全く同じ処理をVBAで作成しても、Excel関数を超えることはできません。
必要があれば「値」に変換してもよい。
 
一般機能でも、左上のセルにSUMIFS関数を入力し、
下へ、右へフィルドラッグすれば、入力の手間は省けます。
その後セル範囲を選択して、一挙に「値」に変換するとよいでしょう。

回答
投稿日時: 23/09/29 09:21:31
投稿者: 半平太

一つ確認します。
  
これは単純転記なんですか、それとも集計なんですか?
(違いは、元シートに同じ「商品CDと納期」が2つ以上あるかどうかですが)
 
集計タイプで処理すれば、大は小を兼ねる形にはなりますが、
「小」でいいなら無駄は無駄なので。

回答
投稿日時: 23/09/29 10:03:52
投稿者: simple

日付があるデータということは、一回だけではなく、何度も発生するんでしょうかねえ。
だとすると、VBAで自前のロジックをつくるよりも、
ピボットテーブルと言ったExcelに備わった機能を使ったほうが楽じゃないですか?
・一度作成してしまえば、データ範囲を指示し直すだけでデータの追加にも耐えられますし、
・月間集計といったことにも対応できるはずです。
 
# Dictionaryなどを使う練習ということであれば、それはそれでありうるかもしれませんが,
# ピボットを使ってくださいと言わんばかりのデータの形式ですよね。

投稿日時: 23/09/29 10:19:05
投稿者: ひろまさ

WinArrowさん、半平太さん simpleさんご回答ありがとうございます。
 
WinArrowさん
事前に2行目にSUMIFS関数を入力て、VBAで下へドラッグを行う仕組みを
作成してみました。
多少、早く処理が修了しました。
「ループでは庫処理効率が悪い」という事ですが、一度確認してみたいので、
どのように作成をすればよいのか、構成だけでもご教示をお願いできたら
幸いです。
 
半平太さん
商品CD、納期毎に集計を行うVBAの作成を行いました。
それを転記先シートの該当する商品CDの納期に数量を転記したいのです。
 
simpleさん
最初に元シートのデータをピボットテーブルを利用して集計を行いました。
確かにsimpleさんがおっしゃる通りに楽です。
しかし、私以外にも利用します。
本当に私が言える立場ではないですが、私以上にExcelのレベルがないので、
できるだけ自動化したいのが本音です。
そこで、集計を行ったデータを転記先シートの該当する商品CDの納期に転記を
行うアドバイスを頂きたくご質問をさせて頂きました。
 
よろしくお願い致します。

回答
投稿日時: 23/09/29 10:52:52
投稿者: 半平太

>商品CD、納期毎に集計を行うVBAの作成を行いました。
>それを転記先シートの該当する商品CDの納期に数量を転記したいのです。
 
ちょっと不明瞭ですね・・(単に集計か転記かの別が分かればよかったのですが)
再確認するのも面倒なので集計タイプにします(処理速度は多分微差でしょう)
 

Sub Sample()
    Dim rSRC As Range
    Dim vOutDate, vOutComo, vOutRslt()
    Dim i As Long, k As Long
    Dim dicT As Object, ky
    Dim t
    
    t = Timer '速度計測
    
    Set dicT = CreateObject("Scripting.Dictionary")
    Set rSRC = Worksheets("元シート").Range("A1").CurrentRegion
    
    For i = 2 To rSRC.Rows.Count
    
        If rSRC(i, 1) <> "" Then
            ky = rSRC(i, 1).Value & "♪" & rSRC(i, 2).Value2
            dicT(ky) = dicT(ky) + rSRC(i, 3).Value
        End If
    Next i
    
    With Worksheets("転記先シート").Range("A1").CurrentRegion
        vOutComo = .Columns("A").Value
        vOutDate = .Rows(1).Value2
    End With
    
    ReDim vOutRslt(2 To UBound(vOutComo), 2 To UBound(vOutDate, 2))
    
    For i = 2 To UBound(vOutComo)
    
        If vOutComo(i, 1) <> "" Then
            For k = 2 To UBound(vOutDate, 2)
                ky = vOutComo(i, 1) & "♪" & vOutDate(1, k)
                vOutRslt(i, k) = dicT(ky)
            Next k
        End If
    Next i
    
    Worksheets("転記先シート").Range("B2").Resize(UBound(vOutRslt) - 1, UBound(vOutRslt, 2) - 1) = vOutRslt
    dicT.RemoveAll
    
    Debug.Print Timer - t '経過時間打出し
End Sub

回答
投稿日時: 23/09/29 11:21:06
投稿者: WinArrow

ひろまさ さんの引用:

どのように作成をすればよいのか、構成だけでもご教示をお願いできたら
幸いです。

 
例:転記先シートのレイアウトが
A列:商品CD
1行目:項目名(納期)
と考えると
A1のCurentRegionが対象セル範囲になります。
また、数式を入力する先頭セルは"B2"となります。
B2セルは、A1からみると、OFFSET(1,1)の関係にあるから、
次のようにコードを記述すると、一挙に数式を代入できます。
ループせずに数式を代入する方法の例
    Set shtsaki = Worksheets("転記先シート")
    
    With shtsaki.Range("A1").CurrentRegion
        Application.Intersect(.Cells, .Offset(1, 1)).Formula = "=ROW()*COLUMN()"
    End With

 
※「ROW()*COLUMN()」の個所は変更してください。
 

投稿日時: 23/09/29 14:45:09
投稿者: ひろまさ

半平太さん、WinArrowさんご回答ありがとうございます。
  
半平太さん
参考のコードを記載して頂きありがとございます。
望んでいた結果が表示されました。
今後も同様な処理がありますので、解読をさせて頂きます。
  
最後に1点ご質問がございます。
下記の「"♪" 」の部分です。
  ky = rSRC(i, 1).Value & "♪" & rSRC(i, 2).Value2
  
恐縮ではございますが「"♪" 」意味をご教示して頂けないでしょうか?
  
 
WinArrowさん
ループせずに数式を代入する事ができました。
このような処理が事が出来るとは思いもしませんでした。
今後、利用させて頂きます。

回答
投稿日時: 23/09/29 15:51:49
投稿者: 半平太

>「"♪" 」意味
 
Dictionaryのキーを 商品CD と 納期 で合成しているので、
両データの境を明確に区切るものです。
何でもいいんですが、できるだけデータとして使われてないものがいいので。。
 
つまり、
商品コードが、AAA45202なんて番号付きで、納期が空白だった、
なんてことに耐えられるようにする為です。
まぁ、老婆心ですけどね。
 
ところで、何秒くらい掛かったですか?
(イミディエイトウィンドウに出たと思うのですが・・)

投稿日時: 23/09/29 16:35:46
投稿者: ひろまさ

半平太さんご回答ありがとうございます。
ご質問をさせて頂いた件、ご説明ありがとうございました。
時間ですが、10月度の約500件のデータですが、約5秒で完了しました。
今後、データが増えていくと思いますが、月単位で処理を行いますので、
問題はないと思います。
色々とアドバイスを頂きありがとうございました。
 
 
ご回答を頂いた皆様
今回も多くの皆様にご回答を頂き感謝しています。
いろいろな手法をご教示して頂きましたが今後、同様の処理が発生した場合、
アレンジをして活用させて頂きます。
ありがとうございました。