Excel VBA質問箱 IV

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

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


22058 / 76734 ←次へ | 前へ→

【60061】Re:年間月別合計の出し方
発言  kanabun  - 09/1/26(月) 14:39 -

引用なし
パスワード
   ▼ひかる さん:
>▼kanabun さん:
>ご指摘いただきました解説をじっくりとみさせていただきました。
>最初よりだいぶ理解できたと思います。
>それで、この関連で最後の質問をさせてください。
>前のデータより次の表をうめる便利な方法があればお教えください。

あの、その方法を習得してもらうために、これまで長々とTry1()の解説
をして来たつもりなのですが?

ぼくは前々回のレスで、
> いちど、ひかるさんご自身で、ぼくがTry1()に対して行ったような解析
> (コードのトレース)を日本語で行ってみて、コードの各行が何をして
> いるものなのか、何をするためにこの一行があるのか、コメントをつけて
> 見てください。
と発言しました。
それに対して、ひかるさんは
> ▼kanabun さん:
> お返事ありがとうございます。
> 解析(コードのトレース)を日本語で行ってみて、コメントをつけてみます。
> また、コメントをつけたものをだしてみますので、添削のほど
> よろしくお願いします。
とおっしゃっていますから、ぼくはどのようなコメント付きコードが
出てくるか、楽しみにしていたのですよ。

◆要望 シート構成に 合わせて Try1() 〜 Try4() と同様のコードが
    空で(サンプルコードを見ないで)書けるようになるまで、
    反復練習してみてください。
もちろん、コードの意味が分からない部分があれば、時間のあるときに
お答えしますよ

>それで、この関連で最後の質問をさせてください。
別に期限があるわけではないので、閉じ急ぐ必要はさらさらないですよ。
Try1()〜 Try4() までの サンプルコードが理解でき、
ご自分で、↓のようなレイアウトのばあいに、それらを応用したコードが
試行錯誤しながらでも、書けるようになったときが、このスレッドを
終了するときです。

> 集計表                           単位:円
>    A     B     C      D     E  ........... K
> 1            4月     5月    6月  ...........12月  
> 2  大人   男
> 3       女
> 4  小人   男
> 5       女

'主に Sub Try4()を参考にして、上の集計表に合うように修正
していきます
'下に、サンプルコードを示します。
 現在の Sub Try5()をコピーしてモジュールに
 貼り付けると、たくさん 赤字になります。
 から、コメントにガイダンスがあるように
 空白部を実際のコードで埋めていってください。
'--------------------------------------------------
Option Explicit 'モジュールの先頭に宣言する(変数は必ず _
         宣言して使うため )

Sub Try5() '集計先のシートをアクティブにして実行
  Dim WS1 As Worksheet
  Dim WS2 As Worksheet
  Dim dic As Object
  Dim r As Range, c As Range
  Dim tbl
  Dim i As Long, ss As String
  Dim strFirst As String  '変数strRoomを変更
               '(集計シートのA列:大人/小人)
  Dim strSecond As String '集計シートのB列:男/女
  
  '抽出元の表のあるシートを変数WS1 にセットしてください
  Set WS1 = Worksheets("    ") 
  Set WS2 = ActiveSheet  'アクティブシート(集計表)
  '集計表シートがアクティブになっているか、確認する
  If WS2.Name = WS1.Name Then
    MsgBox "集計用シートをアクティブにして実行すること"
    Exit Sub '中断
  End If

'◆これより 集計表のレイアウトの取得
  '書きこみ先(集計表)表範囲を変数r にセットしてください
  Set r = WS2.             '書きこみ先表範囲
  Set r = Intersect( ,    ) 'そのうち、正味データ部を _
                  変数r に再代入してください
   '↑◆ヒント 上のような集計表構成では _
        [A1].CurrentRegion により変数rrに表全体範囲が _
        入っていますから、その範囲と、 _
        その範囲を1行下に、2列右にシフトした範囲 _
        とが重なる範囲を Intersectメソッドで取得すれば _
        いいです

  r.clearcontents  '行列見出しを除く正味データ部をクリア
  tbl = r.      'クリア後の範囲を配列に格納してください
        '↑◆ヒント RangeオブジェクトのValueプロパティ

  '---- 集計テーブルの情報を Dictionary に格納 -----
  '↓Dictionaryオブジェクトのインストール
                         ←
  'A列見出しと B列見出しを結合して 行位置(行index)を辞書に格納
  For Each c In r.Resize(, 1).Offset(, -1) 'B列見出し項目でLoop
    i = i + 1
    If Len(c(1, 0).Text) Then strFirst = c(1, 0).Text 'A列文字列
    dic(strFirst & c.Text) = i 
     'この処理で dic("大人男") に(行番号) 1 が、 _
           dic("大人女") に(行番号) 2 が、 _
           dic("小人女") に(行番号) 3 が、 _
           dic("小人女") に(行番号) 4 が格納されます
  Next
  Stop
  '上のLoopが終わったあと 変数strFirstには「小人」が格納されて _
   います。Stopはプログラムの実行を中断するための命令です。 _
   Stopしたら、メニュ−[表示]−[ローカルウィンドウ]で
   ローカルウィンドウをのぞいて 変数の内容を確かめてください。

  '次に ---------------------------------------------------
   '1行目見出し項目(◆年月)情報をdicに記憶しておきます
   'この部分は Try4()がそのまま使えると思います。
                         ←
   '--------------------------------------------------------
  '↓変数strSecond に集計表B列の見出し項目を記憶
  strSecond = WS2.range("B2").Value 'この例では「男」が代入 _
        されます。ステップ実行[F8]してこの行を実行したら _
        マウスを変数strSecond に近づけて 確認してください
  
  '---- 元表のA列×1行目の見出しに対応する 書きこみ先の _
    配列tblの 行列番号を Dictionaryから得る  -----
  Dim rr As Range, cc As Range
  Dim MonData, dat
  Dim FirstData 'B列またはC列格納用変数
  Dim SecondData 'B列またはC列格納用変数
  Dim j As Long, n As Long, m As Long
  Dim x As Long '◆見出し列位置(B列/C列)
  
'◆ここからが データ元表より抽出する部分です
  With WS1
    .Activate               'デバッグ用
    Set rr =        '変数rr に表範囲をセットする
  End With
  '例によって 元表の数値データ部分をとりだし、 _
    変数rr に再セットしてください
  Set rr = Intersect(rr,         )
   '◆ヒント 下のような元表構成では 表全体範囲rr と その範囲を _
        1行下に、3列右にシフトした範囲 とが重なる範囲です

>>>    A   B   C    D      E     F      G
>>>----------------------------------------------------------------------
>>>1  日付  利用者 性別  会議室   研修室   和室   調理室
>>>2  4月15日 大人   男   560    800    1000    500
>>>3  4月19日 小人   女   1500    600    5200    1500
>>>4  5月21日 大人   女   800    2000    800    2100
>>>5  5月31日 小人   女   5000    480    2500    600
>>>6  6月13日 小人   男   4500    3600    4800    1600
>>>7  6月18日 大人   女   100    3600    8400    2650
>>>8  6月21日 大人   男   7000    600    8000    7900

  '配列変数に A列日付データを格納してください
  MonData = rr.                 'A列
  
  '次に 元表のA,B列範囲から strFirst(具体的には「小人」)が _
   元表のどこにあるか調べます
  Set cc = rr.Offset(, -2).Resize(, 2)
  Set c = cc.Find(strFirst, , xlValues, xlWhole)
  If c Is Nothing Then
    MsgBox "第1項目の列取得に失敗しました" & vbCr _
       & " 元データシートの B,C列に <" & strSecond & _
       "> が見つかりませんでした"
    Exit Sub
  Else
    x = c.Column - 1
    MsgBox cc.Item(0, x).Value _
        & " の列を集計に使います"
    '見つかった列のデータを配列変数FirstData に格納します。
    'そのまま2次元配列(行, 列)として格納してもいいのですが、 _
     簡単のためTransposeで縦に並んだデータをよこにすると、 _
     一次元配列になります
    FirstData = Application.Transpose(cc.Columns(x))
  End If
  
  Set c = cc.Find(strSecond, , xlValues, xlWhole)
  If c Is Nothing Then
    MsgBox "第2項目の列取得に失敗しました" & vbCr _
       & " 元データシートの B,C列に <" & strSecond & _
       "> が見つかりませんでした"
    Exit Sub
  Else
    x = c.Column - 1
    MsgBox cc.Item(0, x).Value _
        & " の列を集計に使います"
    SecondData = Application.Transpose(cc.Columns(x))
  End If
  
  For i = 1 To UBound(MonData, 1) '日付のレコード順に
    dat = MonData(i, 1)
    If IsDate(dat) Then
      ss = Format$(dat, "yyyy/mm") '年月日を 年月に直す
      If dic.Exists(ss) Then
        m = dic(ss) '書きこみ先は 何列目か ?
        ss = FirstData(i) & SecondData(i)
        If dic.Exists(ss) Then
          n = dic(ss) '書きこみ先は 何行目か ?
          '↑ここまでは Try4()と同じです
          '↓集計のしかたが変わりました。 _
           これまでは一つのセルデータを集計先に累加 _
           していましたが、今回は i行のデータはすべて _
           SUM して、対象要素位置(n,m) に渡します。
       '------tblのn行,m列目の要素に 数量を累加 -----
          With Application
            tbl(n, m) = tbl(n, m) _
            + .Sum(.Index(rr.Rows(i).Value, 0))
          End With
        End If
      End If
    End If
  Next
  
  '---- 配列に集計した結果を表に書き出す ------
  r.Value = tbl
  WS2.Activate
  MsgBox "集計が終わりました"
End Sub

◆コードの穴埋めがおわりましたら、ここに報告してくださいね
7 hits

【59849】年間月別合計の出し方 ひかる 09/1/13(火) 20:39 質問
【59850】Re:年間月別合計の出し方 kanabun 09/1/13(火) 21:18 発言
【59855】Re:年間月別合計の出し方 ひかる 09/1/13(火) 22:47 質問
【59856】Re:年間月別合計の出し方 kanabun 09/1/14(水) 0:09 発言
【59857】Re:年間月別合計の出し方 kanabun 09/1/14(水) 0:15 発言
【59858】Re:年間月別合計の出し方 ひかる 09/1/14(水) 7:07 お礼
【59859】Re:年間月別合計の出し方 kanabun 09/1/14(水) 9:33 発言
【59886】Re:年間月別合計の出し方 ひかる 09/1/15(木) 16:07 質問
【59887】Re:年間月別合計の出し方 ひかる 09/1/15(木) 16:21 お礼
【59892】Re:年間月別合計の出し方 kanabun 09/1/15(木) 16:51 発言
【59949】Re:年間月別合計の出し方 ひかる 09/1/20(火) 18:29 質問
【59950】Re:年間月別合計の出し方 kanabun 09/1/20(火) 20:25 発言
【59954】Re:年間月別合計の出し方 ひかる 09/1/20(火) 21:35 質問
【59955】Re:年間月別合計の出し方 kanabun 09/1/20(火) 21:49 発言
【59956】Re:年間月別合計の出し方 ひかる 09/1/20(火) 22:09 質問
【59957】Re:年間月別合計の出し方 kanabun 09/1/20(火) 22:50 発言
【59958】Re:年間月別合計の出し方 kanabun 09/1/20(火) 23:04 発言
【59959】Re:年間月別合計の出し方 kanabun 09/1/20(火) 23:31 発言
【59960】Re:年間月別合計の出し方 ひかる 09/1/20(火) 23:42 お礼
【59981】Re:年間月別合計の出し方 ひかる 09/1/22(木) 12:02 お礼
【59983】Re:年間月別合計の出し方 ひかる 09/1/22(木) 12:52 質問
【59988】Re:年間月別合計の出し方 ひかる 09/1/22(木) 18:07 質問
【60025】Re:年間月別合計の出し方 kanabun 09/1/24(土) 10:35 発言
【60026】Re:年間月別合計の出し方 kanabun 09/1/24(土) 10:40 発言
【60036】Re:年間月別合計の出し方 ひかる 09/1/24(土) 19:18 お礼
【60054】Re:年間月別合計の出し方 ひかる 09/1/26(月) 11:50 質問
【60061】Re:年間月別合計の出し方 kanabun 09/1/26(月) 14:39 発言
【60097】Re:年間月別合計の出し方 ひかる 09/1/27(火) 12:42 お礼
【60105】Re:年間月別合計の出し方 kanabun 09/1/27(火) 15:56 発言
【60106】Re:年間月別合計の出し方 ひかる 09/1/27(火) 16:27 お礼
【59889】Re:年間月別合計の出し方 kanabun 09/1/15(木) 16:48 発言

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