|
UO3 さん:
こんばんは。非常に分かりやすいご回答ありがとうございます。返信遅くなって申し訳ありませんでした。
>効率は若干おちますが(といって、気にするレベルではありません)これを
>強制的に「10進演算」で処理した結果で取得するには、たとえば
>CDec関数を使います。
>Select Case CDec(t3 - Fix(t3))
>こうしますと、もとの Case 0.16 To 0.25 でもOKのはずです。
>お試しください。
早速、試してみましたが、完璧に計算してくれます。
前回アドバイス頂いたように実行した場合、一部計算できない部分があったのですが、CDecを使うと完璧に計算してくれますね。
>もし、データ開始行が 1行目あるいは2行目。で、データのある最後の行まで
>という仕様であれば、最後の行を動的にVBAで把握することができます。
>ただ、もしかしたら、本当に、固定されていない行から始まり、最後のデータ行の
>下に、別のデータがあって、その中で、時間データを抽出しなければいけないと
>いうことであれば、現在のコードでOKです。(Matchを使う手もありますが)
おっしゃる通り、固定されていない行から始まりますので現状のままと思いましたが、これもまたMatch関数を使うとすっきりしますね。使わせていただきたいと思います。
>ただ、念のための、有無をNothingかどうかでチェックしておられるところは
>いいのですが、なかった場合、メッセージを出すものの、
>For i = Gy1 + 1 To Gy2 - 1 以降の処理がされてしまいますね。
>メッセージ(2ヶ所)を出した後に、Exit Sub をいれておかれればよろしいかと。
ご指摘ありがとうございます。失念していました。
>実行のタイミングがWorksheet_SelectionChange。
>これはこれで、なかなか考えられた起動方法だなぁとも思いますが、
>たとえばシートのデータを変更するために、どこかのセルを選択するたびに
>実行されてしまいます。
>むしろ、普通のプロシジャとして標準モジュールに記述し、マクロショートカットキーで
>呼び出すなり、シートにボタンを配置して、そのクリックで起動するなりのほうが
>扱いやすいかもしれません。
ここもご指摘の通りと思いますが、総合的に判断して取り敢えず現状のままとしたいと思います。使用してみて不具合が発生した時は再考したいと思います。
>変数規定は、それを使う前に宣言すればいいわけですが、コードの可読性、保守性の
>観点から、コードの最初に集めておいたほうがよろしいですね。
ありがとうございます。
>また、インデントは「適切」につけないと、かえって可読性が悪くなります。
悩んだ末の指定だったのですが…なかなか難しいですね。
>Sub Sample()
> Dim Gy1 As Variant, Gy2 As Variant, i As Long
> Dim myH1 As Integer, myH2 As Integer, myS As Integer
> Dim myM1 As Integer, myM2 As Integer
> Dim T As Variant, t1 As Double, t2 As Double, t3 As Double, M As Double
> Dim myM As Integer
>
> Gy1 = Application.Match("最初", Columns("A"), 0)
> If Not IsNumeric(Gy1) Then
> MsgBox "最初の文字列がありません"
> Exit Sub
> Else
> Gy1 = Gy1 + 1
> End If
>
> Gy2 = Application.Match("最後", Columns("A"), 0)
> If Not IsNumeric(Gy2) Then
> MsgBox "最後の文字列がありません"
> Exit Sub
> Else
> Gy2 = Gy2 - 1
> End If
>
> For i = Gy1 To Gy2
>
> If WorksheetFunction.CountBlank(Range("A" & i & ":B" & i)) > 0 Then
> '検索範囲のA or B列が空白の場合は時数は空白とする
> Range(i, "C").ClearContents
ここの部分はLenを使って、4文字以外はClearContentsというものにしたいと思います。A、B列に時間を入力する際に、入力ミスで4桁以外の場合にエラーとなってしまうためです。
> Else
> myH1 = Mid(Cells(i, 1).Value, 1, 2) 'A列の「時」を取得
> myM1 = Mid(Cells(i, 1).Value, 3) 'A列の「分」を取得
> myH2 = Mid(Cells(i, 2).Value, 1, 2) 'B列の「時」を取得
> myM2 = Mid(Cells(i, 2).Value, 3) 'B列の「分」を取得
> myS = "00"
> t1 = TimeSerial(myH1, myM1, myS) 'A列の文字を時刻に変換する
> t2 = TimeSerial(myH2, myM2, myS) 'B列の文字を時刻に変換する
> t3 = (t2 - t1) * 24 'AからBの時間を計算する
> T = Int(t3)
>
> If t1 >= t2 Then 'B列よりもA列が大きいときは「エラー」と表示する
> Cells(i, 3) = "エラー"
> ElseIf t3 - Fix(t3) < 0 Then '「分」を四捨六入し、0.0時間表示する
> Cells(i, 3) = T
> Else
> Select Case CDec(t3 - Fix(t3))
> Case 0 To 0.05
> Cells(i, 3) = T
> Case 0.06 To 0.15
> Cells(i, 3) = T + 0.1
> Case 0.16 To 0.25
> Cells(i, 3) = T + 0.2
> Case 0.26 To 0.35
> Cells(i, 3) = T + 0.3
> Case 0.36 To 0.45
> Cells(i, 3) = T + 0.4
> Case 0.46 To 0.55
> Cells(i, 3) = T + 0.5
> Case 0.56 To 0.65
> Cells(i, 3) = T + 0.6
> Case 0.66 To 0.75
> Cells(i, 3) = T + 0.7
> Case 0.76 To 0.85
> Cells(i, 3) = T + 0.8
> Case 0.86 To 0.95
> Cells(i, 3) = T + 0.9
> Case 0.96 To 0.99
> Cells(i, 3) = T + 1
> End Select
> End If
> End If
> Next i
>End Sub
これを参考にもう一度自分なりに組み立ててみたいと思います。
貴重なお時間割いていただいて誠にありがとうございました。
またお時間がありましたらご指導いただければ幸いです。
|
|