Tính thời gian làm việc thực tế

Liên hệ QC
Mình nói rõ thêm là Giờ định mức ấy có thể là : 10 ph ,15 ph , ... 30 ph,35 ph...1 g ,..
Em mày mò gần xong rồi, nhưng chỉ tính giờ định mức là bội số của 30 phút thôi... theo cái ví dụ ban đầu của bác. Giờ nghe bác nói vầy... oải quá!
 
Xin lỗi do nói chưa rõ ràng , nhưng các bạn đã làm bội số 30 được thì bội số cho 1 hoặc 5 chắc là không khó . Còn định dạng thì mình có thể đổi qua lại được mà .
 
PHP:
Xin lỗi do nói chưa rõ ràng , nhưng các bạn đã làm bội số 30 được thì bội số cho 1 hoặc 5 chắc là không khó . Còn định dạng thì mình có thể đổi qua lại được mà .
Bác cụ thể cho em một ví dụ. Và quan trọng là Định mức công việc(g) Bác nhập theo dạng gì. 1.5h hay là 1:30' hay 1.2h hay là 1:12'. Bác sửa trong UDF của em thay block =1 xem thử nhưng mà sẽ chậm vì step 1'
Bác sử dụng code sau thử.
PHP:
Function EndTime(NgayDau As Variant, SoPhut As Double)
Dim NgayCuoi As Variant, iPhut As Double, Block As Long
On Error Resume Next
SoPhut = Round(SoPhut * 60, 0) 'xem lai neu 1h5' thi nhap so the nao'
If Weekday(NgayDau) = 1 Then Exit Function 'xem lai cac dieu kien ve t7, CN'
If Not IsDate(NgayDau) Then Exit Function
Block = 1
If SoPhut = 0 Then
    EndTime = NgayCuoi
    Exit Function
End If
iPhut = Block
Do While Not iPhut = SoPhut + Block
    NgayCuoi = DateAdd("n", Block, NgayDau)
        If Weekday(NgayDau) <> 7 And Hour(NgayCuoi) = 11 And Minute(NgayCuoi) = 30 Then
            NgayDau = DateAdd("n", 120, NgayCuoi)
        ElseIf Weekday(NgayDau) <> 7 And Hour(NgayCuoi) = 17 And Minute(NgayCuoi) = 0 Then
             NgayDau = DateAdd("n", 14 * 60 + 30, NgayCuoi)
        ElseIf Weekday(NgayDau) = 7 And Hour(NgayCuoi) = 11 And Minute(NgayCuoi) = 30 Then
             NgayDau = DateAdd("n", 44 * 60, NgayCuoi)
        Else
            NgayDau = NgayCuoi
        End If
        iPhut = iPhut + Block
Loop
EndTime = NgayCuoi
End Function
 
Lần chỉnh sửa cuối:
Ok ,chậm không đáng kể
 
Cho em góp vui 1 đoạn code, ko rõ có đúng không mong các bác kiểm tra lại giúp. Trong code em chưa kiểm tra trường hợp người dùng nhập vào giá trị không hợp lệ :)
Mã:
Function GetEndTime(BatDau, ThoiGian)
    Dim SoTuan, SoNgay, ret, ThoiGianCon
    
    Dim ThoiGianTemp
    ThoiGianTemp = TimeSerial(Hour(BatDau), Minute(BatDau), 0)
    If ThoiGianTemp > TimeSerial(13, 30, 0) Then
        ThoiGianTemp = TimeSerial(4, 0, 0) + TimeSerial(13, 30, 0) - ThoiGianTemp
    Else
        ThoiGianTemp = ThoiGianTemp - TimeSerial(7, 30, 0)
    End If
    ThoiGian = ThoiGian + Hour(ThoiGianTemp) + Minute(ThoiGianTemp) / 60
    
    BatDau = DateSerial(Year(BatDau), Month(BatDau), Day(BatDau)) + TimeSerial(7, 30, 0)
    
    SoTuan = ThoiGian \ 41.5
    ThoiGianCon = ThoiGian - SoTuan * 41.5
    ret = BatDau + SoTuan * 7
    Do While (Weekday(ret) <> 7 And ThoiGianCon >= 7.5) Or (Weekday(ret) = 7 And ThoiGianCon >= 4)
        ThoiGianCon = ThoiGianCon - 4
        If Weekday(ret) < 7 Then ThoiGianCon = ThoiGianCon - 3.5
        If ThoiGianCon = 0 Then Exit Do
        ret = ret + 1
        If Weekday(ret) = 1 Then ret = ret + 1
    Loop
    If ThoiGianCon = 0 Then
        ret = ret + TimeSerial(4, 0, 0)
        If Weekday(ret) <> 7 Then ret = ret + TimeSerial(5, 30, 0)
    ElseIf ThoiGianCon > 4 Then
        ThoiGianCon = ThoiGianCon - 4
        ret = ret + TimeSerial(Int(ThoiGianCon), (ThoiGianCon - Int(ThoiGianCon)) * 60, 0) + TimeSerial(6, 0, 0)
    Else
        ret = ret + TimeSerial(Int(ThoiGianCon), (ThoiGianCon - Int(ThoiGianCon)) * 60, 0)
    End If
    GetEndTime = ret
End Function
 

File đính kèm

  • Time.xls
    25.5 KB · Đọc: 13
Xin gửi lên bài giải của em. Hoàn toàn bằng công thức.
Nhưng đơn vị thời gian nhỏ nhất là mỗi 30 phút. Em không thể làm với thời gian nhỏ hơn...
Nhờ các bác kiểm tra dùm xem có sai ở đâu nữa không.
 

File đính kèm

  • DMTgian ver1.3.xls
    33 KB · Đọc: 26
Cho em góp vui 1 đoạn code, ko rõ có đúng không mong các bác kiểm tra lại giúp. Trong code em chưa kiểm tra trường hợp người dùng nhập vào giá trị không hợp lệ :)
Bạn rollover79 xem thử nha:
Công thức của bạn bị sai khi số thời gian định mức = 41.5
Ví dụ:
  • Ngày 05/1/2009, bắt đầu lúc 7 giờ 30, định mức 41 tiếng -- Kết quả: 11 giờ ngày 10/1/2009 (đúng)
  • Tăng định mức thêm nửa tiếng, nghĩa là kết quả cũng phải tăng nửa tiếng (11 giờ 30 ngày 10/1/2009), nhưng UDF của bạn ra 17 giờ ngày 12/1/2009 !
  • Tăng thêm nửa tiếng nửa, kết quả là 8 giờ ngày 12/1/2009: Đúng!

-----------------------------
Em tính test luôn cái của anh Thu Nghi, nhưng nó chạy chậm quá anh ơi, không kiên nhẫn nổi...
 
Lần chỉnh sửa cuối:
Cảm ơn bác BNTT, test nhiều trường hợp mà quên mất trường hợp làm chẵn tuần và thời gian bắt đầu là 7h:30. Xin sửa lại code như sau các bác test tiếp xem còn lỗi nào không nhé.
Với cách của bác ThuNghi mà khi dữ liệu lớn hoặc nhiều thì không ổn về mặt tốc độ, vì bác dùng vòng For với step là 1 phút nên tốc độ sẽ bị phụ thuộc nhiều vào thời gian.
Còn đây là thuật toán của em, hơi dài nên xin được tóm tắt thế này mong các bác góp ý thêm.
- Đưa thời gian bắt đầu về 7:30(bắt đầu 1 ngày) bằng cách cộng thêm vào thời gian định mức 1 khoảng hợp lý. Ví dụ đang bắt đầu từ 8:30 ngày 5/1/2009 và định mức là 5 thì thay bằng bắt đầu từ 7:30 ngày 5/1/2009 và định mức là 5.5
- Từ bảng thời gian làm việc ban đầu ta thấy mỗi tuần làm 41.5 tiếng, vậy với định mức ban đầu ta tính xem phải làm bao nhiêu tuần, cộng luôn số ngày trong các tuần này vào ngày ban đầu, phần thời gian còn lại(còn lại chắc chắn chưa đến 1 tuần<41.5). Duyệt lần lượt các ngày tiếp theo, ngày thường thì thời gian còn lại trừ đi 7.5 là thời gian làm việc ngày thường, tương tự nếu là ngày thứ 7 thì trừ đi 4, chủ nhật thì trừ đi 0, đến khi nào thời gian còn lại không đủ cho 1 ngày làm việc thì đem thời gian đó cộng với ngày cuối cùng tìm được.
- Với giải thuật này có thể thực hiện hoàn toàn bằng công thức được, nhưng vẫn hơi phức tạp và sẽ phải tạo thêm cột phụ. Và với VBA thì số vòng lặp cũng không vượt quá 7 nên tốc độ sẽ hầu như không phụ thuộc vào thời gian định mức.
Mã:
Function GetEndTime(BatDau, ThoiGian)
    Dim SoTuan, SoNgay, ret, ThoiGianCon
    
    Dim ThoiGianTemp
    ThoiGianTemp = TimeSerial(Hour(BatDau), Minute(BatDau), 0)
    If ThoiGianTemp > TimeSerial(13, 30, 0) Then
        ThoiGianTemp = TimeSerial(4, 0, 0) + TimeSerial(13, 30, 0) - ThoiGianTemp
    Else
        ThoiGianTemp = ThoiGianTemp - TimeSerial(7, 30, 0)
    End If
    ThoiGian = ThoiGian + Hour(ThoiGianTemp) + Minute(ThoiGianTemp) / 60
    
    BatDau = DateSerial(Year(BatDau), Month(BatDau), Day(BatDau)) + TimeSerial(7, 30, 0)
    
    SoTuan = ThoiGian \ 41.5
    ThoiGianCon = ThoiGian - SoTuan * 41.5
    ret = BatDau + SoTuan * 7
    If ThoiGianCon > 0 Then
        Do While (Weekday(ret) <> 7 And ThoiGianCon >= 7.5) Or (Weekday(ret) = 7 And ThoiGianCon >= 4)
            ThoiGianCon = ThoiGianCon - 4
            If Weekday(ret) < 7 Then ThoiGianCon = ThoiGianCon - 3.5
            If ThoiGianCon = 0 Then Exit Do
            ret = ret + 1
            If Weekday(ret) = 1 Then ret = ret + 1
        Loop
        If ThoiGianCon = 0 Then
            ret = ret + TimeSerial(4, 0, 0)
            If Weekday(ret) <> 7 Then ret = ret + TimeSerial(5, 30, 0)
        ElseIf ThoiGianCon > 4 Then
            ThoiGianCon = ThoiGianCon - 4
            ret = ret + TimeSerial(Int(ThoiGianCon), (ThoiGianCon - Int(ThoiGianCon)) * 60, 0) + TimeSerial(6, 0, 0)
        Else
            ret = ret + TimeSerial(Int(ThoiGianCon), (ThoiGianCon - Int(ThoiGianCon)) * 60, 0)
        End If
    End If
    
    If True And TimeSerial(7, 30, 0) = TimeSerial(Hour(ret), Minute(ret), Second(ret)) Then
        ret = (ret - 1) + TimeSerial(9, 30, 0)
        If Weekday(ret) = 1 Then ret = (ret - 1) - TimeSerial(5, 30, 0)
    End If
    GetEndTime = ret
End Function
 

File đính kèm

  • Time.xls
    27 KB · Đọc: 16
Nhờ Bác RollOver79 làm hộ code ngược lại
Ta có ngày giờ đầu, cuối => số phút (h).
Tôi dùng code trên làm ngược lại vòng do sao cho có ngày giờ đầu = cuối => => số phút (h) mà chưa được
Cụ thể như
Function TimGio(NgayDau, NgayCuoi)
Do while endTime(NgayDau,SoGio) = NgayCuoi
...
Loop
end Function
Cám ơn Bạn nhiều. Đang học Do ...Loop mà chưa hiểu nhiểu.
 
Sau một đêm ngủ không được, tôi đã tìm được cách để đưa đơn vị thời gian định mức về mỗi 5 phút. Xin gửi lên bản "version 1.4", đã được hiệu chỉnh. Bảng tính này cũng hoàn toàn dùng công thức và các Name, không dùng cột phụ.

Khi nhập liệu, phải nhập cho đúng quy cách: Thời gian định mức (ô F3) là mỗi 5 phút, và phải chia cho 60, thời gian bắt đầu (ô F4) thì phải đúng dạng dd/mm/yyyy hh:mm, nhập sai nó tính sai ráng chịu! Chính vì cái phiền toái này mà tôi chế thêm cách dùng chuột để điều khiển các Control, đỡ mất công tính nhẩm, nhớ định dạng, mà lại dễ dàng để test các kết quả. Hiện tại các Control này bị giới hạn mức Maximum và Minimum, nếu cảm thấy như vậy là chưa đủ, các bạn chỉ việc thay đổi Properties của nó.
000-166.png

Cũng gần gần giống bạn rollover79, tất cả các ngày trong tuần, tôi đều đưa về thứ Hai, bằng cách bù trừ một khoảng thời gian hợp lý.
Dựa vào khoảng thời gian định mức đã biết, trước hết tôi tìm ra số tuần lễ sẽ trôi qua, bằng cách chia cho 41.5 (thời gian làm việc của một tuần).
Sau đó tính tiếp số giờ nghỉ buổi trưa (2 tiếng) nếu có.
Rồi tìm tiếp thời gian nghỉ qua đêm (16.5 tiếng) nếu có.
Bởi đã giới hạn thời gian chỉ trong khoảng 41.5 tiếng, nên tôi không cần phải xét đến ngày thứ Bảy. Hễ mốc thời gian chạm mức 41.5 thì nó sẽ nhảy sang thứ Hai kế tiếp.
Sau cùng, tôi lấy thời gian bắt đầu, cộng thêm định mức, cộng thêm các khoảng nghỉ trưa, nghỉ qua đêm, và cộng thêm khoảng thời gian nghỉ (126.5 tiếng) nếu như định mức lớn hơn 1 tuần... Đó chính là kết quả cuối cùng.

Hy vọng bảng tính này sẽ đáp ứng được yêu cầu của bác Letin.

Giải thuật dùng trong bảng tính này, nếu so với các UserDefineName thì không đáng, bởi nó dài dòng... Tuy nhiên, nói cho vui, các bác có thể dùng nó để test các UDF... Hôm qua, tôi đã dùng bảng tính này để test code của bạn rollover79, nhờ đó mới khám phá cái lỗi đã nói cho bạn ở trên.

Lỗi nhảy sớm khi chạm mức 41.5 này, tôi cũng đã mắc phải. Cách xử lý của tôi hơi củ chuối tí... Tôi cộng thêm một khoảng thời gian tối thiểu (ở đây là 5 phút) vào tổng thời gian trước khi đem chia cho 41.5, như thế, nếu như thời gian định mức bằng đúng 41.5, kết quả sẽ không bị nhảy sớm. Tôi chỉ tính nhẩm thôi, ví dụ bắt đầu làm lúc 7:30 ngày thứ Hai, với định mức bằng 41.5 tiếng, bằng đúng thời gian làm của 1 tuần, thì kết quả phải là lúc 11:30 ngày thứ Bảy... (chưa đủ để nhảy sang 1 tuần mới, mặc dù 41.5/41.5 là 1)
 

File đính kèm

  • DMTgian ver1.4.xls
    34.5 KB · Đọc: 33
Lần chỉnh sửa cuối:
Nhờ Bác RollOver79 làm hộ code ngược lại
Ta có ngày giờ đầu, cuối => số phút (h).
Tôi dùng code trên làm ngược lại vòng do sao cho có ngày giờ đầu = cuối => => số phút (h) mà chưa được
Cụ thể như
Function TimGio(NgayDau, NgayCuoi)
Do while endTime(NgayDau,SoGio) = NgayCuoi
...
Loop
end Function
Cám ơn Bạn nhiều. Đang học Do ...Loop mà chưa hiểu nhiểu.
Với bài toán ngược này thì dễ hơn bài toàn xuôi nhiều, cách đơn giản là bác lặp hết các ngày cũng ra. Nhưng bác có thể giảm bớt số vòng lặp bằng cách tính trọn thời gian trong ngày và trong tuần. Mỗi tuần là 41.5, mỗi ngày thường là 7.5, thứ 7 là 4. Sau khi ra kết quả thì bác trừ đi 2 khoảng đầu ngày bắt đầu và khoảng cuối của ngày kết thúc là xong.
Mã:
Function GetTime(BatDau, KetThuc)
    Dim NgayDau, NgayCuoi, SoTuan, ret, i
    NgayDau = DateSerial(Year(BatDau), Month(BatDau), Day(BatDau))
    NgayCuoi = DateSerial(Year(KetThuc), Month(KetThuc), Day(KetThuc))
    SoTuan = DateDiff("d", NgayDau, NgayCuoi) \ 7
    ret = SoTuan * 41.5
    NgayDau = NgayDau + SoTuan * 7
    For i = NgayDau To NgayCuoi
        Select Case Weekday(i)
            Case 7: ret = ret + 4
            Case 2, 3, 4, 5, 6: ret = ret + 7.5
        End Select
    Next
    Dim ThoiGianTemp
    ThoiGianTemp = TimeSerial(Hour(BatDau), Minute(BatDau), 0)
    If ThoiGianTemp > TimeSerial(13, 30, 0) Then
        ThoiGianTemp = TimeSerial(4, 0, 0) + TimeSerial(13, 30, 0) - ThoiGianTemp
    Else
        ThoiGianTemp = ThoiGianTemp - TimeSerial(7, 30, 0)
    End If
    
    ret = ret - Hour(ThoiGianTemp) - Minute(ThoiGianTemp) / 60
    
    ThoiGianTemp = TimeSerial(Hour(KetThuc), Minute(KetThuc), 0)
    If ThoiGianTemp > TimeSerial(13, 30, 0) Then
        ThoiGianTemp = TimeSerial(17, 0, 0) - ThoiGianTemp
    Else
        ThoiGianTemp = TimeSerial(11, 30, 0) - ThoiGianTemp
        If Weekday(KetThuc) <> 7 Then ThoiGianTemp = ThoiGianTemp + TimeSerial(3, 30, 0)
    End If
    
    ret = ret - Hour(ThoiGianTemp) - Minute(ThoiGianTemp) / 60
    
    GetTime = ret
End Function
 
Bác Letin có thể cho nhận xét cái bảng tính của em được không ạ ?
Về tốc độ, về sự chính xác ?
 
Tôi xin điều chỉnh lại code, do chưa kiểm tra giờ ngày đầu có phải là 11h30 hay 17h
PHP:
Option Explicit
Public Function EndTime(NgayDau As Variant, SoGio As Double)
Dim NgayCuoi As Variant, iPhut As Double, Block As Long, SoPhut As Long
On Error Resume Next
Application.Volatile
SoPhut = Round(SoGio * 60, 0) 'xem lai neu 1h5' thi nhap so the nao'
If Not IsDate(NgayDau) Then Exit Function
'Xac dinh gio ngay dau co phai la 11h30 hay 17h hay 11h30 TB'
Select Case Weekday(NgayDau)
  Case Weekday(NgayDau) = 1 'neu la CN'
    Exit Function
  Case Is <> 7 'Neu khac thu 7'
    If Hour(NgayDau) = 11 And Minute(NgayDau) = 30 Then
      NgayDau = DateAdd("n", 120, NgayDau)
    ElseIf Hour(NgayDau) = 17 And Minute(NgayDau) = 0 Then
     NgayDau = DateAdd("n", 14 * 60 + 30, NgayDau)
    End If
  Case Is = 7 'neu la th 7'
    If Hour(NgayDau) = 11 And Minute(NgayDau) = 30 Then
      NgayDau = DateAdd("n", 44 * 60, NgayDau)
    End If
End Select
If SoPhut = 0 Then
  EndTime = NgayCuoi
  Exit Function
End If
Block = 1
iPhut = Block
Do While Not iPhut = SoPhut + Block
  NgayCuoi = DateAdd("n", Block, NgayDau)
  If Weekday(NgayDau) <> 7 And Hour(NgayCuoi) = 11 And Minute(NgayCuoi) = 30 Then
    NgayDau = DateAdd("n", 120, NgayCuoi)
  ElseIf Weekday(NgayDau) <> 7 And Hour(NgayCuoi) = 17 And Minute(NgayCuoi) = 0 Then
     NgayDau = DateAdd("n", 14 * 60 + 30, NgayCuoi)
  ElseIf Weekday(NgayDau) = 7 And Hour(NgayCuoi) = 11 And Minute(NgayCuoi) = 30 Then
     NgayDau = DateAdd("n", 44 * 60, NgayCuoi)
  Else
    NgayDau = NgayCuoi
  End If
  iPhut = iPhut + Block
Loop
EndTime = NgayCuoi
End Function
To RollOver79
Hình như UDF GetEndTim chưa chuẩn với ngaydau là
12/01/2009 3:00:00 PM và sogio là 1.
Đáp số phải là 12/01/2009 4:00:00 PM
 
Cảm ơn bác BNTT, test nhiều trường hợp mà quên mất trường hợp làm chẵn tuần và thời gian bắt đầu là 7h:30. Xin sửa lại code như sau các bác test tiếp xem còn lỗi nào không nhé.
Với cách của bác ThuNghi mà khi dữ liệu lớn hoặc nhiều thì không ổn về mặt tốc độ, vì bác dùng vòng For với step là 1 phút nên tốc độ sẽ bị phụ thuộc nhiều vào thời gian.
Còn đây là thuật toán của em, hơi dài nên xin được tóm tắt thế này mong các bác góp ý thêm.
- Đưa thời gian bắt đầu về 7:30(bắt đầu 1 ngày) bằng cách cộng thêm vào thời gian định mức 1 khoảng hợp lý. Ví dụ đang bắt đầu từ 8:30 ngày 5/1/2009 và định mức là 5 thì thay bằng bắt đầu từ 7:30 ngày 5/1/2009 và định mức là 5.5
- Từ bảng thời gian làm việc ban đầu ta thấy mỗi tuần làm 41.5 tiếng, vậy với định mức ban đầu ta tính xem phải làm bao nhiêu tuần, cộng luôn số ngày trong các tuần này vào ngày ban đầu, phần thời gian còn lại(còn lại chắc chắn chưa đến 1 tuần<41.5). Duyệt lần lượt các ngày tiếp theo, ngày thường thì thời gian còn lại trừ đi 7.5 là thời gian làm việc ngày thường, tương tự nếu là ngày thứ 7 thì trừ đi 4, chủ nhật thì trừ đi 0, đến khi nào thời gian còn lại không đủ cho 1 ngày làm việc thì đem thời gian đó cộng với ngày cuối cùng tìm được.
- Với giải thuật này có thể thực hiện hoàn toàn bằng công thức được, nhưng vẫn hơi phức tạp và sẽ phải tạo thêm cột phụ. Và với VBA thì số vòng lặp cũng không vượt quá 7 nên tốc độ sẽ hầu như không phụ thuộc vào thời gian định mức.

rollover79 thân, code của bạn, nếu thời gian bắt đầu là 13:30 trở đi thì chạy không đúng nữa. Tất cả các ngày, không riêng gì thứ 2.
 
Cảm ơn 2 bác ThuNghi và BNTT, trong code có 1 dòng bị sai logic
Mã:
Function GetEndTime(BatDau, ThoiGian)
    Dim SoTuan, SoNgay, ret, ThoiGianCon
    
    Dim ThoiGianTemp
    ThoiGianTemp = TimeSerial(Hour(BatDau), Minute(BatDau), 0)
    If ThoiGianTemp > TimeSerial(13, 30, 0) Then
        ThoiGianTemp = TimeSerial(4, 0, 0) + [COLOR=Red][B]TimeSerial(13, 30, 0) - ThoiGianTemp[/B][/COLOR]
    Else
        ThoiGianTemp = ThoiGianTemp - TimeSerial(7, 30, 0)
    End If
    ThoiGian = ThoiGian + Hour(ThoiGianTemp) + Minute(ThoiGianTemp) / 60
    
    BatDau = DateSerial(Year(BatDau), Month(BatDau), Day(BatDau)) + TimeSerial(7, 30, 0)
    
    SoTuan = ThoiGian \ 41.5
    ThoiGianCon = ThoiGian - SoTuan * 41.5
    ret = BatDau + SoTuan * 7
    If ThoiGianCon > 0 Then
        Do While (Weekday(ret) <> 7 And ThoiGianCon >= 7.5) Or (Weekday(ret) = 7 And ThoiGianCon >= 4)
            ThoiGianCon = ThoiGianCon - 4
            If Weekday(ret) < 7 Then ThoiGianCon = ThoiGianCon - 3.5
            If ThoiGianCon = 0 Then Exit Do
            ret = ret + 1
            If Weekday(ret) = 1 Then ret = ret + 1
        Loop
        If ThoiGianCon = 0 Then
            ret = ret + TimeSerial(4, 0, 0)
            If Weekday(ret) <> 7 Then ret = ret + TimeSerial(5, 30, 0)
        ElseIf ThoiGianCon > 4 Then
            ThoiGianCon = ThoiGianCon - 4
            ret = ret + TimeSerial(Int(ThoiGianCon), (ThoiGianCon - Int(ThoiGianCon)) * 60, 0) + TimeSerial(6, 0, 0)
        Else
            ret = ret + TimeSerial(Int(ThoiGianCon), (ThoiGianCon - Int(ThoiGianCon)) * 60, 0)
        End If
    End If
    
    If True And TimeSerial(7, 30, 0) = TimeSerial(Hour(ret), Minute(ret), Second(ret)) Then
        ret = (ret - 1) + TimeSerial(9, 30, 0)
        If Weekday(ret) = 1 Then ret = (ret - 1) - TimeSerial(5, 30, 0)
    End If
    GetEndTime = ret
End Function
Các bác thay lại giúp em chỗ bôi đỏ thành ThoiGianTemp - TimeSerial(13, 30, 0)
 
Version 2.0 đây.
Chính xác tới từng phút luôn.
Nếu dùng Control để nhập dữ liệu, có thêm tùy chọn cho bước nhảy của đơn vị thời gian định mức nhỏ nhất: Có thể chọn nhảy từng 1 phút, 5 phút, hay 30 phút mỗi lần.
000-168.jpg

--------------------------------------------------------
Em nói thêm một chút. Giải bài này, em mất hết 5 ngày (từ hôm mồng 9). Làm gì cũng nghĩ đến nó, cả khi ngủ, cho đến đêm hôm qua. Khi test lần cuối, thấy nó chạy quá ngọt, mừng ơi là mừng. Cảm ơn bác Letin đã cho một đề bài thật hay, và cảm ơn anh ndu96081631 nữa, anh chính là động lực để em quyết làm cho bằng được:
Bài toán dạng này không phải là KHÓ, mà là CỰC KHÓ
Cảm ơn cả sư nương nữa, đã bỏ công test lại dùm em và động viên em...
 

File đính kèm

  • DMTgian ver2.0.xls
    36.5 KB · Đọc: 45
Lần chỉnh sửa cuối:
Cảm ơn các bạn đã tham gia và động viên .
Thật là cảm động đối với bạn BNTT , rất kỳ công , tôi cũng đã tốn thời gian với việc này và tôi nghĩ các bạn ThuNghi , rollover79 cũng vậy ,bạn NDU đã châm ngòi và nhiều bạn khác động viên .
Kết quả của mỗi giải pháp các bạn đưa ra ,đối với tôi đều đáng học tập cả .
Rất nhiệt tình , tuy Khó nhưng không tay là điều thật đáng quí , đều được trân trọng .
Một lần nữa cảm ơn và chúc các bạn thành đạt .
 
Chậm chân một chút!
Có 1 thuật toán đơn giản, tôi nghĩ ra từ 3 ngày nay, nhưng chưa làm được. Bây giờ mới xong, nhờ các bạn kiểm tra hộ:

1. tính thời gian còn lại (A) của ngày bắt đầu: thí dụ bắt đầu 10:00, số giờ còn lại là 1,5 giờ cho ngày thứ bảy và 5 giờ cho ngày thường.

2. So sánh giờ định mức với A:
a. nếu nhỏ hơn thì tính ngay
b. Nếu lớn hơn:​
b.1- số ngày cộng thêm = 0, Dùng 1 vòng lặp Do:

b.2- cho số ngày cộng thêm tăng thêm 1
b.3- nếu ngày bắt đầu cộng với số ngày cộng thêm là chủ nhật, tăng số ngày cộng thêm lên 1 nữa
b.4- tính số giờ còn lại sau khi cộng thêm 1 ngày
b.4.1- Nếu số giờ còn lại đó lớn hơn 4 giờ (thứ bảy), hoặc 7,5 giờ (ngày thường), loop (quay lại b.2)
b.4.2- Nếu số giờ còn lại nhỏ hơn 4 giờ (thứ bảy), hoặc 7,5 giờ (ngày thường), thoát Do​
3. Ngày kết thúc = ngày bắt đầu (quy về 0:00 sáng) + số ngày cộng thêm

4. Giờ kết thúc = 7:30 + số giờ còn lại (ở cuối phần Do loop) + thêm 2 giờ nếu ngày thường và sau 11:30

Có thể tính chính xác đến 1 phút.

Nhờ mọi người kiểm tra hộ. Có 3 cái scrollbar để tiện cho việc kiểm tra: 1 cái tăng định mức thêm 1 giờ, 1 cái tăng thêm 5 phút, 1 cái tăng thêm 1 phút.
Xin cám ơn.
 

File đính kèm

  • TimePtm.xls
    43.5 KB · Đọc: 20
Lần chỉnh sửa cuối:
Web KT

Bài viết mới nhất

Back
Top Bottom