Hãy tính xem từ năm 1900 đến nay có bao nhiêu ngày thuộc dạng THỨ SÁU NGÀY 13

Chia sẻ bởi:hands
★★★★★
Quảng cáo

Những ai đã từng xem qua bài viết này: [URL="https://www.giaiphapexcel.com/forum/showthread.php?6354-Gi%E1%BB%9Bi-thi%E1%BB%87u-C%C6%A1-b%E1%BA%A3n-v%E1%BB%81-v%C3%B2ng-l%E1%BA%B7p-For-.-.-.-next/page12"]Giới thiệu Cơ bản về vòng lặp For . . . next của sư phụ ptm0412 giờ hãy cùng làm 1 vài bài tập từ đơn giản đến nâng cao nhé
Xin mở màn bằng 1 bài tập sau:

Bài tập 01:

Hãy tính xem từ năm 1900 đến nay có bao nhiêu ngày thuộc dạng THỨ SÁU NGÀY 13
————————
Các bạn ai có bài tập gì hay xin post lên đây nhé! Cảm ơn

Không biết như thế này có đúng không, Anh xem giúp nhé!

Sub tinhngay()
Dim i As Date: Dim tong As Long
tong = 0
  For i = DateSerial(1900, 1, 1) To DateSerial(2010, 8, 17)
    If Weekday(i) = 6 And Day(i) = 13 Then tong = tong + 1
  Next
 MsgBox "So ngay la: " & tong
End Sub

Cám ơn ndu đã nhắc tới và tiếp tục topic cũ. Quả thực lúc viết topic đó, mình nhớ gì viết nấy, và cũng muốn có nhiều bài tập hay hay từ thấp đến cao, nhưng nhất thời không nghĩ ra.

Nhân đây, mình rất mong mỏi những thành viên đang tập tành học VBA , nên tham gia topic này. Kể cả một vài thành viên đang viết code ầm ầm, nhưng theo nhận xét riêng thì đang rất mất căn bản trong tư duy logic.

Tư duy logic là cái cần thiết nhất, căn bản nhất mà người lập trình cần phải có. Các câu lệnh, cú pháp, hàm có sẵn, từ khoá, … có thể mở Help lên xem, hoặc vào GPE hỏi, chứ tư duy logic thì không ai giúp được. Chỉ có thể rèn luyện bằng những bài tập nhỏ, những ứng dụng nhỏ, vận động trí óc tìm ra thuật toán để giải, ..

Rèn luyện tư duy, thì đây là 1 topic rất hay để các bạn tham gia và rèn luyện.

Đừng nghĩ rằng khi Excel đã có hàm giai thừa mà bắt các bạn tính giai thừa 1 số n bằng VBA là vô bổ, đó là rèn luyện suy luận đấy.

Hãy bắt đầu từ cái đơn giản nhất.

Gởi ndu:
Hãy từ từ nhé, hãy để vài người tham gia giải quyết cho rốt ráo 1 bài tập, rồi hãy đưa bài tập kế.

Đúng, chắc vậy, nhưng bạn còn lãng fí kkhoảng 30 llần tthời gian cơ dđấy!

Thêm 1 vòng lặp nữa xem sao!
1 vòng lặp theo tháng, 1 vòng lặp theo năm . . . .

Tôi nghĩ cũng chỉ cần 1 vòng lặp thôi.
Sub Test()
Dim SoNgay As Long
For i = 1 To (Year(Date) – 1900) * 12 + Month(Date) + (Day(Date) < 13)
If Weekday(DateSerial(1900, i, 13)) = 6 Then SoNgay = SoNgay + 1
Next
MsgBox SoNgay
End Sub
Trường hợp này dùng Do Until… Loop có lẽ là hay hơn
Sub Test()
Dim SoNgay As Long, i As Long
Do Until DateSerial(1900, i, 13) > Date
i = i + 1
If Weekday(DateSerial(1900, i, 13)) = 6 Then SoNgay = SoNgay + 1
Loop
MsgBox SoNgay
End Sub

Tôi nghĩ cũng chỉ cần 1 vòng lặp thôi.

Đúng là cần gì phải lặp theo ngày, vì ngày có sẵn là 13 rồi. Em sửa code lại như sau:

Sub tinhngay1()
Dim i, j As Date: Dim tong As Long
tong = 0
 For j = 1900 To 2010
   For i = 1 To 12
    If Weekday(DateSerial(j, i, 13)) = 6 Then tong = tong + 1
   Next i
  Next j
 MsgBox "So ngay la: " & tong
End Sub

Tuy nhiên cái hàm Weekday(DateSerial(j, i, 13)) Em không biết thay hàm nào khác cả?

– Vì thay thuật toán, nên i, j không phải là Date nữa, mà là Long
– Sự thực là i chưa khai báo kiểu, chỉ mới khai báo kiểu cho j và tong.
– Tính dư cho tháng 9 đến tháng 12 của năm 2010.
– Dùng Weekday đâu có vấn đề gì đâu?

Anh giải thích giúp Em sao biến i chưa được khai báo với, vì Em nghĩ đặt i và j cách nhau dấu "," thì nó hiểu hết chứ nhỉ?

Sub tinhngay()
Dim i As Integer
Dim j As Long: Dim tong As Long
tong = 0
 For j = 1900 To 2010
   For i = 1 To 12
    If Weekday(DateSerial(j, i, 13)) = 6 And DateSerial(j, i, 13) <= Date Then tong = tong + 1
   Next i
  Next j
 MsgBox "So ngay la: " & tong
End Sub

Dim I, J as Date ==> biến J kiểu Date, biến I kiểu Variant
Anh Bill quy định thế mà, biết làm sao được.
Phải khai báo đầy đủ:

Dim i As Long, j As Long, tong As Long.

Thử như vầy sẽ biết: Dùng 1 dòng lệnh kiểm tra:

i = "GPE"

Nếu khai báo đủ như dòng trên, thì dòng lệnh này sẽ báo lỗi Type Mismatch. Điều này có lợi khi muốn loại giá trị không thích hợp.
Nếu khai báo thiếu, anh Bill thấy text cũng mặc kệ.

www.giaiphapexcel.com/diendan/threads/b%C3%A0i-t%E1%BA%ADp-v%E1%BB%81-v%C3%B2ng-l%E1%BA%B7p.39326/#post-261171

Xây dựng Lương 3P, KPI cho Doanh nghiệp
Khóa học SprinGO phù hợp

Xây dựng Lương 3P, KPI cho Doanh nghiệp

Làm thế nào để trả lương cho nhân viên chính xác nhất? Đây là một trong những câu hỏi khó trong quản trị nhân...

Xem khóa học
★★★★★ 5 ★ 1 👤 2 ▥ 0
Quảng cáo

Bạn nên đọc

2 Responses

  1. hands says:

    Tính từ đầu năm đến cuối năm tôi đã đi làm được bao nhiều ngày (nghỉ CN và lễ, không tính nghỉ đột xuất)
    Dễ hơn rất nhiều
    Ẹc… Ẹc…

    Vậy cứ thống nhất vậy nhé.
    Từ 19/08/2010 – 31/12/2010 mình sẽ làm việc bao nhiêu ngày. Ngày lễ gồm có: 2/9 và ngày nghỉ là CN. Và liệt kê những ngày thứ hai gán vào A1->An của 1 sheet. Dòng vòng lặp thông thường.

    Các anh xem góp ý cho Em nhé!

    Sub lamviec()
    Dim i As Integer, j As Integer, k As Integer, dk As Boolean
      Dim ngayle As Integer, ngaynghi As Integer, ngaylam As Long
      ngayle = 1: ngaynghi = 0
       For i = 8 To 12
           dk = i Mod 8
           k = IIf(dk, 1, 19)
           For j = k To 31
               With [COLOR=Red]ActiveCell[/COLOR]
                   If Weekday(DateSerial(2010, i, j)) = 1 Then
                      ngaynghi = ngaynghi + 1
                      .Value = DateSerial(2010, i, j)
                      .Offset(1, 0).Select
                   End If
               End With
           Next j
       Next i
           ngaylam = DateSerial(2010, 12, 31) - DateSerial(2010, 8, 19) - ngayle - ngaynghi
           MsgBox "Tong ngay lam viec la: " & ngaylam
    End Sub

    Điều kiện đưa vào bắt đầu cells(1,1) Em chưa biết, nên dùng Activecell thì nó mới chạy, mong các Anh giúp.

  2. hands says:

    Mình xin xúi 1 cách làm tầm bậy, như sau

    (*) Tính tổng số ngày;

    (*) Tạo 1 vòng lặp từ ngày đầu tiên đến 7 ngày sau đó để tìm ra ngày CN đầu tiên

    (*) Tạo vòng lặp từ ngày CN đầu tiên cho đến ngày cuối bước nhảy là 7 để đếm hết các ngày CN

    (*) Kiểm thêm ngày Quốc khánh là thứ máy trong tuần

    (*) Đáp án là tổng đại số các ngày trên;

    Khà, khà,. . . .

    Em sửa lại đoạn code theo hướng dẫn của Bác HYen17 như sau:

    Sub Tinhngay()
    Dim tongngay As Long, nghi As Integer, le As Integer
    Dim i As Long, j As Date
    Cells.Clear
    tongngay = DateSerial(2010, 12, 31) - DateSerial(2010, 8, 19)
    le = 1: nghi = 0
    For i = 19 To 26
        If Weekday(DateSerial(2010, 8, i)) = 1 Then
           For j = DateSerial(2010, 8, i) To DateSerial(2010, 12, 31) Step 7
            With ActiveCell
                 .Value = j
                 nghi = nghi + ActiveCell.Count
                 .Offset(1, 0).Select
            End With
            Next
        End If
    Next
    If Weekday(DateSerial(2010, 9, 2)) <> 1 Then ActiveCell = DateSerial(2010, 9, 2)
    MsgBox "Tong ngay lam viec la: " & tongngay - le - nghi
    End Sub

    Các Anh xem và góp ý cho Em nhé!

    Muốn nhận được góp í thì đây, xin mời

    (*) Sau lại nhốt chung vòng lặp sau vô trong vòng lặp trước vậy?

    Nếu gặp ngay ngày CN từ đầu, có fải bạn fí fạm 6 lần lặp không cần thiết không nào?
    Nên thoát khỏi nó ngay khi gặp ngày CN chứ; Tuy thêm 1 dòng lệnh, nhưng thưởng giảm đi được khoảng gần nữa đọan đường trong vòng lặp thứ nhật đó bạn.

    Em sửa lại đoạn code theo góp ý của Bác ChanhTQ@ như sau:

    Sub Tinhngay()
    Dim tongngay As Long, nghi As Integer, le As Integer
    Dim i As Long, j As Date
    Cells.ClearContents
    tongngay = DateSerial(2010, 12, 31) - DateSerial(2010, 8, 19): le = 1
      For i = 19 To 25
        If Weekday(DateSerial(2010, 8, i)) = 1 Then Exit For
      Next
      For j = DateSerial(2010, 8, i) To DateSerial(2010, 12, 31) Step 7
        With [COLOR=Red]ActiveCell[/COLOR]
            .NumberFormat = "dd/mm/yyyy"
            .Value = j
            nghi = nghi + ActiveCell.Count
            .Offset(1, 0).Select
        End With
      Next
    If Weekday(DateSerial(2010, 9, 2)) <> 1 Then ActiveCell = DateSerial(2010, 9, 2)
    MsgBox "Tong ngay lam viec la: " & tongngay - le - nghi
    End Sub

    Tuy nhiên chỗ ActiveCell muốn nó nằm ở cột A thì làm sao nhỉ? Không lẽ phải thêm 1 vòng lặp nữa?

    Một cách để cho kết quả từ A1:
    _ Tạo một biến, thí dụ : Dim K as Integer
    _ With ActiveCell thay bằng With .Offset(K) hoặc With Cells(K + 1, 1)
    _ Thay .Offset(1, 0).Select bằng K= K + 1
    Đây là code liệt kê tất cả những ngày đi làm ra cột A, từ đầu năm 2010 đến cuối năm 2010 (không tính chủ nhât)

    Sub Tinhngay()
    Dim i As Long, j As Long
    With Range("A:A")
    .ClearContents
    .NumberFormat = "dd/mm/yyyy"
    For i = DateSerial(2010, 1, 1) To DateSerial(2010, 12, 31)
    If Weekday(i, 1) > 1 Then
    j = j + 1
    .Cells(j, 1) = i
    End If
    Next
    End With
    End SubCode này chưa tính đến nghỉ lễ —> Bạn cứ cải tiến nhé

    (Nhìn qua nhìn lại chỉ thấy có mỗi bạn MinhCong —> cái vụ VBA này xem ra ít người khoái nhỉ?)

Leave a Reply

Your email address will not be published. Required fields are marked *

Quảng cáo

Cũ vẫn chất

Xem thêm