Excel VBA質問箱 IV

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

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


6947 / 13646 ツリー ←次へ | 前へ→

【42129】名指しでごめんなさい。Hirofumi さん、ご教授下さいませんでしょうか。 みなみ 06/9/2(土) 14:42 質問[未読]
【42138】Re:名指しでごめんなさい。Hirofumi さん、... Hirofumi 06/9/2(土) 18:00 回答[未読]
【42155】Re:名指しでごめんなさい。Hirofumi さん、... みなみ 06/9/3(日) 0:15 お礼[未読]
【42158】Re:名指しでごめんなさい。Hirofumi さん、... Blue 06/9/3(日) 2:07 回答[未読]
【42181】反省です・・・ みなみ 06/9/3(日) 22:09 お礼[未読]

【42129】名指しでごめんなさい。Hirofumi さん、...
質問  みなみ  - 06/9/2(土) 14:42 -

引用なし
パスワード
   みなさん、こんにちは。いつもありがとうございます。
 
[#41674]で時間の重なり分を除いた日ごとの合計を別シートに当てはめたいという質問をさせて頂きました、みなみです。

Hirofumiさんのご回答[#41684]を元に月末の集計を取らせて頂きました。
そこで、うまくいかない事があって、再度ご質問させて頂きたく思います。

この集計は夜勤をされる方の時間を計算する為に使用しています。

夜勤の方の勤務時間が15:00〜翌朝9:00で、その間に外出した時間を集計しています。

下記のように1行目が8/2の外出時間なんですが、2行目からは本来ならば0時を回っているので日付は8/3になりますよね。ですが、便宜上8/2集計としたいので、8/2と入力しています。


    A    B   C   
1 2006/8/2  23:45 0:52   (67)
2 2006/8/2   0:01 0:56   (55) 
3 2006/8/2   1:01 1:11   (10) 

ですので、上記の重なり除去した計算結果を、sheet2の2日の欄に81分と記載したいのです。

15時を基準にして0:00から14:59までならば8/2とみなす、
つまり、1日を0:00〜0:00の24時間ではなく、15:00〜15:00の24時間としたいんです。

どうかご教授頂けませんでしょうか。
本当にお願いばかりで申し訳ありません。
宜しくお願いいたします。

【42138】Re:名指しでごめんなさい。Hirofumi さん...
回答  Hirofumi  - 06/9/2(土) 18:00 -

引用なし
パスワード
   此れで、集計出きると思います?
ただし
>15時を基準にして0:00から14:59までならば8/2とみなす、
>つまり、1日を0:00〜0:00の24時間ではなく、15:00〜15:00の24時間としたいんです。
この様な計算方法は取っていません(計算が縺れそうだし?)
データの補正で対応しています

Option Explicit

Public Sub Sample2()

  'データ列数
  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 vntResult As Variant
  Dim lngTop As Long
  Dim lngCount As Long
  Dim strProm As String
  
  'Listの左上隅セル位置を基準として設定
  Set rngList = Worksheets("Sheet1").Cells(1, "A")
  
  '出力先の先頭セル位置を出力基準とします
  Set rngResult = Worksheets("Sheet2").Cells(1, "B")
  
  With rngList
    'データ行数を取得
    lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row + 1
    'データが無い場合
    If lngRows <= 1 And .Value = "" Then
      strProm = "データが有りません"
      GoTo Wayout
    End If
    'データを配列に取得
    vntData = .Resize(lngRows + 1, clngColumns).Value
  End With
  
  '結果出力用配列を確保
  ReDim vntResult(1 To 31, 1 To 1)
  
  '先頭データを初期値とする
  lngTop = 1
  lngCount = 1
  'データ2行目〜最終行+1まで繰り返し
  For i = 2 To lngRows + 1
    '日付が替わった場合
    If vntData(lngTop, 1) <> vntData(i, 1) Then
      '1日分の時間を計算(シリアル値の場合)
'      vntResult(vntData(lngTop, 1), 1) _
          = DayTimes(vntData, lngTop, lngTop + lngCount - 1)
      '1日分の時間を計算(70分なら70と表示する場合)
      vntResult(vntData(lngTop, 1), 1) _
          = Int(DayTimes(vntData, lngTop, _
              lngTop + lngCount - 1) * 24 * 60 + 0.5)
      'この行を先頭に
      lngTop = i
      'カウントを初期値に
      lngCount = 1
    Else
      'カウントを更新
      lngCount = lngCount + 1
    End If
  Next i
  
  '画面更新を停止
  Application.ScreenUpdating = False
  
  '結果を出力
  With rngResult.Resize(UBound(vntResult, 1))
    'セル書式設定(シリアル値の場合)
'    .NumberFormat = "[mm]"
    .Value = vntResult
  End With
  
  strProm = "処理が完了しました"
  
Wayout:
  
  '画面更新を再開
  Application.ScreenUpdating = True
  
  Set rngList = Nothing
  Set rngResult = Nothing
  
  MsgBox strProm, vbInformation
  
End Sub

Private Function DayTimes(vntData As Variant, _
              lngTop As Long, _
              lngEnd As Long) As Double

  '集計配列の行数
  Const clngRowsCount As Long = 3
  
  Dim i As Long
  Dim j As Long
  Dim vntResult As Variant
  
  'データの補正(ブロック先頭開始より各時刻が小さい場合、翌日の時間とする)
  'ブロック先頭開始よりブロック先頭終了時刻が小さい場合、翌日の時間とする
  If vntData(lngTop, 2) > vntData(lngTop, 3) Then
    vntData(lngTop, 3) = vntData(lngTop, 3) + 1
  End If
  'ブロック全てに就いて繰り返し
  For i = lngTop + 1 To lngEnd
    'ブロック先頭開始より現在行開始時刻が小さい場合、翌日の時間とする
    If vntData(lngTop, 2) > vntData(i, 2) Then
      vntData(i, 2) = vntData(i, 2) + 1
    End If
    '開始より頭終了時刻が小さい場合、翌日の時間とする
    If vntData(i, 2) > vntData(i, 3) Then
      vntData(i, 3) = vntData(i, 3) + 1
    End If
  Next i
  
  '時間の重なりを除去したデータの配列を作成
  '1日の集計配列ブロック数
  j = 1
  '集計用配列を確保
  ReDim vntResult(1 To clngRowsCount, 1 To j)
  '初期値を集計用配列に代入
  vntResult(1, j) = vntData(lngTop, 2)
  vntResult(2, j) = vntData(lngTop, 3)
  '2ブロック目〜最終ブロックまで繰り返し
  For i = lngTop + 1 To lngEnd
    'データ配列の開始が、集計配列の終了より大きい場合(重なりが無い場合)
    If vntData(i, 2) > vntResult(2, j) Then
      '集計配列のブロック数を拡張
      j = j + 1
      ReDim Preserve vntResult(1 To clngRowsCount, 1 To j)
      '集計配列の開始にデータ配列の開始時間を代入
      vntResult(1, j) = vntData(i, 2)
      '集計配列の終了にデータ配列の終了時間を代入
      vntResult(2, j) = vntData(i, 3)
    Else
      '集計配列の開始よりデータ配列の開始が大きい場合
      If vntResult(1, j) <= vntData(i, 2) Then
        '集計配列の終了よりデータ配列の終了が大きい場合(重なりが有る場合)
        If vntResult(2, j) < vntData(i, 3) Then
          '集計配列の終了にデータ配列の終了を代入
          vntResult(2, j) = vntData(i, 3)
        End If
      End If
    End If
  Next i
  
  '1日の時間(分)を集計
  j = j + 1
  ReDim Preserve vntResult(1 To clngRowsCount, 1 To j)
  For i = 1 To j - 1
    vntResult(3, i) = vntResult(2, i) - vntResult(1, i)
    vntResult(3, j) = vntResult(3, j) + vntResult(3, i)
  Next i
  
  DayTimes = vntResult(3, j)
  
End Function

【42155】Re:名指しでごめんなさい。Hirofumi さん...
お礼  みなみ  - 06/9/3(日) 0:15 -

引用なし
パスワード
   ▼Hirofumi さん:
こんばんは。みなみです。
すばやいご回答、本当にありがとうございます。
1を足して、時間ののシリアル値を次の日に変更されているんですね。

こうやって、一つ一つに説明を入れて下さっているので、本当わかりやすいです。
家では出来ましたので、月曜に会社で試させていただきます。

質問ついでといっては何ですが、変数のvnt ing strは何の頭文字なんですか?
変なところに興味がいっちゃってごめんなさい。
お暇があれば教えてください。

【42158】Re:名指しでごめんなさい。Hirofumi さん...
回答  Blue  - 06/9/3(日) 2:07 -

引用なし
パスワード
   Hirofumi さんではありませんが。。。

▼みなみ さん:
>質問ついでといっては何ですが、変数のvnt ing strは何の頭文字なんですか?
>変なところに興味がいっちゃってごめんなさい。
>お暇があれば教えてください。
変数の型を表す接頭辞です。
ハンガリアン記法と呼ばれるものです。
Google検索結果:http://www.google.com/search?num=50&hl=ja&q=%E3%83%8F%E3%83%B3%E3%82%AC%E3%83%AA%E3%82%A2%E3%83%B3%E8%A8%98%E6%B3%95&lr=lang_ja

ただ、一般的にはハンガリアンはあまりよくないと呼ばれています。
参考スレッド:http://oshiete1.goo.ne.jp/kotaeru.php3?q=1427562

私は、なるべく使わないように気をつけています。
(仕事でやっているC/C++ではコーディング規約でハンガリアンを使っていますが。)

ちなみに、名指しでの質問はあまりやらないほうが良いです。
指名されたほうは、解答しなければいけないという気にさせられます。
(回答するかしないかは、自由ですから)
また、指名された人以外が回答とつけにくくなります。
ついでに、表題は質問内容を表すようにしたほうが良いです。
それに対して自分の意見は本文に書くようにしましょう。

【42181】反省です・・・
お礼  みなみ  - 06/9/3(日) 22:09 -

引用なし
パスワード
   ▼Blue さん:
こんばんは。みなみです。

私も名指しでは駄目だろう・・・と散々悩みました。
基本ポリシーにある助けてくださいや、わかりませんなどの「タイトルは内容を示すものに」にも違反するだろうとも思いました。

ですが、[#41674]で時間の重なり分を除いた日ごとの合計を別シートに当てはめたいという質問をさせて頂き、回答を頂いたHirofumiさんの式に対して皆さんに聞くのもマナー違反なのかな・・・と思ってしまい、結果としてこういう質問の仕方になってしまいました。

そうですよね、ご指摘のとおり、本文に書けばよかったんですよね。

皆さんのご好意で、助け合いで成り立っている掲示板ですもの、私だけっていうスタンスでは駄目ですよね。

以後気をつけたいと思います。
ありがとうございました。


最後に、Hirofumiさん、すみませんでした。

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