Bài tập VBA đơn giản dành cho người mới bắt đầu [Phần 2]

Liên hệ QC

ChanhTQ@

0901452không62
Tham gia
5/9/08
Bài viết
4,256
Được thích
4,863
Xin các bạn có bài tập nào hay hay đăng lên để cùng nhau luyện cho mau tiến bộ nhe!
Mình xin mở màn bài đầu:
ĐỀ BÀI 1:

Tôi có bảng số liệu từ cột [A..E] như sau:

| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W 2 |HoTen|Date1|Date2|Date3|Date4|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18
3 |Hồ Lễ|3|5|7|13|Do|Do|Do|Xh|Xh|Vg|Vg|Tm|Tm|Tm|Tm|Tm|Tm||.|||
4 |Đỗ Nè|4|8|13|15|Nu|Nu|Nu|Nu|Xh|Xh|Xh|Xh|Xm|Xm|Xm|Xm|Xm|Dn|Dn|||
5 |Vũ Xe|2|4|12|13|Do|Do|Vg|Vg|Nu|Nu|Nu|Nu|Nu|Nu|Nu|Nu|Hg|||.|||

Phần từ cột [F] trở đi là phần cần viết 1 macro để nó tô màu nền khác nhau theo những giá trị cùng dòng từ cột [B..E];
Màu tô do bạn tự chọn, cốt fân biệt giữa chúng & dịu mắt là được!


PHẦN TỔNG HỢP CÁC ĐỀ BÀI TẬP:

Tên|Tóm tắc|Bài thứ
Đề bài 1|Tô màu theo trị số các ô bên trái cùng dòng| #1
Đề bài 1A|Lọc theo các số cần thiết từ các chuỗi số| #73
Đề bài 1B|Xác định loại tam giác dựa trên 3 số ngẫu nhiên được tạo ra| #82
Đề bài 2|Lập danh sách học sinh theo từng lớp| #11
Đề bài 2A|Dịch ngôn ngữ VBA sang tiếng Việt| #19
BĐT(*)|Lập danh sách các nữ HS có ngày sinh trong 1 quí| #101
Đề bài 3|Thống kế kết quả điểm của từng lớp theo từng môn học| #22
Đề bài 4|Lập danh sách HS các lớp đạt điểm cực trị của từng môn| #46
Đề bài 4A|Tìm trong danh sách thí sinh, số báo danh nào có tổng điểm các môn cao nhất| #94
Đề bài 5|Thống kê từng khoảng điểm của môn học| #58
Đề bài 6|Thống kê điểm trung bình theo giới tính| #71

(*) BĐT: Bài đọc thêm

.
.
.
 
Lần chỉnh sửa cuối:
[Thongbao] Vo Tinh;654437:[/ThongBao]
Có thể xài 1 vòng lặp, như macro sự kiện sau:
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
 Dim Rng As Range, Cls As Range
 Dim Thang%, Nam%, Wek%, J%, Dat&
 
 If Not Intersect(Target, [J1]) Is Nothing Then
    Set Rng = [G3].Resize(6, 7)
    Rng.Value = ""
    Thang = Target.Value:       Nam = [U1].Value
    Dat = DateSerial(Nam, Thang, 1)
    Wek = Weekday(Dat)
    Dat = Dat - Choose(Wek, 6, 0, 1, 2, 3, 4, 5)
    For Each Cls In Rng
        If Month(Dat + J) = Thang Then
            Cls.Value = Day(Dat + J)
        End If
        J = J + 1
    Next Cls
End If
End Sub

Có nghĩa là bài này có rất nhiều cách. Rất mong sự tìm tòi của các bạn khác nữa để thêm fần xôm tụ!

Chúc ngày nghỉ cuối tuần vui vẻ & chất lượng!
 
Upvote 0
Bài tập: Tạo lịch các ngày trong tuần của 1 tháng như hình kèm theo

Bài này không khó nhưng nếu dùng code sự kiện thì việc bẫy lỗi mới thật sự là đáng sợ (nghĩ ra mọi tình huống mà người dùng cố tình "phá")
Chưa thấy ai viết code để ý đến chuyện này nhỉ?
 
Upvote 0
[thongbao]Chưa thấy ai viết code để ý đến chuyện này nhỉ? [/thongbao]

(/ì có thể ô để chọn tháng người ta thiết kế là chỉ chọn được từ số 1 đến số 12 mà thôi;

Cũng như vậy với ô chứa số biểu thị của năm của lịch cần làm.

Xin mọi người quan tâm & tiếp tục tham gia.
 
Upvote 0
[thongbao]Chưa thấy ai viết code để ý đến chuyện này nhỉ? [/thongbao]

(/ì có thể ô để chọn tháng người ta thiết kế là chỉ chọn được từ số 1 đến số 12 mà thôi;

Cũng như vậy với ô chứa số biểu thị của năm của lịch cần làm.

Sư phụ muốn nói đến Validation chăng? Vẫn copy/paste giá trị tào lao vào được mà sư phụ
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
Hic, Thế này mà là mới bắt đầu ah?
Em con if với then lằng nhà lằng nhằng

Cảm ơn bạn đã quan tâm!

Ở đâu mà bạn tránh được "IF . . . Then"!
 
Upvote 0
Bài tập: Xác định "Ngày của cha" hàng năm bằng hàm tự tạo.

Các bạn viết giúp hàm tự tạo để khi nó được cung cấp con số chỉ năm (1930,. . . ,2029) bất kì, thì hàm trả về ngày chủ nhật thứ ba của tháng sáu năm đó.
 
Upvote 0
Các bạn viết giúp hàm tự tạo để khi nó được cung cấp con số chỉ năm (1930,. . . ,2029) bất kì, thì hàm trả về ngày chủ nhật thứ ba của tháng sáu năm đó.

Em chơi:

PHP:
Function findDate(year, Optional month, Optional day_of_week, Optional nth)    
    If IsMissing(month) Then month = 6    
    If IsMissing(day_of_week) Then day_of_week = 1    
    If IsMissing(nth) Then nth = 3    

    findDate = DateSerial(year, month, 1 + 7 * nth) - Weekday(DateSerial(year, month, 8 - day_of_week))
End Function

' hoặc ngắn hơn:

Function findDate(year, Optional month = 6, Optional day_of_week = 1, Optional nth = 3)
    findDate = DateSerial(year, month, 1 + 7 * nth) - Weekday(DateSerial(year, month, 8 - day_of_week))
End Function

Sử dụng:
Year: năm cần tính​
Month: tháng cần tính (mặc định: tháng 6)
day_of_week: ngày cần tính trong tuần( mặc định chủ nhật = 1)
nth: là day_of_week thứ mấy (mặc định thứ 3)​

PHP:
findDate(2015) = 6/21/2015 
findDate(2014) = 6/15/2014
 
Lần chỉnh sửa cuối:
Upvote 0
Các bạn viết giúp hàm tự tạo để khi nó được cung cấp con số chỉ năm (1930,. . . ,2029) bất kì, thì hàm trả về ngày chủ nhật thứ ba của tháng sáu năm đó.
nhìn bài này em nhớ lại ngày xưa đi học vi tính lấy bằng A bị thầy giáo đố 1 bài đơ luôn :
đếm xem 1 năm bất kì có bao nhiêu cái thứ 6 ngày 13 ?
 
Upvote 0
nhìn bài này em nhớ lại ngày xưa đi học vi tính lấy bằng A bị thầy giáo đố 1 bài đơ luôn :
đếm xem 1 năm bất kì có bao nhiêu cái thứ 6 ngày 13 ?

Toán vi tính khác với VBA. Trong VBA có sẵn nhiều hàm làm việc với ngày tháng. Trong cái ngôn ngữ nào đó thầy giáo bạn dùng để dạy vi tính chưa chắc có. Phương pháp phân tích giải thuật hầu như hoàn toàn khác nhau.
 
Upvote 0
Công thức này gợi í cho các bạn mới bắt đầu VBA:

=DATE(AA1,6,22)-WEEKDAY(DATE(AA1,6,21))

nhìn bài này em nhớ lại ngày xưa đi học vi tính lấy bằng; Thầy giáo đố luôn bài :
đếm xem 1 năm bất kì có bao nhiêu cái thứ 6 ngày 13 ?

PHP:
Option Explicit
Function Thu6Ngay13(Nam%)
 Dim J%, Dat As Date, Dg As Byte
 ReDim Arr(1 To 12, 1 To 1)
 
 For J = 1 To 12
    Dat = DateSerial(Nam, J, 13)
    If Weekday(Dat) = 6 Then
        Dg = Dg + 1:        Arr(Dg, 1) = Format(Dat, "mm/dd/yy")
    End If
 Next J
 Thu6Ngay13 = Arr()
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Bây giờ đố ngược lại thầy giáo, không dùng vòng lặp, không dùng hàm ngày tháng, làm cách nào?
- Lập bảng tra ứng với ngày 13/1 là thứ mấy và năm nhuận hay không thì cả năm có mấy thứ 6 ngày 13, bước này cộng bằng tay rồi lưu vào biến mảng.
- Tính thứ ngày 13 /1 theo công thức:
A=y + int(y/4) -int(y/100) +int(y/400)+4
Mod(A, 7) sẽ là thứ trong tuần. - Xác định năm nhuận hay không ( ((y mod 4=0) and (y mod 100 <>0)) or (y mod 400=0) ).
- Tìm số thứ 6 trong mảng ở bước 1.
 
Upvote 0
- Lập bảng tra ứng với ngày 13/1 là thứ mấy và năm nhuận hay không thì cả năm có mấy thứ 6 ngày 13, bước này cộng bằng tay rồi lưu vào biến mảng.
- Tính thứ ngày 13 /1 theo công thức:
A=y + int(y/4) -int(y/100) +int(y/400)+4
Mod(A, 7) sẽ là thứ trong tuần. - Xác định năm nhuận hay không ( ((y mod 4=0) and (y mod 100 <>0)) or (y mod 400=0) ).
- Tìm số thứ 6 trong mảng ở bước 1.

Đại khái là vậy. Nguyên tắc giải bài này nằm ở chỗ sự suy luận về con tính, trái với nguyên tắc VBA là cố gắng dùng những công cụ có sẵn để làm việc.

Đó là lý do tôi đưa câu hỏi này ở đây (hộp bài tập). Bài này chỉ cần hiểu con toán là xong, viết code là vấn đề nhỏ.
 
Upvote 0
Đại khái là vậy. Nguyên tắc giải bài này nằm ở chỗ sự suy luận về con tính, trái với nguyên tắc VBA là cố gắng dùng những công cụ có sẵn để làm việc.

Đó là lý do tôi đưa câu hỏi này ở đây (hộp bài tập). Bài này chỉ cần hiểu con toán là xong, viết code là vấn đề nhỏ.

Em lười quá, cũng chẳng suy luận nữa, người ta suy luận hết rồi =))
https://en.wikipedia.org/wiki/Deter...bular_method_to_calculate_the_day_of_the_week
 
Upvote 0
Em lười quá, cũng chẳng suy luận nữa, người ta suy luận hết rồi =))
https://en.wikipedia.org/wiki/Deter...bular_method_to_calculate_the_day_of_the_week

Chịu thua không rõ bạn "lười" chỗ nào. Đề bài là "số ngày thứ 6, 13". Cái link bạn đưa ra tìm ngày trong tuần. Trừ phi do tôi dốt tiếng Anh.
Tìm ngày trong tuần chỉ là một bước. Tìm số ngày thứ sau là bước nữa.
 
Upvote 0
Các bạn viết giúp hàm tự tạo để khi nó được cung cấp con số chỉ năm (1930,. . . ,2029) bất kì, thì hàm trả về ngày chủ nhật thứ ba của tháng sáu năm đó.

Em cũng tham gia để học

Mã:
Public Function FatherDay(ByVal yr As Date)Dim i%, k%, myDay As Date
If yr < 1900 Then Exit Function
For i = 1 To 30
myDay = DateSerial(yr, 6, i)
    If Weekday(myDay) = 1 Then
    k = k + 1
        If k = 3 Then
           FatherDay = Format(DateSerial(yr, 6, i), "dd / MM / yyyy")
           Exit Function
        End If
    End If
Next i
End Function

Các Thầy cho em hỏi muốn bẫy lỗi yr là chuỗi thì exit mình làm thế nào ạ
 
Upvote 0
Mình có vài í thế này:

(1) Câu lệnh
MyDay = DateSerial(yr, 6, i)
Như vậy ta cần cung cấp cho biến "yr" là 1 số, như 2001,2009,. . .
Đối chiếu với với câu

Public Function FatherDay(ByVal yr As Date)
là khập khiển & dễ gây hiểu lầm.
Bạn nên sửa lại câu này như:
Public Function FatherDay(ByVal yr As Integer)

(2) Bạn có thể không xài vòng lặp, mà lập bảng
Nếu 1/6/yr là chủ nhật thì ngày của cha là xx/06/yr (xx=?)
Nếu 1/6/yr là thứ hai thì ngày của cha là xx/06/yr (= xx +6)
. . . . . . . . .
. . . . . . . . .
Sau khi có bảng rồi, ta sẽ rút ra 1 qui luật khác ngắn hơn; đó là
=DATE(AA1,6,22)-WEEKDAY(DATE(AA1,6,21)) chính là "Ngày của Cha";
Đổi công thức này sang sang thành câu lệnh VBA là quá dễ; chỉ việc thay [AA1] bằng yr là xong thôi & trong tầm tay của bạn.

Chúc bạn có nhiều niềm vui trong công cuộc chinh fục VBA
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom