Những bài tập VBA đơn giản dành cho những người mới bắt đầu (2 người xem)

  • Thread starter Thread starter SA_DQ
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

SA_DQ

/(hông là gì!
Thành viên danh dự
Tham gia
8/6/06
Bài viết
14,602
Được thích
22,922
Nghề nghiệp
U80

Bài 01

Macro to merge values from one column into one cell and retain source formatting.
Example:

Source:
A1= "It is going to cost "
A2= "$1000.00" (A2 is formatted to underline value)

Destination: (desired result)
B2= "It is going to cost $1000.00" (A2 value is still underlined)

Đề bài có thể tóm gọn lại như sau:

Trên cột [A:A] ta có những dòng thuyết minh & dưới nó là những con số đã được định dạng bằng nhiều cách khác nhau để fân biệt như chữ in nghiên, chữ số được tô đậm hay Font có màu đỏ,. . . .

Macro có nhiệm vụ: Hễ dòng nào có số thì ô bên fải liền kề cần được mang nội dung cũa ô trên ô có số & bản thân số của ô đang xét; Mặt khác định dạng ô giống với ô mang số liệu

Chúc thành công
--=0
--=0

Bảng liệt kê:

TT | Tên bài | Tại | Diễn giải
01|Bài tập 01|#1|Nối chuỗi & định dạng
02|Bài tập 02 | #11|Thống kê số lần lặp
03|Bài tập 03|#19|Trích lọc danh sách theo năm
04|Bài tập 04|#27|Thêm dòng theo số liệu tháng - năm
05|Bài tập 05|#31|Tổng hợp số liệu hoạt động theo từng kỳ (tháng)
06|Bài tập 06|#73|Ghí chú ngày có chi fí lớn nhất trong từng tháng khảo sát
07|Bài tập 07|#84|Thêm dòng tính tổng, sau khi đã thống kê số liệu
08|Bài tập 08|#103|Kẻ dòng, viền khung & format báo cáo hoàn chỉnh
09| BT Fần B | #206 | (Ở đây có bảng liệt kê riêng)


Rất mong các bạn ủng hộ & hỗ trợ tối đa.

! --=0 --=0 --=0
 
Chỉnh sửa lần cuối bởi điều hành viên:
Thừa nhận top này khá hay và quá là bổ ích, phát triển khá nhanh, Xin cám ơn Chủ tóp và tất cả các thầy và bạn bè anh chị em trong đại gia đình GPE đã đống gốp cho tóp này.
 
Upvote 0
Sau khi thống kê số liệu theo yêu cầu của các bài trước (Xem tại bài #41), ta cần thêm dòng tổng cộng, như sau

Mọi người giải bài tập hết rồi, em "đi sau" vậy.
Giải bài tập 7:
Mã:
Public Sub Xuan4()
Application.ScreenUpdating = False
Dim Rng As Range, Cll As Range, Dau As Long, Cuoi As Long, I As Long, TC As Double
Dim Tem As Long, SoThang As Long, Thang As Long, Mx As Double, Tong As String, Xuan As String
With Sheets("ChiFi")
    Set Rng = .Range(.[A4], .[A65000].End(xlUp))
End With
With Sheets("sheet1")
Xuan = .[B7].Value: Tong = .[B6].Value
.[A8:D1000].ClearContents
Dau = DateSerial(Year(.[C4]), Month(.[C4]), 1)
Cuoi = DateSerial(Year(.[C5]), Month(.[C5]), 1)
SoThang = DateDiff("m", Dau, Cuoi) + 1
For I = 1 To SoThang
    Mx = 0
    Thang = DateSerial(Year(Dau), Month(Dau) + I - 1, 1)
    .Cells(I + 7, 1).Value = I
    .Cells(I + 7, 2).Value = Xuan & " " & Format(Thang, "mm/yyyy")
    For Each Cll In Rng
        If Cll >= .[C4] And Cll <= .[C5] Then
                Tem = DateSerial(Year(Cll), Month(Cll), 1)
            If Tem = Thang Then
                .Cells(I + 7, 3).Value = .Cells(I + 7, 3).Value + Cll.Offset(, 4).Value
                TC = TC + Cll.Offset(, 4).Value
                If Mx < Cll.Offset(, 4).Value Then
                    Mx = Cll.Offset(, 4).Value
                    .Cells(I + 7, 4).Value = Cll.Value
                End If
            End If
        End If
    Next
Next I
End With
Range("B65000").End(xlUp).Offset(1).Value = Tong
Range("B65000").End(xlUp).Offset(, 1).Value = TC
Set Rng = Nothing
Application.ScreenUpdating = True
End Sub
 

File đính kèm

Upvote 0
Bài tập số 8: Kẻ dòng, viền khung bảng dữ liệu theo thẩm mỹ mỗi người & . . . .

(*) Thêm dưới khung viền fía fải là (Địa điểm & ngày tháng năm (lập B/C))

(*) Thêm dòng <Người lập bảng> & <Người kiểm soát.> cân đối trong bảng B/C


(Đến giờ các bạn sẽ thấy rằng công việc sẽ giảm thiểu, nếu ta không quá lệ thuộc vô VBA)


Gần xong loạt bài này rồi, & chúc các bạn nhiều thành công!
 
Upvote 0
Thủ tục này hơi lạ hen! Sao lại Selection.AutoFilter ở dòng đầu và dòng cuối nhỉ? Tác dụng của nó là gì và nó lọc cái gì vậy?
uh hen thủ tục trên là thừa rùi như vậy chắc là được:
PHP:
Sub tong2()
[B5:B997].SpecialCells(4).EntireRow.Hidden = True
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn bạn Nghĩa, mình viết được thế đã đủ "tắc thở", Thấy nó chạy, không chống lại là mừng rồi . Học thêm được món bỏ "cam quýt" của bạn, chạy cho nhanh . Mình nhớ rồi ! xin cám ơn bạn .

Nói như vậy chưa phải là chuẩn, dùng with đôi khi lại nhanh hơn chứ không phải làm chậm. Tôi nói code của bạn chậm là vì bạn dùng nhiều cách để thực hiện một hành động. Mục đích của bạn là từ A đến kết kết quả D, bạn lại phải đi vòng vèo từ A > B > C > D thay vì chỉ cần đi tắt A > D mà không cần thông qua 2 chặng đường B và C.

Khi nào dùng With và khi nào không? Khi một object, một control hay một cái gì đó xảy ra nhiều hành động, sự kiện trên chính nó thì ta dùng with. Thông thường thì từ 3 sự việc liên quan đến nó thì ta nên dùng with để code nó ngắn gọn dễ hiểu và tường minh.

Ví dụ, khi ta viết về một thủ tục trên một cell, về định dạng chẳng hạn:

Thay vì ta viết như vầy, tuy nó chẳng sai tí nào cả:

Mã:
Sub Macro1()

    Range("C5").Select
    Range("C5").Font.ColorIndex = 3
    Range("C5").Interior.ColorIndex = 38
    Range("C5").Interior.Pattern = xlSolid
    Range("C5").HorizontalAlignment = xlCenter
    Range("C5").VerticalAlignment = xlBottom
    Range("C5").WrapText = False
    Range("C5").Orientation = 0
    Range("C5").AddIndent = False
    Range("C5").IndentLevel = 0
    Range("C5").ShrinkToFit = False
    Range("C5").ReadingOrder = xlContext
    Range("C5").MergeCells = False
    Range("C5").Font.Bold = True
    Range("C5").Font.Italic = True
    Range("C5").Font.Underline = xlUnderlineStyleSingle
    Range("C5").Borders(xlDiagonalDown).LineStyle = xlNone
    Range("C5").Borders(xlDiagonalUp).LineStyle = xlNone
End Sub

Thì ta có thể dùng with như sau:

Mã:
Sub Macro1()
    With Range("C5")
        .Select
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlBottom
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
        .Borders(xlDiagonalDown).LineStyle = xlNone
        .Borders(xlDiagonalUp).LineStyle = xlNone
        
        With .Interior
            .ColorIndex = 38
            .Pattern = xlSolid
        End With
        
        With .Font
            .ColorIndex = 3
            .Bold = True
            .Italic = True
            .Underline = xlUnderlineStyleSingle
        End With
    End With
End Sub

Vì thế, đôi khi thiếu vitamin C ta nên ăn cam quýt cho ta có đủ khoáng chất là như vậy!
 
Upvote 0
Nói như vậy chưa phải là chuẩn, dùng with đôi khi lại nhanh hơn chứ không phải làm chậm. Tôi nói code của bạn chậm là vì bạn dùng nhiều cách để thực hiện một hành động. Mục đích của bạn là từ A đến kết kết quả D, bạn lại phải đi vòng vèo từ A > B > C > D thay vì chỉ cần đi tắt A > D mà không cần thông qua 2 chặng đường B và C.

Vì thế, đôi khi thiếu vitamin C ta nên ăn cam quýt cho ta có đủ khoáng chất là như vậy!

Thực ra khi bắt đầu học, em nghĩ là phải đi từng bước, từ A ->B->C->D. Khi nẵm rõ bản chất mới có thể "đi tắt, đón đầu". Việc "đốt cháy giai đoạn" cũng tốt nhưng sẽ khó cho những người mới bắt đầu.

(tuy nhiên cũng tùy người, có những người học theokiểu "đốt cháy giai đoạn" vẫn tiếp thu tốt kiến thức như ...anh Ếch Xanh đó...hihihi)
Thiếu vitamin C, ăn nhiều thứ cho thêm chất, nhưng ăn nhiều quá sẽ bội thực và nhai không kỹ sẽ đau dạ dày. Hic hic...
 
Lần chỉnh sửa cuối:
Upvote 0
Nói như vậy chưa phải là chuẩn, dùng with đôi khi lại nhanh hơn chứ không phải làm chậm. Tôi nói code của bạn chậm là vì bạn dùng nhiều cách để thực hiện một hành động. Mục đích của bạn là từ A đến kết kết quả D, bạn lại phải đi vòng vèo từ A > B > C > D thay vì chỉ cần đi tắt A > D mà không cần thông qua 2 chặng đường B và C.

Khi nào dùng With và khi nào không? Khi một object, một control hay một cái gì đó xảy ra nhiều hành động, sự kiện trên chính nó thì ta dùng with. Thông thường thì từ 3 sự việc liên quan đến nó thì ta nên dùng with để code nó ngắn gọn dễ hiểu và tường minh.

Ví dụ, khi ta viết về một thủ tục trên một cell, về định dạng chẳng hạn:

Thay vì ta viết như vầy, tuy nó chẳng sai tí nào cả:

Mã:
Sub Macro1()

    Range("C5").Select
    Range("C5").Font.ColorIndex = 3
    Range("C5").Interior.ColorIndex = 38
    Range("C5").Interior.Pattern = xlSolid
    Range("C5").HorizontalAlignment = xlCenter
    Range("C5").VerticalAlignment = xlBottom
    Range("C5").WrapText = False
    Range("C5").Orientation = 0
    Range("C5").AddIndent = False
    Range("C5").IndentLevel = 0
    Range("C5").ShrinkToFit = False
    Range("C5").ReadingOrder = xlContext
    Range("C5").MergeCells = False
    Range("C5").Font.Bold = True
    Range("C5").Font.Italic = True
    Range("C5").Font.Underline = xlUnderlineStyleSingle
    Range("C5").Borders(xlDiagonalDown).LineStyle = xlNone
    Range("C5").Borders(xlDiagonalUp).LineStyle = xlNone
End Sub

Thì ta có thể dùng with như sau:

Mã:
Sub Macro1()
    With Range("C5")
        .Select
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlBottom
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
        .Borders(xlDiagonalDown).LineStyle = xlNone
        .Borders(xlDiagonalUp).LineStyle = xlNone
        
        With .Interior
            .ColorIndex = 38
            .Pattern = xlSolid
        End With
        
        With .Font
            .ColorIndex = 3
            .Bold = True
            .Italic = True
            .Underline = xlUnderlineStyleSingle
        End With
    End With
End Sub

Vì thế, đôi khi thiếu vitamin C ta nên ăn cam quýt cho ta có đủ khoáng chất là như vậy!
Trời ơi! không phải "Tắc thở" mà là "Tắc tử" luôn. Cám ơn bạn! Thực ra là cám ơn "thầy" thì đúng hơn, Nhưng thấy chiêu bài "Độc thân,vui tính" nhà em không dám chào là thầy, sợ có cô nào rắp tâm "nhòm" đến lại chạy "mất dép" thì khổ; Thực ra có người phụ nữ ở bên cạnh, lắm lúc "hay" đáo để.
Người ta nói "Trâu con không sợ hổ", nhà em cứ xông ra, nếu "đụng" phải ai, người đó chịu, không tránh trẻ con, tự mình có lỗi nhé .
 
Lần chỉnh sửa cuối:
Upvote 0
Mọi người giải bài tập hết rồi, em "đi sau" vậy.
Giải bài tập 7:

Code của XN82 đã thực hiện xong các nhiệm vụ đề ra. Nhưng có thể cải tiến để tăng tốc độ hơn, theo gợi í sau:

Ta tính ra được mốc thời gian đầu & cuối của từng kỳ/tháng; 2 trị này cung cấp cho vùng Criteria & lọc số liệu kỳ/tháng đó ra 1 vùng trống nào đó;

Sau khi lọc rồi thì ta có thể xài hàm SUMIF() như chàng độc thân Ba Tê, hay DSUM() (mình khoái khẩu) để tính & điền vô bảng biểu báo cáo;
(Nói là khoái khẩu vì ta có thể xài DMAX() để hoàn thành #7 1 cách trọn vẹn mà chưa cần đến E2007)

Lúc nào rỗi, bạn nào thử xem sao (!?!)

Lúc đó ta có số liệu về thời lượng cho mỗi 1 fương cách của chúng ta; & như vậy sự thích thú VBA sẽ ta lên trong ta!

(húc thành công.
 
Upvote 0
Thực ra khi bắt đầu học, em nghĩ là phải đi từng bước, từ A ->B->C->D. Khi nẵm rõ bản chất mới có thể "đi tắt, đón đầu". Việc "đốt cháy giai đoạn" cũng tốt nhưng sẽ khó cho những người mới bắt đầu.

(tuy nhiên cũng tùy người, có những người học theo kiểu "đốt cháy giai đoạn" vẫn tiếp thu tốt kiến thức như ...anh Ếch Xanh đó...hihihi)
Thiếu vitamin C, ăn nhiều thứ cho thêm chất, nhưng ăn nhiều quá sẽ bội thực và nhai không kỹ sẽ đau dạ dày. Hic hic...

Thật ra With ... End With là một anh đại diện cho một đối tượng nào đó, anh này cũng sẽ không chịu trách nhiệm nếu hành động liên quan đến anh ta mà không có dấu chấm (.) đứng trước hành động của mình. Thấy dấu chấm tức là anh ta nhận nhiệm vụ, còn không anh ta bỏ qua hoặc thậm chí còn cự nự lên nữa!

Việc này ta nên đốt cháy giai đoạn vì bản chất của nó cũng không có gì là quá khó khăn phải không!

Liên quan đến nó còn có việc khai báo biến, anh biến này (chẳng phải anh ta làm biếng đâu nha) cũng là một đại diện cho một kiểu data type nào đó mà sau này bác Sa sẽ hướng dẫn cho các bạn.
 
Upvote 0
Code của XN82 đã thực hiện xong các nhiệm vụ đề ra. Nhưng có thể cải tiến để tăng tốc độ hơn, theo gợi í sau:

Ta tính ra được mốc thời gian đầu & cuối của từng kỳ/tháng; 2 trị này cung cấp cho vùng Criteria & lọc số liệu kỳ/tháng đó ra 1 vùng trống nào đó;

Sau khi lọc rồi thì ta có thể xài hàm SUMIF() như chàng độc thân Ba Tê, hay DSUM() (mình khoái khẩu) để tính & điền vô bảng biểu báo cáo;
(Nói là khoái khẩu vì ta có thể xài DMAX() để hoàn thành #7 1 cách trọn vẹn mà chưa cần đến E2007)

Lúc nào rỗi, bạn nào thử xem sao (!?!)

Lúc đó ta có số liệu về thời lượng cho mỗi 1 fương cách của chúng ta; & như vậy sự thích thú VBA sẽ ta lên trong ta!

(húc thành công.
Em thấy dùng ado tốc độ cũng không đến nổi chậm mà anh?
 
Upvote 0
Upvote 0
Upvote 0
Bạn nghĩ ADO đơn giản hơn VBA sao? Nếu bạn có sẳn cái sườn và thay thế, lắp ghép vào thì đó cũng là chuyện dễ, tuy nhiên, bạn biết bản chất của nó như thế nào không? Mình chỉ hỏi ở mức độ bạn hiểu về nó.
Bản chất là sao bạn? Mức độ hiểu của mình chỉ đủ để áp dụng cho đề bài này, vậy theo bạn bản chất của nó là gì? Bạn nói có cái sườn rồi lắp ghép vào? vậy muốn lắp ghép vào thì có hiểu mới có thể lắp ghép. Tôi không nói ADO đơn giản hơn VBA mà tôi chỉ muốn nói là tôi muốn đưa ra 1 trong muôn triệu cách để giải quyết vấn đề. Bạn hiểu chứ?
 
Upvote 0
Bản chất là sao bạn? Mức độ hiểu của mình chỉ đủ để áp dụng cho đề bài này, vậy theo bạn bản chất của nó là gì? Bạn nói có cái sườn rồi lắp ghép vào? vậy muốn lắp ghép vào thì có hiểu mới có thể lắp ghép. Tôi không nói ADO đơn giản hơn VBA mà tôi chỉ muốn nói là tôi muốn đưa ra 1 trong muôn triệu cách để giải quyết vấn đề. Bạn hiểu chứ?

ADO là một dạng, nôm na là "siêu liên kết", nó có thể kết nối ngay trên file đang đóng và lấy dữ liệu trên đó. Có thể nói rằng sử dụng nó để lấy dữ liệu, truy xuất dữ liệu từ một file đang mở, liên kết với một file đang không hoạt động thì đó chính là sức mạnh của ADO.

Quay lại với code của VBA nó hoạt động trên những file đang mở và chỉ lấy được dữ liệu của file đang được kích hoạt mà thôi. Vậy thì, ngay tại file mình đang mở và mình thực hiện ngay chính trên file này thì mình không cần gì phải dùng ADO để thực hiện công việc của mình. Điều đó cũng giống như là: một căn nhà có 2 phòng, thay vì từ phòng này mình mở cửa phòng kia bằng chìa khóa mình sẳn có để vào thì mình lại chạy một vòng rồi tìm anh thợ mở khóa để mở ngay cái phòng đó mà mình đang giữ chìa khóa.

Như thế giống như việc "Dùng dao mỗ trâu để cắt cổ gà" vậy đó bạn.

tôi muốn đưa ra 1 trong muôn triệu cách để giải quyết vấn đề

Ngay chính công thức trên sheet, dùng hàm SUM, SUMIF, SUBTOTAL, SUMPRODUCT... thậm chí cộng từng mục cũng đều cho ra kết quả như nhau, vậy sao ta không chọn hàm SUM để làm cái rẹt cho xong nhỉ?

Huống chi tiêu đề của topic này là "dành cho người mới bắt đầu", sao mình phải đưa trường hợp dùng ADO vào trong đây?
 
Lần chỉnh sửa cuối:
Upvote 0
(*) Thêm dưới khung viền fía fải là (Địa điểm & ngày tháng năm (lập B/C))

(*) Thêm dòng <Người lập bảng> & <Người kiểm soát.> cân đối trong bảng B/C


(Đến giờ các bạn sẽ thấy rằng công việc sẽ giảm thiểu, nếu ta không quá lệ thuộc vô VBA)


Gần xong loạt bài này rồi, & chúc các bạn nhiều thành công!

Tiếp tục bài 8 (Hic, em chỉ kẻ vẽ khung viền được như thế này thôi)

Mã:
Sub Xuan5()
Worksheets("Sheet1").Activate
With Range([B8], [B1000].End(xlUp)).Offset(, -1).Resize(, 4)
.Borders.LineStyle = xlContinuous
 End With
With Range("B1000").End(xlUp)
 .Offset(1, 1) = "Ngay        thang          nam"
 .Offset(2) = "Nguoi Lap Bang"
 .Offset(2, 2) = "Nguoi Kiem Soat"
 End With
 End Sub
 

File đính kèm

Upvote 0
ADO là một dạng, nôm na là "siêu liên kết", nó có thể kết nối ngay trên file đang đóng và lấy dữ liệu trên đó. Có thể nói rằng sử dụng nó để lấy dữ liệu, truy xuất dữ liệu từ một file đang mở, liên kết với một file đang không hoạt động thì đó chính là sức mạnh của ADO.

Quay lại với code của VBA nó hoạt động trên những file đang mở và chỉ lấy được dữ liệu của file đang được kích hoạt mà thôi. Vậy thì, ngay tại file mình đang mở và mình thực hiện ngay chính trên file này thì mình không cần gì phải dùng ADO để thực hiện công việc của mình. Điều đó cũng giống như là: một căn nhà có 2 phòng, thay vì từ phòng này mình mở cửa phòng kia bằng chìa khóa mình sẳn có để vào thì mình lại chạy một vòng rồi tìm anh thợ mở khóa để mở ngay cái phòng đó mà mình đang giữ chìa khóa.

Như thế giống như việc "Dùng dao mỗ trâu để cắt cổ gà" vậy đó bạn.
Việc kết nối hay truy vấn thì ai mà chẳng biết nhưng bạn dùng từ "Bản chất" tôi chưa hiểu cái "Bản chất" mà bạn diễn tả. Còn việc dùng dao mổ trâu để giết gà thì mình cho rằng là bạn dùng cảm quan của bạn để mà phán đoán 1 cách phiếm diện. Việc kết nối và truy vấn với tốc độ nhanh như thế thì tội gì mà chẳng dùng nó, điều này chắc bạn hiểu nhỉ. Bạn lấy ví dụ về căn phòng tôi thấy tức cười quá, nó đâu ăn nhập gì đến cái này, cái chìa khóa của 2 căn phòng đó bạn đang giữ mà chìa khóa đó có nhiều loại, chìa khóa của chính nó hay là chìa khóa vạn năng... Cho dù là chìa khóa nào đi nữa thì mục đích cuối cùng là mở được cửa phòng đó nhanh gọn lẹ là được. Bạn hiểu ý tôi muốn nói gì chư?
 
Lần chỉnh sửa cuối:
Upvote 0
Tiếp tục bài 8 (Hic, em chỉ kẻ vẽ khung viền được như thế này thôi)

Mã:
Sub Xuan5()
Worksheets("Sheet1").Activate
With Range([B8], [B1000].End(xlUp)).Offset(, -1).Resize(, 4)
.Borders.LineStyle = xlContinuous
 End With
With Range("B1000").End(xlUp)
 .Offset(1, 1) = "Ngay        thang          nam"
 .Offset(2) = "Nguoi Lap Bang"
 .Offset(2, 2) = "Nguoi Kiem Soat"
 End With
 End Sub

Hi Hi , cái code này bấm 2 lần sao nhỉ
---------------
Spam 1 tý, mình cũng đang học hỏi đó!
 
Upvote 0
Web KT

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

Back
Top Bottom