Đố vui về VBA!

Liên hệ QC

anhtuan1066

Thành viên gạo cội
Tham gia
10/3/07
Bài viết
5,802
Được thích
6,906
Nhằm cũng cố kiến thức về VBA cho các bạn mới bắt đầu và cả những bạn đang ứng dụng mà chưa hiểu nhiều về nó, tôi mở topic này với mong mõi qua những câu hỏi vui, các bạn sẽ nhận định lại sự hiểu biết cũa mình... (Kễ cã chính tôi cũng đang tập tành nên có rất nhiều cái chưa biết)
Mong rằng topic sẽ mang đến cho các bạn những khám phá thú vị với những cái tưỡng chừng như đã biết
Mong nhận dc bài viết về câu đố cũa các cao thủ! Còn các bạn mới thì đừng ngại khi đưa ra ý kiến cũa mình.. Có sai có sữa sẽ hoàn thiện!
Tôi xin mỡ màn trước bằng 1 câu hỏi đơn giãn
ANH TUẤN

CÂU HỎI 1: Tại sao biến K ko hoạt động?
Tôi muốn khi nhấn vào 1 button thì cell A1 sẽ tăng lên 1 đơn vị... Tôi đã làm như sau:
-Tạo 1 Command Button (nút nhấn thuộc thanh Control Toolbox), click phải chuột lên nút nhấn, chọn View code, rồi gõ vào đoạn code sau:
PHP:
Private Sub CommandButton1_Click()
   K = K + 1
   Range("A1").Value = K
End Sub
Ban đầu K chưa có gì, xem như =0, nhấn nút lần thứ nhất thì K dc tăng thêm 1, vậy K hiện tại sẽ bằng 1, và gán K vào cell A1 thì đương nhiên A1 sẽ =1... Nhấn nút lần 2, K lại dc tăng thêm 1 nên hiện tại K sẽ =2 và cell A1 cũng sẽ =2... vân vân.. từ đó diễn tiến tiếp...
Hi.. hi.. Điều này nghe qua có vẽ rất hợp lý, ấy thế mà khi nhấn nút nó chỉ hoạt động dc duy nhất 1 lần (A1 = 1) rồi thôi ko nhút nhít nữa...
Các bạn có thể giãi thích tại sao lại như thế ko? Tại sao những lần nhấn nút sau đó K lại ko tăng thêm tí nào (vì thực tế A1 vẫn cứ = 1 hoài) ?
ANH TUẤN
 
Nó làm việc như thế này, còn tại sao thì chắc phải hỏi ngài BG thôi!

Ỳ tôi muốn nói đến trường hợp dử liệu cần tìm nằm ngay cell đầu tiên ấy
Và trong trường này Find làm việc ra sao?
Mình lập vùng dữ liệu sau:

A | B TN=TN/1.000 |
TN <6|0
TN <34|(TN-6)*150
TN <80|(34-6)*150 + (TN-34)*300
TN <150|4.200 + (80-34)*300+ (TN - 80)*400
150<TN|18.000 + (150-80)* 400 + (TN-150)* 45

Và cho chạy macro sau:
PHP:
Option Explicit
Sub FindFirst()
Dim Srng As Range, Rng As Range
Dim MyAdd As String, StrC As String
 
Set Rng = Range("A1:A20")
 
Set Srng = Rng.Find("TN", , xlFormulas, xlPart)
If Not Srng Is Nothing Then
    MyAdd = Srng.Address
    Do
        StrC = StrC & Srng.Address & " "
7       Set Srng = Rng.FindNext(Srng)
    Loop While Not Srng Is Nothing And Srng.Address <> MyAdd
    MsgBox Srng.Address, , StrC
End If
End Sub
Kết quả trên nút chữ OK là hai dòng sau:
$A$2 $A$3 $A$4 $A$5 $A$6 $A$1
$A$2

Còn nếu thay dòng lệnh 7 thành
Mã:
Set Srng = Rng.FindPrevious(Srng)

thì kết quả như sau
$A$2 $A$1 $A$6 $A$5 $A$4 $A$3
$A$2

Kiểu này giống như: Sinh con rồi mới sinh cha, sinh cháu giữ nhà rồi mới sinh ông.
 
Upvote 0
Cái này của bác là hàm Chr(charcode), nó sẽ trả về kí tự tương ứng theo bảng mã ASCII. Công thức của bác phức tạp quá nhưng em biết nó ra tập hợp là "Hello World!"
Bạn có thể thí nghiệm bằng công thức như sau:
- Từ cell A2 đến A7, gõ lần lượt các số từ 0 đến 5
- Tại B2, gõ công thức:
PHP:
=B1&CHAR(ROUND((A2 * (A2 * (A2 * (A2 * (-0.75 * A2 + 7.2917) - 22.5) + 16.708) + 28.25) + 72),0))
kéo fill xuống đến B7
- Tại cell C2, gõ công thức:
PHP:
=C1&CHAR(ROUND((A2 * (A2 * (A2 * (A2 * (A2 * (0.425 * A2 - 6.8667) + 40.833) - 109.58) + 122.24) - 23.05) + 87),0))
Kéo fill xuống đến C7
- Tại cell D7, gõ công thức: =B7&C7 ===> Và đây là kết quả cuối cùng
Đây chỉ là trò đùa vui thôi! Hi.. hi..
 
Upvote 0
Consolidate có tổng hợp được dử liệu bài này không?

Hãy xem dử liệu tôi đang có:

attachment.php


Vùng màu vàng tôi dùng SUMIF để tính tổng... Các bạn hãy thử xem nếu bài này tôi làm bằng Consolidate (Hoặc Find method) thì có ra kết quả hay không?
 

File đính kèm

  • Test.xls
    14 KB · Đọc: 18
  • untitled.JPG
    untitled.JPG
    39.4 KB · Đọc: 137
Upvote 0
Tôi có 1 câu hỏi mời các bạn tham khảo!
Giả sử có đoạn code như sau:
PHP:
Sub Test()
  Dim i As Long
  With Range("A:A")
    For i = 1 To 10
      .Cells(i) = i
      MsgBox .SpecialCells(4).Areas(1)(1).Address
    Next i
  End With
End Sub
Vấn đề là: Các bạn chạy code này ngay trong file đính kém dưới đây của tôi thì không có vấn đề, nhưng nếu các bạn copy code cho vào 1 file mới thì code lại báo lổi
???
Tại sao lại thế? --=0
 

File đính kèm

  • SpecialCells.xls
    18 KB · Đọc: 38
Lần chỉnh sửa cuối:
Upvote 0
Nhằm cũng cố kiến thức về VBA cho các bạn mới bắt đầu và cả những bạn đang ứng dụng mà chưa hiểu nhiều về nó, tôi mở topic này với mong mõi qua những câu hỏi vui, các bạn sẽ nhận định lại sự hiểu biết cũa mình... (Kễ cã chính tôi cũng đang tập tành nên có rất nhiều cái chưa biết)
Mong rằng topic sẽ mang đến cho các bạn những khám phá thú vị với những cái tưỡng chừng như đã biết
Mong nhận dc bài viết về câu đố cũa các cao thủ! Còn các bạn mới thì đừng ngại khi đưa ra ý kiến cũa mình.. Có sai có sữa sẽ hoàn thiện!
Tôi xin mỡ màn trước bằng 1 câu hỏi đơn giãn
ANH TUẤN

CÂU HỎI 1: Tại sao biến K ko hoạt động?
Tôi muốn khi nhấn vào 1 button thì cell A1 sẽ tăng lên 1 đơn vị... Tôi đã làm như sau:
-Tạo 1 Command Button (nút nhấn thuộc thanh Control Toolbox), click phải chuột lên nút nhấn, chọn View code, rồi gõ vào đoạn code sau:
PHP:
Private Sub CommandButton1_Click()
   K = K + 1
   Range("A1").Value = K
End Sub
Ban đầu K chưa có gì, xem như =0, nhấn nút lần thứ nhất thì K dc tăng thêm 1, vậy K hiện tại sẽ bằng 1, và gán K vào cell A1 thì đương nhiên A1 sẽ =1... Nhấn nút lần 2, K lại dc tăng thêm 1 nên hiện tại K sẽ =2 và cell A1 cũng sẽ =2... vân vân.. từ đó diễn tiến tiếp...
Hi.. hi.. Điều này nghe qua có vẽ rất hợp lý, ấy thế mà khi nhấn nút nó chỉ hoạt động dc duy nhất 1 lần (A1 = 1) rồi thôi ko nhút nhít nữa...
Các bạn có thể giãi thích tại sao lại như thế ko? Tại sao những lần nhấn nút sau đó K lại ko tăng thêm tí nào (vì thực tế A1 vẫn cứ = 1 hoài) ?
ANH TUẤN
Mình thuộc loại gà mờ VBA nhưng rất thích và đang học, theo mình biến K là biến thông thương nên phải khai báo K như sau: STATIC K AS INTEGER. Hổng biết đúng hông nữa
 
Upvote 0
Tôi có 1 câu hỏi mời các bạn tham khảo!
Giả sử có đoạn code như sau:
PHP:
Sub Test()
  Dim i As Long
  With Range("A:A")
    For i = 1 To 10
      .Cells(i) = i
      MsgBox .SpecialCells(4).Areas(1)(1).Address
    Next i
  End With
End Sub
Vấn đề là: Các bạn chạy code này ngay trong file đính kém dưới đây của tôi thì không có vấn đề, nhưng nếu các bạn copy code cho vào 1 file mới thì code lại báo lổi
???
Tại sao lại thế? --=0

Anh Tuấn nghĩ ra mấy cái này vui thật!

Vào PB xem sẽ thấy?

Thanh Phong
 
Lần chỉnh sửa cuối:
Upvote 0
Thế này nhé:
- Phong chọn toàn bộ bảng tính, vào menu Edit\Clear\All
- Thế là chẳng còn cell nào rổng
Giờ chạy lại code xem, nó cũng đâu báo lổi gì
??? Hi... hi...

Anh làm như anh nói save file lại rồi mở file ra và chạy lại xem thế nào :)!

TTP
 
Upvote 0
Em cũng tham gia tí :
Anh muốn biến K tăng thì Anh cần khai báo biến Public. Ví dụ :
PHP:
Public K As Integer 
Private Sub CommandButton1_Click()
   K = K + 1
   Range("A1").Value = K
End Sub
hoặc anh dùng cách sau (có khác đôi chút)
PHP:
Private Sub CommandButton1_Click()
   Range("A1").Value = Range("A1").Value + 1
End Sub
TDN
</span></span>
Sao mình làm cách 1 không được, báo lỗi, còn cách 2 thì được. Lạ nhỉ?
 
Upvote 0
Em nghĩ rằng cái SpecialCells(xlCellTypeBlanks) là vùng trống (của file đang lưu trên RAM) tính từ lúc bác chỉnh sữa dữ liệu trên file (hay nói cách khác là từ lúc mở file đến trước lúc lưu mới [Save; Save As]) đến trước khi lưu file lại. Vậy có ổn không?
Thân.
 
Upvote 0
Public K As Integer
Private Sub CommandButton1_Click()
K = K + 1
Range
("A1").Value = K
End Sub

Private Sub CommandButton1_Click()
Range("A1").Value = Range("A1").Value + 1
End Sub

Sao mình làm cách 1 không được, báo lỗi, còn cách 2 thì được. Lạ nhỉ?

Cách 1 báo lỗi vì ngay từ lúc đầu, K bằng bao nhiêu làm sao biết được, nên K+1 sẽ không có kết quả.
 
Upvote 0
Em nghĩ rằng cái SpecialCells(xlCellTypeBlanks) là vùng trống (của file đang lưu trên RAM) tính từ lúc bác chỉnh sữa dữ liệu trên file (hay nói cách khác là từ lúc mở file đến trước lúc lưu mới [Save; Save As]) đến trước khi lưu file lại. Vậy có ổn không?
Thân.
Tôi không dám chắc việc này, nhưng các bạn hãy cùng tôi làm 1 thí nghiệm nhé
- Xóa rổng cột A rồi chọn toàn bộ cột A này, bấm Ctrl + G\Special\Blanks: Excel báo lổi
- Xóa rổng cột A, gõ gì đó vào A1 rồi chọn toàn bộ cột A, bấm Ctrl + G\Special\Blanks: Excel vẫn báo lổi
- - Xóa rổng cột A, gõ gì đó vào A2 rồi chọn toàn bộ cột A, bấm Ctrl + G\Special\Blanks: Hết lổi
------------------------
Lưu ý quan trọng: Kể từ khi Excel hết báo lổi thì dù ta có làm gì (chẳng hạn lập lại các thao tác trên) nó cũng vẫn không còn báo lổi nữa
Sao lại thế chứ?
 
Lần chỉnh sửa cuối:
Upvote 0
Cách 1 báo lỗi vì ngay từ lúc đầu, K bằng bao nhiêu làm sao biết được, nên K+1 sẽ không có kết quả.

Không phải bạn ạ, biến Public K kiểu integer sau khi khai báo sẽ có giá trị mặc định là 0 chứ, mình thử code 1 hoàn toàn bình thường, bạn trên làm không được chắc là do nhập code sai chỗ nào rồi.
 
Upvote 0
Tôi không dám chắc việc này, nhưng các bạn hãy cùng tôi làm 1 thí nghiệm nhé
{B1}- Xóa rổng cột A rồi chọn toàn bộ cột A này, bấm Ctrl + G\Special\Blanks: Excel báo lổi
{B2}- Xóa rổng cột A, gõ gì đó vào A1 rồi chọn toàn bộ cột A, bấm Ctrl + G\Special\Blanks: Excel vẫn báo lổi
{B3}- Xóa rổng cột A, gõ gì đó vào A2 rồi chọn toàn bộ cột A, bấm Ctrl + G\Special\Blanks: Hết lổi
------------------------
Lưu ý quan trọng: Kể từ khi Excel hết báo lổi thì dù ta có làm gì (chẳng hạn lập lại các thao tác trên) nó cũng vẫn không còn báo lổi nữa
Sao lại thế chứ?
Bác làm các thao tác này liên tục trên 1 bảng tính thì tất nhiên nó phải vậy rồi. Vì ở {B1}{B2} nó làm gì có ô rỗng. Rồi vào {B3} thì xuất hiện ô rỗng A1. Vậy là xong rồi.
Bác thử làm 3 bước này ở 3 bảng tính hoàn toàn mới xem. Có thể bỏ qua việc "Xóa rổng cột A" đi, vì bảng tính mới thì làm gì có dữ liệu đâu mà xóa chứ.
Mã:
[U]TH1:[/U]
[I]Mở bảng tính mới, nhập dữ liệu A1, rồi bấm[/I] [B]Ctrl + G\Special\Blanks[/B]: [B][I][COLOR=#ff0000]Excel báo lổi[/COLOR][/I][/B]
Mã:
[COLOR=#ff0000][I][COLOR=black][U]TH2:[/U][/COLOR][/I]
[I][COLOR=black]Mở bảng tính mới, nhập dữ liệu A2, rồi bấm [B]Ctrl + G\Special\Blanks: [/B][/COLOR][B][COLOR=red][I]Excel báo ô A1[/I][/COLOR][/B][/I][/COLOR]
Mã:
[/COLOR]
[COLOR=#ff0000][I][COLOR=black][U]TH3:[/U][/COLOR][/I]
[I][COLOR=black]Mở bảng tính mới, nhập dữ liệu A2, rồi xóa nó đi, rồi bấm [B]Ctrl + G\Special\Blanks: [/B][/COLOR][B][COLOR=red][I]Excel báo ô A1 và A2[/I][/COLOR][/B][/I][/COLOR]

Thậm chí bác có xóa luôn cột A ở TH3 thì Excel vẫn báo [A1:A2] rổng à. Vậy bác nghĩ sao về điều này?
Thân.
 
Upvote 0
Thử với code này xem. Dù có thao tác thế nào. Khi xóa hết dữ liệu rồi chạy code này cũng sẽ báo lỗi.
PHP:
Sub Text()
ActiveSheet.UsedRange.Select
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks).Select
End Sub
Theo tôi, SpecialCells(xlCellTypeBlanks) là những cell rỗng trong vùng bảng tính từ cell A1 đến Cell cuối cùng đã sử dụng. Bạn đã nhập liệu vào một cell nào đó, cho dù bạn có xóa nó đi thì cell đó vẫn được tính là cell đã sử dụng rồi. Nhưng khi đóng file hoặc sử dụng thuộc tính UsedRange thì cell cuối cùng đã sử dụng sẽ được xác định lại. Chỉ những cell thực sự được sử dụng mới tính là cell đã sử dụng.
 
Upvote 0
Thử với code này xem. Dù có thao tác thế nào. Khi xóa hết dữ liệu rồi chạy code này cũng sẽ báo lỗi.
PHP:
Sub Text()
ActiveSheet.UsedRange.Select
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks).Select
End Sub
Theo tôi, SpecialCells(xlCellTypeBlanks) là những cell rỗng trong vùng bảng tính từ cell A1 đến Cell cuối cùng đã sử dụng. Bạn đã nhập liệu vào một cell nào đó, cho dù bạn có xóa nó đi thì cell đó vẫn được tính là cell đã sử dụng rồi. Nhưng khi đóng file hoặc sử dụng thuộc tính UsedRange thì cell cuối cùng đã sử dụng sẽ được xác định lại. Chỉ những cell thực sự được sử dụng mới tính là cell đã sử dụng.
Vâng! Chính xác là thế này:
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks)
tương đương với
ActiveSheet.UsedRange.SpecialCells(xlCellTypeBlanks)

Range("... gì gì đó... ").SpecialCells(xlCellTypeBlanks)
tương đương với
Intersect(ActiveSheet.UsedRange,Range("... gì gì đó... ")).SpecialCells(xlCellTypeBlanks)
Chỉ thế thôi
Và các bạn khi dùng SpecialCells(4) phải hết sức cẩn thận về điều này
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng! Chính xác là thế này:
ActiveSheet.Cells.SpecialCells(xlCellTypeBlanks)
tương đương với
ActiveSheet.UsedRange.SpecialCells(xlCellTypeBlanks)

Range("... gì gì đó... ").SpecialCells(xlCellTypeBlanks)
tương đương với
Intersect(ActiveSheet.UsedRange,Range("... gì gì đó... ")).SpecialCells(xlCellTypeBlanks)
Chỉ thế thôi
Và các bạn khi dùng SpecialCells(4) phải hết sức cẩn thận về điều này

Cảm ơn anhtuan1066! Tôi hay sử dụng SpecialCells(4) nhưng hôm nay mới biết điều này. Những thông tin từ bạn thật là hữu ích.
 
Upvote 0
Web KT
Back
Top Bottom