Bài 01: Tổng hợp bài thực hành cơ bản về VBA

Liên hệ QC

TUYEN DO VAN

Thành viên mới
Tham gia
12/4/18
Bài viết
11
Được thích
1
Giới tính
Nam
Mình mới tham gia học VBA, đang tập giải các bài tập cơ bản, nên mình post tại đây hy vọng được giao lưu học hỏi cùng các bạn.
Bài 01: In ra một dãy số từ 1 đến 100 và kiểm tra xem
  • Số nào chỉ chia hết cho 3 thì in ô đó là GP
  • Số nào chỉ chia hết cho 5 thì in ô đó là EC
  • Số nào vừa chia hết cho 3 và 5 thì in ô đó là GPEC
Mình sẽ đưa lời giải lên sau, mọi người có hứng thú thì giải thử nhé. Cùng nhau trao đổi để cùng tiến bộ nào.
 

File đính kèm

  • ex01.jpg
    ex01.jpg
    14.9 KB · Đọc: 42
hàm có sẵn trong Exel hay thật đó, rất nhanh mình cố gắng ghi nhớ.
Về cơ bản thì mình muốn viết code một cách mềm mại mà khi người sử dụng có thay đổi gì về số liệu thì code vẫn chạy và đưa ra kết qua cho người dùng. Giả sử bảng thống kê tìm giá trị lớn nhất một cột và phải thỏa mãn thêm một điều kiện A nào đó chẳng hạn thì hàm Max này có vẻ hơi khó sử dụng
Dĩ nhiên muốn ra kết quả thì có nhiều cách làm, trong bài bạn ghi thì đâu có nói là dùng vòng lặp để kiểm tra, tôi chỉ đưa ra kết quả để các bạn mới làm quen với VBA có thêm được cách để làm. Còn vận dụng bài toán theo chữ mà tôi tô đỏ như trên vào thực tế thì cũng có nhiều cách, cũng đâu nhất thiết phải dùng vòng lặp như bạn, vì dùng vòng lặp mà duyệt qua từng cell như bạn với dữ liệu lớn thì tốc độ rất hạn chế.
 
Upvote 0
tiếp bài 03 đi a tuyen gì đó ơi iiiiiiiiiiiii. sẵn thì a gửi vài chục bài lun í hi
Đây là Bài 03: Trình bày phép nhân các bạn nêu từng bước thực hiện phép nhân ra nhé
giả sử 14 x 12 thì ta sẽ diễn giải nó ra như các bước :
  1. lấy 2 nhân 14 rồi ghi tuần tự vào các cells
  2. lấy 1 nhân 14 rồi ghi vào dòng kế tiếp
  3. cộng tổng hai dòng (1) và (2) để được kết quả của phép nhân
Mình có gửi hình đính kèm, các bạn làm thử xem sao nhé(Bài này mình cũng chưa làm được :()
 
Upvote 0
Thực tế cho thấy rằng: đừng bao giờ cố viết code "thi đấu" với mấy hàm có sẵn của anh Bill, bởi kết quả thua là cái chắc. Nếu có nêu ví dụ để làm bài tập thì cố mà "né" những thứ anh Bill đã viết, không thì cứ một chút lại phát hiện ra sơ hở cần cải thiện và cải thiện miết vẫn cứ thấy sơ hở
 
Upvote 0
thua1 = 14 ' thừa 1
thua2 = 12 ' thừa 2
' nhân 2 thừa số bằng cách nhân từng hàng đơn vị và cộng lại
sthua2 = Cstr(thua2) ' đổi thành string
cothua2 = Len(thua2) ' độ lớn của thừa 2
sboi2 = Cstr(10 ^ (cothua2-1)) ' độ lớn của thừa 2 tính trên đơn vị
tich = 0 ' tích số, kết quả
For i = 1 to cothua2
tich = tich + thua1 * Cint(Mid(sthua2, cothua2 - i + 1, 1)) * CLong(Left(sboi2, i))
Next i

Yêu cầu sao làm vậy, chứ trong giải thuật thực tế, ngừoi ta nhân ngược từ trái sang phải, code đẹp hơn.
 
Upvote 0
Thực tế cho thấy rằng: đừng bao giờ cố viết code "thi đấu" với mấy hàm có sẵn của anh Bill, bởi kết quả thua là cái chắc. Nếu có nêu ví dụ để làm bài tập thì cố mà "né" những thứ anh Bill đã viết, không thì cứ một chút lại phát hiện ra sơ hở cần cải thiện và cải thiện miết vẫn cứ thấy sơ hở
Không biết thì lấy gì mà né?
Cho nên nguyên tắc là trước khi học VBA thì phải học tất cả những hàm và công cụ của Excel, từ căn bản đến nâng cao. Trừ những hàm chuyên môn thì có thể châm chế chưa cần học (điển hình là nhóm hàm thống kê)
 
Upvote 0
Mình trả bài thế này được không nhỉ?
Mã:
Sub inkq()
  for i = 1 to 100
       if i mod 3 = 0 then
           cells(i,1) = "GP"
      elseif i mod 5 = 0 then
          cells(i,1) = "EC"
    elseif i mod 15 = 0 then
          cells(i,1) = "GPEC"
   else
          cells(i,1) = i
  end if
  next

End Sub

Lô gic của bạn sai rồi. Nếu xét If-ElseIf phải xét 15 trước 3 và 5.

Đây là lời giải bài 02 của mình viết
Mã:
Sub Ex02()
Dim i As Integer
Dim temp As Integer
For i = 1 To Cells(Rows.count, 1).End(xlUp).Row
   If Cells(i, 1) > temp Then
    temp = Cells(i, 1)
    End If
Next
Cells(2, 3) = temp
End Sub

Bài tìm lớn/nhỏ nhất trong một mảng là bài tập căn bản của lập trình.
Giải thuật mà 99% mọi người chấp nhận là khởi số lớn/nhỏ nhất bằng phần tử đầu tiên của mảng và duyệt từ phần tử 2 trở đi.
(ở bài #11 tôi chỉ viết hàm tượng trưng để chứng tỏ rằng hầu hết các code vòng lặp đều có thể thay bằng đệ quy)

mx = mang(LBound(mang))
for i = LBound(mang) + 1 to UBound(mang)
if mang(i) > mx then mx = mang(i)
next i
 
Upvote 0
Bàn về bài 1:
Tuy lô gic mod là lô gic căn bản, nhưng mặt khác đề bài 1 là đề bài đặc biệt mà giải thuật có thể hơi khác 1 chút tùy theo ngôn ngữ.
Điển hình là các ngôn ngữ dòng họ C (C++, Java,...) có con toán tự tăng/giảm cho nên dùng phương pháp đếm có thể hiệu quả hơn (con toán mod tốn vài lần tính, tuy rằng số nguyên tính rất nhanh nhưng chia+nhân+trừ vẫn gồm 3 con tính)
Code C:
for (int i = 1, boi3 = 0, boi 5 = 0, boi35 = 0; i <= 100; i++) {
// in ra i ở đây
if (++boi3 >= 3) {
// in ra GP ở đây
boi3 = 0;
}
if (++boi5 >= 5) {
// in ra PE ở đây
boi5 = 0;
}
if (++boi35 >= 15) {
// in ra GPE ở đây
boi35 = 0;
}
}
 
Upvote 0
Bàn về bài 3:

Bài này khong hẳn khó nhưng đòi hỏi phân tích và thiết kế cẩn thận trước khi bắt đầu code.
Sự phân tích phức tạp ở chỗ bài đòi hỏi mỗi ô là một chữ số.
Câu hỏi đầu tiên: vậy thì bắt đầu từ ô nào?
Lô gic: số a nhân b thì sẽ có kết quả dài tối đa Len(a) + Len(b)
Như vậy số a sẽ bắt đầu tự cột Len(b) + 1, và tương tự số b sẽ bắt đầu từ Len(a) + 1
Những chỗ còn lại tương đối dễ thiết kế hơn.

Bạn có cách khác là làm ngược số. Hàng đơn vị ở cột 1, hàng chục ở cột 2... Sau khi làm xong thì lộn ngược chúng lại. Cách này dễ hơn cách trên một chút.

Nhưng cách tôi làm thì sẽ là một mảng 2 chiều. Mỗi phần tử là 1 chữ số. Và tôi sẽ làm từ trái sang phải (tức là lộn ngược số). Sau khi tính xong thì tôi lộn lại và chép vào bảng tính.

Chú thích: bài này nếu làm đúng theo tinh thần giả cách nhân tay (tức là nhân và cộng từng chữ số, với số dư đầy đủ) thì đòi hỏi kiến thức sử dụng mảng cao. Vì vậy gọi là "căn bản" thì không đúng. Bạn nào muốn thử tay nghề thì thử. Nhưng tôi không khuyến khích cho người mới học, chỉ tổ nhức đầu mà chả học được bao nhiêu.
 
Lần chỉnh sửa cuối:
Upvote 0
Bàn về bài 3:

Bài này khong hẳn khó nhưng đòi hỏi phân tích và thiết kế cẩn thận trước khi bắt đầu code.
Sự phân tích phức tạp ở chỗ bài đòi hỏi mỗi ô là một chữ số.
Câu hỏi đầu tiên: vậy thì bắt đầu từ ô nào?
Lô gic: số a nhân b thì sẽ có kết quả dài tối đa Len(a) + Len(b)
Như vậy số a sẽ bắt đầu tự cột Len(b) + 1, và tương tự số b sẽ bắt đầu từ Len(a) + 1
Những chỗ còn lại tương đối dễ thiết kế hơn.

Bạn có cách khác là làm ngược số. Hàng đơn vị ở cột 1, hàng chục ở cột 2... Sau khi làm xong thì lộn ngược chúng lại. Cách này dễ hơn cách trên một chút.

Nhưng cách tôi làm thì sẽ là một mảng 2 chiều. Mỗi phần tử là 1 chữ số. Và tôi sẽ làm từ trái sang phải (tức là lộn ngược số). Sau khi tính xong thì tôi lộn lại và chép vào bảng tính.

Chú thích: bài này nếu làm đúng theo tinh thần giả cách nhân tay (tức là nhân và cộng từng chữ số, với số dư đầy đủ) thì đòi hỏi kiến thức sử dụng mảng cao. Vì vậy gọi là "căn bản" thì không đúng. Bạn nào muốn thử tay nghề thì thử. Nhưng tôi không khuyến khích cho người mới học, chỉ tổ nhức đầu mà chả học được bao nhiêu.
Xin lỗi bác nhé, tại hôm qua đưa mấy bài lên các bạn giải nhanh quá, nên đưa bài này lên, thực chất thì mình cũng đang tìm cách giải nó mà chưa tìm ra
 
Upvote 0
Mình trả bài thế này được không nhỉ?
Mã:
Sub inkq()
  for i = 1 to 100
       if i mod 3 = 0 then
           cells(i,1) = "GP"
      elseif i mod 5 = 0 then
          cells(i,1) = "EC"
    elseif i mod 15 = 0 then
          cells(i,1) = "GPEC"
   else
          cells(i,1) = i
  end if
  next

End Sub
Bai này hình như sao sao ý!
15 chia hết cho 3 và 5 thì GPEC mới ổn :p
 
Upvote 0
Mình mới tham gia học VBA, đang tập giải các bài tập cơ bản, nên mình post tại đây hy vọng được giao lưu học hỏi cùng các bạn.
Bài 01: In ra một dãy số từ 1 đến 100 và kiểm tra xem
  • Số nào chỉ chia hết cho 3 thì in ô đó là GP
  • Số nào chỉ chia hết cho 5 thì in ô đó là EC
  • Số nào vừa chia hết cho 3 và 5 thì in ô đó là GPEC
Mình sẽ đưa lời giải lên sau, mọi người có hứng thú thì giải thử nhé. Cùng nhau trao đổi để cùng tiến bộ nào.
Sub demo()
Dim i As Integer

For i = 1 To 100
Application.ActiveCell(i, 1) = i

If Cells(i, 1) Mod 15 = 0 Then
Cells(i, 2) = "GEPC"
ElseIf Cells(i, 1) Mod 3 = 0 Then
Cells(i, 2) = "GC"
ElseIf Cells(i, 1) Mod 5 = 0 Then
Cells(i, 2) = "EC"
End If



Next

End Sub
 
Upvote 0
Sub demo()
Dim i As Integer
For i = 1 To 100
Application.ActiveCell(i, 1) = i
If Cells(i, 1) Mod 15 = 0 Then
Cells(i, 2) = "GEPC"
ElseIf Cells(i, 1) Mod 3 = 0 Then
Cells(i, 2) = "GC"
ElseIf Cells(i, 1) Mod 5 = 0 Then
Cells(i, 2) = "EC"
End If
Next
End Sub
Code dài quá.
Và tuy gặp trường hợp tốt thì chỉ mất một con toán MOD. Nhưng trường hợp xấu thì phải qua 3 con toán Mod. Trong khi có nhiều cách chỉ phải qua 2.
Tuy có theo sát điều kiện nhưng không có chỗ nào nói 3*5 = 15 (điều này bắt buộc người ta hiểu ngầm).
Chú: trường hợp tốt chiếm 1/15 = 6.67% (93.33% là phải tính thêm chia cho 3, rối 5, tối thiểu 2 con toán). Trường hợp xấu chiếm 1 - 1/3 = 66.67% (nếu không chia chẵn cho 3 thì phải làm đến con toán tính chia cho 5).

Lỡ phải hiểu ngầm thì chịu khó chút nữa.
Cells(i, 2) = IIF(Cells(i, 1) Mod 3, "", "GP") & IIF(Cells(i, 1) Mod 5, "", "EC")
100% phải làm 2 con toán. 0% phải làm 3 con toán.

Tự thú: thật ra code trên ăn gian, không tính phí của hàm IIF và phép ghép chuỗi.
Tôi chỉ cốt yếu nêu ra đây lô gic của giải thuật thôi: sự sắp xếp của lệnh IF có liên hệ mật thiết với độ ưu việt của code.
.
 
Lần chỉnh sửa cuối:
Upvote 0
Code dài quá.
Và tuy gặp trường hợp tốt thì chỉ mất một con toán MOD. Nhưng trường hợp xấu thì phải qua 3 con toán Mod. Trong khi có nhiều cách chỉ phải qua 2.
Tuy có theo sát điều kiện nhưng không có chỗ nào nói 3*5 = 15 (điều này bắt buộc người ta hiểu ngầm).
Chú: trường hợp tốt chiếm 1/15 = 6.67% (93.33% là phải tính thêm chia cho 3, rối 5, tối thiểu 2 con toán). Trường hợp xấu chiếm 1 - 1/3 = 66.67% (nếu không chia chẵn cho 3 thì phải làm đến con toán tính chia cho 5).

Lỡ phải hiểu ngầm thì chịu khó chút nữa.
Cells(i, 2) = IIF(Cells(i, 1) Mod 3, "", "GP") & IIF(Cells(i, 1) Mod 5, "", "EC")
100% phải làm 2 con toán. 0% phải làm 3 con toán.

Tự thú: thật ra code trên ăn gian, không tính phí của hàm IIF và phép ghép chuỗi.
Tôi chỉ cốt yếu nêu ra đây lô gic của giải thuật thôi: sự sắp xếp của lệnh IF có liên hệ mật thiết với độ ưu việt của code.
.
cảm ơn bạn mình cũng mới tham gia vba chưa dành kỹ thuật phân tích code , nên chỉ để ý cho ra kết quả đúng thôi
 
Upvote 0
Web KT
Back
Top Bottom