Đố vui về VBA! (1 người xem)

Liên hệ QC

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

anhtuan1066

Thành viên gạo cội
Tham gia
10/3/07
Bài viết
5,802
Được thích
6,912
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
 
Xác định 1 chuổi có tồn tại trong 1 file hay không?

Bài toán này với Excel 2003 là quá dể dàng: Dùng FileSearch, nhưng còn Excel 2007 thì sao?
Ví dụ: Ta muốn biết từ khóa "GPE" có tồn tại trong file D:\Test.xls thì làm thế nào?
Các bạn thử nghĩ đến tình huống này xem, biết đâu có lúc cần đến
Ghi chú:
- Chuổi tìm không cần phân biệt chữ HOA hay thường
- Code phải chạy được trên Excel 2007
-------------------------------------------------------------------------------------------------------
Nói thêm:
Bài toán này tôi tin chắc rằng cho dù các bạn có search khắp google cũng e rằng không tìm thấy câu trả lời dù đã từng có rất nhiều người quan tâm... Tuy nhiên, đã là ĐỐ VUI thì các bạn cứ yên tâm rằng code không hề phức tạp tí nào
 
Upvote 0
Đóng 1 file .EXE đang chạy

Trước tiên mời các bạn xem bài này:
Đóng file .exe đã mở bằng Shell như thế nào?
Ở đây người ta cần 1 code có khả năng đóng 1 file EXE đang chạy! Giải pháp cũng đã có rồi và nếu như search trên google các bạn sẽ thấy người ta đều dùng giải pháp này (hộ trợ bằng hàm API)
Xin hỏi: Liệu có code nào ngắn gọn hơn không? (ngắn cở 1 vài dòng càng tốt)
 
Upvote 0
Anh ơi, code sau không biết có đúng ý anh không?
Mã:
Sub Close_Process()
Dim sCloseProcess As String

sCloseProcess = "TASKKILL /F /IM Excel.exe"
Shell sCloseProcess , vbHide

End Sub

Lê Văn Duyệt
 
Upvote 0
Anh ơi, code sau không biết có đúng ý anh không?
Mã:
Sub Close_Process()
Dim sCloseProcess As String
 
sCloseProcess = "TASKKILL /F /IM Excel.exe"
Shell sCloseProcess , vbHide
 
End Sub

Lê Văn Duyệt
Chính xác! Và tôi nghĩ đây là cách ngắn gọn nhất!
Còn câu trên Duyệt làm luôn đi.. cũng có liên quan đến lệnh DOS như câu này đấy!
Thử nghiên cứu lệnh FIND trong DOS xem! Nó có khả năng phát hiện 1 chuổi nào đó có tồn tại trong 1 file hay không!
Hãy xem hình:

untitled.JPG

Vấn đề còn lại là làm sao áp dụng được lệnh này vào VBA (quá dể)
 

File đính kèm

  • untitled.JPG
    untitled.JPG
    58.7 KB · Đọc: 81
Lần chỉnh sửa cuối:
Upvote 0
Vòng lập FOR có thể nhanh hơn không?

Tôi thường đánh số thứ tự cho 1 cột bằng cách dùng Evaluate("ROW(R:R)")
Ví dụ đoạn code này:
PHP:
Sub Test1()
  Dim TG As Double
  TG = Timer
  Range("A:A").Value = Evaluate("ROW(R:R)")
  MsgBox Format(Timer - TG, "0.000000000")
End Sub
Các bạn hãy cho biết nếu tôi dùng vòng lập For.. Next để làm công việc đánh STT này thì liệu tốc độ làm việc có thể bằng với code trên hay không?
(Tôi nghĩ thậm chí còn hơn nữa đấy)
-------------------------------
Hãy dùng Excel 2007 với 1,048,576 dòng mà thử nghiệm cho ngon ăn nhé
 
Upvote 0
Tôi thường đánh số thứ tự cho 1 cột bằng cách dùng Evaluate("ROW(R:R)")
Ví dụ đoạn code này:
PHP:
Sub Test1()
  Dim TG As Double
  TG = Timer
  Range("A:A").Value = Evaluate("ROW(R:R)")
  MsgBox Format(Timer - TG, "0.000000000")
End Sub
Các bạn hãy cho biết nếu tôi dùng vòng lập For.. Next để làm công việc đánh STT này thì liệu tốc độ làm việc có thể bằng với code trên hay không?

Theo em thì nếu dùng For... Next tốc độ sẽ không bằng việc dùng Evaluate. Em có nói ở đây, chắc anh chưa đọc.

Lê Văn Duyệt
 
Upvote 0
Theo em thì nếu dùng For... Next tốc độ sẽ không bằng việc dùng Evaluate. Em có nói ở đây, chắc anh chưa đọc.

Lê Văn Duyệt
Chưa chắc đâu, ít nhất là với bài này!
Mời nghiên cứu tiếp
(Tôi thí nghiệm mấy chục lần trên cả Excel 2003 và 2007 rồi mới dám.. đố ấy chứ... Ẹc... Ec...)
 
Upvote 0
Chưa chắc đâu, ít nhất là với bài này!
Mời nghiên cứu tiếp
(Tôi thí nghiệm mấy chục lần trên cả Excel 2003 và 2007 rồi mới dám.. đố ấy chứ... Ẹc... Ec...)

Ẹc...Ẹc...Chán anh quá anh nói luôn đi... Ẹc ... Ẹc... Anh nói ghét cái Excel 2007 mà... Ẹc...Ẹc...

Lê Văn Duyệt
 
Upvote 0
Ẹc...Ẹc...Chán anh quá anh nói luôn đi...
Nếu dùng For... Next bình thường, quét đến đâu điền dữ liệu đến nấy thì lết bánh là cái chắc... Nhưng nếu ta gán giá trị STT vào các phần tử của 1 Array, xong vòng lập ta quăng Array này vào vùng dữ liệu luôn thì khác à nha
PHP:
Sub Test2()
  Dim i As Long, Arr() As Long, TG As Double
  TG = Timer
  ReDim Arr(1 To Cells.Rows.Count, 1 To 1)
  For i = 1 To Cells.Rows.Count
    Arr(i, 1) = i
  Next
  Range("C:C").Value = Arr
  MsgBox Format(Timer - TG, "0.000000000")
End Sub
Thử nghiệm sẽ biết câu trả lời ---> Tôi thử nhiều lần và thấy tốc độ gần như tương đương nhau (có đôi lúc cách dùng vòng lập này còn cho tốc độ cao hơn)
Từ thí nghiệm này ta rút ra kết luận:
- Với công việc có liên quan đến vòng lập, ta không nên làm theo kiẻu quét đến đâu ra kết quả đến nấy
- Chúng ta nên làm công tác "chuẩn bị" theo kiểu "thu gom"... để khi hoàn tất vòng lập là "cạp" 1 cái xong mọi thứ
- Phương pháp này sẽ đẩy tốc độ lên cao đến không ngờ
--------------------------------------------------------------------------------------------------
Anh nói ghét cái Excel 2007 mà... Ẹc...Ẹc...
Ghét, bởi vậy tôi đâu có cài, chỉ xài Portable để mở file của người khác thôi!... Ẹc... Ẹc...
--------------------------------------------------------------------------------------------------
Tôi biết chắc Duyệt vẫn dùng cách này thường xuyên, có điều bất chợt nên chưa nghĩ đến đấy thôi (thế nên mới dám đố, gọi là đánh bất ngờ, địch không kịp trở tay... Ẹc... Ẹc...)
Có điều:
Cái này thì chẳng thú vị gì cả ---> Mình ta độc diển.. vui gì.. ai ơi!
 

File đính kèm

Upvote 0
Gởi Anh Tuấn,

Nếu xét hai thủ tục trên, em thấy rằng việc so sánh như anh không công bằng.

Mã:
Sub Test1()
  Dim TG As Double
  TG = Timer
  [A:A] = [ROW(R:R)]
  [E1] = Format(Timer - TG, "0.000000000")
End Sub
Với thủ tục này thì phải Evaluate từng hàng một.

Trong khi thủ tục này:
Mã:
Sub Test2()
  Dim i As Long, Arr() As Long, TG As Double
  TG = Timer
  ReDim Arr(1 To Cells.Rows.Count, 1 To 1)
  For i = 1 To Cells.Rows.Count
    [COLOR="Red"][B]Arr(i, 1) = i[/B][/COLOR]
  Next
  Range("B:B").Value = Arr
  [G1] = Format(Timer - TG, "0.000000000")
End Sub
Chỉ gán giá trị.

Để cho công bằng thì ta thử cái này xem sao:
Mã:
Sub Test3()
    Dim i As Long, Arr() As Long, TG As Double
    TG = Timer
    ReDim Arr(1 To Cells.Rows.Count, 1 To 1)
    For i = 1 To Cells.Rows.Count
       [COLOR="Red"] Arr(i, 1) = Cells(i, 1).Row[/COLOR]
    Next
    Range("C:C").Value = Arr
    [I1] = Format(Timer - TG, "0.000000000")
End Sub

Thực sự ra khi làm việc với một vùng dữ liệu, thì chuyển vùng dữ liệu này qua mảng, rồi làm việc với mảng này, xong đưa lại vùng.
Đây là cách mà các VBA Expert thường khuyên nên thực hiện
. (Em sẽ đưa cái này vào đây)


Lê Văn Duyệt
PS: Em phải tham khảo một số nguồn.
 
Lần chỉnh sửa cuối:
Upvote 0
Gởi Anh Tuấn,

Nếu xét hai thủ tục trên, em thấy rằng việc so sánh như anh không công bằng.

Mã:
Sub Test1()
  Dim TG As Double
  TG = Timer
  [A:A] = [ROW(R:R)]
  [E1] = Format(Timer - TG, "0.000000000")
End Sub
Với thủ tục này thì phải Evaluate từng hàng một.

Trong khi thủ tục này:
Mã:
Sub Test2()
  Dim i As Long, Arr() As Long, TG As Double
  TG = Timer
  ReDim Arr(1 To Cells.Rows.Count, 1 To 1)
  For i = 1 To Cells.Rows.Count
    [COLOR=Red][B]Arr(i, 1) = i[/B][/COLOR]
  Next
  Range("B:B").Value = Arr
  [G1] = Format(Timer - TG, "0.000000000")
End Sub
Chỉ gán giá trị.

Để cho công bằng thì ta thử cái này xem sao:
Mã:
Sub Test3()
    Dim i As Long, Arr() As Long, TG As Double
    TG = Timer
    ReDim Arr(1 To Cells.Rows.Count, 1 To 1)
    For i = 1 To Cells.Rows.Count
       [COLOR=Red] Arr(i, 1) = Cells(i, 1).Row[/COLOR]
    Next
    Range("C:C").Value = Arr
    [I1] = Format(Timer - TG, "0.000000000")
End Sub
Lê Văn Duyệt
PS: Em phải tham khảo một số nguồn.
Vậy là Duyệt hiểu sai ý của tôi rồi
Tôi đâu cố ý so sánh Evaluate với For... Next ---> Chỉ muốn nói rằng trong 1 số trường hợp khi dùng For... Next, ta vẫn có cách để tăng tốc cho nó bằng những xảo thuật riêng!
Bài trên chỉ đưa file giả lập để chúng ta tìm cách gì đó khi dùng For.. next sao cho đạt được tốc độ như khi dùng Evaluate
Mục đích cuối cùng là: TĂNG TỐC CHO VÒNG LẬP... Chỉ vậy thôi!
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy là Duyệt hiểu sai ý của tôi rồi
Tôi đâu cố ý so sánh Evaluate với For... Next ---> Chỉ muốn nói rằng trong 1 số trường hợp khi dùng For... Next, ta vẫn có cách để tăng tốc cho nó bằng những xảo thuật riêng!
Bài trên chỉ đưa file giả lập để chúng ta tìm cách gì đó khi dùng For.. next sao cho đạt được tốc độ như khi dùng Evaluate
Mục đích cuối cùng là: TĂNG TỐC CHO VÒNG LẬP... Chỉ vậy thôi!

Trời, vậy mà em cứ tưởng. Mà theo cách lập luận của anh, em nghĩ không chỉ em tưởng vậy mà người khác cũng tưởng vậy. Ẹc...Ẹc...

Anh ơi, theo em nghĩ "Không phải tăng tốc cho vòng lập" mà là tăng tốc cho các đoạn mã xử lý mới đúng... Ẹc... Ẹc...

Lê Văn Duyệt
 
Upvote 0
Trời, vậy mà em cứ tưởng. Mà theo cách lập luận của anh, em nghĩ không chỉ em tưởng vậy mà người khác cũng tưởng vậy. Ẹc...Ẹc...

Anh ơi, theo em nghĩ "Không phải tăng tốc cho vòng lập" mà là tăng tốc cho các đoạn mã xử lý mới đúng... Ẹc... Ẹc...

Lê Văn Duyệt
Tôi thấy Duyệt có bài viết:
Tăng tốc cho code VBA của bạn
Chắc là phải thêm rất nhiều bài viết nữa... Vì cái vụ TĂNG TỐC này có thể nói là: NÓI HOÀI KHÔNG HẾT (đôi lúc làm thực tế mới phát hiện ra)
---------------------------------------
Giờ có 1 câu đố khác đây:
Đố các bạn biết làm thế nào để khi MsgBox hiện ra mà ta vẫn có thể Select cell thoải mái
Nói thêm: Cái MsgBox mà tôi đề cập ở đây nói đúng hơn là 1 control có dạng như MsgBox (tức cũng có nút OK, Yes, No, Cancel.. vân vân)
(Cái trò này hơi... khoai đây)
 
Lần chỉnh sửa cuối:
Upvote 0
Một câu hỏi khá thú vị:
Một câu hỏi khá thú vị đã viết:
Định dạng tập tin *.xls có thể lưu được bao nhiêu hàng (row)?

Các bạn hãy thử tìm hiểu xem?

Lê Văn Duyệt
 
Upvote 0

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Để thử nghiệm, các bạn hãy tải về tập tin đính kèm và đặt cùng thư mục với tập tin ở thread trên.

Sau đó mở tập tin testmacro2.xls và thực hiện thủ tục FindTheLastRow bạn sẽ biết được số dòng hiện tại của tập tin trên.

Lê Văn Duyệt
 

File đính kèm

Upvote 0
Vậy vấn đề là làm sao chúng ta có thể lưu dữ liệu lớn hơn số dòng mà định dạng *.xls đạt được 65,536 dòng?

Lê Văn Duyệt
 
Upvote 0
Vậy vấn đề là làm sao chúng ta có thể lưu dữ liệu lớn hơn số dòng mà định dạng *.xls đạt được 65,536 dòng?

Lê Văn Duyệt
Khi mở file lên, tôi thấy có cảnh báo này:

untitled.JPG


Đọc thông báo và suy ra rằng: Tôi có thể làm được điều này khi Save As *.xls từ 1 file *.txt nào đó
Đúng không?
Tại file đính kèm này về, Save As *.xls là biết liền
 

File đính kèm

Upvote 0
Vâng, Đúng như anh nói.

Đây là một giải pháp đường vòng.

Chúng ta thao tác với một tập tin text nhưng đuôi của file text không phải là txt mà là xls.

Khi kết nối với tập tin này (xls), chúng ta sẽ kết nối bình thường giống như tôi đã làm ở trên.
Như vậy chúng ta có thể lưu dữ liệu trên tập tin xls với số lượng dòng lớn hơn. Nhưng chú ý rằng nếu bạn mở tập tin trong Excel 2003 trở về trước thì coi như các dòng vượt trên 65,536 sẽ mất đi.

Lê Văn Duyệt
 
Upvote 0
Vâng, Đúng như anh nói.

Đây là một giải pháp đường vòng.

Chúng ta thao tác với một tập tin text nhưng đuôi của file text không phải là txt mà là xls.

Khi kết nối với tập tin này (xls), chúng ta sẽ kết nối bình thường giống như tôi đã làm ở trên.
Như vậy chúng ta có thể lưu dữ liệu trên tập tin xls với số lượng dòng lớn hơn. Nhưng chú ý rằng nếu bạn mở tập tin trong Excel 2003 trở về trước thì coi như các dòng vượt trên 65,536 sẽ mất đi.

Lê Văn Duyệt
Duyệt ơi, mình xin hỏi thêm ngoài lề 1 chút: Mình có thể lấy giá trị tại cell A70000 được không? (code lấy dữ liệu nằm ở 1 file khác) ---> Nếu lấy được thì có cần thủ tục gì đặc biệt hay không?
 
Upvote 0
Anh Tuấn,

ndu96081631 đã viết:
Duyệt ơi, mình xin hỏi thêm ngoài lề 1 chút: Mình có thể lấy giá trị tại cell A70000 được không? (code lấy dữ liệu nằm ở 1 file khác)
(Em chưa hiểu câu màu xanh của Anh.)

Dĩ nhiên là được anh à.
Các bước như sau:
Mã:
'Khai báo biến
Dim oXL    As Object
Dim oXLWb  As Object
Dim oXLWs  As Object

'Khởi tạo đối tượng
Set oXL = CreateObject("Excel.Application")
'sFilePath là đường dẫn đầy đủ của tập tin
Set oXLWb = oXL.Workbooks.Open(sFilePath)
Set oXLWs = oXLWb.Worksheets(1)

'Sau đó anh tham chiếu đến đối tượng bình thường
'Giả sử anh cần lấy dữ liệu ở A70000
debug.Print oXLWs.Range("A70000")

'Giải phóng bộ nhớ
Set oXLWs = Nothing
oXLWb.Close SaveChanges:=False
Set oXLWb = Nothing
oXL.Quit
Set oXL = Nothing

Như vậy chúng ta có thể tạo một tập tin lưu giữ dữ liệu có số hàng lớn hơn số hàng có trong tập tin xls theo các bước sau:

  1. Bạn hãy tạo một tập tin text mới và lưu lại với định dạng xls như hình sau.

    excel20031.jpg



    excel20032.jpg



  2. Thực hiện các bước như ở trên, nhưng sau đó bạn lưu lại
    Mã:
    oXLWb.Close SaveChanges:=True, FileName="Tên tập tin.xls"


    Chú ý rằng cách tham chiếu đến một Range áp dụng bình thường, không có gì đặc biệt cả.

Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Anh Tuấn,


(Em chưa hiểu câu màu xanh của Anh.)

Dĩ nhiên là được anh à.
Các bước như sau:
Mã:
'Khai báo biến
Dim oXL    As Object
Dim oXLWb  As Object
Dim oXLWs  As Object

'Khởi tạo đối tượng
Set oXL = CreateObject("Excel.Application")
'sFilePath là đường dẫn đầy đủ của tập tin
Set oXLWb = oXL.Workbooks.Open(sFilePath)
Set oXLWs = oXLWb.Worksheets(1)

'Sau đó anh tham chiếu đến đối tượng bình thường
'Giả sử anh cần lấy dữ liệu ở A70000
debug.Print oXLWs.Range("A70000")

'Giải phóng bộ nhớ
Set oXLWs = Nothing
oXLWb.Close SaveChanges:=False
Set oXLWb = Nothing
oXL.Quit
Set oXL = Nothing
Lê Văn Duyệt
Không được Duyệt ơi
Tôi đặt file Test.xls ấy vào ổ D:\
Chạy code sau:
PHP:
Sub Test()
  Dim oXL As Object, oXLWb As Object, oXLWs As Object
  Set oXL = CreateObject("Excel.Application")
  Set oXLWb = oXL.Workbooks.Open("D:\Test.xls")
  Set oXLWs = oXLWb.Worksheets(1)
  Debug.Print oXLWs.Range("A70000")
  Set oXLWs = Nothing
  oXLWb.Close SaveChanges:=False
  Set oXLWb = Nothing
  oXL.Quit
  Set oXL = Nothing
End Sub
Nó báo lỗi:
Run-time error '1004'
Application-defined or object-defined error
Lỗi được đánh dấu tại dòng này:
Debug.Print oXLWs.Range("A70000")
Sửa thành:
Debug.Print oXLWs.Range("A60000")
Là hết lỗi
 
Lần chỉnh sửa cuối:
Upvote 0
Không được Duyệt ơi
Tôi đặt file Test.xls ấy vào ổ D:\
Chạy code sau:
PHP:
Sub Test()
  Dim oXL As Object, oXLWb As Object, oXLWs As Object
  Set oXL = CreateObject("Excel.Application")
  Set oXLWb = oXL.Workbooks.Open("D:\Test.xls")
  Set oXLWs = oXLWb.Worksheets(1)
  Debug.Print oXLWs.Range("A70000")
  Set oXLWs = Nothing
  oXLWb.Close SaveChanges:=False
  Set oXLWb = Nothing
  oXL.Quit
  Set oXL = Nothing
End Sub
Nó báo lỗi:

Lỗi được đánh dấu tại dòng này:
Debug.Print oXLWs.Range("A70000")
Sửa thành:
Debug.Print oXLWs.Range("A60000")
Là hết lỗi

Anh ơi anh nhớ kiểm tra hàng cuối cùng của tập tin của anh.
Mã:
lRows = FindLastRow(oXLWs)

Hàm tìm hàng cuối:
Mã:
Function FindLastRow(wsObj As Worksheet) As Long
    On Error Resume Next
    FindLastRow = wsObj.Cells.Find(What:="*", _
                                   After:=wsObj.Range("A1"), _
                                   LookAt:=xlPart, _
                                   LookIn:=xlFormulas, _
                                   SearchOrder:=xlByRows, _
                                   SearchDirection:=xlPrevious, _
                                   MatchCase:=False).Row
    On Error GoTo 0
End Function

Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Ah... xin nói thêm:
Code ở bài 323, nếu chạy trên Excel 2007 thì càng tệ ---> Báo lỗi tùm lum và thậm chí treo máy luôn (phải Task manager mới xử được)
Duyệt có thể cho code hoàn hảo vào 1 file và đưa lên đây không? (code để lấy dữ liệu tại cell A70000 ấy)
 
Upvote 0
Ah... xin nói thêm:
Code ở bài 323, nếu chạy trên Excel 2007 thì càng tệ ---> Báo lỗi tùm lum và thậm chí treo máy luôn (phải Task manager mới xử được)
Duyệt có thể cho code hoàn hảo vào 1 file và đưa lên đây không? (code để lấy dữ liệu tại cell A70000 ấy)

Anh ơi,
Coi chừng Excel 2007 của anh có vấn đề. :)
Em đã dùng mấy cái code này trên Excel 2007 lâu lắm rồi. Không có lỗi gì cả anh ơi. :)
Anh gởi file của anh lên đây đi.


Lê Văn Duyệt
 
Upvote 0
Anh ơi,
Coi chừng Excel 2007 của anh có vấn đề. :)
Em đã dùng mấy cái code này trên Excel 2007 lâu lắm rồi. Không có lỗi gì cả anh ơi. :)
Anh gởi file của anh lên đây đi.


Lê Văn Duyệt
Thì code là của Duyệt mà, tôi copy và paste vào thôi (chỉ sửa đường dẩn đến file)
--------------------------------
Ah... chắc Office có vấn đề thật, vì thử trên Excel 2010 thì OK
--------------------------------
Một vấn đề đặt ra là: Chúng ta lưu dữ liệu có số dòng > 65536 dòng để làm gì nếu như ta không có bộ Office 2007 hoặc Office 2010 để chạy code? Mà nếu đã có bộ Office đời mới này rồi thì ta đâu cần phải đi đường vòng như thế?
(Vì code này đâu có chạy được trên Excel 2003)
Duyệt có thể nói rõ hơn về mục đích của việc làm này không?
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Một vấn đề đặt ra là: Chúng ta lưu dữ liệu có số dòng > 65536 dòng để làm gì nếu như ta không có bộ Office 2007 hoặc Office 2010 để chạy code?
Duyệt có thể nói rõ hơn về mục đích của việc làm này không?
Chắc có lẻ anh chưa bao giờ làm việc với những tập tin có trên 100,000 dòng.
Thông thường các dữ liệu này là từ phần mềm xuất ra.

Từ đó em mới có ý nghĩ là dùng một tập tin *.xls (mà thực chất là *.txt) để em lưu và thao tác đối với những dữ liệu lớn mà Excel 2003 không đáp ứng số dòng.
Tập tin *.xls chỉ để lưu dữ liệu, chúng ta không được mở ra với Excel 2003 để chỉnh sửa.

Vì code này đâu có chạy được trên Excel 2003
Anh ơi, em vẫn chạy trên Excel 2003 mà?

Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Anh ơi, em vẫn chạy trên Excel 2003 mà?
Lê Văn Duyệt
Chắc trên máy của Duyệt có cài Office 2007 nên chạy code ấy không có vấn đề, chứ tôi thử mấy máy rồi, những máy ấy đều không cài Office 2007 và không có máy nào thí nghiệm thành công cả ---> Toàn báo lỗi
Có bạn nào đang dùng Office 2003 test giúp tôi với
 
Upvote 0
Báo lỗi: "Application defined or Object Defined Error". Lỗi tại dòng lệnh Debug Print.

(Test trên máy chỉ có 1 bộ 2003)
 
Upvote 0
Báo lỗi: "Application defined or Object Defined Error". Lỗi tại dòng lệnh Debug Print.

(Test trên máy chỉ có 1 bộ 2003)
Điều đó là HIỂN NHIÊN và em nghĩ không thể nào khác hơn được, trừ phi trên máy ta có cài Office 2007
Nhưng đã cài Office 2007 rồi thì em tự hỏi có cần thiết phải đi đường vòng thế không? (lưu file thành .txt rồi lại lưu thành .xls) ---> Tại sao không lưu thành .xlsx cho nó đở mất công
???
Tóm lại: em cảm thấy công việc này thiếu thực tế quá...
 
Upvote 0
Anh Tuấn,

Tại sao lại thiếu thực tế? Vấn đề là có thực, cụ thể là ở công ty em.

Từ SAP xuất ra file *.xls, tất cả các máy đều dùng Office 2003. Vậy thì làm sao thao tác và lấy dữ liệu với tập tin này.
Chẳng lẻ đây không phải là vấn đề thực tế?

Như em đã nói, anh phải kiểm tra hàng cuối cùng. Chắc chắn là anh không kiểm tra.
Xin nói lại tập tin này em đã sử dụng trên máy Office 2003 của công ty mấy năm rồi.

Lê Văn Duyệt
Duyệt à! Tôi không bàn về tập tin xls có số dòng > 65536 ---> Chỉ nói về code lấy dữ liệu tại cell A70000 thôi!
Nó không thể nào chạy được nếu máy tính của Duyệt chưa cài Office 2007
Duyệt cứ mang code ấy đến máy nào chỉ có Office 2003 mà thử sẽ biết liền (tôi thử trên 5 máy rồi đấy... Sư phụ ptm0412 cũng vừa kiểm tra xong, kết quả là Error)
Điều này quá hiển nhiên, lý nào Duyệt lại không biết
Kiểm tra LastRow, đương nhiên nó chỉ = 65536 thôi (lấy đâu ra 70000)
---------------------------------
Cái sự KHÔNG THỰC TẾ ở đây là: Muốn chạy được code thì phải cài Office 2007 ---> Có phải là quá vô lý hay không?
 
Lần chỉnh sửa cuối:
Upvote 0
Cái sự KHÔNG THỰC TẾ ở đây là: Muốn chạy được code thì phải cài Office 2007 ---> Có phải là quá vô lý hay không?
Chào anh,

Em kiểm tra lại máy đang dùng code này cài 2 Office. Còn mấy máy khác thì khi thực hiện không liên quan đến code này.

Ngoài ra code này em còn dùng trên VB và em cài đặt cho tất cả các máy trong mạng LAN xài. Để em kiểm tra lại việc dùng code này trong VB ở các máy khác xem sao.

Lê Văn Duyệt
 
Upvote 0
Chào anh,

Em kiểm tra lại máy đang dùng code này cài 2 Office. Còn mấy máy khác thì khi thực hiện không liên quan đến code này.

Ngoài ra code này em còn dùng trên VB và em cài đặt cho tất cả các máy trong mạng LAN xài. Để em kiểm tra lại việc dùng code này trong VB ở các máy khác xem sao.

Lê Văn Duyệt
Nói thật, tôi đang rất hứng thú nếu có cách nào đó có thể lấy được dữ liệu tại cell A70000 mà không cần phải cài Office 2007
Duyệt nghiên cứu giúp xem, dùng VB6 cũng được (miễn chạy được trên máy chỉ có Office 2003)
Nếu thành công thì mới thật sự là HỮU ÍCH đây!
 
Upvote 0
Chắc các bạn đều biết công cụ Consolidate, nó có khả năng tổng hợp dữ liệu từ nhiều sheet, thậm chí từ nhiều file
Việc viết code có thể dựa trên cơ sơ Record macro rồi chỉnh lại
Vấn đề ở đây là tôi có 4 file nằm trong 1 thư mục, tôi muốn dùng Consolidate để tổng hợp nó ra 1 file khác mà không cần đến 1 vòng lập nào
Các bạn hãy thử xem
Có file đính kèm, ra kết quả giống như trong file ConsolMutiFiles.xls là xem như thành công! (các file con nằm trong thư mục Source)
Lưu ý:
- Ta chỉ biết các file con nằm trong 1 thư mục chỉ định trước chứ không biết có tổng cộng bao nhiêu file con và tên file con là gì đâu nha
- Biết trước: các file con nằm trong thư mục Source (là thư mục con của thư mục chứa file ConsolMutiFiles.xls)
- Biết trước: Dữ liệu cần tổng hợp trong các file con nằm ở "Sheet1", vùng "A2:B30"

Anh ơi,

Tiếp cái vụ này đi.

Lê Văn Duyệt
 
Upvote 0
Anh ơi,

Tiếp cái vụ này đi.

Lê Văn Duyệt
Cũng đơn giản thôi! Thuật toán dựa vào hàm FILES của macro4, nó có khả năng lấy list file trong 1 thư mục mà không cần vòng lập:
PHP:
Sub ConsolMutiFiles(Folder As String, ShName As String, SrcRng As String, Target As Range)
  Dim Temp As String
  Temp = ShName & "'!" & Range(SrcRng).Address(, , 2)
  If Right(Folder, 1) <> "\" Then Folder = Folder & "\"
  ActiveWorkbook.Names.Add "Arr", "=""'" & Folder & "[""&Files(""" & Folder & "*.*"")&""]" & Temp & """"
  Target.Consolidate Evaluate("Arr"), 9, 0, 1
  ActiveWorkbook.Names("Arr").Delete
End Sub
PHP:
Sub Test()
  Dim Folder As String, ShName As String, SrcRng As String
  Range("A2:B1000").ClearContents
  With CreateObject("Shell.Application")
    On Error Resume Next
    Folder = .BrowseForFolder(0, "", 1).Self.Path
  End With
  ShName = "Sheet1": SrcRng = "A2:B30"
  ConsolMutiFiles Folder, ShName, SrcRng, Range("A2")
End Sub
Vụ bẩy lỗi gì đó các bạn tự làm nha!
 

File đính kèm

Upvote 0
Hàm người dùng nằm trong nhóm "Hàm của tôi!"

Tôi xây dựng 1 hàm nào đó, code nằm trong 1 module, ví dụ thế này
PHP:
Function MyFunction() As String
  MyFunction = "Test My Function"
End Function
Đương nhiên khi tôi vào menu Insert\Function thì tôi sẽ nhìn thấy hàm mà tôi xây dựng nằm trong nhóm "User Defined"

untitled1.JPG

Vậy có khi nào ta sửa được chữ "User Defined" thành 1 tên nào khác không nhỉ? Chẳng hạn là "Hàm của tôi!"

untitled2.JPG

Hi... hi...
 
Upvote 0
Tôi xây dựng 1 hàm nào đó, code nằm trong 1 module, ví dụ thế này
PHP:
Function MyFunction() As String
  MyFunction = "Test My Function"
End Function
Đương nhiên khi tôi vào menu Insert\Function thì tôi sẽ nhìn thấy hàm mà tôi xây dựng nằm trong nhóm "User Defined"

View attachment 51077

Vậy có khi nào ta sửa được chữ "User Defined" thành 1 tên nào khác không nhỉ? Chẳng hạn là "Hàm của tôi!"

View attachment 51078

Hi... hi...
Giả sử hàm tên là test, sau khi thực hiện câu lệnh này sẽ thấy hiệu quả của nó
Mã:
Application.MacroOptions Macro:="test", Description:="Thu test thoi ma", Category:="Ham cua toi"
Chú ý giá trị tham số Category, có thể thay bằng 1 tên có sẵn như "Text", hay "Logical"
attachment.php
 

File đính kèm

  • test.GIF
    test.GIF
    14.3 KB · Đọc: 250
Upvote 0
Giả sử hàm tên là test, sau khi thực hiện câu lệnh này sẽ thấy hiệu quả của nó
Mã:
Application.MacroOptions Macro:="test", Description:="Thu test thoi ma", Category:="Ham cua toi"
Chú ý giá trị tham số Category, có thể thay bằng 1 tên có sẵn như "Text", hay "Logical"

Đại ca làm "lộ chiêu" hết trơn rồi! Định "để dành" hỏi tiếp câu nữa: "Làm sao cho MyFunction và nhóm Date & Time"
Giờ thì coi như.... XONG! Hi... hi...
 
Upvote 0
Chuyện gì xảy ra với vòng lặp For...Next

Tôi có đoạn code như sau:
PHP:
For i = 1 to erowNX
    if true then erowNX=erowNX + 1
next
msgbox "Gia tri hien tai cua i la " & i & chr(13) & "Gia tri hien tai cua erownx la " & erownx

Vấn đề là sau khi biến erowNX tăng, vòng lặp vẫn chạy theo giá trị ban đầu của erowNX. Dễ dàng kiểm tra điều này qua câu lệnh msgbox...

Nhờ các bạn giải thich lý do vì sao và xin hỏi có cách nào giải quyết tình huống này không?

Thân.
 
Upvote 0
Tôi có đoạn code như sau:
PHP:
For i = 1 to erowNX
    if true then erowNX=erowNX + 1
next
msgbox "Gia tri hien tai cua i la " & i & chr(13) & "Gia tri hien tai cua erownx la " & erownx

Vấn đề là sau khi biến erowNX tăng, vòng lặp vẫn chạy theo giá trị ban đầu của erowNX. Dễ dàng kiểm tra điều này qua câu lệnh msgbox...

Nhờ các bạn giải thich lý do vì sao và xin hỏi có cách nào giải quyết tình huống này không?

Thân.
Ý bạn muốn "đố vui" hay là nhờ tìm giải pháp?
Nếu là tìm giải pháp thì bạn phải đưa nguyên file (có code này) lên đây, nói rõ yêu cầu và những trục trặc bạn đang gặp phải
Mặc khác, nếu là nhờ tìm giải pháp thì bài của bạn lý ra không nên đăng ở đây
Nếu là "đố vui" là code này dường như hơi thiếu gì đó ---> Giả định vòng lập có thể chạy theo biến erowNX mới thì... chạy đến bao giờ?
 
Upvote 0
Cám ơn Bác NDU đã nhắc nhở.
ndu96081631 đã viết:
Ý bạn muốn "đố vui" hay là nhờ tìm giải pháp?
Tất nhiên là "đố vui" rồi, vì đây là chủ đề của mục này mà.
ndu96081631 đã viết:
Nếu là "đố vui" là code này dường như hơi thiếu gì đó
Chịu sư phụ luôn. Đúng là erowNX phải nhận giá trị trước khi chạy vòng lặp For...Next.

Tôi sửa code ví dụ như sau:
Mã:
[FONT=Times New Roman][SIZE=1][COLOR=black]erowNX = 5[/COLOR][/SIZE][/FONT]
[SIZE=1][COLOR=black][FONT=Courier New]For [/FONT][FONT=Courier New]i [/FONT][FONT=Courier New]= [/FONT][FONT=Courier New]1 to erowNX[/FONT][/COLOR][/SIZE]
[SIZE=1][COLOR=black][FONT=Courier New]if [/FONT][FONT=Courier New]true then erowNX[/FONT][FONT=Courier New]=[/FONT][FONT=Courier New]erowNX [/FONT][FONT=Courier New]+ [/FONT][FONT=Courier New]1[/FONT][/COLOR][/SIZE]
[FONT=Courier New][SIZE=1][COLOR=black]next[/COLOR][/SIZE][/FONT]
[SIZE=3][COLOR=black][SIZE=1][FONT=Courier New]msgbox [/FONT][FONT=Courier New]"Gia tri hien tai cua i la " [/FONT][FONT=Courier New]& [/FONT][FONT=Courier New]i [/FONT][FONT=Courier New]& [/FONT][FONT=Courier New]chr[/FONT][FONT=Courier New]([/FONT][FONT=Courier New]13[/FONT][FONT=Courier New]) & [/FONT][FONT=Courier New]"Gia tri hien tai cua erownx la " [/FONT][FONT=Courier New]& [/FONT][/SIZE][/COLOR][FONT=Courier New][SIZE=1][COLOR=black]erownx[/COLOR][/SIZE][COLOR=#0000bb] [/COLOR][/FONT][/SIZE]

Mong nhận được ý kiến trao đổi của các bạn. Tôi nghĩ lỗi này rất hay xảy ra, nhất là với những người còn đang chập chững với VBA (như tôi chẳng hạn).

Trân trọng.
 
Upvote 0
Cám ơn Bác NDU đã nhắc nhở.

Tất nhiên là "đố vui" rồi, vì đây là chủ đề của mục này mà.

Chịu sư phụ luôn. Đúng là erowNX phải nhận giá trị trước khi chạy vòng lặp For...Next.

Tôi sửa code ví dụ như sau:
Mã:
[FONT=Times New Roman][SIZE=1][COLOR=black]erowNX = 5[/COLOR][/SIZE][/FONT]
[SIZE=1][COLOR=black][FONT=Courier New]For [/FONT][FONT=Courier New]i [/FONT][FONT=Courier New]= [/FONT][FONT=Courier New]1 to erowNX[/FONT][/COLOR][/SIZE]
[SIZE=1][COLOR=black][FONT=Courier New]if [/FONT][FONT=Courier New]true then erowNX[/FONT][FONT=Courier New]=[/FONT][FONT=Courier New]erowNX [/FONT][FONT=Courier New]+ [/FONT][FONT=Courier New]1[/FONT][/COLOR][/SIZE]
[FONT=Courier New][SIZE=1][COLOR=black]next[/COLOR][/SIZE][/FONT]
[SIZE=3][COLOR=black][SIZE=1][FONT=Courier New]msgbox [/FONT][FONT=Courier New]"Gia tri hien tai cua i la " [/FONT][FONT=Courier New]& [/FONT][FONT=Courier New]i [/FONT][FONT=Courier New]& [/FONT][FONT=Courier New]chr[/FONT][FONT=Courier New]([/FONT][FONT=Courier New]13[/FONT][FONT=Courier New]) & [/FONT][FONT=Courier New]"Gia tri hien tai cua erownx la " [/FONT][FONT=Courier New]& [/FONT][/SIZE][/COLOR][FONT=Courier New][SIZE=1][COLOR=black]erownx[/COLOR][/SIZE][/FONT][/SIZE]
Mong nhận được ý kiến trao đổi của các bạn. Tôi nghĩ lỗi này rất hay xảy ra, nhất là với những người còn đang chập chững với VBA (như tôi chẳng hạn).

Trân trọng.
Vòng lập For... Next có cú pháp:
PHP:
For counter = start To end
 .....
 .....
Next
Tôi nghĩ ta không thể thay đổi được giá trị end trong quá trình thực thị vòng lập đâu
Ví dụ thế này:
PHP:
Sub Test()
  Dim i As Long, er As Long
  er = 5
  For i = 1 To 5
    er = 7
    MsgBox i
  Next
End Sub
Ban đầu er = 5 và trong vòng lập tôi lại thay đổi er = 7, thế nhưng vòng lập vẫn cứ chạy theo giá trị end ban đầu
Chắc đây thuộc về quy định rồi ---> Còn bạn, bạn giải thích thế nào?
 
Upvote 0
Vòng lập For... Next có cú pháp:
PHP:
For counter = start To end
.....
.....
Next
Tôi nghĩ ta không thể thay đổi được giá trị end trong quá trình thực thị vòng lập đâu
Ví dụ thế này:
PHP:
Sub Test()
Dim i As Long, er As Long
er = 5
For i = 1 To 5
er = 7
MsgBox i
Next
End Sub
Ban đầu er = 5 và trong vòng lập tôi lại thay đổi er = 7, thế nhưng vòng lập vẫn cứ chạy theo giá trị end ban đầu
Chắc đây thuộc về quy định rồi ---> Còn bạn, bạn giải thích thế nào?

Có cách này thay đổi được "giá trị end"
Mã:
Public Sub thu1()
k = 5
j = 1
n:
erownx = k
For i = j To erownx
If True Then erownx = erownx + 1
k = erownx
j = j + 1
If erownx = 100 Then GoTo m
'If i = 100 Then GoTo m
GoTo n
Next
m:
MsgBox "Gia tri hien tai cua i la " & i & Chr(13) & "Gia tri hien tai cua erownx la " & erownx
End Sub
 
Upvote 0
Có cách này thay đổi được "giá trị end"
Mã:
Public Sub thu1()
k = 5
j = 1
n:
erownx = k
For i = j To erownx
If True Then erownx = erownx + 1
k = erownx
j = j + 1
If erownx = 100 Then GoTo m
'If i = 100 Then GoTo m
GoTo n
Next
m:
MsgBox "Gia tri hien tai cua i la " & i & Chr(13) & "Gia tri hien tai cua erownx la " & erownx
End Sub
Trời!
Cái bạn đang dùng mà gọi là "thay đổi giá trị end" uh?
Bạn dùng Goto là quay lại vòng lập ---> Chuyện đó quá bình thường
 
Upvote 0
Tầm thường chớ! nhưng mà chưa có cách nào khác.
Ý tôi muốn nói là vầy: Trong quá trình code chạy, hình như ta không thể thay đổi được giá trị End mà ta đã gán trước đó
(Nói là hình như là vì không chắc có cách hay không, có điều thí nghiệm chứng minh là không thể làm được)
Còn cách bạn nếu chỉ là GIẢI QUYẾT VẤN ĐỀ LÀM SAO CHO erownx ĐẠT ĐƯỢC GIÁ TRỊ NÀO ĐÓ ---> Tôi nghĩ nó chưa đúng với những gì mà bạn tungson_mrcc đã nêu
Tóm lại: Giải pháp mà ta cần tìm là: "Liệu có cách nào thay đổi được giá trị End khi vòng lập đang chạy không?"
Chú ý là: KHI VÒNG LẬP ĐANG CHẠY nha
 
Upvote 0
Cám ơn các bạn đã quan tâm tới vấn đề mình nêu ra.

Theo tôi, cách giải thích của Bác NDU là chí lý.

Vòng lập For... Next có cú pháp:
PHP:
For counter = start To end
.....
.....
Next
Tôi nghĩ ta không thể thay đổi được giá trị end trong quá trình thực thị vòng lập đâu
Chắc đây thuộc về quy định rồi

Vấn đề là khi vòng lặp For... Next đang chạy ta không có cách nào thay đổi giá trị end, trong khi trên thực tế, có rất nhiều bài toán đòi hỏi giá trị end thay đổi trong quá trình cho biến i thay đổi. Ví dụ như ở bài toán Tạo Số Thứ tự nhiều cấp...

Có lẽ vì vậy Bác Bill mới nghĩ ra vòng lặp Do... Loop để giải quyết vấn đề này.

Trong bài toán tạo số thứ tự nhiều cấp, tôi đã dùng cách sau:
Mã:
erow3 = Cells(Rows.Count, "B").End(xlUp).Row
i = 28
Do While i <= erow3
    If Cells(i, "G") <> "" And Cells(i, "G") <> N1 Then
        N1 = Cells(i, "G")
        sttN1 = sttN1 + 1
        sttN2 = 0
        sttN3 = 0
 
        Cells(i, "G").EntireRow.Insert shift:=xlDown
        Cells(i, "A") = Chr(sttN1 + 64) & ". " & N1
        Cells(i, "G") = N1
 
        Range("A" & i & ":B" & i).HorizontalAlignment = xlLeft
        Range("A" & i & ":B" & i).Font.FontStyle = "Bold"
        Range("A" & i & ":F" & i).Interior.ColorIndex = 8 'Mau xanh coban
        erow3 = erow3 + 1
    End If    
    If Cells(i + 1, "G") = N1 Then Cells(i + 1, "G") = ""
    If Cells(i + 1, "H") = N2 Then Cells(i + 1, "H") = ""
    If Cells(i + 1, "I") = N3 Then Cells(i + 1, "I") = ""
 
    i = i + 1
Loop

Như vậy, đáp án của tôi là:
1. Khi vòng lặp For...Next đang chạy theo biến i, dù biến end có thay đổi giá trị thì vòng lặp vẫn cứ chạy với giá trị ban đầu của biến end. Đấy là nhược điểm của For...Next (sinh ra đã là như vậy, không biết có sửa được không?!!!).
2. Gặp bài toán như vậy, cách giải quyết là dùng vòng Do... Loop ( Cám ơn Bác Bill )

Đây chỉ là thiển nghĩ của tôi. Mong các bạn góp ý thêm.

Trân trọng.
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn các bạn đã quan tâm tới vấn đề mình nêu ra.

Theo tôi, cách giải thích của Bác NDU là chí lý.



Vấn đề là khi vòng lặp For... Next đang chạy ta không có cách nào thay đổi giá trị end, trong khi trên thực tế, có rất nhiều bài toán đòi hỏi giá trị end thay đổi trong quá trình cho biến i thay đổi. Ví dụ như ở bài toán Tạo Số Thứ tự nhiều cấp...

Có lẽ vì vậy Bác Bill mới nghĩ ra vòng lặp Do... Loop để giải quyết vấn đề này.

Trong bài toán tạo số thứ tự nhiều cấp, tôi đã dùng cách sau:
Mã:
erow3 = Cells(Rows.Count, "B").End(xlUp).Row
i = 28
Do While i <= erow3
    If Cells(i, "G") <> "" And Cells(i, "G") <> N1 Then
        N1 = Cells(i, "G")
        sttN1 = sttN1 + 1
        sttN2 = 0
        sttN3 = 0
 
        Cells(i, "G").EntireRow.Insert shift:=xlDown
        Cells(i, "A") = Chr(sttN1 + 64) & ". " & N1
        Cells(i, "G") = N1
 
        Range("A" & i & ":B" & i).HorizontalAlignment = xlLeft
        Range("A" & i & ":B" & i).Font.FontStyle = "Bold"
        Range("A" & i & ":F" & i).Interior.ColorIndex = 8 'Mau xanh coban
        erow3 = erow3 + 1
    End If    
    If Cells(i + 1, "G") = N1 Then Cells(i + 1, "G") = ""
    If Cells(i + 1, "H") = N2 Then Cells(i + 1, "H") = ""
    If Cells(i + 1, "I") = N3 Then Cells(i + 1, "I") = ""
 
    i = i + 1
Loop

Như vậy, đáp án của tôi là:
1. Khi vòng lặp For...Next đang chạy theo biến i, dù biến end có thay đổi giá trị thì vòng lặp vẫn cứ chạy với giá trị ban đầu của biến end. Đấy là nhược điểm của For...Next (sinh ra đã là như vậy, không biết có sửa được không?!!!).
2. Gặp bài toán như vậy, cách giải quyết là dùng vòng Do... Loop ( Cám ơn Bác Bill )

Đây chỉ là thiển nghĩ của tôi. Mong các bạn góp ý thêm.

Trân trọng.
Có 2 loại vòng lặp là vòng lặp xác định và vòng lặp không xác định. Vòng lặp xác định là vòng lặp mà số vòng lặp đã được xác định từ trước (For ... Next), vòng lặp không xác định là vòng lặp có số vòng lặp không xác định trước (Do ... Loop), người ta đã định ra 2 loại vòng lặp này rồi thì tùy từng trường hợp cụ thể mà sử dụng chứ đừng nghĩ cách thay đổi nó làm gì. Còn thực tế thì với For ... Next thì vai trò của Start và End là như nhau, ở đây mọi người mới chỉ quan tâm tới làm sao để thay đổi End nên nghe thì có vẻ có lý, nhưng hay thử hình dung ta đang đi tìm cách thay đổi Start xem sao, tự dưng sẽ thấy nó vô lý. Ví dụ For i = erowNX to 1 step -1 chẳng hạn, nếu erowNX mà thay đổi được thì thử hình dung vòng lặp sẽ chạy như nào???
 
Upvote 0
Sao lại viết là:
if true then erowNX=erowNX + 1
mà không viết luôn là:
erowNX=erowNX + 1
(luôn thực hiện và mã lệnh ngắn hơn).
Còn về lệnh FOR, nhiều bạn nói khá rõ: không thể thay đổi số lần lặp bằng thay đổi End
Tôi đã chạy thử lệnh:
i=10
FOR i = i-2 to 2*i
...
...
next i
với Start = i - 2 = 8, End = 2*i = 20 thì số lần lặp là 20 - 8 + 1 = 13
Nghĩa là các biểu thức Start, End được tính và lưu riêng khi bắt đầu vòng lặp.
Có thể thoát khỏi vòng lặp bằng các IF...EXIT FOR
hoặc thay đổi biến đếm. Ví dụ lại mã lệnh trên:
i=10
FOR i = i-2 to 2*i
i=i+50
next i

thì chỉ lặp 1 lần.
 
Upvote 0
Kiểm tra xem Dictionary Object có tồn tại hay không

Tôi có đoạn code thế này:
PHP:
Public Dic
Sub Main()
  If Dic Is Nothing Then
    Set Dic = CreateObject("Scripting.Dictionary")
    Dic.Add "a", ""
    Dic.Add "b", ""
    Dic.Add "c", ""
  End If
  MsgBox Join(Dic.Keys, " - ")
End Sub
Ý tôi muốn rằng: Nếu biến Dic không tồn tại thì sẽ làm động tác Add Key Item vào Dic
Tuy nhiên, đoạn code trên báo lỗi. Vậy các bạn sẽ khắc phục như thế nào?
 
Upvote 0
Tôi có đoạn code thế này:
PHP:
Public Dic
Sub Main()
  If Dic Is Nothing Then
    Set Dic = CreateObject("Scripting.Dictionary")
    Dic.Add "a", ""
    Dic.Add "b", ""
    Dic.Add "c", ""
  End If
  MsgBox Join(Dic.Keys, " - ")
End Sub
Ý tôi muốn rằng: Nếu biến Dic không tồn tại thì sẽ làm động tác Add Key Item vào Dic
Tuy nhiên, đoạn code trên báo lỗi. Vậy các bạn sẽ khắc phục như thế nào?
Chả biết thế nào nhưng khi khai báo Dic rành mạch thì nó OK.
Cụ thể như:
PHP:
Public Dic As Object
Sub Main()
  If Dic Is Nothing Then
    Set Dic = CreateObject("Scripting.Dictionary")
    Dic.Add "a", "1"
    Dic.Add "b", "2"
    Dic.Add "c", "3"
  End If
  'MsgBox Join(Dic.Keys, " - ")
  MsgBox Join(Dic.Items, "-")
  Set Dic = Nothing
End Sub
 
Upvote 0
Chả biết thế nào nhưng khi khai báo Dic rành mạch thì nó OK.
Chính xác là thế... Xem kỹ thông báo lỗi sẽ thấy ngay!
(Hầu hết người dùng đều ít khi xem thông báo lỗi, khi có lỗi xuất hiện chỉ biết OK rồi.. la làng... Ẹc.. Ẹc...)
Câu này xem ra quá dễ với ThuNghi nhỉ?
 
Upvote 0
Hôm nay trở lại topic này với 1 câu đố rất dễ nhưng cũng.. vui vui
Như ta đã biết, nếu thiết lập Security ở mức High thì không thể chạy được macro ---> Vậy xin hỏi các bạn liệu có trường hợp ngoại lệ nào không?
(Máy tôi đang đặt security ở mức High nhưng tôi vẫn chạy code được đấy... Hi... Hi...)
 
Upvote 0
Chào anh, không biết có phải là cái này không?

MS đã viết:
When you set security levels to Very High, High, Medium, or Low, the following conditions apply:

* Very High security

VBA macros can run only if the Trust all installed add-ins and templates option is checked and the macros (signed or unsigned) are stored in a specific trusted folder on the user's hard disk. If all these conditions are not met, VBA macros cannot run under Very High security.

* High security

Executables must be signed by an acknowledged trusted source (certificate of trust) in order to run. Otherwise, all executables associated with, or embedded in, documents are automatically disabled without warning the user when the documents are opened. All Office applications are installed with macro security set to High by default.

Le Van Duyet
 
Upvote 0
Chào anh, không biết có phải là cái này không?



Le Van Duyet
Cũng không phức tạp thế đâu Duyệt ơi! Mình làm đơn giản hơn nhiều, gần như là chạy được ngay mà chẳng phải làm gì cả (thế mới gọi là đố vui, hay nói đúng hơn là đố mẹo 1 chút)
Nói thêm: Mình thường dùng cách này để test những code đơn giản trên 1 máy tính có security = High đấy
 
Lần chỉnh sửa cuối:
Upvote 0
...
Nói thêm: Mình thường dùng cách này để test những code đơn giản trên 1 máy tính có security = High đấy
Em thật sự không hiểu, code đơn giản là thế nào. Nhưng theo anh nói em nghĩ nếu có thể chạy code đơn giản thì cũng có thể chạy code phức tạp chứ anh nhỉ.
Hay anh dùng Immediate window à?

Lê Văn Duyệt
 
Upvote 0
Em thật sự không hiểu, code đơn giản là thế nào. Nhưng theo anh nói em nghĩ nếu có thể chạy code đơn giản thì cũng có thể chạy code phức tạp chứ anh nhỉ.
Hay anh dùng Immediate window à?

Lê Văn Duyệt
Cho dù ta có đặt Security cho Excel ở mức nào đi nữa, chỉ cần mở 1 Workbook mới, chèn code vào là nó chạy thôi ---> Nó chỉ "cằn nhằn" khi file ấy đã được lưu rồi mở lại mà thôi!
Ẹc... Ẹc...
 
Upvote 0
Thì em cũng đã test rồi với High Security, và dùng Immediate Window cũng test được mà.

Lê Văn Duyệt
 
Upvote 0
Cũng không phức tạp thế đâu Duyệt ơi! Mình làm đơn giản hơn nhiều, gần như là chạy được ngay mà chẳng phải làm gì cả (thế mới gọi là đố vui, hay nói đúng hơn là đố mẹo 1 chút)
Nói thêm: Mình thường dùng cách này để test những code đơn giản trên 1 máy tính có security = High đấy
Bác anhtuan1066 ơi. các đại cao thủ đang chờ bác giải đáp đấy. Hổng lẻ dùng công cụ hỗ trợ sao?
 
Upvote 0
Đọc bài này chưa vậy Minh?
Cho dù ta có đặt Security cho Excel ở mức nào đi nữa, chỉ cần mở 1 Workbook mới, chèn code vào là nó chạy thôi ---> Nó chỉ "cằn nhằn" khi file ấy đã được lưu rồi mở lại mà thôi!
Ẹc... Ẹc...
 
Upvote 0
Đọc bài này chưa vậy Minh?

Dạ. Em làm như vậy rùi. chỉ copy code vào cửa sổ VB thì nó chạy. Lưu lại lần sau chạy thì ko được nữa.

E tưởng có cách nào xử lý cái vụ Security hight khi người dùng chạy ứng dụng.

(Can thiệp vụ này chắc phải có công cụ khác rùi)
 
Upvote 0
Lấy ListFile trong 1 thư mục

Câu này hơi khó chút đây:
Làm sao lấy được list file trong 1 thư mục (có thể bao gồm thư mục con hoặc không, tùy ta chọn) mà không dùng bất cứ vòng lập nào?
Mở rộng thêm 1 chút: Có thể tùy chọn lọc ra 1 Extension nào đó (*.xls chẳng hạn)
 
Upvote 0
Câu này hơi khó chút đây:
Làm sao lấy được list file trong 1 thư mục (có thể bao gồm thư mục con hoặc không, tùy ta chọn) mà không dùng bất cứ vòng lập nào?
Mở rộng thêm 1 chút: Có thể tùy chọn lọc ra 1 Extension nào đó (*.xls chẳng hạn)
Bác Tuấn lặn 1 hơi dài, bữa nay lại ra câu đố cho anh em, bác ra luôn giải thưởng nữa chứ.
 
Upvote 0
Đưa mảng 1 chiều vào 1 cột

Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)
--------------------------
Bác Tuấn lặn 1 hơi dài, bữa nay lại ra câu đố cho anh em, bác ra luôn giải thưởng nữa chứ.
Các bạn cố gắng suy nghĩ, dù đúng sai gì cũng không sao, quan trọng ở thuật toán. Còn giải thưởng thì... về Đồng Nai uống cafe nhé
Hi... hi...
 
Upvote 0
Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)

Mã:
'Biến xác định chiều dài của mảng
Dim lArrLength As Long
lArrLength= UBound(arr)
'Đưa ra vùng mình muốn
'Giả sử là cột A, Sheet1
'Do UBound bắt đầu là 0 nên ta phải cộng thêm 1
Range("A1:A" & (lArrLength+1)) = arr
Có phải không anh.


Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
'Biến xác định chiều dài của mảng
Dim lArrLength As Long
lArrLength= UBound(arr)
'Đưa ra vùng mình muốn
'Giả sử là cột A, Sheet1
'Do UBound bắt đầu là 0 nên ta phải cộng thêm 1
Range("A1:A" & (lArrLength+1)) = arr
Có phải không anh.
Lê Văn Duyệt
Thì mình thí nghiệm cái là biết liền chứ gì
PHP:
Sub Test()
  Dim lArrLength As Long, Arr
  Arr = Array("a", "b", "c")
  lArrLength = UBound(Arr)
  Range("A1:A" & (lArrLength + 1)) = Arr
End Sub
Sau khi chạy code xong nó ra kết quả thế này

untitled.JPG

Hi... hi....
-------------------------
Nói thêm: Câu đố ở bài #365 có liên quan đến bài #363 đó nha (hay nói đúng hơn là 1 phần trong thuật toán ở bài #363 để bỏ vòng lập)
 
Lần chỉnh sửa cuối:
Upvote 0
Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)
--------------------------

Các bạn cố gắng suy nghĩ, dù đúng sai gì cũng không sao, quan trọng ở thuật toán. Còn giải thưởng thì... về Đồng Nai uống cafe nhé
Hi... hi...
Cái này thì dể nhưng quan trọng là làm sao để đưa filename vào trong Arr mà không dùng vòng lặp. Thôi Thầy bật mí luôn đi

Mã:
Sub Test()
  Dim lArrLength As Long, Arr
  Arr = Array("a", "b", "c")
  lArrLength = UBound(Arr)
  Range("A1:A" & (lArrLength + 1)) = [B][COLOR=blue]WorksheetFunction.Transpose[/COLOR][/B](Arr)
  
End Sub
 
Upvote 0
Cái này thì dể nhưng quan trọng là làm sao để đưa filename vào trong Arr mà không dùng vòng lặp. Thôi Thầy bật mí luôn đi
1> Nghiên cứu thử lệnh DOS này: DIR D:\Excel\*.xls /ON /B /S /A-D >C:\List.txt
Trong đoạn lệnh trên, ta chỉ cần chú ý mấy chổ tô màu
- Màu đỏ: Đường dẩn đến thư mục cần lấy list file
- Màu nâu: Extension
- Màu hồng: Lấy file trong cả thư mục con (/S)
- Màu xanh: Lưu kết quả vào trong 1 txt file nào đó
Việc còn lại là làm cách nào đưa đoạn lệnh DOS này vào trong VBA? Quá dễ.... Ví dụ thế này:
PHP:
CreateObject("Wscript.Shell").Run "cmd /c DIR D:\Excel\*.xls /ON /B / S/ A-D >C:\ List.txt", 0, True
2> Từ txt File, đọc nội dung và đưa vào Excel cũng chẳng khó gì. Có thể dùng:
a) Import External Data (từ menu Data trong Excel)
b) Dùng Scripting.FileSystemObject theo kiểu
PHP:
With CreateObject("Scripting.FileSystemObject")
    tmpFile = "C:\List.txt"
    Arr= Split(.OpenTextFile(tmpFile, 1).ReadAll, vbCrLf)
  End With
Trong code này, ta đã đưa được toàn bộ nội dung của file List.txt vào 1 mảng... Nếu file của ta có 1 ListBox để hiện thị thì có phải việc đưa vào ListBox là quá dễ không
PHP:
Me.ListBox1.List() = Arr
Từ ListBox này, nếu muốn đưa vào cột A cũng đơn giản
PHP:
With Me.ListBox1
  Range("A1").Resize(.ListCount).Value = .List
End With
Toàn bộ thuật toán chẳng động đến bất cứ vòng lập nào! Thử nghiên cứu xem... Ăn tiền ở chổ tốc độ làm việc rất nhanh (lấy list 30,000 file trong vòng 1s)
Tuy nhiên nếu làm y chang như trên thì code sẽ bị lỗi với những đường dẫn có khoảng trắng (ví dụ "D:\Excel\Form and Object control"). Vậy dùng cách gì để giải quyết tiếp đây?
Gữi các bạn file đính kèm, cứ từ từ nghiên cứu nha

untitled.JPG
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Cho trước mảng 1 chiều (chẳng hạn Arr = Array("a", "b", "c") )
Bằng cách nào đưa mảng này vào cột A mà không dùng hàm TRANSPOSE và vòng lập (khi ấy giá trị của A1:A3 lần lượt sẽ là a, b và c)
Để mình làm thử bài này bằng code đơn giản nhất nha
PHP:
Sub Test()
  Dim Arr
  Arr = Array("a", "b", "c")
  With ActiveSheet.OLEObjects.Add("Forms.ListBox.1")
    .Object.List = Arr
    .Parent.Range("A1").Resize(.Object.ListCount) = .Object.List
    .Delete
  End With
End Sub
Nghiên cứu xem có thú vị không?
 
Upvote 0
Chào bạn NDU , nếu mình muốn chọn trong máy thì có phải duyệt qua các ổ đĩa (vòng lặp ) không , và chỉnh lại thế nào ?
Cảm ơn
 
Upvote 0
Upvote 0
Đây là việc chúng ta ứng dụng hàm Split và đối tượng WScript.Shell nằm trong DLL (hình như là Shell32.dll). Rất có thể bản chất trong đối tượng và hàm này bên trong vẫn dùng vòng lặp để xử lý. Chúng ta chỉ việc dùng đối tượng và hàm nên không nhìn thấy cơ chế bên trong hàm. Còn tốc độ nhanh phần về thuật toán tìm kiếm phần là bởi DLL viết bằng các ngôn ngữ, như là các ngôn ngữ C, C++, Delphi, ASM (Assembler).
 
Upvote 0
Chào bạn NDU , nếu mình muốn chọn trong máy thì có phải duyệt qua các ổ đĩa (vòng lặp ) không , và chỉnh lại thế nào ?
Cảm ơn
Gợi ý bạn thêm 1 câu lệnh để tìm 1 lần trên nhiều ổ đĩa:
Mã:
DIR C:\*.xls D:\*.xls E:\*.xls /ON /B /S /A-D >C:\List.txt
Lệnh này sẽ tim file XLS trên 3 ổ đĩa C, D và E
Từ cú pháp này, có thể bạn sẽ không cần đến vòng lập mà vẫn làm được (việc còn lại là xử lý chuổi để cho vào code)
------------------------
Đây là việc chúng ta ứng dụng hàm Split và đối tượng WScript.Shell nằm trong DLL (hình như là Shell32.dll). Rất có thể bản chất trong đối tượng và hàm này bên trong vẫn dùng vòng lặp để xử lý. Chúng ta chỉ việc dùng đối tượng và hàm nên không nhìn thấy cơ chế bên trong hàm. Còn tốc độ nhanh phần về thuật toán tìm kiếm phần là bởi DLL viết bằng các ngôn ngữ, như là các ngôn ngữ C, C++, Delphi, ASM (Assembler).
Tôi cũng nghĩ vậy! Vấn đề là "nó" đã làm cả rồi thì ta chẳng việc gì phải tốn thêm vòng lập nữa cả
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi cũng nghĩ vậy! Vấn đề là "nó" đã làm cả rồi thì ta chẳng việc gì phải tốn thêm vòng lập nữa cả

Em cũng theo trường phái ứng dụng mà. Những dll chuẩn mà hệ thống đã cung cấp theo HĐH rồi (đương nhiên miễn phí) thì ta nên tìm cách vận dụng là tốt lắm rồi. Vì các dll này là trí tuệ của nhiều chuyên gia hàng đầu và họ cũng dùng nó cho hệ thống lớn nên ta dùng là yên tâm.
 
Upvote 0
Lấy đường dẫn file, folder bằng cách kéo thả chuột

Từ cửa sổ Windows Explorer, dùng chuột nắm lấy file hoặc thư mục, kéo và thả vào UserForm (hoặc 1 control nào đó trên UserForm). Sau đó lấy đường dẫn của file hoặc thư mục mà ta vừa kéo thả
Vậy xin hỏi các bạn: Họ đã làm điều đó như thế nào?
Hi... hi...
 
Upvote 0
Chào Anh Tuấn,

Câu hỏi của anh khó hiểu quá:
anhtuan1066 đã viết:
Vậy xin hỏi các bạn: Họ đã làm điều đó như thế nào?
Anh muốn nói về thuật toán, lập trình,... hay cái gì.

Lê Văn Duyệt
 
Upvote 0
Chào Anh Tuấn,

Câu hỏi của anh khó hiểu quá:

Anh muốn nói về thuật toán, lập trình,... hay cái gì.

Lê Văn Duyệt
Tức là vầy:
- Ta sẽ xây dựng 1 UserForm (có Control hoặc không tùy ý)
- Ta sẽ viết code gì đó sao cho khi ta dùng chuột nắm kéo file từ cửa sổ Explorer vào UserForm thì sẽ lấy được tên file
Vậy thôi... Trò này gần giống như khi ta kéo file, thư mục vào hộp RUN (start menu) thì ta có ngay đường dẫn
Với VB6 thì việc làm này quá dễ, ví dụ code trên VB6 với Form có 1 TextBox được viết như sau
PHP:
Private Sub Form_Load()
  Me.Text1.OLEDragMode = 1
  Me.Text1.OLEDropMode = 1
End Sub
PHP:
Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
  Text1.Text = Data.Files(1)
End Sub
Cái khó ở đây là phải viết bằng VBA code trên Excel
 
Lần chỉnh sửa cuối:
Upvote 0
Mở 1 file và hiện thông báo khi file đã đóng

Giả sử tôi có 1 file nằm ở đâu đó trên đĩa (chẳng hạn là D:\Ebooks\Macros.doc)
Tôi dùng code VBA trên Excel để mở file này (rất đơn giản). Nhưng nếu tôi muốn rằng: Sau khi đọc xong file Macros.doc, tôi đóng file này lại thì lập tức code VBA trên Excel sẽ xuất hiện thông báo cho biết "File da dong!"
Đại khái thế này:
Mã:
Sub Main()
  'Code mở 1 file từ đương dẫn [B][COLOR=red]D:\Ebooks\Macros.doc[/COLOR][/B]
  'Khi file [B][COLOR=red]Macros.doc[/COLOR][/B] đóng lại thì xuất hiện thông báo bên dưới
  MsgBox "File da dong!"
End Sub
Xin hỏi ta sẽ viết code thế nào đây?
 
Upvote 0
Làm sao có thể nhập liệu được ngay vào cell khi Form load

- Tôi có 1 UserForm với 1 TextBox
- Trên sheet đang select cell C5
- Khi gọi form lên, nếu ta nhập liệu gì đó từ bàn phím thì đương nhiên chuổi sẽ được nhập vào TextBox trên Form
Tôi muốn rằng: Khi form load lên, nếu nhập liệu từ bàn phím thì chuổi sẽ được nhập vào ActiveCell
Xin hỏi: Phải viết code thế nào?
----------------------------------------------
(Chủ đề này ít người quan tâm nhưng chắc chắn rồi 1 ngày nào đó các bạn sẽ dùng đến)
 

File đính kèm

Upvote 0
- Tôi có 1 UserForm với 1 TextBox
- Trên sheet đang select cell C5
- Khi gọi form lên, nếu ta nhập liệu gì đó từ bàn phím thì đương nhiên chuổi sẽ được nhập vào TextBox trên Form
Tôi muốn rằng: Khi form load lên, nếu nhập liệu từ bàn phím thì chuổi sẽ được nhập vào ActiveCell
Xin hỏi: Phải viết code thế nào?
----------------------------------------------
(Chủ đề này ít người quan tâm nhưng chắc chắn rồi 1 ngày nào đó các bạn sẽ dùng đến)

Có phải là khi nhập liệu vào textbox trên form thì dữ liệu sẽ đưa vào ActiveCell không Thầy ?
 
Upvote 0
Có phải là khi nhập liệu vào textbox trên form thì dữ liệu sẽ đưa vào ActiveCell không Thầy ?

Hỏng phải vậy!
Tôi muốn rằng: Bấm nút gọi form lên, nếu tôi gõ gì từ bàn phím thì ngay lập tức chuổi ấy sẽ được cho vào ActiveCell (thay vì sẽ vào TextBox) chứ không phải là chuyển dữ liệu từ TextBox vào cell
(Khi gõ bàn phím thì TextBox chẳng có gì cả)
Nói đúng hơn là Focus tại ActiveCell để sẳn sàng cho việc nhập liệu vào cell (dù hiện tại form đang được load)
 
Upvote 0
Hỏng phải vậy!
Tôi muốn rằng: Bấm nút gọi form lên, nếu tôi gõ gì từ bàn phím thì ngay lập tức chuổi ấy sẽ được cho vào ActiveCell (thay vì sẽ vào TextBox) chứ không phải là chuyển dữ liệu từ TextBox vào cell
(Khi gõ bàn phím thì TextBox chẳng có gì cả)
Nói đúng hơn là Focus tại ActiveCell để sẳn sàng cho việc nhập liệu vào cell (dù hiện tại form đang được load)

Có phải code sau không Thầy:

Mã:
Sub ShowForm()
  UserForm1.Show (False)
 [B][COLOR=blue] AppActivate Application[/COLOR][/B]
End Sub
 
Upvote 0
Tạo hiệu ứng gõ chữ trên cell

Đố các bạn làm được HIỆU ỨNG GÕ CHỮ
Lưu ý rằng: Hiệu ứng gõ chữ có nghĩa là từng ký tự được điền vào cell, kèm theo con nháy chuột phải dịch chuyển theo (khác với viêc gán ký tự vào cell nha)
Xem minh họa bằng clip này:

[video=youtube;5lfe35s765I]http://www.youtube.com/watch?v=5lfe35s765I[/video]
 
Lần chỉnh sửa cuối:
Upvote 0
Add List cho ComboBox thuộc thanh Forms

Nhân co người hỏi bài về ComboBox tại đây: Cách tạo Compobox để mở 1 sheet ẩn
Tôi chợt nãy ra ý tưởng dùng code để Add List cho ComboBox thuộc thanh Forms
Đối với ComboBox thuộc thanh Control ToolBox thì mọi người quá quen thuộc rồi, còn với ComboBox Forms thì sao? Liệu có thể Add list cho nó được không?
Mời các bạn thử xem
 
Upvote 0
Có lẽ giống thế này phải không. mình nêu cách thôi chưa hoàn thiện theo ý anhtuan được vì mổ cò lâu quá, các bạn bổ xung nha.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Có lẽ giống thế này phải không. mình nêu cách thôi chưa hoàn thiện theo ý anhtuan được vì mổ cò lâu quá, các bạn bổ xung nha.
Ý em là làm trên ComboBox (thuộc thanh Forms) chứ hổng phải menu anh à
Giống file đính kèm này đây
Anh và mọi người xem và nghiên cứu thử xem em đã Add list vào ComboBox như thế nào nhé
(Đã là VUI thế code cũng ngắn gọn lắm, chẳng phức tạp đâu)
 

File đính kèm

Upvote 0
Có lẽ file thế này hợp hơn.
ôi, giờ mới dọc bai tiếp và hiểu câu hỏi khác so với mình hiểu
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Em xin gợi ý thế này: Cách Add list cho ComboBox Forms hoàn toàn y chang như với ComboBox Control ToolBox
Mày mò hoài mà chả biết cái source nằm ở đâu, nhấn Alt Sh F11 thì thấy mà kg biết làm sao.
Xóa thử vài dòng thì thấy CB bớt dòng.
Bác chỉ giúp cách gì mà ghi vào Microsoft Script Editor hay vậy.
Cám ơn nhiều.
 
Upvote 0
Bác chỉ giúp cách gì mà ghi vào Microsoft Script Editor hay vậy.
Cám ơn nhiều.
Tôi đâu có dùng Microsoft Script Editor, tôi dùng VBA đàng hoàng à nha
Mày mò hoài mà chả biết cái source nằm ở đâu,
.
Vấn đề là phải biết được cái ComboBox này trong VBA nó được gọi tên là gì.
Xem lại bài này:
http://www.giaiphapexcel.com/forum/showthread.php?31515-Tạo-Form-bằng-DialogSheet&
sẽ thấy rằng:
- Label thì trong VBA gọi tên là Labels
- CheckBox thì trong VBA gọi tên là CheckBoxes
....................
Ngoài ra, khi ta vẽ ComboBox Forms lên sheet thì tên của nó trong Name Box là Drop Down 1, vậy tên được gọi trong VBA chắc cũng gần gần giống thế! Dropdowns chăng? Thử là biết liền
- Vẽ 1 ComboBox Form lên Sheet (để ý tên của nó trong hộp Name box, thường là Drop Down 1)
- Chèn 1 Module và cho code này vào để thử nghiệm:
PHP:
Sub Test()
  Sheet1.DropDowns("Drop Down 1").Select
End Sub
Chạy thử thấy OK
Vậy kết luận trong VBA, tên của ComboBox Forms được gọi là Dropdowns
Thế thì thử nghiệm Add list xem
PHP:
Sub cboAddList()
  Dim i As Long
  With Sheet1.DropDowns("Drop Down 1")
    For i = 1 To 3
      .AddItem "Item " & i
    Next
  End With
End Sub
Chạy thử rồi bấm mũi tên xổ xuống của ComboBox để kiểm chứng
----------------------
Xem file đính kèm tôi đã làm sẳn
Kết luận: Với các control thuộc thanh Forms thì cách viết code cũng gần giống như các ActiveX control mà thôi
 

File đính kèm

Upvote 0
Vậy Anh có thể tạo cho nó nhiều cột được không?
Bản thân ComboBox Forms không cho phép thể hiện list nhièu cột, cho dù có cố làm thì nó cũng sẽ biến mảng 2 chiều thành 1 chiều mà thôi
Ví dụ thế này sẽ biết liền:
PHP:
Sub Test()
  Dim Arr
  Arr = gì gì đó
  With Sheet1.DropDowns("Cbo1")
    .List() = Arr
  End With
End Sub
Mảng Arr tự bạn khai báo sao cho nó là 2 chiều, gán vào code và chạy thử, xong, bấm mũi tên ComboBox để kiểm chứng
 
Upvote 0
Lấy giá trị mà ta vừa chọn trong ComboBox Forms

Đố tiếp về ComboBox Forms
Giả sử tôi có code sau:
PHP:
Sub AddCbo()
 With ActiveSheet.DropDowns.Add(165.75, 39, 92.25, 21.75)
   .List() = Array("Tên 1", "Tên 2", "Tên 3", "Tên 4", "Tên 5")
 End With
End Sub
Chạy code này, ta được 1 ComboBox với List được add sẳn
Xin hỏi: Khi tôi chọn 1 Item nào đó trong ComboBox, làm sao để nhận được 1 MsgBox với giá trị mà tôi vừa chọn

untitled.JPG
 

File đính kèm

Upvote 0
Đố tiếp về ComboBox Forms
Giả sử tôi có code sau:
PHP:
Sub AddCbo()
With ActiveSheet.DropDowns.Add(165.75, 39, 92.25, 21.75)
.List() = Array("Tên 1", "Tên 2", "Tên 3", "Tên 4", "Tên 5")
End With
End Sub
Chạy code này, ta được 1 ComboBox với List được add sẳn
Xin hỏi: Khi tôi chọn 1 Item nào đó trong ComboBox, làm sao để nhận được 1 MsgBox với giá trị mà tôi vừa chọn

View attachment 60208
Có cho sửa nguồn và thao tác thủ công không vậy anh?
Nếu có thì em làm như sau:
1. Sửa nguồn một chút:
PHP:
Sub AddCbo()
 With ActiveSheet.DropDowns
    .Delete
    With .Add(165.75, 39, 92.25, 21.75)
        .List() = Array("Tên 1", "Tên 2", "Tên 3", "Tên 4", "Tên 5")
        .Name = "Cbo1"
    End With
 End With
End Sub
2. Tạo thêm 1 Sub:
PHP:
Sub ShowSelectedItem()
  With ActiveSheet.DropDowns("Cbo1")
    MsgBox .List(.Value)
  End With
End Sub
3. Assign Macro cho Cbo1 là ShowSelectedItem
 

File đính kèm

Upvote 0
Có cho sửa nguồn và thao tác thủ công không vậy anh?
Nếu có thì em làm như sau:
1. Sửa nguồn một chút:
PHP:
Sub AddCbo()
 With ActiveSheet.DropDowns
    .Delete
    With .Add(165.75, 39, 92.25, 21.75)
        .List() = Array("Tên 1", "Tên 2", "Tên 3", "Tên 4", "Tên 5")
        .Name = "Cbo1"
    End With
 End With
End Sub
2. Tạo thêm 1 Sub:
PHP:
Sub ShowSelectedItem()
  With ActiveSheet.DropDowns("Cbo1")
    MsgBox .List(.Value)
  End With
End Sub
3. Assign Macro cho Cbo1 là ShowSelectedItem
Cảm ơn bạn đã quan tâm. Bạn làm chính xác rồi đấy
Nếu thêm 1 chút tự động như vầy thì đở mất công Assign Macro
Mã:
Sub AddCbo()
  With ActiveSheet.DropDowns
    .Delete
    With .Add(165.75, 39, 92.25, 21.75)
      .List() = Array("Tên 1", "Tên 2", "Tên 3", "Tên 4", "Tên 5")
      .Name = "Cbo1"
      [B][COLOR="red"].OnAction = "ShowSelectedItem"[/COLOR][/B]
    End With
   End With
End Sub
Thêm chổ màu đỏ ấy
------------------------
Nói thêm: Nếu bạn khai báo 1 biến dạng vầy:
PHP:
Dim cbo as Dropdown
Thì ngay khi bạn gõ cbo.
sau dấu chấm sẽ có 1 tooltip xổ xuống gợi ý về các thuộc tính và phương thức (khỏe, khỏi mất công thuộc lòng)
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom