[[20120409105405]] 『複数のシートを参照して売り上げを出したい』(peridot) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『複数のシートを参照して売り上げを出したい』(peridot)

 すみません、助けてください

 Excelで複数のシートを参照して、その日の売上を出したいのですが、参照がうまく行きません。

 ★シート"箱サンプル"(データシート)

   A   B   C   D  E   F   G  H  I  J   K   L
 1 SK作業                    合計
 2 記号 媒体名 件数    記号 媒体名 件数     記号 媒体名 件数
 3 SK1  KZ         SK2  KZ   2       SK  KZ   2
 4 SK1  MZ         SK2  MZ
 5 SK1  HY   82     SK2  HY   4       SK  HY   86
 6 SK1  FR   11     SK2  FR          SK  FR   11
 7 VA1  KK   1516    VA2  KK   224      VA  KK   1740
 8 VE1  KK   9     VE2  KK   4       VE  KK   13
 9 VS1  10P   6192    VS2  10P   672      VS  10P   6864
 10 VS3  10P   1008                  VS  10P   1008  
 

 ★シート"有料"(データシート)
 (フォームは「箱サンプル」と同じ)

 ★シート"単価マスタ"
   A   B    C    D    E   F    G    H    I
 1 単価表
 2    記号  媒体名 基本単価 追加分 付帯業務 区分 基本コスト 単価
 3    SK    KZ   19    1    1.2  1.5  22.7    17.0
 4    SK    MZ   19    1    1.2  1.5  22.7    17.0
 5    SK    HY   19    2    0   1.5  22.5    16.9
 6    SK    FR   19    0    0   1.5  20.5    15.4
 7    VA    KK   19    2    1.2  1.5  23.7    17.8
 8    VE    KK   19    0    0   1.5  20.5    15.4
 9    VS    10P   19    0    12.2  1.5  32.7    24.5

 上記のようなデータシートと単価マスタがあります。

 データシートには、その日に発生する業務の記号・媒体・件数がA〜Gに入力されます。
 その合計件数がJ〜L列に関数で表示されます。
 (A〜Gの中で件数が0のものはJ〜L列のその行は空白になります)

 「記号」「媒体」はそれぞれ同じものがあります。
 基本的にA列の記号は「xx1」、E列の記号は「xx2」となっていますが、ごく稀に「xx3」が発生すると
 A列に「xx3」が記載されます。
 「合計」の記号はA列・E列から数字を取り除いたものです。

 単価マスタの「基本コスト」(H列)はD〜G列の合計、「単価」(I列)はH列×0.75の数式が入っています。

 それで、「合計」の部分と単価マスタを照合して、それぞれの売上を下記のように出したいです。
 ○売上=データシートの合計件数×単価マスタの単価

 ★シート"売上"
    A  B   C  D   E
 1  記号 媒体 件数 単価 売上
 2  SK  KZ  2  17.0 34.0
 3  SK  HY  86  16.9 1453.4 
 4  SK  FR  11  15.4 169.4
 5  VA  KK  1740 17.8 3097.2
 6  VE  10P  13  15.4 200.2
 7  VS  10P 7872 24.5 19286.4
 〜〜〜〜〜〜〜〜
 45 合計    SUM(C列)  SUM(E列)

 このように「売上」シートに一覧表を作りたいのですが、最初VLOOKUPで抽出しようと思ったのですが
 シート"箱サンプル"の9〜10行目のように見出しが同じものがあったりするのでうまくいきません。
 マクロでやろうと思ったのですが、データシートの「合計」の中から件数があるものを抽出し、
 その「記号&媒体名」の組み合わせが一致するものを「単価マスタ」で探して取り出す&
 シート"箱サンプル"の9〜10行目のように見出しが同じものを一つにまとめるというのが
 よくわかりません…

 ↓とりあえず「箱サンプル」シートからデータを抜き出そうとしたコード

 Option Explicit

 Sub 売上データ()

 Dim i As Long
 Dim j As Long
 Dim k As Long
 Dim tenso As String
 Dim baitai As String
 Dim qty As Long
 Dim cost As Long
 Dim sales As Long
 Dim sh1 As Worksheet
 Dim sh2 As Worksheet
 Dim sh3 As Worksheet

     Set sh1 = ThisWorkbook.Sheets("箱サンプル")
     Set sh2 = ThisWorkbook.Sheets("有料")
     Set sh3 = ThisWorkbook.Sheets("単価マスタ")

    With Sheets("売上")
        For j = 3 To .Cells(Rows.Count, 1).End(xlUp).Row
            If sh1.Cells(j, 10).Value <> "" Then
                For i = 3 To sh1.Cells(Rows.Count, 1).End(xlUp).Row - 1

                    .Cells(i, 1).Value = sh1.Cells(j, 10).Value
                    .Cells(i, 2).Value = sh1.Cells(j, 11).Value
                    .Cells(i, 3).Value = sh1.Cells(j, 12).Value
                    '.Cells(i, 4).Value = 単価マスタから一致するものを抽出?
                    .Cells(i, 5).Formula = "=C" & i & "*D" & i
                Next i
            End If
        Next j
    End With

    Set sh1 = Nothing
    Set sh2 = Nothing
    Set sh3 = Nothing

 End Sub

 このコードを実行しましたが、「箱サンプル」シートの最終行だけが「売上」シートにずらーっと並んでしまいます。
 最初からつまづいて、単価マスタを参照したり同じ「記号&媒体名」の組み合わせを統合したり…
 もさっぱり分かりません。

 どのようにすればよいかお教えください。
 Excelのバージョンは2007です。

 ★シート"箱サンプル"(データシート)

 ★シート"有料"(データシート)
 (フォームは「箱サンプル」と同じ)

 の関係が解りません?

 (Bun)


 すみません、「箱サンプル」「有料」両方のシートからデータを抜き出して「単価マスタ」シートと照合、
 「箱サンプル」「有料」にあるデータの売上をまとめて「売上」シートに書き出したいのです。

 (peridot)

 >すみません、「箱サンプル」「有料」両方のシートからデータを抜き出して「単価マスタ」シートと照合、
 >「箱サンプル」「有料」にあるデータの売上をまとめて「売上」シートに書き出したいのです。

 と言う事は、「箱サンプル」「有料」両方のシートは、同じ意味のデータとして合算して善いんですね?

 (Bun)


 >と言う事は、「箱サンプル」「有料」両方のシートは、同じ意味のデータとして合算して善いんですね?
 はい、そうです。

 (peridot)

 "箱サンプル" のデータを、"売上" へ転記処理するサンプルです。
 Dic を利用して、単価マスタから、該当単価を引いてきます。

 Sub test()
   Dim i&, j&, n&, S$, Sh As Worksheet
   Dim D As Object

      Set D = CreateObject("scripting.dictionary")
      Set Sh = Sheets("売上")

      With Sheets("単価マスタ") 'Dicへ単価セット
         For i = 3 To .Cells(.Rows.Count, "b").End(xlUp).Row
            S = .Cells(i, 2).Value & .Cells(i, 3).Value
            D(S) = .Cells(i, "i").Value
         Next
      End With

      n = 1: S = ""
      With Sheets("箱サンプル")
         For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row
            If .Cells(i, "l").Value <> "" Then
               If .Cells(i, "j").Value & .Cells(i, "k").Value <> S Then
                  n = n + 1
                  S = .Cells(i, "j").Value & .Cells(i, "k").Value
                  Sh.Cells(n, 1).Value = .Cells(i, "j").Value '記号
                  Sh.Cells(n, 2).Value = .Cells(i, "k").Value '媒体
                  Sh.Cells(n, 3).Value = .Cells(i, "l").Value '件数
               Else
                  Sh.Cells(n, 3).Value = Sh.Cells(n, 3).Value + .Cells(i, "l").Value '件数
               End If
               Sh.Cells(n, 4).Value = D(S)
               Sh.Cells(n, 5).Value = Sh.Cells(n, 3).Value * Sh.Cells(n, 4).Value
            End If
         Next
      End With
      Set D = Nothing
 End Sub
 (HM)

 こんなのでは?
 Dictionaryを使って集計を行っています

 Option Explicit

 Public Sub Sample()

    Dim i As Long
    Dim lngCount As Long
    Dim lngRows As Long
    Dim rngList1 As Range
    Dim rngList2 As Range
    Dim rngTable As Range
    Dim rngResult As Range
    Dim vntData As Variant
    Dim vntResult As Variant
    Dim vntKey As Variant
    Dim dicIndex As Object
    Dim strProm As String

    '箱サンプルの先頭セル位置を基準とする(先頭列の列見出し「記号」のセル位置)
    Set rngList1 = Worksheets("箱サンプル").Range("A2")

    '有料の先頭セル位置を基準とする(先頭列の列見出し「記号」のセル位置)
    Set rngList2 = Worksheets("有料").Range("A2")

    '単価マスタの先頭セル位置を基準とする(先頭列の列見出し「記号」のセル位置)
    Set rngTable = Worksheets("単価マスタ").Range("B2")

    '結果出力の先頭セル位置を基準とする(先頭列の列見出し「記号」のセル位置)
    Set rngResult = Worksheets("売上").Range("A1")

    'Dictionaryオブジェクトを取得
    Set dicIndex = CreateObject("Scripting.Dictionary")

    '単価マスタに就いて
    With rngTable
        '行数の取得
        lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows <= 0 Then
            strProm = "データが有りません"
            GoTo Wayout
        End If
        'B、C列データを配列に取得
        vntResult = .Offset(1).Resize(lngRows, 2).Value
        'I列データを配列に取得
        vntData = .Offset(1, 7).Resize(lngRows + 1).Value
    End With

    '結果用配列を作成
    ReDim Preserve vntResult(1 To lngRows, 1 To 6)
    'Dictionaryに「記号」「媒体名」をKeyとして登録し、「単価」を転記
    With dicIndex
        For i = 1 To lngRows
            '「単価」を転記
            vntResult(i, 4) = vntData(i, 1)
            '最終列Flagを代入
            vntResult(i, 6) = 0
            '「記号」「媒体名」を登録
            vntKey = vntResult(i, 1) & vbLf & vntResult(i, 2)
            If Not .Exists(vntKey) Then
                .Item(vntKey) = i
            End If
        Next i
    End With

    '箱サンプルデータを結果用配列に集計
    AddUp rngList1, vntResult, dicIndex

    '有料データを結果用配列に集計
    AddUp rngList2, vntResult, dicIndex

    '結果用配列の先頭行〜最終行まで
    For i = 1 To lngRows
        '結果用配列に「件数」が無い場合
        If IsEmpty(vntResult(i, 3)) Then
            '削除Flagを立てる
            vntResult(i, 6) = 1
            '削除行をカウント
            lngCount = lngCount + 1
        Else
            '「売上」を計算
            vntResult(i, 5) = vntResult(i, 3) * vntResult(i, 4)
        End If
    Next i

    If lngCount = lngRows Then
        strProm = "箱サンプルと有料にデータが有りません"
        GoTo Wayout
    End If

    '画面更新を停止
    Application.ScreenUpdating = False

    '売上シートに就いて
    With rngResult
        '元のデータをクリア
        .CurrentRegion.Offset(1).ClearContents
        '結果用配列を出力
        .Offset(1).Resize(lngRows, 6).Value = vntResult
        '削除FlagをKeyとして結果表を整列
        DataSort .Offset(1).Resize(lngRows, 6), .Offset(1, 5)
        '削除Flagが立っている行をクリア
        .Offset(lngRows - lngCount + 1).Resize(lngCount, 6).ClearContents
        '削除Flagをクリア
        .Offset(1, 5).EntireColumn.ClearContents
        '合計の数式を出力
        lngRows = lngRows - lngCount
        .Offset(lngRows + 1).Value = "合計"
        .Offset(lngRows + 1, 2).FormulaR1C1 = "=SUM(R[-" & lngRows & "]C:R[-1]C)"
        .Offset(lngRows + 1, 4).FormulaR1C1 = "=SUM(R[-" & lngRows & "]C:R[-1]C)"
    End With

    strProm = "処理が完了しました"

 Wayout:

    '画面更新を再開
    Application.ScreenUpdating = True

    Set dicIndex = Nothing
    Set rngList1 = Nothing
    Set rngList2 = Nothing
    Set rngTable = Nothing
    Set rngResult = Nothing

    MsgBox strProm, vbInformation

 End Sub

 Private Sub AddUp(rngList As Range, vntResult As Variant, dicIndex As Object)

    Dim i As Long
    Dim lngRows As Long
    Dim vntData As Variant
    Dim vntKey As Variant

    With rngList
        '行数の取得
        lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows <= 0 Then
            Exit Sub
        End If
        'I列データを配列に取得
        vntData = .Offset(1, 9).Resize(lngRows + 1, 3).Value
    End With

    'データを結果用配列に集計
    With dicIndex
        For i = 1 To lngRows
            '「記号」「媒体名」がEmptyで無いなら
            If Not IsEmpty(vntData(i, 1)) And Not IsEmpty(vntData(i, 2)) Then
                '「記号」「媒体名」でKeyを作成
                vntKey = vntData(i, 1) & vbLf & vntData(i, 2)
                If .Exists(vntKey) Then
                    '「件数」を集計
                    vntResult(.Item(vntKey), 3) = vntResult(.Item(vntKey), 3) + vntData(i, 3)
                End If
            End If
        Next i
    End With

 End Sub

 Private Sub DataSort(rngScope As Range, _
                    rngKey As Range, _
                    Optional lngSortOrder As Long = xlAscending, _
                    Optional lngOrientation As Long = xlTopToBottom)

    rngScope.Sort _
            Key1:=rngKey, Order1:=lngSortOrder, _
            Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
            Orientation:=lngOrientation, SortMethod:=xlStroke

 End Sub

 (Bun)


 (HM)様(Bun)様
 ありがとうございます。

 すみません、仕様変更がありました。
 データシート「箱サンプル」「有料」どちらのシートもなのですが、データをあるグループ毎に3〜4つの表に分けて記載するようになりました。
 (グループ分けの基準はその日の作業状況によるのでこれといった判断になるものがなく、入力する人がその都度グループ分けするとのこと)

 なので、例えば

   A   B   C   D  E   F   G  H  I  J   K   L
 1 SK作業                    合計
 2 記号 媒体名 件数    記号 媒体名 件数     記号 媒体名 件数
 3 SK1  KZ         SK2  KZ   2       SK  KZ   2
 4 SK1  MZ         SK2  MZ
 5 SK1  HY   82     SK2  HY   4       SK  HY   86
 6 SK1  FR   11     SK2  FR          SK  FR   11
 7 VA1  KK   1516    VA2  KK   224      VA  KK   1740
 8                                   SUM(L3:L7)
 9 記号 媒体名 件数    記号 媒体名 件数     記号 媒体名 件数
 10 VE1  KK   9     VE2  KK   4       VE  KK   13
 11 VS1  10P   6192    VS2  10P   672      VS  10P   6864
 12 VS3  10P   1008                  VS  10P   1008  

 このように途中に小計行&見出し行が入るようになります。
 後からすみません…
 なので、合計を判断する際に「J列が空白でない&"記号"という文字が入っていない」で条件分岐させたいのですが
 お二人のコードに自分で手を加えてみましたが「オブジェクト定義のエラーです」「型が一致しません」などのエラーが出ます。

 申し訳ございませんが、条件分岐をどのようにすればよいかお教えいただけないでしょうか。

 (peridot) 


 内容を一部修正しました。
 データ数が多い場合は、配列内処理等が必要かも・・・。

 Sub test2()
   Dim i&, j&, m&, n&, S$, Sh As Worksheet
   Dim D As Object, Sa, p&

      Set D = CreateObject("scripting.dictionary")
      Set Sh = Sheets("売上")

      With Sheets("単価マスタ") 'Dicへ単価セット
         For i = 3 To .Cells(.Rows.Count, "b").End(xlUp).Row
            S = .Cells(i, 2).Value & .Cells(i, 3).Value
            D(S) = .Cells(i, "i").Value
         Next
      End With

      m = 1: S = ""
      Sa = Array("箱サンプル", "有料")
      Sh.UsedRange.Offset(1).ClearContents
      For p = 0 To 1
         With Sheets(Sa(p)) 'Sheets("箱サンプル")
            For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row
               If .Cells(i, "j").Value <> "" And .Cells(i, "j").Value <> "記号" Then
                  S = .Cells(i, "j").Value & .Cells(i, "k").Value
                  If Not D.exists(S & "a") Then
                     m = m + 1
                     D(S & "a") = m '記入位置行番号
                  End If
                  n = D(S & "a")
                  If n > 0 Then
                     Sh.Cells(n, 1).Value = .Cells(i, "j").Value '記号
                     Sh.Cells(n, 2).Value = .Cells(i, "k").Value '媒体
                     Sh.Cells(n, 3).Value = Sh.Cells(n, 3).Value + .Cells(i, "l").Value '件数
                     Sh.Cells(n, 4).Value = D(S) '単価
                     Sh.Cells(n, 5).Value = Sh.Cells(n, 3).Value * Sh.Cells(n, 4).Value '売上
                  End If
               End If
            Next
         End With
      Next
      With Sheets("売上")
         i = .Cells(.Rows.Count, "a").End(xlUp).Row + 2
         .Cells(i, "c").Value = Application.Sum(.Columns(3)) '計
         .Cells(i, "e").Value = Application.Sum(.Columns(5)) '計
      End With
      Set D = Nothing
 End Sub

 私が列位置を勘違いして無ければ、全く元のコードのままで、修正無しで動くと思いますよ?

 (Bun)


 >このように途中に小計行&見出し行が入るようになります。
 >後からすみません…
 >なので、合計を判断する際に「J列が空白でない&"記号"という文字が入っていない」で条件分岐させたいのですが

 後、私のコードの場合は、単価表に無い「記号」「媒体」の組み合わせに就いては集計を蹴る様にしている筈なので、特に条件分岐をする必要は無いと思います

 (Bun)


 あ!、削除行が無いとエラーに成るのに気が付きました
 以下の★印の行を追加して下さい

    '売上シートに就いて
    With rngResult
        '元のデータをクリア
	・
	・
        '削除FlagをKeyとして結果表を整列
        DataSort .Offset(1).Resize(lngRows, 6), .Offset(1, 5)
        '★削除行が在ったなら
        If lngCount > 0 Then '★追加
            '削除Flagが立っている行をクリア
            .Offset(lngRows - lngCount + 1).Resize(lngCount, 6).ClearContents
        End If '★追加
        '削除Flagをクリア
        .Offset(1, 5).EntireColumn.ClearContents

 (Bun)


 (HM)様(Bun)様
 ありがとうございました!
 集計できました

 (peridot)

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.