Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


5751 / 13645 ツリー ←次へ | 前へ→

【49008】月別集計 hiro 07/5/20(日) 23:52 質問[未読]
【49016】Re:月別集計 Hirofumi 07/5/21(月) 7:43 発言[未読]
【49018】Re:月別集計 Hirofumi 07/5/21(月) 8:42 発言[未読]
【49049】Re:月別集計 Hirofumi 07/5/21(月) 19:49 回答[未読]
【49052】Re:月別集計 hiro 07/5/21(月) 21:27 お礼[未読]
【49056】Re:月別集計 hiro 07/5/21(月) 23:31 発言[未読]
【49058】Re:月別集計 Hirofumi 07/5/22(火) 0:39 回答[未読]
【49062】Re:月別集計 Hirofumi 07/5/22(火) 10:20 回答[未読]
【49063】Re:月別集計 hiro 07/5/22(火) 10:35 発言[未読]
【49075】Re:月別集計 Hirofumi 07/5/22(火) 15:19 発言[未読]
【49078】Re:月別集計 Hirofumi 07/5/22(火) 16:04 回答[未読]
【49079】Re:月別集計 Hirofumi 07/5/22(火) 16:06 回答[未読]
【49088】Re:月別集計 Hirofumi 07/5/22(火) 18:51 発言[未読]
【49089】Re:月別集計 hiro 07/5/22(火) 19:13 発言[未読]
【49091】Re:月別集計 Hirofumi 07/5/22(火) 19:53 回答[未読]
【49092】Re:月別集計 Hirofumi 07/5/22(火) 20:28 回答[未読]
【49094】Re:月別集計 hiro 07/5/22(火) 20:46 発言[未読]
【49095】Re:月別集計 Hirofumi 07/5/22(火) 21:35 回答[未読]
【49102】Re:月別集計 Hirofumi 07/5/23(水) 9:36 回答[未読]
【49114】Re:月別集計 hiro 07/5/23(水) 21:23 お礼[未読]
【49116】Re:月別集計 Hirofumi 07/5/23(水) 21:45 発言[未読]

【49008】月別集計
質問  hiro  - 07/5/20(日) 23:52 -

引用なし
パスワード
   以前オートフィルタについて教えて頂いた者です その節はまことにありがとうございました
またお聞きしたいのですが
日々データを下記のように入力しております

シート1(List1)
日付    店舗    項目    1係    2係    3係
20070401    本店    売上    1    1    1
20070401    本店    差益    2    2    2
20070401    本店    在庫    3    3    3
20070401    支店A    売上    4    4    4
20070401    支店A    差益    5    5    5
20070401    支店A    在庫    6    6    6
20070401    支店B    売上    7    7    7
20070401    支店B    差益    8    8    8
20070401    支店B    在庫    9    9    9
20070402    本店    売上    1    1    1
20070402    本店    差益    2    2    2
20070402    本店    在庫    3    3    3
20070402    支店A    売上    4    4    4
20070402    支店A    差益    5    5    5
20070402    支店A    在庫    6    6    6
20070402    支店B    売上    7    7    7
20070402    支店B    差益    8    8    8
20070402    支店B    在庫    9    9    9

これを月別・店別・項目別・係別で集計したいのですが
オートフィルタで可能でしょうか?
出力したい表は下記のレイアウトです(本店売上)
  A   B     C   D
1
2
3 係        4月  5月 
4    06年実績
5    07年目標 
6 01係 07年実績
7    前年比
8    達成率
9    06年実績
10    07年目標 
11 02係 07年実績
12    前年比
13    達成率

現在こちらのサイトで検索して似通ったサンプルがありましたので勝手ながら
使わして頂いております

Public Sub CrossTabulation()

  'データ列数(A列〜C列)
  Const clngColumns As Long = 3
 
  Dim i As Long
  Dim lngRows As Long
  Dim rngList As Range
  Dim vntData As Variant
  Dim rngResult As Range
  Dim rngDate As Range
  Dim rngScope As Range
  Dim lngColumn As Long
  Dim lngRow As Long
  Dim vntMonth As Variant
  Dim strProm As String
 
  'データListの左上隅セル位置を基準として設定(列見出しの「日付」セル位置)
  Set rngList = Worksheets("Sheet1").Cells(1, "A")
  With rngList
    'データ行数を取得
    lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
    'データが無い場合
    If lngRows <= 0 Then
      strProm = "データが有りません"
      GoTo Wayout
    End If
    'データを配列に取得
    vntData = .Offset(1).Resize(lngRows + 1, clngColumns).Value
  End With
 
  '結果出力シートのA1セルを基準とする(Listの左上隅)
  Set rngResult = Worksheets("Sheet2").Cells(1, "A")
  With rngResult
    '日付の書かれている列数を取得
    lngColumn = .Offset(, Columns.Count - _
              .Column).End(xlToLeft).Column - .Column
    '日付列の範囲を取得
    If lngColumn > 0 Then
      Set rngDate = .Offset(, 1).Resize(, lngColumn)
    End If
    '品名が有る行数を取得
    lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
    '品名が有る範囲を取得
    If lngRow > 0 Then
      Set rngScope = .Offset(1).Resize(lngRow)
    End If
  End With

  '画面更新を停止
  Application.ScreenUpdating = False
 
  'データの最終行まで繰り返し
  For i = 1 To lngRows
      '日付のシリアル値から月初の値を取得
      vntMonth = DateSerial(Year(vntData(i, 1)), Month(vntData(i, 1)), 1)
      '日付を探索
      lngColumn = GetColumnPos(vntMonth, rngDate, rngResult)
      '品名を探索
      lngRow = GetRowPos(vntData(i, 2), rngScope, rngResult)
      '日付、品名の交差するセルに値を書き込み
      With rngResult.Offset(lngRow, lngColumn)
        .NumberFormatLocal = "#,##0;""▲ ""#,##0"
        .Value = .Value + vntData(i, 3)
      End With
  Next i
 
  strProm = "処理が完了しました"
 'データListの左上隅セル位置を基準として設定(列見出しの「日付」セル位置)
  Set rngList = Worksheets("Sheet1").Cells(1, "A")
  With rngList
    'データ行数を取得
    lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
    'データが無い場合
    If lngRows <= 0 Then
      strProm = "データが有りません"
      GoTo Wayout
    End If
    'データを配列に取得
    vntData = .Offset(1).Resize(lngRows + 1, clngColumns).Value
  End With
 
  '結果出力シートのA1セルを基準とする(Listの左上隅)
  Set rngResult = Worksheets("Sheet2").Cells(12, "A")
  With rngResult
    '日付の書かれている列数を取得
    lngColumn = .Offset(, Columns.Count - _
              .Column).End(xlToLeft).Column - .Column
    '日付列の範囲を取得
    If lngColumn > 0 Then
      Set rngDate = .Offset(, 1).Resize(, lngColumn)
    End If
    '品名が有る行数を取得
    lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
    '品名が有る範囲を取得
    If lngRow > 0 Then
      Set rngScope = .Offset(1).Resize(lngRow)
    End If
  End With

  '画面更新を停止
  Application.ScreenUpdating = False
 
  'データの最終行まで繰り返し
  For i = 1 To lngRows
      '日付のシリアル値から月初の値を取得
      vntMonth = DateSerial(Year(vntData(i, 1)), Month(vntData(i, 1)), 1)
      '日付を探索
      lngColumn = GetColumnPos(vntMonth, rngDate, rngResult)
      '品名を探索
      lngRow = GetRowPos(vntData(i, 2), rngScope, rngResult)
      '日付、品名の交差するセルに値を書き込み
      With rngResult.Offset(lngRow, lngColumn)
        .NumberFormatLocal = "#,##0;""▲ ""#,##0"
        .Value = .Value + vntData(i, 4)
      End With
  Next i
 
Wayout:
 
  '画面更新を再開
  Application.ScreenUpdating = True
 
  Set rngList = Nothing
  Set rngResult = Nothing
  Set rngScope = Nothing
  Set rngDate = Nothing
 
  MsgBox strProm, vbInformation
 
End Sub

Private Function GetColumnPos(vntDate As Variant, _
                rngScope As Range, _
                rngDateTop As Range) As Long

  Dim lngFound As Long
  Dim lngOver As Long
  Dim lngCount As Long

  '日付範囲に日付が無いなら
  If rngScope Is Nothing Then
    lngFound = 0
    lngCount = 0
    lngOver = 1
  Else
    '日付の探索
    'セル値が数値として入力されている場合
    lngFound = DataSearch(CLng(vntDate), rngScope, lngOver)
    'セル値が文字列として入力されている場合
'    lngFound = DataSearch(vntDate, rngScope, lngOver)
    lngCount = rngScope.Columns.Count
  End If

  '日付が見つかった場合
  If lngFound > 0 Then
    '位置を返す
    GetColumnPos = lngFound
  Else
    With rngDateTop
      '日付が最終列の以内の場合
      If lngOver <= lngCount Then
        '指定位置に列を挿入
        .Offset(, lngOver).EntireColumn.Insert
      End If
      '日付を書き込み
      With .Offset(, lngOver)
        .NumberFormatLocal = "yyyy/m"
'        .NumberFormatLocal = "m""月"""
        .Value = vntDate
      End With
      '挿入位置を返す
      GetColumnPos = lngOver
      '日付列の範囲を更新
      Set rngScope = .Offset(, 1).Resize(, lngCount + 1)
    End With
  End If
  

End Function

Private Function GetRowPos(vntKey As Variant, _
            rngScope As Range, _
            rngListTop As Range) As Long

  Dim lngFound As Long
  Dim lngCount As Long

  '品名範囲に品名が無いなら
  If rngScope Is Nothing Then
    lngFound = 0
    lngCount = 0
  Else
    '品名を探索
    lngFound = DataSearch(vntKey, rngScope, , 0)
    lngCount = rngScope.Rows.Count
  End If

  '探索成功(品名が有るなら)
  If lngFound > 0 Then
    '位置を返す
    GetRowPos = lngFound
  Else
    With rngListTop
      '行末位置を更新
      lngCount = lngCount + 1
      'セルの書式を文字列に設定
      '(001の様な場合無いと探索が出来ない)
      .Offset(lngCount).NumberFormatLocal = "@"
      '行末に品名を書き込み
      .Offset(lngCount).Value = vntKey
      '挿入位置を返す
      GetRowPos = lngCount
      '探索範囲の更新
      Set rngScope = .Offset(1).Resize(lngCount)
    End With
  End If
 

End Function

Private Function DataSearch(vntKey As Variant, _
            rngScope As Range, _
            Optional lngOver As Long, _
            Optional lngMode As Long = 1) As Long

  Dim vntFind As Variant

  'Matchによる二分探索
  vntFind = Application.Match(vntKey, rngScope, lngMode)
  lngOver = 1
  'もし、エラーで無いなら
  If Not IsError(vntFind) Then
    'もし、Key値と探索位置の値が等しいなら
    If vntKey = rngScope(vntFind).Value Then
      '戻り値として、行位置を代入
      DataSearch = vntFind
    End If
    'Key値を超える最小値のある行
    lngOver = vntFind + 1
  End If


End Function

このコードで、店舗と項目を結合さして07年の1係の実績は表示できるのですが
店舗と項目を指定して1係〜30係まで月別集計を出力できるでしょうか
上記に示しました表は本店の売上を指定したときのレイアウトです
わかりにくい説明で申し訳ありません
よろしくお願いいたします

【49016】Re:月別集計
発言  Hirofumi  - 07/5/21(月) 7:43 -

引用なし
パスワード
   >出力したい表は下記のレイアウトです(本店売上)
>
>  A   B     C   D
>1
>2
>3 係        4月  5月 
>4    06年実績
>5    07年目標 
>6 01係 07年実績
>7    前年比
>8    達成率
>9    06年実績
>10    07年目標 
>11 02係 07年実績
>12    前年比
>13    達成率


>シート1(List1)
>日付    店舗    項目    1係    2係    3係
>20070401    本店    売上    1    1    1
>20070401    本店    差益    2    2    2
>20070401    本店    在庫    3    3    3
>20070401    支店A    売上    4    4    4
>20070401    支店A    差益    5    5    5
>20070401    支店A    在庫    6    6    6
>20070401    支店B    売上    7    7    7
>20070401    支店B    差益    8    8    8
>20070401    支店B    在庫    9    9    9
>20070402    本店    売上    1    1    1
>20070402    本店    差益    2    2    2
>20070402    本店    在庫    3    3    3
>20070402    支店A    売上    4    4    4
>20070402    支店A    差益    5    5    5
>20070402    支店A    在庫    6    6    6
>20070402    支店B    売上    7    7    7
>20070402    支店B    差益    8    8    8
>20070402    支店B    在庫    9    9    9


 List1の何処の項目を集計して、各係の「07年実績」、「前年比」、
「達成率」、「06年実績」、「07年目標」を出すのでですか?
その計算方法を提示して欲しいのですが?

【49018】Re:月別集計
発言  Hirofumi  - 07/5/21(月) 8:42 -

引用なし
パスワード
   もう一つ質問が有ります

「日付」列に就いてですが?
セルの値は、シリアル値を、セル書式「yyyymmdd」で表示させているのですか?
それとも、「20070401」と直接入力されているのですか?

また、「20070401」と直接入力されているのでしたら、セルの書式は、
文字列ですか?、数値ですか?

それと、「日付」列は、整列されていますか?
また、「日付」の範囲は?(例えば、4月〜翌年の3月迄とか?)

【49049】Re:月別集計
回答  Hirofumi  - 07/5/21(月) 19:49 -

引用なし
パスワード
   AdvancedFilterを使って店別・月別・項目別・係別で「売上」だけを集計しています
尚、日付は、1年分しか無い物としてコードを作っています
また、日付が、シリアル値の場合と「20070401」形式の場合でコードが違います
日付が、シリアル値の場合は、●印の下の行を活かして下さい
日付が、「20070401」形式の場合は、★印の下の行を活かして下さい
(Upのコードはコメントアウトして有ります)
集計結果は、店舗名のシートが有ればそれが使われますし、無い場合は作成されます
ただし、作成されると言っても、見出しが出力される程度でので、
予め、店舗名のシートを作って、罫線、書式等が有るならそれを設定して下さい

Option Explicit

Public Sub Sample()

  'List1の各緒言
  '◆List1のデータ列数(A列〜AG列)
  Const clngColumns As Long = 33
  '◆「1係」の列位置を指定(基準セル位置からの列Offset:基準がA1で「1係」がD列なら3)
  Const clngBegin As Long = 3
  '◆「日付」の列位置を指定(基準セル位置からの列Offset:基準がA1で「日付」がA列なら0)
  Const clngDate As Long = 0
  '◆「店舗」の列位置を指定(基準セル位置からの列Offset:基準がA1で「店舗」がB列なら1)
  Const clngStores As Long = 1
  '◆「項目」の列位置を指定(基準セル位置からの列Offset:基準がA1で「項目」がC列なら2)
  Const clngItem As Long = 2

  '出力シートの各緒言
  '◆出力基準位置を指定
  Const cstrResult As String = "A3"
  '◆先頭「01係」の行位置(上記の基準からの行Offset)
  Const clngNo As Long = 3

  Dim i As Long
  Dim j As Long
  Dim k As Long
  Dim lngTop As Long
  Dim lngRow As Long
  Dim lngColumn As Long
  Dim lngRows As Long
  Dim rngList As Range
  Dim rngResult() As Range
  Dim rngWork As Range
  Dim vntResult As Variant
  Dim vntStores As Variant
  Dim vntData As Variant
  Dim vntTitle As Variant
  Dim vntItems As Variant
  Dim lngMonth As Long
  Dim lngPitch As Long
  Dim lngCalc As Long
  Dim strProm As String

  '再計算の方法を保存
  lngCalc = Application.Calculation

  '◆Listの先頭セル位置を基準とする(列見出し「日付」のセル位置)
  Set rngList = Worksheets("List1").Cells(1, "A")

  '◆出力表の行見出しを設定
  vntTitle = Array("年実績", "前年比", "達成率", "年実績", "年目標")
  lngPitch = UBound(vntTitle) + 1

  With rngList
    '行数の取得
    lngRows = .CurrentRegion.Rows.Count - 1
    If lngRows <= 0 Then
      strProm = "データが有りません"
      GoTo Wayout
    End If
    vntData = .Offset(1, clngStores).Resize(lngRows + 1).Value
    ReDim vntStores(0)
    vntStores(0) = vntData(1, 1)
    For i = 2 To lngRows
      For j = 0 To UBound(vntStores)
        If vntData(i, 1) = vntStores(j) Then
          Exit For
        End If
      Next j
      If j > UBound(vntStores) Then
        ReDim Preserve vntStores(UBound(vntStores) + 1)
        vntStores(UBound(vntStores)) = vntData(i, 1)
      End If
    Next i
    Erase vntData
    vntItems = .Offset(, clngBegin).Resize(, clngColumns - clngBegin)
  End With

  With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
  End With

  '出力シートの存在確認
  ReDim rngResult(UBound(vntStores))
  For i = 0 To UBound(vntStores)
    If SheetExists(vntStores(i)) Then
      Set rngResult(i) = Worksheets(vntStores(i)).Range(cstrResult)
      With rngResult(i).Parent
        .Cells.ClearContents
        .Activate
      End With
    Else
      Set rngResult(i) = Worksheets.Add( _
                  After:=ActiveSheet).Range(cstrResult)
      rngResult(i).Parent.Name = vntStores(i)
    End If
  Next i

  '作業用シートを追加
  With Worksheets
    Set rngWork = .Add(After:=.Item(.Count)).Cells(1, "A")
  End With

  With rngWork
    rngList.Resize(, clngColumns).Copy Destination:=.Item(1)
    With .Offset(, clngColumns)
      .Offset(, 1).Value = rngList.Offset(, clngStores).Value
      .Offset(, 2).Value = rngList.Offset(, clngItem).Value
      .Offset(1, 2).Value = "売上"
    End With
    '「店舗」別にAdvancedFilterで、「売上」を抽出
    For i = 0 To UBound(vntStores)
      '店舗条件を出力
      .Offset(1, clngColumns + 1).Value = vntStores(i)
      DoFilter rngList.CurrentRegion, .Offset(, clngColumns _
              + 1).Resize(2, 2), .Resize(, clngColumns)
      lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
      If lngRows < 1 Then
        Exit For
      End If
      .Offset(1).Resize(lngRows, clngColumns).Sort _
        Key1:=.Offset(1), Order1:=xlAscending, _
        Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
        Orientation:=xlTopToBottom, SortMethod:=xlStroke
      vntData = .Offset(1).Resize(lngRows, clngColumns).Value
      ReDim vntResult(1 To (clngColumns - clngBegin) * lngPitch, 1 To 12)
      lngTop = 1
      '★月の値を取得(「20070401」形式の場合)
'      lngMonth = Val(Mid(vntData(lngTop, clngDate + 1), 5, 2))
      '●月の値を取得(シリアル値の場合)
      lngMonth = Month(vntData(lngTop, clngDate + 1))
      lngColumn = (lngMonth + 8) Mod 12 + 1
      For j = 1 To clngColumns - clngBegin
        lngRow = (j - 1) * lngPitch + 1
        vntResult(lngRow, lngColumn) = vntData(lngTop, clngBegin + j)
      Next j
      For j = 2 To lngRows
        '★月が違った場合(「20070401」形式の場合)
'        If Val(Mid(vntData(j, clngDate + 1), 5, 2)) <> lngMonth Then
        '●月が違った場合(シリアル値の場合)
        If Month(vntData(j, clngDate + 1)) <> lngMonth Then
          lngTop = j
          '★月の値を取得(「20070401」形式の場合)
'          lngMonth = Val(Mid(vntData(lngTop, clngDate + 1), 5, 2))
          '●月の値を取得(シリアル値の場合)
          lngMonth = Month(vntData(lngTop, clngDate + 1))
        End If
        lngColumn = (lngMonth + 8) Mod 12 + 1
        For k = 1 To clngColumns - clngBegin
          lngRow = (k - 1) * lngPitch + 1
          vntResult(lngRow, lngColumn) _
              = vntResult(lngRow, lngColumn) _
                  + vntData(lngTop, clngBegin + k)
        Next k
      Next j
      With rngResult(i)
        .Offset(clngNo, 2).Resize(UBound(vntResult, 1), _
                UBound(vntResult, 2)).Value = vntResult
        OutputTerminate .Item(1), vntItems, _
            Val(Left(vntData(1, clngDate + 1), 4)), vntTitle, clngNo
      End With
    Next i
    rngResult(0).Parent.Activate
  End With

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

Wayout:

  If Not rngWork Is Nothing Then
    Application.DisplayAlerts = False
    rngWork.Parent.Delete
    Application.DisplayAlerts = True
  End If

  With Application
    .Calculation = lngCalc
    .Calculate
    .ScreenUpdating = True
  End With

  Set rngWork = Nothing
  Set rngList = Nothing
  For i = 0 To UBound(rngResult)
    Set rngResult(i) = Nothing
  Next i

  MsgBox strProm, vbInformation

End Sub

Private Sub DoFilter(rngScope As Range, rngCriteria As Range, _
          rngCopyTo As Range)

  rngScope.AdvancedFilter _
      Action:=xlFilterCopy, _
      CriteriaRange:=rngCriteria, _
      CopyToRange:=rngCopyTo, _
      Unique:=False

End Sub

Private Function SheetExists(vntName As Variant) As Boolean

  Dim i As Long

  For i = 1 To Worksheets.Count
    If StrComp(Worksheets(i).Name, vntName, vbTextCompare) = 0 Then
      Exit For
    End If
  Next i
  If i <= Worksheets.Count Then
    vntName = Worksheets(i).Name
    SheetExists = True
  End If
      
End Function

Private Sub OutputTerminate(rngTop As Range, _
              vntName As Variant, _
              lngYear As Long, _
              vntTitle As Variant, _
              lngStart As Long)

  Dim i As Long
  Dim j As Long
  Dim lngPitch As Long
  Dim vntResult As Variant
  Dim vntTmp As Variant

  '出力ピッチを取得
  lngPitch = UBound(vntTitle) + 1

  '行見出し作成用の配列を作成
  ReDim vntResult(1 To UBound(vntName, 2) * lngPitch + lngStart, 1 To 2)
  vntResult(1, 1) = "係"
  vntResult(2, 2) = Right(CStr(lngYear - 1), 2) & vntTitle(0)
  vntResult(3, 2) = Right(CStr(lngYear), 2) & vntTitle(UBound(vntTitle))
  For i = 1 To UBound(vntName, 2)
    vntResult(lngStart + (i - 1) * lngPitch + 1, 1) = vntName(1, i)
    For j = 0 To UBound(vntTitle)
      vntTmp = vntTitle(j)
      Select Case j
        Case 0, lngPitch - 1
          vntTmp = Right(CStr(lngYear), 2) & vntTmp
        Case lngPitch - 2
          vntTmp = Right(CStr(lngYear - 1), 2) & vntTmp
      End Select
      vntResult(lngStart + (i - 1) * lngPitch + j + 1, 2) = vntTmp
    Next j
  Next i
  With rngTop
    '行見出しの出力
    .Resize(UBound(vntResult, 1), 2).Value = vntResult
    '列見出しの作成
    ReDim vntResult(11)
    For i = 0 To 11
      vntResult(i) = ((i + 3) Mod 12 + 1) & "月"
    Next i
    .Offset(, 2).Resize(, UBound(vntResult) + 1).Value = vntResult
    '算式の代入
    For i = 1 To UBound(vntName, 2)
      .Offset(lngStart + (i - 1) * lngPitch + 1, 2).Resize(, 12).FormulaR1C1 _
          = "=IF(R[2]C="""","""",ROUND(R[-1]C/R[2]C,2))"
      .Offset(lngStart + (i - 1) * lngPitch + 2, 2).Resize(, 12).FormulaR1C1 _
          = "=IF(R[2]C="""","""",ROUND(R[-2]C/R[2]C,4))"
    Next i
  End With

End Sub

【49052】Re:月別集計
お礼  hiro  - 07/5/21(月) 21:27 -

引用なし
パスワード
   ▼Hirofumi さん
返事がおそくなり大変失礼いたしました 只今帰宅し拝見いたしております
その前に以前はオートフィルターの件で大変御世話になりありがとうございました
そしてまた今回もご指導頂き感謝いたします
昨日は説明不足ですいません

List1には2007年4月1日〜2008年3月31日までの売上・差益・在庫・売上目標・差益目標と、2006年4月1日〜2007年3月31日までの売上・差益・在庫それを3店舗ずつ入力しております出力したいのは 売上の月別集計3店舗分
               差益の月別集計3店舗分の計6パターンです


本店売上      4月 5月 6月

   06年売上
   07年売上目標
01係 07年売上
   月前年比
   月達成率


本店差益
          4月 5月 6月

   06年差益
   07年差益目標
01係 07年差益
   月前年比
   月達成率

こんなレイアウトでそれぞれ30係まで出力したくおもております
説明不足ですいません
早速頂いたコード使わしていただきます
後ほどまた質問させてください

【49056】Re:月別集計
発言  hiro  - 07/5/21(月) 23:31 -

引用なし
パスワード
   >▼Hirofumi さん
頂いたコード実行さして頂きました
レイアウトは希望どおり出力できました ありがとうございます
でも集計の結果がなぜか12月の列に表示されてしまいます
データーは4月と5月を入力(2007年)して試してみました日付はすべて
20070401形式にしています
日にちの入力に問題があるのでしょか?

【49058】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 0:39 -

引用なし
パスワード
   >レイアウトは希望どおり出力できました ありがとうございます
>でも集計の結果がなぜか12月の列に表示されてしまいます
>データーは4月と5月を入力(2007年)して試してみました日付はすべて
>20070401形式にしています
>日にちの入力に問題があるのでしょか?

と在りますが?

1、12月の列に集計されるのは?
 たぶん、「日付」列が、シリアル値で入力されていて、
 セル書式に因って、表面ずらが20070401形式に成っている為だと思います
 List1の「日付」列の何れかのセルにセルポンタを移して、数式バーを
 見て下さい、「2007/4/1」の表示に成っていると思います
 因って、コード中の●印の下の行を活かし、
 ★印をコメントアウト若しくは、削除して見て下さい
 
2、「レイアウトは希望どおり出力できました ありがとうございます」と在りますが?
 hiroさん - 07/5/21(月) 21:27のレスと違いますが?
 どちらがほんと?
 また、データには、今年度の売上・差益・在庫・売上目標・差益目標、
 前年度の売上・差益・在庫が有り、今年度の売上目標の集計と、別表で、差益の集計も行うのですか?
3、3店舗に就いて、出力をシート単位としてますが、此れもこのままで善いのですか?

【49062】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 10:20 -

引用なし
パスワード
   Hirofumi - 07/5/21(月) 19:49 - のコードに間違いが有りましたので修正して下さい
「Public Sub Sample()」の中で

        lngColumn = (lngMonth + 8) Mod 12 + 1
        For k = 1 To clngColumns - clngBegin
          lngRow = (k - 1) * lngPitch + 1
'          vntResult(lngRow, lngColumn) _
'              = vntResult(lngRow, lngColumn) _
'                  + vntData(lngTop, clngBegin + k)
          vntResult(lngRow, lngColumn) _
              = vntResult(lngRow, lngColumn) _
                  + vntData(j, clngBegin + k) '★修正
        Next k
      Next j
      With rngResult(i)

【49063】Re:月別集計
発言  hiro  - 07/5/22(火) 10:35 -

引用なし
パスワード
   ▼Hirofumi さん
昨晩は遅くまでありがとうございました
大変失礼しました 削除する行を間違っていました
20070401形式でうまく集計できました すいません

> hiroさん - 07/5/21(月) 21:27のレスと違いますが?
> どちらがほんと?
レイアウトは頂いたコードの表で正解です

> また、データには、今年度の売上・差益・在庫・売上目標・差益目標、
> 前年度の売上・差益・在庫が有り、今年度の売上目標の集計と、別表で、差益の集計も行うのですか?
はい おっしゃるとおり売上で各店舗1枚ずつ 差益で各店舗一枚ずつ計6シート
作成する予定でした
差益の集計は頂いたコードを修正すればよいでしょうか?

ただできましたら2006年分(06年実績)と2007年の目標(07年目標)の集計もできれば
と、思っております
可能でしたらそちらも教えていただけますでしょうか
よろしくお願いいたします

【49075】Re:月別集計
発言  Hirofumi  - 07/5/22(火) 15:19 -

引用なし
パスワード
   >大変失礼しました 削除する行を間違っていました
>20070401形式でうまく集計できました すいません

結果的に、どちらの行を活かしたのですか?
それに因って、コードが大分違うのですが?

●印を使って上手くいくの?
★印を使って上手くいくの?

【49078】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 16:04 -

引用なし
パスワード
   店別・月別・項目別・係別で「2006年分(06年実績)と2007年の目標(07年目標)の集計も行いました
日付が、シリアル値の場合は、●印の下の行を活かして下さい
(Upのコードはコメントアウトして有ります)
日付が、「20070401」形式の場合は、★印の下の行を活かして下さい
ただし、「20070401」形式でもセルの書式が文字列の場合上手く行かないと思います
集計結果は、店舗名のシートが有ればそれが使われますし、無い場合は作成されます
また、売上表と差益表は同一シートに、売上表を上、差益表を下として作成されます、
ただし、作成されると言っても、見出しが出力される程度でので、
予め、店舗名のシートを作って、罫線、書式等が有るならそれを設定して下さい
尚、「Private Sub DoFilter」「Private Function SheetExists」「Private Sub OutputTerminate」
は、前のコードと同じ物を使います

Upしたコードを新規も標準モジュールに記述して、上記のプロシージャを同じ標準モジュールCopyして下さい

また、コードが長すぎるのでコメントは全て削除して有ります

【49079】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 16:06 -

引用なし
パスワード
   Option Explicit

Public Sub Sample2()

  Const clngColumns As Long = 33
  Const clngBegin As Long = 3
  Const clngDate As Long = 0
  Const clngStores As Long = 1
  Const clngItem As Long = 2

  '出力シートの各緒言
  Const cstrResult As String = "A3"
  Const clngNo As Long = 3
  Const clngBlock As Long = 163

  Dim i As Long, j As Long, k As Long, l As Long
  Dim lngRows As Long
  Dim rngList As Range
  Dim rngResult() As Range
  Dim rngWork As Range
  Dim vntResult As Variant
  Dim vntStores As Variant
  Dim vntData As Variant
  Dim vntTitle(1) As Variant
  Dim vntItems As Variant
  Dim lngMonth As Long
  Dim lngPitch As Long
  Dim vntYear As Long
  Dim vntCriteria(1) As Variant
  Dim vntOffset As Variant
  Dim lngCalc As Long
  Dim strProm As String

  lngCalc = Application.Calculation

  Set rngList = Worksheets("List1").Cells(1, "A")

  vntTitle(0) = Array("年実績", "前年比", _
          "達成率", "年実績", "年目標")
  vntTitle(1) = Array("年差益", "前年比", _
          "達成率", "年差益", "年目標")
  lngPitch = UBound(vntTitle(0)) + 1

  vntCriteria(0) = Array("売上", "売上", "売上目標")
  vntCriteria(1) = Array("差益", "差益", "差益目標")
  '出力行位置を設定
  vntOffset = Array(0, 3, 4)

  With rngList
    lngRows = .CurrentRegion.Rows.Count - 1
    If lngRows <= 0 Then
      strProm = "データが有りません"
      GoTo Wayout
    End If
    vntData = .Offset(1, clngStores).Resize(lngRows + 1).Value
    ReDim vntStores(0)
    vntStores(0) = vntData(1, 1)
    For i = 2 To lngRows
      For j = 0 To UBound(vntStores)
        If vntData(i, 1) = vntStores(j) Then
          Exit For
        End If
      Next j
      If j > UBound(vntStores) Then
        '無重複で取得している配列に店舗名を追加
        ReDim Preserve vntStores(UBound(vntStores) + 1)
        vntStores(UBound(vntStores)) = vntData(i, 1)
      End If
    Next i
    vntItems = .Offset(, clngBegin) _
        .Resize(, clngColumns - clngBegin)
    '最大の日付を取得
    vntYear = Application.Max(.Offset(1, _
            clngDate).Resize(lngRows))
    '★「20070401」形式の場合は下記を活かす
    vntYear = DateValue(Left(vntYear, 4) & "/" _
        & Mid(vntYear, 5, 2) & "/" & Right(vntYear, 2))
    If Month(vntYear) <= 3 Then
      vntYear = Year(vntYear) - 1
    Else
      vntYear = Year(vntYear)
    End If
  End With

  With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
  End With

  ReDim rngResult(UBound(vntStores))
  For i = 0 To UBound(vntStores)
    If SheetExists(vntStores(i)) Then
      Set rngResult(i) _
          = Worksheets(vntStores(i)).Range(cstrResult)
      With rngResult(i).Parent
        .Cells.ClearContents
        .Activate
      End With
    Else
      Set rngResult(i) = Worksheets.Add( _
            After:=ActiveSheet).Range(cstrResult)
      rngResult(i).Parent.Name = vntStores(i)
    End If
  Next i

  With Worksheets
    Set rngWork = .Add(After:=.Item(.Count)).Cells(1, "A")
  End With

  With rngWork
    rngList.Resize(, clngColumns).Copy Destination:=.Item(1)
    With .Offset(, clngColumns)
      'AdvancedFilter条件範囲の列見出しの出力
      .Offset(, 1).Value = rngList.Offset(, clngStores).Value
      .Offset(, 2).Value = rngList.Offset(, clngItem).Value
      .Offset(, 3).Resize(, 2).Value _
          = rngList.Offset(, clngDate).Value
    End With
    For i = 0 To UBound(vntStores)
      .Offset(1, clngColumns + 1).Value _
          = "=" & """=" & vntStores(i) & """"
      For j = 0 To 1
        ReDim vntResult(1 To (clngColumns _
            - clngBegin) * lngPitch, 1 To 12)
        For k = 0 To 2
          .Offset(1, clngColumns + 2).Value _
              = "=" & """=" & vntCriteria(j)(k) & """"
          If k = 0 Or k = 2 Then
            '●月の値を代入(シリアル値の場合)
'            .Offset(1, clngColumns + 3).Value = "=" & """>=" _
'                & CStr(CLng(DateSerial(vntYear, 4, 1))) & """"
'            .Offset(1, clngColumns + 4).Value = "=" & """<=" _
'                & CStr(CLng(DateSerial(vntYear + 1, 3, 31))) & """"
            '★月の値を代入(「20070401」形式の場合)
            .Offset(1, clngColumns + 3).Value = "=" & """>=" _
                & Format(DateSerial(vntYear, 4, 1), "yyyymmdd") & """"
            .Offset(1, clngColumns + 4).Value = "=" & """<=" _
                & Format(DateSerial(vntYear + 1, 3, 31), "yyyymmdd") & """"
          Else
            '●月の値を代入(シリアル値の場合)
'            .Offset(1, clngColumns + 3).Value = "=" & """>=" _
'                & CStr(CLng(DateSerial(vntYear - 1, 4, 1))) & """"
'            .Offset(1, clngColumns + 4).Value = "=" & """<=" _
'                & CStr(CLng(DateSerial(vntYear, 3, 31))) & """"
            '★月の値を代入(「20070401」形式の場合)
            .Offset(1, clngColumns + 3).Value = "=" & """>=" _
                & Format(DateSerial(vntYear - 1, 4, 1), "yyyymmdd") & """"
            .Offset(1, clngColumns + 4).Value = "=" & """<=" _
                & Format(DateSerial(vntYear, 3, 31), "yyyymmdd") & """"
          End If
          DoFilter rngList.CurrentRegion, .Offset(, _
              clngColumns + 1).Resize(2, 4), .Resize(, clngColumns)
          lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
          If lngRows >= 1 Then
            .Offset(1).Resize(lngRows, clngColumns).Sort _
                Key1:=.Offset(1), Order1:=xlAscending, _
                Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
                Orientation:=xlTopToBottom, SortMethod:=xlStroke
            vntData = .Offset(1).Resize(lngRows, clngColumns).Value
            '★月の値を取得(「20070401」形式の場合)
            lngMonth = Val(Mid(vntData(1, clngDate + 1), 5, 2))
            '●月の値を取得(シリアル値の場合)
'            lngMonth = Month(vntData(1, clngDate + 1))
            DataCalc vntResult, lngMonth, vntData, 1, _
                  clngColumns, lngPitch, clngBegin, vntOffset(k)
            For l = 2 To lngRows
              '★月が違った場合(「20070401」形式の場合)
              If Val(Mid(vntData(l, clngDate + 1), 5, 2)) <> lngMonth Then
              '●月が違った場合(シリアル値の場合)
'              If Month(vntData(l, clngDate + 1)) <> lngMonth Then
                '★月の値を取得(「20070401」形式の場合)
                lngMonth = Val(Mid(vntData(l, clngDate + 1), 5, 2))
                '●月の値を取得(シリアル値の場合)
'                lngMonth = Month(vntData(l, clngDate + 1))
              End If
              DataCalc vntResult, lngMonth, vntData, l, _
                    clngColumns, lngPitch, clngBegin, vntOffset(k)
            Next l
          End If
        Next k
        With rngResult(i)
          .Offset(clngNo + clngBlock * j, 2).Resize(UBound(vntResult, 1), _
                  UBound(vntResult, 2)).Value = vntResult
          OutputTerminate .Offset(clngBlock * j), vntItems, _
              vntYear, vntTitle(j), clngNo
        End With
      Next j
    Next i
    rngResult(0).Parent.Activate
  End With

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

Wayout:

  If Not rngWork Is Nothing Then
    Application.DisplayAlerts = False
    rngWork.Parent.Delete
    Application.DisplayAlerts = True
  End If

  With Application
    .Calculation = lngCalc
    .Calculate
    .ScreenUpdating = True
  End With

  Set rngWork = Nothing
  Set rngList = Nothing
  For i = 0 To UBound(rngResult)
    Set rngResult(i) = Nothing
  Next i

  MsgBox strProm, vbInformation
     
End Sub

Private Sub DataCalc(vntResult As Variant, lngMonth As Long, _
          vntData As Variant, lngPos As Long, _
          lngColumns As Long, lngPitch As Long, _
          lngBegin As Long, vntOffset As Variant)

  Dim i As Long
  Dim lngColumn As Long
  Dim lngRow As Long

  lngColumn = (lngMonth + 8) Mod 12 + 1
  For i = 1 To lngColumns - lngBegin
    lngRow = (i - 1) * lngPitch + 1 + vntOffset
    vntResult(lngRow, lngColumn) _
      = vntResult(lngRow, lngColumn) + vntData(lngPos, lngBegin + i)
  Next i

End Sub

【49088】Re:月別集計
発言  Hirofumi  - 07/5/22(火) 18:51 -

引用なし
パスワード
   コメントを殆ど削除してしまったので、何をやって居るのか解らないと思いますので?

まず以下は、パラメタの部分で適当に変更して下さい

  'List1の各緒言
  '◆List1のデータ列数(A列〜AG列)
  Const clngColumns As Long = 33
  '◆「1係」の列位置を指定(基準セル位置からの列Offset:基準がA1で「1係」がD列なら3)
  Const clngBegin As Long = 3
  '◆「日付」の列位置を指定(基準セル位置からの列Offset:基準がA1で「日付」がA列なら0)
  Const clngDate As Long = 0
  '◆「店舗」の列位置を指定(基準セル位置からの列Offset:基準がA1で「店舗」がB列なら1)
  Const clngStores As Long = 1
  '◆「項目」の列位置を指定(基準セル位置からの列Offset:基準がA1で「項目」がC列なら2)
  Const clngItem As Long = 2

  '出力シートの各緒言
  '◆出力基準位置を指定
  Const cstrResult As String = "A3"
  '◆先頭「01係」の行位置(上記の基準からの行Offset)
  Const clngNo As Long = 3
  '◆売上集計表と差益集計表の上下ピッチ
  Const clngBlock As Long = 163

  '◆Listの先頭セル位置を基準とする(列見出し「日付」のセル位置)
  Set rngList = Worksheets("List1").Cells(1, "A")

  '◆出力表の行見出しを設定
  vntTitle(0) = Array("年実績", "前年比", _
          "達成率", "年実績", "年目標")
  vntTitle(1) = Array("年差益", "前年比", _
          "達成率", "年差益", "年目標")

  '◆抽出条件を設定
  vntCriteria(0) = Array("売上", "売上", "売上目標")
  vntCriteria(1) = Array("差益", "差益", "差益目標")

次に、コードが行っている手順を簡単に説明して置きます

1、上記の種々の緒言設定を行っています
2、「With rngList」以下で、List1の各種のデータを集めます
 データListのデータ行数取得
 「店舗」全ての名称を取得(無重複で)
 「係」の列見出しを取得(作表時に行見出しを作成するのに使用)
 Listの最大の(最終の)日付を取得(この日付から、当年度の年を決めています)
3、「With Application」以下で、'画面更新の停止、再計算を手動へ(再計算の停止)を
 行っています
4、出力シート(各店舗名の付いたシート)を探し、有ればセルを全てクリアし
 無ければ、シートを追加して、シート名を店舗名に変更しています
5、「With Worksheets」以下で、作業用のシートを追加しています
 このシートに、AdvancedFilter(フィルタオプション)で必要データを抽出して行きます
6、追加したシートに、List1の列見出し(抽出範囲)、店舗、項目、日付(2列)を抽出条件範囲
 として、転記します
7、「For i = 0 To UBound(vntStores)」で店舗分のLoopを行います
8、上記iで指定された店舗名を抽出条件範囲に書き込みます
9、「For j = 0 To 1」のLoopで、売上集計と差益集計で2度回しています
10、結果出力用の配列を確保します(売上集計と差益集計で新規の配列を使う為)
11、「For k = 0 To 2」のLoopで当年実績、前年実績、目標を集計の順に集計を行います
12、抽出条件の「日付」に開始日と終了日を出力、「項目」に、売上集計の場合、
 "売上", "売上", "売上目標"のどれかkで決まった値を出力します
13、AdvancedFilterの実行を行い、作業シートにデータを抽出します
14、データの順序を念の為、揃える為に日付昇順で整列(ソート)を掛けます
15、此れを、月別、係別に結果出力用配列に集計を行います
16、集計を行った後、kが3回以内なら「11、」に戻り、
 超えた場合、Loopを抜け、結果を店舗(出力)シートに出力し、
 店舗(出力)シートに行列見出しと算式を出力します
17、「9、」に戻り、差益集計に掛ます
18、売上集計と差益集計が終わると、終了処理に成り、
 まず作業用シートを削除します
19、再計算の仕方を元に戻すし、再計算を実行し、画面更新を再開させます
20、終了と成ります

【49089】Re:月別集計
発言  hiro  - 07/5/22(火) 19:13 -

引用なし
パスワード
   ▼Hirofumi さん
お忙しいのにご足労かけてすいません
只今実行中なのですが、1係の06年実績と07年目標が表示されず 2係の06年実績と07年目標の欄にずれて表示されるのですが?ご指示どおりコードはcopyしたのですが
 Public Sub Sample2()

  Const clngColumns As Long = 33
  Const clngBegin As Long = 3
  Const clngDate As Long = 0
  Const clngStores As Long = 1
  Const clngItem As Long = 2

  '出力シートの各緒言
  Const cstrResult As String = "A3"
  Const clngNo As Long = 3
  Const clngBlock As Long = 163

  Dim i As Long, j As Long, k As Long, l As Long
  Dim lngRows As Long
  Dim rngList As Range
  Dim rngResult() As Range
  Dim rngWork As Range
  Dim vntResult As Variant
  Dim vntStores As Variant
  Dim vntData As Variant
  Dim vntTitle(1) As Variant
  Dim vntItems As Variant
  Dim lngMonth As Long
  Dim lngPitch As Long
  Dim vntYear As Long
  Dim vntCriteria(1) As Variant
  Dim vntOffset As Variant
  Dim lngCalc As Long
  Dim strProm As String

  lngCalc = Application.Calculation

  Set rngList = Worksheets("List1").Cells(1, "A")

  vntTitle(0) = Array("年実績", "前年比", _
          "達成率", "年実績", "年目標")
  vntTitle(1) = Array("年差益", "前年比", _
          "達成率", "年差益", "年目標")
  lngPitch = UBound(vntTitle(0)) + 1

  vntCriteria(0) = Array("売上", "売上", "売上目標")
  vntCriteria(1) = Array("差益", "差益", "差益目標")
  '出力行位置を設定
  vntOffset = Array(0, 3, 4)

  With rngList
    lngRows = .CurrentRegion.Rows.Count - 1
    If lngRows <= 0 Then
      strProm = "データが有りません"
      GoTo Wayout
    End If
    vntData = .Offset(1, clngStores).Resize(lngRows + 1).Value
    ReDim vntStores(0)
    vntStores(0) = vntData(1, 1)
    For i = 2 To lngRows
      For j = 0 To UBound(vntStores)
        If vntData(i, 1) = vntStores(j) Then
          Exit For
        End If
      Next j
      If j > UBound(vntStores) Then
        '無重複で取得している配列に店舗名を追加
        ReDim Preserve vntStores(UBound(vntStores) + 1)
        vntStores(UBound(vntStores)) = vntData(i, 1)
      End If
    Next i
    vntItems = .Offset(, clngBegin) _
        .Resize(, clngColumns - clngBegin)
    '最大の日付を取得
    vntYear = Application.Max(.Offset(1, _
            clngDate).Resize(lngRows))
    '★「20070401」形式の場合は下記を活かす
    vntYear = DateValue(Left(vntYear, 4) & "/" _
        & Mid(vntYear, 5, 2) & "/" & Right(vntYear, 2))
    If Month(vntYear) <= 3 Then
      vntYear = Year(vntYear) - 1
    Else
      vntYear = Year(vntYear)
    End If
  End With

  With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
  End With

  ReDim rngResult(UBound(vntStores))
  For i = 0 To UBound(vntStores)
    If SheetExists(vntStores(i)) Then
      Set rngResult(i) _
          = Worksheets(vntStores(i)).Range(cstrResult)
      With rngResult(i).Parent
        .Cells.ClearContents
        .Activate
      End With
    Else
      Set rngResult(i) = Worksheets.Add( _
            After:=ActiveSheet).Range(cstrResult)
      rngResult(i).Parent.Name = vntStores(i)
    End If
  Next i

  With Worksheets
    Set rngWork = .Add(After:=.Item(.Count)).Cells(1, "A")
  End With

  With rngWork
    rngList.Resize(, clngColumns).Copy Destination:=.Item(1)
    With .Offset(, clngColumns)
      'AdvancedFilter条件範囲の列見出しの出力
      .Offset(, 1).Value = rngList.Offset(, clngStores).Value
      .Offset(, 2).Value = rngList.Offset(, clngItem).Value
      .Offset(, 3).Resize(, 2).Value _
          = rngList.Offset(, clngDate).Value
    End With
    For i = 0 To UBound(vntStores)
      .Offset(1, clngColumns + 1).Value _
          = "=" & """=" & vntStores(i) & """"
      For j = 0 To 1
        ReDim vntResult(1 To (clngColumns _
            - clngBegin) * lngPitch, 1 To 12)
        For k = 0 To 2
          .Offset(1, clngColumns + 2).Value _
              = "=" & """=" & vntCriteria(j)(k) & """"
          If k = 0 Or k = 2 Then
            
            '★月の値を代入(「20070401」形式の場合)
            .Offset(1, clngColumns + 3).Value = "=" & """>=" _
                & Format(DateSerial(vntYear, 4, 1), "yyyymmdd") & """"
            .Offset(1, clngColumns + 4).Value = "=" & """<=" _
                & Format(DateSerial(vntYear + 1, 3, 31), "yyyymmdd") & """"
          Else
            
            '★月の値を代入(「20070401」形式の場合)
            .Offset(1, clngColumns + 3).Value = "=" & """>=" _
                & Format(DateSerial(vntYear - 1, 4, 1), "yyyymmdd") & """"
            .Offset(1, clngColumns + 4).Value = "=" & """<=" _
                & Format(DateSerial(vntYear, 3, 31), "yyyymmdd") & """"
          End If
          DoFilter rngList.CurrentRegion, .Offset(, _
              clngColumns + 1).Resize(2, 4), .Resize(, clngColumns)
          lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
          If lngRows >= 1 Then
            .Offset(1).Resize(lngRows, clngColumns).Sort _
                Key1:=.Offset(1), Order1:=xlAscending, _
                Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
                Orientation:=xlTopToBottom, SortMethod:=xlStroke
            vntData = .Offset(1).Resize(lngRows, clngColumns).Value
            '★月の値を取得(「20070401」形式の場合)
            lngMonth = Val(Mid(vntData(1, clngDate + 1), 5, 2))
           
            DataCalc vntResult, lngMonth, vntData, 1, _
                  clngColumns, lngPitch, clngBegin, vntOffset(k)
            For l = 2 To lngRows
              '★月が違った場合(「20070401」形式の場合)
              If Val(Mid(vntData(l, clngDate + 1), 5, 2)) <> lngMonth Then
             
                '★月の値を取得(「20070401」形式の場合)
                lngMonth = Val(Mid(vntData(l, clngDate + 1), 5, 2))
               
              End If
              DataCalc vntResult, lngMonth, vntData, l, _
                    clngColumns, lngPitch, clngBegin, vntOffset(k)
            Next l
          End If
        Next k
        With rngResult(i)
          .Offset(clngNo + clngBlock * j, 2).Resize(UBound(vntResult, 1), _
                  UBound(vntResult, 2)).Value = vntResult
          OutputTerminate .Offset(clngBlock * j), vntItems, _
              vntYear, vntTitle(j), clngNo
        End With
      Next j
    Next i
    rngResult(0).Parent.Activate
  End With

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

Wayout:

  If Not rngWork Is Nothing Then
    Application.DisplayAlerts = False
    rngWork.Parent.Delete
    Application.DisplayAlerts = True
  End If

  With Application
    .Calculation = lngCalc
    .Calculate
    .ScreenUpdating = True
  End With

  Set rngWork = Nothing
  Set rngList = Nothing
  For i = 0 To UBound(rngResult)
    Set rngResult(i) = Nothing
  Next i

  MsgBox strProm, vbInformation
  
End Sub

Private Sub DataCalc(vntResult As Variant, lngMonth As Long, _
          vntData As Variant, lngPos As Long, _
          lngColumns As Long, lngPitch As Long, _
          lngBegin As Long, vntOffset As Variant)

  Dim i As Long
  Dim lngColumn As Long
  Dim lngRow As Long

  lngColumn = (lngMonth + 8) Mod 12 + 1
  For i = 1 To lngColumns - lngBegin
    lngRow = (i - 1) * lngPitch + 1 + vntOffset
    vntResult(lngRow, lngColumn) _
      = vntResult(lngRow, lngColumn) + vntData(lngPos, lngBegin + i)
  Next i

End Sub

どこかまた私のミスでしょうかご点検お願いできますか
(20070401形式にしました)

【49091】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 19:53 -

引用なし
パスワード
   >只今実行中なのですが、1係の06年実績と07年目標が表示されず
>2係の06年実績と07年目標の欄にずれて表示されるのですが?
>ご指示どおりコードはcopyしたのですが

>どこかまた私のミスでしょうかご点検お願いできますか
>(20070401形式にしました)

当方で、hiroさんがUpされたコードを再度、Excelに取り込んで取り合えず試したのですが?
その様な現象は出ていませんね?

「ずれて表示される」とは、どのように成っているのでしょうか?
もう少し、詳しくお願いします

例えば、全ての店舗に就いて、4月〜3月までの「1係」が「2係」の欄にずれているのか?
この場合、「30係」の所もずれているのですか?
また、差益の集計表はどうなっていますか?

もしかして、出力位置のずれだとUpされたコードでは無く
コピーして下さいと言ったプロシージャかも解りませんので、
出力に関係するプロシージャを載せますので、此れに代えて見て下さい
(ただし、内容は全く変更していません)

Private Sub OutputTerminate(rngTop As Range, _
              vntName As Variant, _
              lngYear As Long, _
              vntTitle As Variant, _
              lngStart As Long)
  
  Dim i As Long
  Dim j As Long
  Dim lngPitch As Long
  Dim vntResult As Variant
  Dim vntTmp As Variant
  
  '出力ピッチを取得
  lngPitch = UBound(vntTitle) + 1
  
  '行見出し作成用の配列を作成
  ReDim vntResult(1 To UBound(vntName, 2) * lngPitch + lngStart, 1 To 2)
  vntResult(1, 1) = "係"
  vntResult(2, 2) = Right(CStr(lngYear - 1), 2) & vntTitle(0)
  vntResult(3, 2) = Right(CStr(lngYear), 2) & vntTitle(UBound(vntTitle))
  For i = 1 To UBound(vntName, 2)
    vntResult(lngStart + (i - 1) * lngPitch + 1, 1) = vntName(1, i)
    For j = 0 To UBound(vntTitle)
      vntTmp = vntTitle(j)
      Select Case j
        Case 0, lngPitch - 1
          vntTmp = Right(CStr(lngYear), 2) & vntTmp
        Case lngPitch - 2
          vntTmp = Right(CStr(lngYear - 1), 2) & vntTmp
      End Select
      vntResult(lngStart + (i - 1) * lngPitch + j + 1, 2) = vntTmp
    Next j
  Next i
  With rngTop
    '行見出しの出力
    .Resize(UBound(vntResult, 1), 2).Value = vntResult
    '列見出しの作成
    ReDim vntResult(11)
    For i = 0 To 11
      vntResult(i) = ((i + 3) Mod 12 + 1) & "月"
    Next i
    .Offset(, 2).Resize(, UBound(vntResult) + 1).Value = vntResult
    '算式の代入
    For i = 1 To UBound(vntName, 2)
      .Offset(lngStart + (i - 1) * lngPitch + 1, 2).Resize(, 12).FormulaR1C1 _
          = "=IF(R[2]C="""","""",ROUND(R[-1]C/R[2]C,2))"
      .Offset(lngStart + (i - 1) * lngPitch + 2, 2).Resize(, 12).FormulaR1C1 _
          = "=IF(R[2]C="""","""",ROUND(R[-2]C/R[2]C,4))"
    Next i
  End With
  
End Sub

【49092】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 20:28 -

引用なし
パスワード
   解りました、私のレイアウトの読み違いでした、ゴメン!!

  A  B      C    D
1
2
3 係        4月   5月 
4    06年実績
5    07年目標 
6 01係 07年実績 ←ここが、「1係」の先頭と思いました?
7    前年比
8    達成率
9    06年実績
10    07年目標 
11 02係 07年実績
12    前年比
13    達成率

対策を考えてみます

【49094】Re:月別集計
発言  hiro  - 07/5/22(火) 20:46 -

引用なし
パスワード
   ▼Hirofumi さん:
何度もすいません

>例えば、全ての店舗に就いて、4月〜3月までの「1係」が「2係」の欄にずれているのか?
すべての店舗でずれています
01係の06年実績と07年目標の2行が4月〜3月まで空白になります
30係りの項目の最後に2行(06年実績と07年目標)余分に入っています

    06年実績 29係の数値が表示されます
    07年目標 29係の数値が表示されます
30係    07年実績
    前年比
    達成率
    06年実績 30係の数値が表示されます  余分な行
    07年目標 30係の数値が表示されます 余分な行
以上のような現象になります
これでわかりますでしょうか?
よろしくお願いいたします

【49095】Re:月別集計
回答  Hirofumi  - 07/5/22(火) 21:35 -

引用なし
パスワード
   変更箇所を示します

1、「Public Sub Sample2」の中の

  '◆先頭「01係」の行位置(上記の基準からの行Offset)
'  Const clngNo As Long = 3
  Const clngNo As Long = 1 '★変更

  '◆出力表の行見出しを設定
'  vntTitle(0) = Array("年実績", "前年比", _
'          "達成率", "年実績", "年目標")
'  vntTitle(1) = Array("年差益", "前年比", _
'          "達成率", "年差益", "年目標")
  vntTitle(0) = Array("年実績", "年目標", "年実績", "前年比", "達成率") '★変更
  vntTitle(1) = Array("年差益", "年目標", "年差益", "前年比", "達成率") '★変更
  lngPitch = UBound(vntTitle(0)) + 1

'  vntOffset = Array(0, 3, 4)
  vntOffset = Array(2, 0, 1) '★変更

2、「Private Sub OutputTerminate」は全面変更の為、差し替え

'★プロシージャの全面変更
Private Sub OutputTerminate(rngTop As Range, _
              vntName As Variant, _
              lngYear As Long, _
              vntTitle As Variant, _
              lngStart As Long)
  
  Dim i As Long
  Dim j As Long
  Dim lngPitch As Long
  Dim vntResult As Variant
  Dim vntTmp As Variant
  
  '出力ピッチを取得
  lngPitch = UBound(vntTitle) + 1
  
  '行見出し作成用の配列を作成
  ReDim vntResult(1 To UBound(vntName, 2) * lngPitch, 1 To 2)
  For i = 1 To UBound(vntName, 2)
    vntResult(lngStart + (i - 1) * lngPitch + 2, 1) = vntName(1, i)
    For j = 0 To UBound(vntTitle)
      vntTmp = vntTitle(j)
      Select Case j
        Case 0
          vntTmp = Right(CStr(lngYear - 1), 2) & vntTmp
        Case 1, 2
          vntTmp = Right(CStr(lngYear), 2) & vntTmp
      End Select
      vntResult((i - 1) * lngPitch + j + 1, 2) = vntTmp
    Next j
  Next i
  
  With rngTop
    .Value = "係"
    '行見出しの出力
    .Offset(1).Resize(UBound(vntResult, 1), 2).Value = vntResult
    '列見出しの作成
    ReDim vntResult(11)
    For i = 0 To 11
      vntResult(i) = ((i + 3) Mod 12 + 1) & "月"
    Next i
    .Offset(, 2).Resize(, UBound(vntResult) + 1).Value = vntResult
    '算式の代入
    For i = 1 To UBound(vntName, 2)
      .Offset(lngStart + (i - 1) * lngPitch + 3, 2).Resize(, 12).FormulaR1C1 _
          = "=IF(R[-3]C="""","""",ROUND(R[-1]C/R[-3]C,2))"
      .Offset(lngStart + (i - 1) * lngPitch + 4, 2).Resize(, 12).FormulaR1C1 _
          = "=IF(R[-3]C="""","""",ROUND(R[-2]C/R[-3]C,4))"
    Next i
  End With
  
End Sub

【49102】Re:月別集計
回答  Hirofumi  - 07/5/23(水) 9:36 -

引用なし
パスワード
   多分、これで動くと思いますが?
一点、修正し忘れた部分と、使い方の部分で少し付け加えて置きます

1、修正し忘れた部分
 現状のList1(データ)のレイアウトで使うならこのままでも問題無いのですが?
 List1のレイアウト変更、同様な処理を違うListで行う場合に問題が出る可能性が
 有りますので修正して置いて下さい
 以下の部分で

          If lngRows >= 1 Then
            '抽出データを日付昇順で整列
'            .Offset(1).Resize(lngRows, clngColumns).Sort _
'                Key1:=.Offset(1), Order1:=xlAscending, _
'                Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
'                Orientation:=xlTopToBottom, SortMethod:=xlStroke
            .Offset(1).Resize(lngRows, clngColumns).Sort _
                Key1:=.Offset(1, clngDate), Order1:=xlAscending, _
                Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
                Orientation:=xlTopToBottom, SortMethod:=xlStroke
            '抽出データを配列に取得
            vntData = .Offset(1).Resize(lngRows, clngColumns).Value

 コメントアウトして有る方が現状で、下のコードが修正したコードです
 違いは、「Key1:=.Offset(1)」と成っている所を「Key1:=.Offset(1, clngDate)」としています
 元のコードでは、日付列が常にListの先頭列で有ることが条件で、列位置が固定に成っています
 コード本来の趣旨では、

  '◆「日付」の列位置を指定(基準セル位置からの列Offset:基準がA1で「日付」がA列なら0)
  Const clngDate As Long = 0

 ここで、「日付」列の変更が可能な様に成っていますので、
 ここを変更した場合それが反映される様にする修正です

2、使い方の部分
 現状は下記の様に成って居ると思いますが?

  '出力シートの各緒言
  '◆出力基準位置を指定
  Const cstrResult As String = "A3"
  '◆先頭「01係」の行位置(上記の基準からの行Offset)
  Const clngNo As Long = 1
  '◆売上集計表と差益集計表の上下ピッチ
  Const clngBlock As Long = 163

このパラメタは、出力される表の位置を制御している物なので、
 それぞれの値をいじってみて下さい
 例えば
  '◆出力基準位置を指定
  Const cstrResult As String = "B4"
 に変更すると、出力される表(売上集計表、差益集計表)の書き出し位置がB4からと成ります
 詰まり、前がA3で指定されていたのを、B4にすると各表は、1列右1行下に出力されます

 次に
  '◆先頭「01係」の行位置(上記の基準からの行Offset)
  Const clngNo As Long = 1
 多分、この値は変更しないと思いますが、此れを2にすると、
 列見出しと計算結果が1行ずれて表示されます(列見出しと結果の縦方向の微調整設定)

次に
  '◆売上集計表と差益集計表の上下ピッチ
  Const clngBlock As Long = 163
 ですが、現状設定して有る163の値は、売上集計表が、30係×5項目+1列見出し=151行と成ります
 これと、差益集計表の間に12行空白行を取って163行と言う意味です
 詰まり、30係の場合、表その物が151行で、取りたい空白行を足した値を設定して下さい
 ただ、30係の場合151以下の値を設定すると、表が重なるので注意して下さい

尚、集計結果は簡単に確認した積りですが、気が付かないバグが有る可能性も有りますので
そこら辺は、hiroさんが、よく確認を行って下さい

【49114】Re:月別集計
お礼  hiro  - 07/5/23(水) 21:23 -

引用なし
パスワード
   ▼Hirofumi さん:
お礼が遅くなりすいません
昨晩upして頂いたコードを実行さしていただきました 無事希望どおり集計できました 本日会社のpcでもテストいたしましたところ見事に成功いたしました。
オートフィルターやsumifなど自力で色々やってみましたが なかなかうまくいかずまたまた、こちらでHirofumi様の助けを頂き、改めて感謝いたします。
また、ご親切に
>2、使い方の部分
もご提示頂き助かります 若干のレイアウト修正を試みたく思いまして早速チャレンジしてみます。結果をまたご報告さしていただきます。
とりあえず、おそくなりましたが御礼申しあげます。貴重なお時間をさいて頂きありがとうございました。

【49116】Re:月別集計
発言  Hirofumi  - 07/5/23(水) 21:45 -

引用なし
パスワード
   後、書き忘れていましたが?
気を付ける事が有ります!!!
 このコードは、処理速度を上げる為、Excelの再計算モードを
コードが実行されると直に。手動再計算に切り替えます
 そして、終了直前に、再計算モードを元に戻しています
 通常、使っている分には、問題無いのですが?
デバグ、エラー其の他で、実行を途中で止めた時に
Excelの再計算モードが手動のままに成ってしまう事が有ります
 因って、中断で終了の時は、Excelのオプションで、
再計算の方法を確認して下さい、またその時、
通常、再計算の方法を「自動」で使用して居るなら「自動」に
設定し直してください

5751 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free