Đố vui về VBA! (2 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
 
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>
 
Upvote 0
CÂU HỎI 2: Sub và Private Sub?
Sau khi hoàn tất câu hõi 1, giờ tôi sữa code 1 chút, đặt code vào 1 module rồi dùng Command Button đễ gọi Sub thông qua lệnh Call
PHP:
Sub Add()
     Cho code vào đây!
End Sub
Private Sub CommandButton1_Click()
     Call Add
End Sub
Hoàn toàn ko có vấn đề gì về cách viết này.. và các bạn cũng thấy các cao thủ đã từng viết kiểu như vậy!
Cho hỏi: Cách viết trong câu hỏi 1 là gọi trực tiếp code bằng Button, còn cách viết thứ 2 này thì gọi code thông qua lệnh Call... Vậy có gì khác nhau giữa 2 cách viết và tại sao đôi khi ta lại cần làm như vậy? Sao ko cho code trực tiếp vào mà lại thông qua Call Add chi cho mất công thế?
ANH TUẤN
 
Upvote 0
Nào, các bạn mới! Tham gia đi.
Hoặc chưa biết làm thì thử 2 cách của tedaynui, rồi cho ý kiến đúng sai.
Lần sau biết làm.
Nghĩa là tham gia theo khả năng của mình. Không ai cười đâu. Ai cũng bắt đầu như thế cả!
Mại dzô! Cuối năm miễn phí!
 
Upvote 0
anhtuan1066 đã viết:
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
ANH TUẤN

Theo em đoạn này thiếu Sub cộng với việc ta phải khai báo biến K.
Tuy nhiên em đang đọc tai liệu thì khai báo là Dim ...
Chứ còn private ... thi chưa hiểu (đừng cười nhé.... còn ngu quá)
hì... Không biết đúng không???
 
Lần chỉnh sửa cuối:
Upvote 0
Đúng và chưa đúng.
Có rồi đấy chứ
ta phải khai báo biến K.
Đúng nhưng chưa phải nguyên nhân.
bạn cố lên tí nữa!

Giải thích thêm:
- Khai báo Private cho cả biến và sub:
biến chỉ dùng trong 1 sub nơi nó được khai báo, Sub chỉ dùng riêng trong sheet nơi nó được khai báo.
- Muốn biến dùng chung cho cả work book (và sub cũng vậy), khai báo Public
- Muốn biến dùng chung cho nhiều work book (đang mở), khai báo Global
Cấu trúc:
Private/Public/Global Sub()/<tenbien>
Riêng biến và sub dùng chung phải khai báo trong Module - General - Declarations
(Nhờ các cao thủ xem dùm đúng hông nha)
 
Upvote 0
anhtuan1066 đã viết:
CÂU HỎI 2: Sub và Private Sub?
Sau khi hoàn tất câu hõi 1, giờ tôi sữa code 1 chút, đặt code vào 1 module rồi dùng Command Button đễ gọi Sub thông qua lệnh Call
PHP:
Sub Add()
     Cho code vào đây!
End Sub
Private Sub CommandButton1_Click()
     Call Add
End Sub
Hoàn toàn ko có vấn đề gì về cách viết này.. và các bạn cũng thấy các cao thủ đã từng viết kiểu như vậy!
Cho hỏi: Cách viết trong câu hỏi 1 là gọi trực tiếp code bằng Button, còn cách viết thứ 2 này thì gọi code thông qua lệnh Call... Vậy có gì khác nhau giữa 2 cách viết và tại sao đôi khi ta lại cần làm như vậy? Sao ko cho code trực tiếp vào mà lại thông qua Call Add chi cho mất công thế?
ANH TUẤN
Cách giải thích của em !
Cách gọi code thông qua lệnh call nhằm mục đích bố trí sắp xếp và quản lý chương trình cho khoa học hơn, nhất là đối với những chương trình lớn và phức tạp, có nhiều lệnh phải thực hiện nhiều lần, khi chúng ta cần đến một nhiệm vụ chúng ta không cần phải viết lại cả đoạn code thực hiện nhiệm vụ đó nữa, chỉ cần dùng lệnh call...
 
Upvote 0
anhtuan1066 đã viết:
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 hôg phải lập trình viên, nên cũng hiểu tạm thế này thôi :D
K là biến cục bộ, khi thoát khỏi sub thì k sẽ trả về giá trị ban đầu, tức là 0, vì thể nếu nút command n lần thì cũng chỉ là 1 mà thôi,
nếu muốn range("A1").value tăng lên thì khai báo thêm
Mã:
 Dim k as integer
trước sub. Hôg biết vậy có đúng hôg nữa,hic
 
Upvote 0
vumian đã viết:
Mình hôg phải lập trình viên, nên cũng hiểu tạm thế này thôi :D
K là biến cục bộ, khi thoát khỏi sub thì k sẽ trả về giá trị ban đầu, tức là 0, vì thể nếu nút command n lần thì cũng chỉ là 1 mà thôi,
nếu muốn range("A1").value tăng lên thì khai báo thêm

Đúng rùi,
NHƯNG còn giải pháp sửa thì chưa cụ thể "khai báo thêm" trước sub (?) là ở đâu nhỉ (???) và tại sao làm thế (???).
Thử suy nghĩ xem sao
 
Upvote 0
Tức là vậy nè
Mã:
Dim k as integer
[COLOR=#000000][COLOR=#0000bb][/COLOR][COLOR=#007700]Private [/COLOR][COLOR=#0000bb]Sub CommandButton1_Click[/COLOR][COLOR=#007700]()
[/COLOR][COLOR=#0000bb]K [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]K [/COLOR][COLOR=#007700]+ [/COLOR][COLOR=#0000bb]1
Range[/COLOR][COLOR=#007700]([/COLOR][COLOR=#dd0000]"A1"[/COLOR][COLOR=#007700]).[/COLOR][COLOR=#0000bb]Value [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]K
End Sub [/COLOR][/COLOR]
[COLOR=#000000][COLOR=#0000bb][/COLOR][/COLOR] 
[COLOR=#000000][COLOR=#0000bb]Để cho nó thành biến toàn cục, thoát khỏi sub này, biến vẫn giữ nguyên giá trị đang có, sub khác mà gọi k thì là k có giá trị n lần click[/COLOR][/COLOR]
 
Upvote 0
Tôi có thễ nói nôm na theo cách hiễu của tôi về câu hõi 1 như sau:
-Biến K lúc đầu chưa có gì xem như = 0 thì đúng rồi...
-Khi chạy code, K sẽ tăng lên =1, đúng luôn
Nhưng khi chạy tiếp lần nữa thì mọi chuyện lại trở về từ đầu... Tức là K sẽ lại từ 0 chuyễn thành 1 mà ko hề biết rằng lần trước nó đã từng =1
Đễ ý xem trong này đâu có chỗ nào gọi là "nhớ" lại giá trị chạy lần trước... hi.. hi... Và nếu như thế thì khi chạy code lần thứ bao nhiêu biến K vẫn xem như còn "trinh nguyên".. từ 0 lại biến lên 1 mà ko bao giờ tăng dc lên 2, 3...
Chuyện khai báo biến là cần thiết nhưng chưa đũ trong trường hợp này... (khai tại đâu? Khai thế nào?).. Chính vì lẽ đó mà sẽ làm theo cách:
-Public K... hoặc Dim nằm trên cùng cũa Sub tạm xem như động tác cho nó "nhớ" giá trị lần trước... và nếu làm như cách này thì K có thể dùng cho những Sub khác
-Cells(1,1).Value = Cells(1,1).Value + 1 ... vùng nhớ chính là cell A1 luôn
--------------------------------
Câu 2:
Sub và Private Sub tôi có thễ hình dung nó giống như cái toilet của tôi và cái Toilet công cộng... he...he...
Cái Toilet công cộng thì ai cũng dùng dc, và ai cũng nhìn thấy nó nếu đi ngang qua... Ko tin cứ bấm Alt + F8 sẽ thấy ngay nó trong danh sách các macro...
Cái toilet cũa tôi là cũa riêng tôi... ai muốn dùng thì phãi vào nhà tôi mới thấy dc... Tôi đây chính là CommandButton1_Click... Và muốn dùng nó đương nhiên phãi thông qua tôi đễ vào nhà... Còn đi ngang qua cũng đương nhiên là sẽ ko thễ nhìn thấy... (Bấm Alt + F8 chã thấy nó tồn tại).. Chã thế mà nó ghi tên gọi Private đó sao? Ha.. ha..
Chính vì lẽ đó mà tùy theo từng trường hợp cụ thễ sẽ xài công cộng hay cá nhân... Nếu như tôi muốn xài lại em macro khi đạt 1 d/k nào đó thì hãy xài kiễu công cộng (Sub).. Lúc cần thì.. Call...
--------------------------
Tôi hiểu đến đây thì giãi thích đến đây!... Mong các cao thủ đóng góp ý kiến
ANH TUẤN

Anh Tuấn ơi, có thể dùng ví dụ khác được không anh ?
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Đúng rùi, chính xác là khai báo K ở đầu module (có thế là module 1, sheet ..., this workbook chẳng hạn), cắt nghĩa thêm 1 chút

như Pmt0412 viết trên
pmt0412 đã viết:
iải thích thêm:
- Khai báo Private cho cả biến và sub:
biến chỉ dùng trong 1 sub nơi nó được khai báo, Sub chỉ dùng riêng trong sheet nơi nó được khai báo.
- Muốn biến dùng chung cho cả work book (và sub cũng vậy), khai báo Public
- Muốn biến dùng chung cho nhiều work book (đang mở), khai báo Global
Cấu trúc:
Private/Public/Global Sub()/<tenbien>
Riêng biến và sub dùng chung phải khai báo trong Module - General - Declarations
(Nhờ các cao thủ xem dùm đúng hông nha)


Tuy nhiên với biến thì ta không cần đặt chữ Private mặt định không viết (không viết public, global ) _. máy sẽ hiểu là Private

Như vumian khai báo trên tức là biến K là biến địa phương của module (tức là dùng trong module đó được - nhưng module khác ko dùng chung được dù có ở chung Workbook đi nữa)

Nói thêm về tại sao bài cua anhtuan1066 thì bấm mãi mà K vẫn là 1: Vì như a tuấn không khai báo gì cả với K -> khi có lệnh K=K+1 -> khi này máy mới khởi tạo biến K (và chỉ coi nó là private - biến địa phương của sub mà thôi - và mặc định ban đầu là 0) -> K=K+1 =0+1 -> K=1 -> do đó A1 =1, thoát khỏi Sub này thì biến được tự động xóa khỏi bộ nhớ
bấm nút lần tiếp theo nữa thì sub đó (CommandButton1_Click())lại chạy lại và thế là lại quá trình trên (khởi tạo K, ban đầu K có giá trị 0, K=K+1=0+1=1) -> kết quả K=1 -> nên A1 lại bằng 1
Vì thế dù có nhấn bao nhiêu lần thì điều lặp lại qtr trên Vì vậy ô A1 lun là 1

Còn nếu chúng ta khai báo ngoài sub (như vumian) thì dù thoát ra khỏi SUB (kết thúc) rồi thì K vẫn còn giữ nguyên giá trị (dĩ nhiên chỉ trong phiên làm việc hiện thời) -> vì thế cứ bấm nút gọi SUB này thì K cứ tăng lên 1 đơn vị

Nói thêm về sử dụng biến
- Khi sử dụng biến nào cần lưu ý mấy điểm sau:
+ sd biến nào thì tốt nhất chúng ta khai báo
+ Cân nhắc về phạm vi hoạt động của biến (có cần sd / lưu lại giá trị cho các sub khác, module khác, workbook khác không?)
+ Không lạm dụng biến dùng chung -> vì tốn bộ nhớ và khó quản lý
+ ....
mong các cao thủ viết thêm
 
Upvote 0
tigertiger đã viết:
Đúng rùi, chính xác là khai báo K ở đầu module (có thế là module 1, sheet ..., this workbook chẳng hạn), cắt nghĩa thêm 1 chút
Thêm chút bác nhé : Hoặc đầu Sub với khai báo :
PHP:
Static K

Thân!
 
Upvote 0
anhtuan1066 đã viết:
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
Khi chạy 1 sub, giá trị ban đầu của các biến ở trong sub đó sẽ dựa vào việc khai báo biến đó.

Có 2 TH xảy ra : (Tính trong trường hợp File vẫn mở)
1 .Giá trị của biến là kết quả cuối cùng trước đó mà nó được gán. Trong trường hợp này chúng ta đã sử dụng phương pháp lưu giữ biến (như trình bày ở trên), để lần sau sử dụng thì giá trị ban đầu của biến (đối với Sub đó)sẽ là giá trị cuối cùng mà biến vừa nhận được.

Việc này tương tự như khi ta mua bán hàng hóa. Giá gốc của hàng hóa chính là giá bán của lần mua bán trước đó.
Như vậy mỗi khi có hành động mua bán xảy ra (Sub hoạt động) thì giá gốc của hàng hóa (đối với hoạt động mua bán này) (giống như giá trị ban đầu của biến đối với SUB này) sẽ là giá mua của lần mua bán trước đó.

2. Giá trị của biến không được lưu giữ, có nghĩa là mỗi khi chạy, biến lại được làm mới một lần. Giá trị ban đầu của nó sẽ là NOTHING (Nếu là Text thì nó là ký tự rỗng, nếu là number thì nó là số 0 . . . ).

Việc này giống như số điểm của đội bóng trong một mùa bóng vậy. Cứ bắt đầu một mùa bóng, số điểm của các đội bóng là 0 điểm. Số điểm khi kết thúc mùa bóng sẽ chỉ được sử dụng trong mùa đó mà không được bảo lưu qua mùa sau.

Nói thì dài dòng, nhưng hy vọng các bạn đã hiểu rằng tại sao khi A1 luôn = 1

Thân!
 
Upvote 0
nhukhang đã viết:
Cách gọi code thông qua lệnh call nhằm mục đích bố trí sắp xếp và quản lý chương trình cho khoa học hơn, nhất là đối với những chương trình lớn và phức tạp, có nhiều lệnh phải thực hiện nhiều lần, khi chúng ta cần đến một nhiệm vụ chúng ta không cần phải viết lại cả đoạn code thực hiện nhiệm vụ đó nữa, chỉ cần dùng lệnh call...
Giải thích rất đúng. Khi 1 code sử dụng nhiều lần và sub nào cũng có thể gọi đến nó, sub ấy gọi là Procedure. Procedure (thủ tục) là thuật ngữ dùng chung trong lý thuyết lập trình của mọi ngôn ngữ, (VBA là 1 trong các ngôn ngữ).
 
Upvote 0
Cách gọi code thông qua lệnh call nhằm mục đích bố trí sắp xếp và quản lý chương trình cho khoa học hơn, nhất là đối với những chương trình lớn và phức tạp, có nhiều lệnh phải thực hiện nhiều lần, khi chúng ta cần đến một nhiệm vụ chúng ta không cần phải viết lại cả đoạn code thực hiện nhiệm vụ đó nữa, chỉ cần dùng lệnh call...

pmt0412 đã viết:
Giải thích rất đúng. Khi 1 code sử dụng nhiều lần và sub nào cũng có thể gọi đến nó, sub ấy gọi là Procedure. Procedure (thủ tục) là thuật ngữ dùng chung trong lý thuyết lập trình của mọi ngôn ngữ, (VBA là 1 trong các ngôn ngữ).

Nhưng phải bổ sung thêm là:

Khi 1 code sử dụng nhiều lần và sub nào cũng có thể gọi đến nó và có thể thay đổi với bộ số liệu đầu vào (truyền ) khi gọi đến nó
 
Upvote 0
Câu hỏi 3:
Tôi tạo 1 macro với mục đích copy vùng A1:A10 và Paste vào B1:B10... Tôi viết như sau:
PHP:
Sub Copy_Paste()
   Range("A1:A10").Copy
   Range("B1").Select
   Selection.Paste
   Application.CutCopyMode = False
End Sub
Thấy cũng rất hợp lý, vậy mà nó ko chạy...
Nếu thay đoạn Selection.Paste thành ActiveSheet.Paste hoặc Selection.PasteSpecial Paste:=xlPasteAll thì ko có vấn đề
Tại sao thế?
ANH TUẤN

Câu hỏi 4: Select
Tôi đặt name cho vùng Sheet1!A1:A10VUNG1
Trong 1 module, tôi viết 1 đoạn code đễ chọn VUNG1 như sau:
PHP:
Sub Chon()
    Range("VUNG1").Select
End Sub
Đứng tại Sheet1, Code chạy ko có vấn đê.. nhưng khi tôi chuyễn Refer to cũa VUNG1 thành Sheet2!A1:A10 rồi cũng đứng tại Sheet1 đễ chạy code thì bị báo lỗi...
Tại sao vậy?
ANH TUẤN
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 1
Có cách nào trên trang tính để hiện đủ ba hộp thoại trong đoạn code sau

Ví dụ tôi có trang tính gồm chí ít 2 cột B & C;
Cột 'B' chứa tên (An, Bi, By, Ca, Cy, Bi, Sy, My, Na, . ..
Cột 'C' chứa hệ số lương, chẳng hạn ( 1,4 ; 1.71; 1,89 ; . . . .)
Và đoạn code như sau:
PHP:
Option Explicit
Sub DatabaseWithHeaders()
Dim rCSDL As Range:            Dim lHeaderRow As Long

2    Set rCSDL = Sheet5.Range("B2").CurrentRegion
    lHeaderRow = rCSDL.ListHeaderRows
4    MsgBox rCSDL.Address, , "A"
    If lHeaderRow > 0 Then
6        Set rCSDL = rCSDL.Resize(rCSDL.Rows.Count - lHeaderRow)
        MsgBox rCSDL.Address, , "B"
8        Set rCSDL = rCSDL.Offset(1)
9        MsgBox rCSDL.Address, , "C"
    End If
End Sub
Hãy sửa 1 hay 2 ô dữ liệu để hiện lên các hộp thoại; Nhất là 2 cái sau!

Phần mới bổ sung (2/01/08):
1*/ Diễn nôm 1 số từ dùng:
Tên macro 'DatabaseWithHeaders' diễn nôm có nghĩa là CSDL với các tiêu đề;
rCSDL - vùng cơ sở dữ liệu;
lHeaderRow - Có thể coi như biến kiểu long (l) chứa dòng tiêu đề;
CurrentRegion := vùng hiện sử dụng, Vùng hiện hành (cái này dịch chưa chuẩn mấy!). Các bạn có thể xem thêm trên DĐ;
Resize - Tính chất của Range. Nếu ta có Set Rng = Range("B1")
Thì Rng.Resize(2,2) sẽ có địa chỉ là '$B$1:$C$2'. Tạm coi như tính chất mở rọng 1 vùng có sẵn;
2*/ Chúng ta có thể gán cho biến lHeaderRow những giá trị <> 0 xen vô các dòng thích hợp để thấy các hộp thoại đưa ra kết quả gì. Từ đó có thể có những kết luận cần thiết (có thể là thú vị với 1 ai đó)!
Mã:
 [B][I][SIZE="3"]           Chúc mừng năm mới: Hạnh phúc & thành đạt với tất cả mọi người!! [/SIZE][/I][/B]
 
Lần chỉnh sửa cuối:
Upvote 0
Ví dụ tôi có trang tính gồm chí ít 2 cột B & C;
Cột 'B' chứa tên (An, Bi, By, Ca, Cy, Bi, Sy, My, Na, . ..
Cột 'C' chứa hệ số lương, chẳng hạn ( 1,4 ; 1.71; 1,89 ; . . . .)
Và đoạn code như sau:
Có lẽ vì topic này là dành cho người mới chập chững VBA
nên thiết nghĩ bác SA_DQ nên gợi ý rõ và mở vấn đề hơn,
thế này thì ........ hơi hoa mắt đây
 
Lần chỉnh sửa cuối:
Upvote 0
anhtuan1066 đã viết:
Câu hỏi 4: Select
Tôi đặt name cho vùng Sheet1!A1:A10VUNG1
Trong 1 module, tôi viết 1 đoạn code đễ chọn VUNG1 như sau:
PHP:
Sub Chon()
Range("VUNG1").Select
End Sub
Đứng tại Sheet1, Code chạy ko có vấn đê.. nhưng khi tôi chuyễn Refer to cũa VUNG1 thành Sheet2!A1:A10 rồi cũng đứng tại Sheet1 đễ chạy code thì bị báo lỗi...
Tại sao vậy?
ANH TUẤN

Xin chào cac anh, em mới lên mong các anh chỉ giáo thêm.
Em đã thử sữa lại như sau:
Mã:
Sub Chon()
Sheets("Sheet2").Select
Range("VUNG1").Select
[COLOR=blue]End Sub[/COLOR]
Vậy em nghĩ rằng nó báo lổi ở chổ chưa xác định được vị trí để hiển thị.
Thêm dòng lệnh trên để nó biết mình đang ở đâu mà thi hành.
Em xin hết.
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
hauomdldgh đã viết:
Vậy em nghĩ rằng nó báo lổi ở chổ chưa xác định được vị trí để hiển thị.
Tại sao lại chưa xác định nhỉ? Rõ ràng Define name tôi đã ghi rõ nó là: Sheet2!A1:A10 rồi còn gì.. chẳng lẽ như thế lại ko rõ ràng?
hi.. hi..
Cách giãi quyết cũa bạn thì đúng rồi... nhưng chưa thễ giãi thích tại sao
Tại sao?... Tại sao?...
ANH TUẤN
Cách giãi
 
Upvote 0
Thôi được em chịu thua, em chỉ biết rằng trong VBA phải xác định được vị trí Sheet đang thi hành còn nó có nạp dữ liệu từ trong Define vào hay không thì chịu. Xin anh giải thích rõ giùm.
 
Upvote 0
Tôi thì nghĩ như thế này đây:
Bất cứ thứ gì mình làm bằng tay dc thì macro gần như cũng làm dc, và phải tuân thủ theo trình tự mà ta đã làm...
Lấy ví dụ.. bạn muốn chọn VUNG1 nằm tại sheet2, nhưng hiện tai bạn đang đứng ở sheet1, nếu bạn thao tác bằng tay có phải là bạn sẽ làm theo 2 cách:
1> Chuyễn con trỏ chuột sang sheet2 rồi quét chọn VUNG1
2> Trong hộp name box bạn gõ vào chử VUNG1 rồi Enter (tương đương lệnh Goto)
Vậy thì khi "dạy" cho macro hiểu dc bạn muốn chọn VUNG1 bạn cũng sẽ làm như thế... Record macro sẽ thấy...
Tất nhiên ta ko thể từ Sheet1 "bay" 1 nhát sang sheet2 lập tức rồi... phải có 1 thao tác gì đó chuyễn tiếp chứ ... hi.. hi.. Nếu ko nó sẽ tưởng bạn đang nói về Sheet hiện hành... (có lẽ đây là quy định của MS)
Trong 2 cách trên tôi khoái nhất là Goto... hi.. hi..
Tóm lại 1 câu: Ta làm bằng tay thế nào thì hãy "nói" cho macro hiễu y chang thế (nếu ko nó sẽ hiễu lầm)
ANH TUẤN
 
Upvote 0
Em đồng ý rằng nó phải biết được Sheet đang chạy là sheet nào.
Nhưng sao em dùng hàm lại có thể chuyển dữ liệu qua giữa các Sheet một cách tự động mà không cần phải thấy sheet hiển thị lên.
Ví dụ như nạp dữ liệu từ Sheet [ThongKe] sang sheet [DanhBa] để lưu trữ thông tin chấm công theo ngày rồi xuất dữ liệu trở lại Sheet [ThongKe] để xem tiền lương của người đó. Em chỉ cần nạp dữ liệu cũng như xem dữ liệu trên 1 Sheet duy nhất mà không cần phải qua các Sheet khác. Vậy, trong Macro phải làm thế nào? Em không thấy Macro có tính năng này.
 
Upvote 0
Bạn dùng hàm thì bạn cũng có chổ phải ghi vào công thức tên Sheet đó thôi.. Ko có thì nó biết đâu mà lần...
ANH TUẤN
 
Upvote 0
À, em hiểu rồi. Nó chỉ có thể lấy dữ liệu trên Sheet khác chứ không thể tạo mới một lệnh nằm ở Sheet khác được phải không anh!
 
Upvote 0
anhtuan1066 đã viết:
Câu hỏi 3:
. . .

Nếu thay đoạn Selection.Paste thành ActiveSheet.Paste hoặc Selection.PasteSpecial Paste:=xlPasteAll thì ko có vấn đề
Tại sao thế?
ANH TUẤN
Gợi ý: câu trả lời nằm trong thông báo lỗi.
 
Upvote 0
anhtuan1066 đã viết:
Câu này tôi nghĩ đơn giãn hơn... Cái này là tại vì... ông Bill ổng quy định thế... Phải nói theo ngôn ngữ cũa ổng thì ổng mới chịu... he... he...
ANH TUẤN

Ko, chắc phải đâu atuan - có những cái nó phải theo logic
hoặc phòng trừ những cái lỗi tránh phải
a giải thích thế thì ........
 
Upvote 0
Xin phép AnhTuan1066 cho ké nha!

Macro được đưa ra dưới đây bắt nguồn từ http://giaiphapexcel.com/forum/showthread.php?t=7302
Xin các bạn dịch từ ngôn ngữ VBA sang ngôn ngữ tiếng việt & giải nghĩa (nếu cần) giúp với nha
Xin cảm ơn đã quan tâm & sẽ có hậu tạ sau 1 tuần!
PHP:
Option Explicit
Dim Rng As Range
Dim lRow As Long:                       Dim iCol As Integer

Sub CopyToVisible()
 Dim vRng As Range, dRng As Range
 Dim lRowV As Long, lColection As Long:          Dim iColV As Integer
 
 Set Rng = Range("A1:C7")                   'Selection'
 lRow = Rng.Rows.Count:                     iCol = Rng.Columns.Count
 Application.ScreenUpdating = False
 Set vRng = Range("D5").Resize(lRow, iCol).SpecialCells(xlCellTypeVisible)
 lRowV = vRng.Rows.Count:                   iColV = vRng.Columns.Count
 Set vRng = Range("D5"):                    lColection = 1
10  ' In Sheet1'
 If lRowV < lRow And iColV = iCol Then
    Do
11        Set dRng = vRng.Resize(lRow, iCol).SpecialCells(xlCellTypeVisible).Cells(1, 1)
12        lRowV = vRng.Resize(lRow, iCol).SpecialCells(xlCellTypeVisible).Rows.Count
13        If lColection + lRowV > lRow Then lRowV = lRow - lColection + 1
14        Rng.Cells(lColection, 1).Resize(lRowV, iCol).Copy Destination:=dRng
15        lColection = lColection + lRowV
16        Set vRng = vRng.Offset(1 + lRowV)
17        If lColection > lRow Then Exit Do
    Loop
20  'In Sheet2'
 ElseIf lRowV = lRow And iColV < iCol Then
    Do
21        Set dRng = vRng.Resize(lRow, iCol).SpecialCells(xlCellTypeVisible).Cells(1, 1)
22        iColV = vRng.Resize(lRow, iCol).SpecialCells(xlCellTypeVisible).Columns.Count
23        If lColection + iColV > iCol Then iColV = iCol - lColection + 1
24        Rng.Cells(1, lColection).Resize(lRow, iColV).Copy Destination:=dRng
25        lColection = lColection + iColV
26        Set vRng = vRng.Offset(, 1 + iColV)
27        If lColection > iCol Then Exit Do
        
    Loop
30
 ElseIf lRowV = lRow And iColV = iCol Then
    Rng.Copy Destination:=Range("D5")
40
 Else
    MsgBox "CHUA LAM DUOC"
 End If
 Set Rng = Nothing
End Sub
 
Upvote 0
Góp vui với bác SA cái nào. Tôi đố các bác làm một hàm xác định một số có phải là số nguyên tố hay không?

Ví dụ : songuyento(7) = true
songuyento(8)=false

Số nhập vào không có giới hạn đâu nhé.
 
Upvote 0
workman đã viết:
Góp vui với bác SA cái nào. Tôi đố các bác làm một hàm xác định một số có phải là số nguyên tố hay không?

Ví dụ : songuyento(7) = true
songuyento(8)=false

Số nhập vào không có giới hạn đâu nhé.

Thế hàm ISEVEN để làm gì hả workman ?
 
Upvote 0
kongcom đã viết:
Thế hàm ISEVEN để làm gì hả workman ?

Chào bạn Kongcom

Rất vui được làm quen với bạn.

Hàm Iseven được định nghĩa như sau: Returns TRUE if number is even, or FALSE if number is odd.

Even là số chẵn, Odd là số lẻ.

Nếu bạn có thời gian, bạn xem thử bài đố của tôi nhé. Đương nhiên việc tìm số nguyên tố có rất nhiều phương pháp, nhưng quan trọng là giải pháp nào tối ưu và nhanh nhất.

À, tôi quên nói lại định nghĩa số nguyên tố, sợ có bạn lại hiểu lầm tôi thì chết:

"Số nguyên tố được định nghĩa là chỉ chia hết cho 1 và cho chính nó", ví dụ: 1, 2, 3, 5, 7, 11, 13 ... là các số nguyên tố.
 
Upvote 0
workman đã viết:
Góp vui với bác SA cái nào. Tôi đố các bác làm một hàm xác định một số có phải là số nguyên tố hay không?

Ví dụ : songuyento(7) = true
songuyento(8)=false

Số nhập vào không có giới hạn đâu nhé.

@workman

Không giới hạn là sao nhỉ?
Số nguyên tố chỉ có thể là số nguyên dương thôi - cái nay có giới hạn không nhỉ?

@TV Khác
workman đã viết:
"Số nguyên tố được định nghĩa là chỉ chia hết cho 1 và cho chính nó", ví dụ: 1, 2, 3, 5, 7, 11, 13 ... là các số nguyên tố.
Gợi ý thêm (hay là câu hỏi mở hướng):
+ vậy sẽ phải xét nó chia với nx số nào nhỉ???
+ nếu nó chia hết cho 1 số nào đó -> nó ko phải là số nguyên tố - trái lại là số ng tố
 
Upvote 0
PHP:
Public Function SoNguyenTo(So As Integer)
    If So < 3 Then
    SoNguyenTo = "SO NGUYEN TO"
    Exit Function
    End If
    For i = 2 To So - 1
        If (So / i) - Int(So / i) = 0 Then
        SoNguyenTo = "SO KHONG NGUYEN TO"
        Exit Function
        End If
    Next
    SoNguyenTo = "SO NGUYEN TO"
End Function
 
Upvote 0
Tôi nghĩ nếu dùng vòng lập For thì chỉ cần i chạy đến INT(i/2) là đũ rồi
ANH TUẤN
 
Upvote 0
anhtuan1066 đã viết:
Tôi nghĩ nếu dùng vòng lập For thì chỉ cần i chạy đến INT(i/2) là đũ rồi
ANH TUẤN
Không chính xác a ơi,
Chính xác là: Vòng lập For thì chỉ cần i chạy từ 2 đến INT( SQR(i) )

Và không cần phải If .........<3 đâu

Nếu thêm thì thêm đều kiện Ktra có phải là số Nguyên Dương k?

 
Lần chỉnh sửa cuối:
Upvote 0
tigertiger đã viết:
Không chính xác a ơi,
Chính xác là: Vòng lập For thì chỉ cần i chạy từ 2 đến INT( SQRT(i) )

Và không cần phải If .........<3 đâu

Nếu thêm thì thêm đều kiện Ktra có phải là số Nguyên Dương k?

Ko phải là ko chính xác... mà là thừa...
ANH TUẤN
 
Upvote 0
Dựa trên cơ sở gợi ý của bác TigerTiger, tôi có chỉnh lại code viết hàm tìm số nguyên tố của bác BNTT như sau:
PHP:
Public Function SoNguyenTo(So As Double) As Boolean
    Dim i As Integer
    If So <= 0 Or Int(So) <> So Then
        SoNguyenTo = False
    Else
        For i = 2 To Int(Sqr(So))
            If So Mod i = 0 Then
                SoNguyenTo = False
                Exit Function
            End If
        Next
        SoNguyenTo = True
    End If
End Function
Nhờ các bác xem có còn lỗi gì không?
 
Lần chỉnh sửa cuối:
Upvote 0
anhtuan1066 đã viết:
Ko phải là ko chính xác... mà là thừa...
ANH TUẤN
a tuấn bắt bẻ wa nhỉ, híc đúng là thừa thôi, KQ vẫn chuẩn

ĐÚng là Sqr(<...>) -> tigertiger nhầm Sqrt(<...>) là hàm tính căn bậc 2

Sửa 1 chút cho nó dễ hỉu hơn
PHP:
Public Function SoNguyenTo(So As Double) As Boolean
    Dim i As Integer, sNt As Boolean
    sNt = True
    If So <= 0 Or Int(So) <> So Then
        sNt = False
    Else
        For i = 2 To Int(Sqr(So))
            If So Mod i = 0 Then
                sNt = False:    Exit For
            End If:  Next
    End If
    SoNguyenTo = sNt
End Function
 
Upvote 0
Nếu số là 2147483647 +1 thì sao? Lúc này nên khai biến thế nào?
 
Upvote 0
Topic chạy tới đây hình như ko còn mang mục đích là "đố vui" nữa rồi nhỉ? Ý tôi muốn nói đến 1 cái gì đó thật đơn giãn, ta dùng và thấy hàng ngày mà lại ko đễ ý tại sao nó lại như vậy!
ANH TUẤN
 
Upvote 0
Cách giải của tiger chuẩn rồi. Khâm phục!

Tiger trau chuốt thêm một chút để chạy nhanh hơn xem nào? Vẫn còn chưa tối ưu đâu.
 
Upvote 0
workman đã viết:
Cách giải của tiger chuẩn rồi. Khâm phục!

Tiger trau chuốt thêm một chút để chạy nhanh hơn xem nào? Vẫn còn chưa tối ưu đâu.
Đúng thuật toán Tìm nguyên tố có nhiều thuật toán (xem thêm ở phần cuối bài này). Ở đây chúng ta sử dụng thuật toán đơn giản,

Tuy vậy có thể tối ưu thêm 1 chút có thể để ý rằng ngoại trừ 2 còn tất cả những những số nguyên tố đều là số lẻ vì thế
thêm đ/k Nếu so thỏa mãn : (So > 2 And Int(So) Mod 2 = 0) -> là số không là số nguyên tố -> chỉ dùng For ktra khi so đó là số lẻ (ngoại trừ 2)

Và cụ thể như sau:

PHP:
Public Function SoNguyenTo(So As Double) As Boolean
    Dim i As Integer, sNt As Boolean
    sNt = True
    If So <= 0 Or Int(So) <> So Or (So > 2 And Int(So) Mod 2 = 0) Then
        sNt = False
    Else
        For i = 2 To Int(Sqr(So))
            If So Mod i = 0 Then
                sNt = False:    Exit For
            End If:  Next
    End If
    SoNguyenTo = sNt
End Function
Về thuật toán tìm số nguyên tố có nhiều thuật toán - thuật toán tối ưu nhanh - hiện người nói nhiều đến thuật toán Lấy ngẫu nhiên như: Kiểm tra Miller-Rabin và Kiểm tra Solovay-Strassen ; tuy nhiên các thuật toán này khá phức tạp
Xem thêm ở đây


@ThuNghi
ThuNghi đã viết:
Nếu số là 2147483647 +1 thì sao? Lúc này nên khai biến thế nào?
Vấn đề là chúng ta khai báo biến thôi -> đổi i thành Long. Nhưng ở đây đang chú ý là lệnh và thuật toán a ah
còn nếu cần tìm số nguyên tố là số rất lớn thì thuật toán lại khác xem thêm tại đây
 
Lần chỉnh sửa cuối:
Upvote 0
tigertiger đã viết:
a tuấn bắt bẻ wa nhỉ, híc đúng là thừa thôi, KQ vẫn chuẩn

ĐÚng là Sqr(<...>) -> tigertiger nhầm Sqrt(<...>) là hàm tính căn bậc 2

Sửa 1 chút cho nó dễ hỉu hơn
PHP:
Public Function SoNguyenTo(So As Double) As Boolean
    Dim i As Integer, sNt As Boolean
    sNt = True
    If So <= 0 Or Int(So) <> So Then
        sNt = False
    Else
        For i = 2 To Int(Sqr(So))
            If So Mod i = 0 Then
                sNt = False:    Exit For
            End If:  Next
    End If
    SoNguyenTo = sNt
End Function


Có lẽ nên dựa vào số cuối cùng của So sau đó mới kiểm tra If So Mod i = 0
Như vậy sẽ nhanh hơn một xíu (tuy nhiên lại phải thêm mấy dòng code nữa - Không biết hàm Mod và hàm Right thì cái nào nhanh hơn nhỉ ??)
Đây chỉ là một ý tưởng thoáng qua thôi.

Thân!
 
Upvote 0
Vậy 1 có phải snt không nhỉ?
Các hàm trên khi tính cho 1 sẽ sai hoặc báo lỗi, trừ cái nào có if So <=2
 
Lần chỉnh sửa cuối:
Upvote 0
ptm0412 đã viết:
Vậy 1 có phải snt không nhỉ?
Các hàm trên khi tính cho 1 sẽ sai hoặc báo lỗi, trừ cái nào có if So <=2
Theo những gì tôi biết từ trước tới giờ thì:
SỐ NGUYÊN TỐ LÀ SỐ CHỈ CHIA HẾT CHO 1 VÀ CHÍNH NÓ, NHỎ NHẤT LÀ 2
Vậy số 1 hình như không được xem như là số nguyên tố, vì số nguyên tố nhỏ nhất là 2.
Có bác nào có ý kiến khác không ạ ?
 
Upvote 0
BNTT đã viết:
Theo những gì tôi biết từ trước tới giờ thì:
SỐ NGUYÊN TỐ LÀ SỐ CHỈ CHIA HẾT CHO 1 VÀ CHÍNH NÓ, NHỎ NHẤT LÀ 2
Vậy số 1 hình như không được xem như là số nguyên tố, vì số nguyên tố nhỏ nhất là 2.
Có bác nào có ý kiến khác không ạ ?

Số nguyên tốsố tự nhiên lớn hơn 1, chỉ chia hết cho 1 và chia hết cho chính nó.
Ví dụ: 2, 3, 5, 7, 11..

Theo :_http://vi.wikipedia.org

Thân!
 
Upvote 0
Mr Okebab đã viết:
Số nguyên tốsố tự nhiên lớn hơn 1, chỉ chia hết cho 1 và chia hết cho chính nó.
Ví dụ: 2, 3, 5, 7, 11..

Theo :_http://vi.wikipedia.org

Thân!
Oh, đây chỉ là khái niệm thôi,
Nhưng đúng là thường thấy là 1 không phải số nguyên tố cũng lạ nhỉ?

Mr Okebab đã viết:
Có lẽ nên dựa vào số cuối cùng của So sau đó mới kiểm tra If So Mod i = 0
Như vậy sẽ nhanh hơn một xíu (tuy nhiên lại phải thêm mấy dòng code nữa - Không biết hàm Mod và hàm Right thì cái nào nhanh hơn nhỉ ??)
Đây chỉ là một ý tưởng thoáng qua thôi.
Thân!
Oh, nghe có vẻ hợp lý khi lấy chữ số cuối -> để xét nó chia hết 2, 3.. sẽ nhanh hơn:
+ tưởng đúng nhưng chưa bao hết ví dụ số 121 chẳng hạn
+ bên cạnh đó i chạy từ 2 -> những số chia hết cho 2, 3 sẽ bị loại ngay (không thực hiện hết vòng for)-> vẫn nhanh như thường
.
 
Lần chỉnh sửa cuối:
Upvote 0
tigertiger đã viết:
Oh, nghe có vẻ hợp lý khi lấy chữ số cuối -> để xét nó chia hết 2, 3.. sẽ nhanh hơn:
+ tưởng đúng nhưng chưa bao hết ví dụ số 121 chẳng hạn
+ bên cạnh đó i chạy từ 2 -> những số chia hết cho 2, 3 sẽ bị loại ngay (không thực hiện hết vòng for)-> vẫn nhanh như thường
.

Bác hiểu sai ý em rồi : Ta không dựa vào dấu hiệu chia hết!
VD : Số cuối của SO là :
: 1, vậy số cuối của i phải là : 1; 3; 7; 9
: 3, vậy số cuối của i phải là : 1; 3; 7; 9
: 5, vậy số cuối của i phải là : 1; 3; 5; 7; 9
: 7, vậy số cuối của i phải là : 1; 3; 7; 9
: 9, vậy số cuối của i phải là : 1; 3; 7; 9
Cái này ta chỉ xét 1 lần trước khi có vòng For.

Cũng chẳng biết là nhanh hơn không, hình như chậm hơn. Híc híc

Thân!
 
Upvote 0
Tôi thì sẽ làm bài toán nguyên tố này như sau:
1> D/k loại bõ các số chẳn và các số ko nguyên:
Mã:
If So < 2 Or (So <> 2 And So Mod 2 = 0) Or So <> Int(So) Then Exit Function
2> Tiếp theo cho vòng lập For chạy từ 3 đến Sqr(So) Step 2
3> Và vòng lập For như sau:
PHP:
For i = 3 To Sqr(So) Step 2
    If So Mod i = 0 Then Exit Function
Next
Vậy là xong...
Ngoài ra cũng có công thức cho vụ này, tuy đưa vào đây ko hợp lắm nhưng cũng xin góp vui (công thức mãng nha)
Mã:
=OR(A1=2,A1=3,ISNA(MATCH(TRUE,A1/ROW(INDIRECT("2:"&INT(SQRT(A1))))=INT(A1/ROW(INDIRECT("2:"&INT(SQRT(A1))))),0)))
Nói chung công thức hay VBA vẫn cùng 1 nguyên tắc TÌM và XÉT ĐIỀU KIỆN...
Mến
ANH TUẤN

Có lỗi gì đâu bạn... Tôi đang thử đây
SoNT(3) cho kết quã = TRUE
SoNT(5) cho kết quã = TRUE
SoNT(7) cũng cho kết quã = TRUE
Cã UDF và công thức cho cùng 1 kết quã
Hi.. hi... Máy bạn bị sao rồi đại ca ơi
ANH TUẤN
 

File đính kèm

Upvote 0
Tớ sai, vì nghĩ rằmg For i = m to n với m>n sẽ không chạy. Thực ra nó cũng chạy. Lạ thực, nó ra ngoài lý luận thông thường. Ai biết giải thích giùm.
Tớ thử thế này: thử với So=11, Int(Sqr(So)) = 3
Theo mình lý luận thì
- For chạy vòng 1, i = 3, OK
- For chạy vòng 2, i = 3 + 2 = 5 (5>Int(Sqr(So)) ) For phải ngưng.

Thế mà vẫn chạy. Kiểm tra (bằng cách Pause) : i vẫn = 5!!!
Kiểm tra với So=29, Int(So)) = 5, i đạt đến 7 !!!
 
Lần chỉnh sửa cuối:
Upvote 0
ptm0412 đã viết:
Tớ sai, vì nghĩ rằmg For i = m to n với m>n sẽ không chạy. Thực ra nó cũng chạy. Lạ thực, nó ra ngoài lý luận thông thường. Ai biết giải thích giùm.
Nhưng mà tôi đâu thấy phần Help nào nói rằng bắt buộc m phải nhỏ hơn n đâu nhỉ... Thử vào nó chạy tuốt...
ANH TUẤN
 
Upvote 0
tigertiger đã viết:
Vấn đề là chúng ta khai báo biến thôi -> đổi i thành Long. Nhưng ở đây đang chú ý là lệnh và thuật toán a ah
còn nếu cần tìm số nguyên tố là số rất lớn thì thuật toán lại khác xem thêm tại đây

Thuật toán của tiger quá tốt, tôi đâu có ý nghiên cứu toán cao cấp đâu (mà cũng không có khả năng, thông cảm già rồi).

Bạn chú ý nếu số nhập vào là số lớn thì việc chạy nhiều vòng lặp chính là nguyên nhân làm có hàm chạy chậm. Tiger nghiên cứu tiếp làm sao giảm vòng lặp xem sao?

Tôi thấy các bạn có nhiều cao thủ toán lý thuyết và toán tin. Thôi không dám ngo ngoe đố linh tinh nữa.

À, mà các bác có bài nào hay hay post lên để anh em giải trí cho vui.
 
Upvote 0
Nhưng mà tôi đâu thấy phần Help nào nói rằng bắt buộc m phải nhỏ hơn n đâu nhỉ... Thử vào nó chạy tuốt...
Không phải Help, mà là lý luận. For i = m to n step k nghĩa là:
i=m: chạy vòng 1
i=m+1*k: chạy vòng 2
i=m+2*k: chạy vòng 3
. . .

khi m+x*k = n, For dừng lại.

Thế mà nếu So=2, Int(Sqr(So)) = 1
Theo mình lý luận thì với For i=2 to 1 mà không có step âm
hoặc For i = 3 to 1 step 2 thì phải báo lỗi ngay khi tính i lần 2.
 
Upvote 0
Xin phép sửa lại chút xíu, tốc độ sẽ được cải thiện.
PHP:
Public Function SoNguyenTo(So As Double) As Boolean
    Application.Volatile (False)
    Dim i As Integer
    If So <= 1 Or Int(So) <> So Or (So > 2 And Int(So) Mod 2 = 0) Then Exit Function
    SoNguyenTo = True
    If So = 2 Or So = 3 Or So = 5 Or So = 7 Then Exit Function
    For i = 3 To Int(Sqr(So)) Step 2
        If So Mod i = 0 Then SoNguyenTo = False: Exit Function
    Next
End Function


Thân!

 
Upvote 0
Mr. Okebab đã viết:
Xin phép sửa lại chút xíu, tốc độ sẽ được cải thiện.

Thực ra cũng không cải thiện nhiều, vì thực ra ngay những vòng lặp đầu tiên -> Fun... đã xét đến chia 2,3,... như vậy nó sẽ bị loại ngay,
Đôi khi thấy Exit Funtion ta tưởng nhanh hơn -> nhưng nếu ta dùng IF, hay Exit For -> kết thúc lệnh - cũng tương đương nhau
Và trên cả vấn đề ở đây đúng như Workman viết đó là vấn đề khi số đó là số nguyên tố có giá trị lớn -> thuật toán đang dùng mất nhiều vòng lặp ->
khi đó phải dùng thuật toán khác

mạn đàm như vậy thôi, -> tôi nghĩ nên chuyển sang vấn đề khác
 
Upvote 0
tigertiger đã viết:
Thực ra cũng không cải thiện nhiều, vì thực ra ngay những vòng lặp đầu tiên -> Fun... đã xét đến chia 2,3,... như vậy nó sẽ bị loại ngay,
Đôi khi thấy Exit Funtion ta tưởng nhanh hơn -> nhưng nếu ta dùng IF, hay Exit For -> kết thúc lệnh - cũng tương đương nhau
Và trên cả vấn đề ở đây đúng như Workman viết đó là vấn đề khi số đó là số nguyên tố có giá trị lớn -> thuật toán đang dùng mất nhiều vòng lặp ->
khi đó phải dùng thuật toán khác

mạn đàm như vậy thôi, -> tôi nghĩ nên chuyển sang vấn đề khác

Cái nhanh hơn chút xíu là cái step 2, chứ mấy cái kia quan trọng gì.

Nhưng thôi có thể kết ở đây được rồi. Ta chuyển sang đề tài khác vậy.

Thân!
 
Upvote 0
Các bạn xem thử với cái vụ SNT này ta dùng Step 6 thì có nhanh thêm ko?
PHP:
Function SoNT(So As Single) As Boolean
    Dim i As Long
    If So < 2 Or (So <> 2 And So Mod 2 = 0) Or So <> Int(So) Then Exit Function
    If So = 3 Or So = 2 Then SoNT = True: Exit Function
    Select Case So Mod 6
         Case 1, 5
         For i = 5 To Sqr(So) Step 6
             If So Mod i = 0 Or So Mod i + 2 = 0 Then Exit Function
         Next i
    Case Else
        Exit Function
    End Select
    SoNT = True
End Function
Trong trường hợp Step 2, nó chỉ ngưng lại đễ xét 1 d/k, còn ở đây tuy Step 6, nhưng khi ngưng lại nó phải xét 2 d/k... Chã biết có nhanh ko nữa... Xin các cao thủ test dùm
ANH TUẤN
 
Upvote 0
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
về mặt lý thuyết là vậy, nhưng khai báo như trên các lần nhấn nút đều ở trạng thái 1, giá trị K khởi tạo đều bắt đầu là 0.
 
Upvote 0
New member cũng muốn đóng góp ý kiến cho câu 1. Ngoài các cách đã nêu ta còn có thể dùng cách sau:
Mã:
Sub Command1_Click()
Static k As Integer
k=k+1
...
End sub
Tuy nhiên cách này chỉ lưu được lại k trong lúc run-time, nếu đóng form lại và chạy lại code thì k sẽ đếm lại từ đầu.
 
Upvote 0
ANHTUAN1066, mình giải thích thế này có đúng không:
cái biến k bạn khai trong sub Cmd...click() vây nó là biến cục bộ của Sub đó. Kết thúc sự kiện click thì biến đó mất. Khi nhấn tiếp thì nó khởi động từ đầu.
Để được như bạn lập luận phải khai ở những dòng đầu tiên trong Module khi chưa có khai báo sub .
 
Upvote 0
ANHTUAN1066, mình giải thích thế này có đúng không:
cái biến k bạn khai trong sub Cmd...click() vây nó là biến cục bộ của Sub đó. Kết thúc sự kiện click thì biến đó mất. Khi nhấn tiếp thì nó khởi động từ đầu.
Để được như bạn lập luận phải khai ở những dòng đầu tiên trong Module khi chưa có khai báo sub .
Chắc là vậy!
Nếu ta không biết vụ khai báo Public cho biến K thì có thể làm theo cách củ chuối: Lưu biến K vào 1 Name (Trước khi chạy code, đặt name K, refer to = 1)
PHP:
Private Sub CommandButton1_Click()
   ActiveWorkbook.Names("K").Delete
   ActiveWorkbook.Names.Add Name:="K", RefersToR1C1:="=" & ([A1] + 1)
   [A1] = Evaluate("K")
End Sub
Cách này xem ra còn "ngầu" hơn khai báo Public ở chổ: Đóng file rồi mở ra, giá trị K vẩn được bảo toàn
 
Lần chỉnh sửa cuối:
Upvote 0
Các bạn ơi giúp mình chuyển lại hay viết lại cái code mã hóa từ tiếng việt thành con số này qua bên VBA của word với:
Function Gen(ByVal s As String) As String
Dim rs As String
Dim uniBytes As Byte() = Encoding.Unicode.GetBytes(s)
For i As Integer = 0 To uniBytes.Length - 1
rs &= uniBytes(i).ToString()
Next
Return rs
End Function
Cái này mình viết bên VB2005
Mong các bạn giúp đỡ.
 
Upvote 0
CÂU HỎI 2: Sub và Private Sub?
Sau khi hoàn tất câu hõi 1, giờ tôi sữa code 1 chút, đặt code vào 1 module rồi dùng Command Button đễ gọi Sub thông qua lệnh Call
PHP:
Sub Add()
     Cho code vào đây!
End Sub
Private Sub CommandButton1_Click()
     Call Add
End Sub
Hoàn toàn ko có vấn đề gì về cách viết này.. và các bạn cũng thấy các cao thủ đã từng viết kiểu như vậy!
Cho hỏi: Cách viết trong câu hỏi 1 là gọi trực tiếp code bằng Button, còn cách viết thứ 2 này thì gọi code thông qua lệnh Call... Vậy có gì khác nhau giữa 2 cách viết và tại sao đôi khi ta lại cần làm như vậy? Sao ko cho code trực tiếp vào mà lại thông qua Call Add chi cho mất công thế?
ANH TUẤN
Cách gọi Sub có các ưu điểm sau:
-Khi Copy sheet, dung lượng code không tăng lên bao nhiêu
-Muốn sửa code chỉ sửa ở 1 chổ
-Khi dùng pass để lock project, ta để sub vào module và copy sheet sang workbook khác thì không thể xem được code mà thấy như sau:
PHP:
Private Sub CommandButton1_Click()
     Call Add
End Sub
nhưng dùng trực tiếp, khi copy sheet sang workbook khác có thể xem được code
 
Lần chỉnh sửa cuối:
Upvote 0
Các bạn ơi giúp mình chuyển lại hay viết lại cái code mã hóa từ tiếng việt thành con số này qua bên VBA của word với:
Function Gen(ByVal s As String) As String
Dim rs As String
Dim uniBytes As Byte() = Encoding.Unicode.GetBytes(s)
For i As Integer = 0 To uniBytes.Length - 1
rs &= uniBytes(i).ToString()
Next
Return rs
End Function
Cái này mình viết bên VB2005
Mong các bạn giúp đỡ.
Hy vọng cái này có thể giúp bạn

http://www.giaiphapexcel.com/forum/showthread.php?p=113616#post113616
 
Upvote 0
Chào tất cả các bác, lâu quá không gặp không biết các bác vẩn khỏe hết chứ! Em có 1 vấn đề muốn hỏi về số nguyên tố nhưng vẫn chưa biết phải viết code như thế nào. Mong các bác chỉ giúp nha! Vấn đề là cần tìm tiệm cận trên, tiệm cận dưới của 1 số mà là số nguyên tố. Ví dụ: Nếu nhập vào công thức: =CTSNT(10)=11 =CDSNT(10)=7 Nếu có thể thì xin ít dùng vòng lặp thôi! Càng ít càng tốt. Ví khi tìm 1 số lớn thì sẽ rất lâu đó bác ơi. À, còn 1 điều nữa em nhận thấy rằng tất cả số nguyên tố điều là số lẻ (ngoại trừ số 2) nên không biết có thể giúp ít được không? Xin cảm ơn mọi người trước nha! Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Theo sự hướng dẫn tận tình của bác ndu96081631 em đã làm được với bộ công thức như sau:
PHP:
Private Function SoNT(So As Single) As Boolean     Dim i As Single     If So < 2 Or (So  2 And So Mod 2 = 0) Or So  Int(So) Then Exit Function     If So = 3 Or So = 2 Then SoNT = True: Exit Function     Select Case So Mod 6          Case 1, 5          For i = 5 To Sqr(So) Step 6              If So Mod i = 0 Or So Mod i + 2 = 0 Then Exit Function          Next i     Case Else         Exit Function     End Select     SoNT = True End Function
PHP:
 Function CDSNT(CheckNum As Single) As Single   Dim Temp As Single   For Temp = CheckNum To 2 Step -1     If SoNT(Temp) Then Exit For   Next   CDSNT = Temp End Function
PHP:
 Function CTSNT(CheckNum As Single) As Single   Dim Temp As Single   For Temp = CheckNum To 10 ^ Val(Len(CheckNum) + 1)     If SoNT(Temp) Then Exit For   Next   CTSNT = Temp End Function
Lúc đầu em dùng biến là Long nhưng đọc trong sách "Lập trình VBA trong Excel" thấy có biến Single với giá trị lưu trữ lớn hơn rất nhiều từ 1.401298E-45 đến 3.40282338 (Sách Lập trình VBA trong Excel trang 102) Nhưng khi áp dụng vào thì code không chạy mà đứng trơ ra không hiểu nguyên do? Không có vị sư phụ nào am hiểu vấn đề có thể trình bày cho em được rõ không ạ? Xin chân thành cảm ơn. Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Lúc đầu em dùng biến là Long nhưng đọc trong sách "Lập trình VBA trong Excel" thấy có biến Single với giá trị lưu trữ lớn hơn rất nhiều từ 1.401298E-45 đến 3.40282338 (Sách Lập trình VBA trong Excel trang 102)


Theo mình thì trong VB (VBA) dạng biến chứa dữ liệu số lớn nhất là Double
 
Upvote 0
Cái này em không chắc lắm, vì em toàn học lóm cả! Còn chính xác như thế nào mời các cao thủ bình luận thêm nha. Và nhất là tác giả sách là bác Phan Tự Hướng sẽ cho bác biết chính xát hơn em. Đây là nội dung bảng kiểu giá trị trong VB mà bác Hướng đã viết.
Kiểu giá trị | Mô tả Byte | Lưu giữ số nguyên dương nhỏ, từ 0 đến 255
Boolean | Lưu giữ kết quả Logic, True hoặc False
Integer | Lưu giữ giá trị nguyên, từ -32,768 đến 32,767 Long | Lưu giữ giá trị nguyên, từ -2,147,483,648 to 2,147,483,647 Single | Lưu giữ giá trị số, từ -3.402823E38 đến -1.401298E-45; từ 1.401298E-45 đến 3.402823E38 Currency | Lưu giữ số liệu kiểu tiền tệ, áp dụng cho lĩnh vực tài chính, kế toán. Từ -922337203685477.5808 đến 922337203685477.5807 Date | Lưu giữ số liệu kiểu thời gian, từ January 1, 100 tới December 31,9999. Dữ liệu kiểu Date phải có dấu # ở hai đầu. Object | Chứa tham khảo đến bất kỳ đối tượng nào. String | Lưu giữ dưới dạng chuỗi, dài của chuỗi từ 0 đến 65535 ký tự, giá trị chuỗi được đặt trong dấu "" Variant | Lưu mọi dữ liệu thuộc kiểu định sẵn như: Date, String, Double, Integer... Nếu bạn không khai báo kiểu rõ ràng cho biến thì được hiểu là Variant. VBA sẽ chuyển đổi dữ liệu thuộc kiểu Variant thành một kiểu dữ liệu khác cho phù hợp trong quá trình tính toán.​
Thân.​
 
Lần chỉnh sửa cuối:
Upvote 0
Biến Single và Double là số nguyên và phân, không phải số nguyên đơn thuần như Integer và Long. Thế mà For ...next nó đòi nguyên mới chịu cơ! Nó không nhảy đỏng lên hoặc đứng ì ra là may đấy!
 
Upvote 0
Dùng Single thì không nguyên đúng không? Mà For... next muốn nguyên. Vậy ta có thể khắc phục bằng cách thêm INT vào để lấy số đầu thôi cho lệnh For... next, vậy là ổn 1 cái. Nhưng em chỉ có thể dùng đến số 16777218 thôi. Lớn hơn thì nó đứng ì ra. Và công thức lấy cận trên thì lại sai và luôn lấy số cuối cùng mà mình nhập vào. Còn cận dưới thì rơi vào số 1677213. Cũng tình huống trên nhưng dùng biến Long thì số tận cùng là 2147483647. Và nó là số nguyên tố cuối cùng luôn. Tức là cận trên hay cận dưới điều là nó cả. Và biến Integer thì là số 32767. Vậy xét thấy biến Long Integer đã làm đúng trách nhiệm của mình là đã hoàn thành chỉ số cho phép còn biến Single thì tại sao lại không đúng vậy? Xin chỉ giáo thêm.
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu tôi không nhầm thì toán tử MOD bạn dùng ở đây có chút vấn đề với số lớn. Bạn thử thay thế toán tử MOD bằng phương pháp khác xem sao.
 
Upvote 0
Hàm MOD chia được số lớn nhất là 402,653,183. Vậy là do hàm MOD không đáp ứng được số quá lớn. =MOD(402653183,3) Nhưng nếu dùng công thức khác để thay thế thì sao? Ví dụ như:
PHP:
Function ModTay(so1 As Variant, so2 As Variant) As Variant ModTay = so1 - Int(so1 / so2) * so2 End Function
Với ModTay thì tính đến số 1E+307 luôn nhưng hình như không chính xác nhỉ? =ModTay(1E+307,3)= 1.2474E+291 (À sao em nhập số này rồi Enter thì Excel tự tắt vậy? Không biết các bác có bị giống em không?) =ModTay(1E+16,3) đến ModTay(1E+306,3) điều ra = 0 cả. Các số 1E+15 trở xuống thì tính mới đúng. Vậy là sao ta? Vậy ta chuyển qua dùng Round thay INT xem sao nha!
PHP:
Function ModTay(so1 As Variant, so2 As Variant) As Variant ModTay = so1 - WorksheetFunction.Round((so1 / so2), 0) * so2 End Function
=ModTay(1E+307,3)|= 9.9792E+291 =modtay(1E+306,3)|= 1.0915E+291 =modtay(1E+305,3)|= 9.7453E+289 =modtay(1E+304,3)|= 9.7453E+288 =modtay(1E+303,3)|= 9.1362E+287 =modtay(1E+302,3)|= 1.142E+287 =modtay(1E+301,3)|= 1.0707E+286 =modtay(1E+300,3)|= 1.0409E+285 =modtay(1E+299,3)|= 1.1153E+284 =modtay(1E+298,3)|= 9.2939E+282 =modtay(1E+297,3)|= 1.1617E+282 =modtay(1E+296,3)|= 9.076E+280 =modtay(1E+295,3)|= 9.076E+279 =modtay(1E+294,3)|= 1.1345E+279 =modtay(1E+293,3)|= 8.8633E+277 =modtay(1E+292,3)|= 8.8633E+276 =modtay(1E+291,3)|= 9.6942E+275
(Và gõ các số lớn này vào cũng gây Exit Excel luôn) Đến =modtay(1E+15,3) nó mới đúng. Và Excel luôn khống chế 1 số lớn hơn 1E+307, tứ là 1E+308 thì sẽ báo lỗi và sẽ hiện giá trị là -1 vào đó. Vậy ta không bao giờ tính được các số lớn hơn 1E+306 sao? Nhưng sao khi đưa vào công thức thì vẫn bị khống chế không chạy là sao ta? Mọi người ơi giúp em tý nữa nha! Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi đã gặp vấn đề này 1 lần mà giờ không nhớ ở bài nào. Nhưng chắc chắn là không dùng INT hay ROUND được. Trong bài đó hình như tôi dùng hàm Floor của WorksheetFunction, bạn thử lại với hàm Floor này xem sao
Mã:
  PhanDu = So1 - WorksheetFunction.Floor(So1/So2,1)*So2
 
Upvote 0
Rất tiết hàm Floor báo lỗi #Value! toàn bộ không tính được bất kỳ số nào? Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Rất tiết hàm Floor báo lỗi #Value! toàn bộ không tính được bất kỳ số nào?
Thân.
Lỗi #VALUE bạn thừa biết là sai kiểu tham số truyền vào mà. Bạn thử kiểm tra lại xem, tôi vừa thử viết 1 hàm và nó chạy tốt mà.
Mã:
Function BigMod(So1 As Double, So2 As Double) As Double
    BigMod = So1 - Application.WorksheetFunction.Floor(So1 / So2, 1) * So2
End Function
 
Upvote 0
À thì ra lúc em dùng Floor đặt thông số cuối là 0 nên nó báo #Value! Và không phải là biến sai đâu bác vì em dùng biến Variant mà. Và nếu dùng công thức trên thì số cũng đâu có vượt ra khỏi 1E+307 đâu. Và kết quả vẫn sai ý như vậy thôi! Đâu có gì thay đổi đâu bác! Em cần tìm số cực lớn và thoát khỏi 16777218 luôn. Mà các hàm Mod tự tạo chỉ cho phép dùng đến 15 chữ số thôi. Còn qua công thức xác định cận số nguyên tố thì chỉ còn có 8 số thôi! Vậy phải làm sao để lấy được số nguyên tố cực lớn hả bác. Mong mọi người tìm thêm cách giúp em với! Thân.
 
Lần chỉnh sửa cuối:
Upvote 0
Theo tôi biết thì bài toán về số nguyên tố cực lớn thuộc nhóm các bài toán có độ phức tạp cao nhất (hình như gọi là NP-Hard). Trong đó có bài toán phân tích nhân tử áp dụng trong mật mã công khai. Khi đó tồn tại các số nguyên tố có đến hàng trăm chữ số.

Với khả năng tính toán có giới hạn trên trường số nguyên (trong Excel cũng như với hầu hết các ngôn ngữ lập trình) thì việc tính các số nguyên lớn thường phải dựa vào các hàm phụ trợ tính toán trên các chuỗi số (xây dựng các lớp để thực hiện các phép tính trên chuỗi số thay vì trên số).

(Có thể tham khảo các phần mềm toán chuyên dụng: MathLap, MathCad...)

Thân!
 
Upvote 0
Bác có thể nói rõ hơn không? Hiện em đang đi theo hướng tìm quy tắc của các số nguyên tố này và hình nhưng chưa có quy tắc nào phù hợp cả. Còn 1 vấn đề nữa em cũng đang nghĩ đến là việc tách số ra lớn ra nhiều số nhỏ hơn kiểu như 15815384 * 10 ^ 5 +1536157 nhưng không biết khi tách ra như vậy có ảnh hưởng gì đến kết quả không?
 
Lần chỉnh sửa cuối:
Upvote 0
Các bác ơi! Em tìm thấy trang này: http://www.codeproject.com/KB/cs/biginteger.aspx?print=true nhưng không biết cách dùng như thế nào? Mong ai đọc được English rành thì chỉ cho em với. Hình như nó nói về cách tính Big Integer nhưng cụ thể dùng ra sao thì ... ? Có ai giỏi toán học không? Dịch giùm em cái này ra Code với? Đọc vào mù luôn! http://vi.wikipedia.org/wiki/Ki%E1%BB%83m_tra_t%C3%ADnh_nguy%C3%AAn_t%E1%BB%91 http://vi.wikipedia.org/wiki/Kiểm_tra_Miller-Rabin http://vi.wikipedia.org/wiki/Kiểm_tra_Solovay-Strassen http://forums.congdongcviet.com/showthread.php?t=1366&page=2 Help!Help!Help!Help!Help!
 
Lần chỉnh sửa cuối:
Upvote 0
Lâu quá chẳng thấy ai ghé thăm, mà nếu có ghé cũng chẳng hỏi chuyện.. vui...
He... he...
Hôm nay xin góp cho bà con 1 câu hỏi đúng là.. vui vui đây
1> Đoạn code 1
PHP:
Sub Test1()
  With Range("D4")
    .Offset(2, 2).Select
    MsgBox Selection.Address
  End With
End Sub

2> Đoạn code 2
PHP:
Sub Test2()
  With Range("D4")
    .Cells(2, 2).Select
    MsgBox Selection.Address
  End With
End Sub
Theo các bạn thì 2 đoạn code trên đã làm điều gì?
- Cell nào sẽ được chọn?
- MsgBox ghi cụ thể là cái gì?
 
Upvote 0
Lâu quá chẳng thấy ai ghé thăm, mà nếu có ghé cũng chẳng hỏi chuyện.. vui...
He... he...
Hôm nay xin góp cho bà con 1 câu hỏi đúng là.. vui vui đây
1> Đoạn code 1
PHP:
Sub Test1()
  With Range("D4")
    .Offset(2, 2).Select
    MsgBox Selection.Address
  End With
End Sub
2> Đoạn code 2
PHP:
Sub Test2()
  With Range("D4")
    .Cells(2, 2).Select
    MsgBox Selection.Address
  End With
End Sub
Theo các bạn thì 2 đoạn code trên đã làm điều gì?
- Cell nào sẽ được chọn?
- MsgBox ghi cụ thể là cái gì?

Code 1:
Range("F6") được chọn [Cell(6,6)]
Msgbox ghi: $F$6

Code 2
Range("E5") được chọn [Cell(5,5)]
Msgbox ghi: $E$5

Hai đoạn code trên chỉ để select cell!
Code 1 dùng Offset. Lấy Range("D4") làm chuẩn

Code 2 khác chút, Range("D4").Cells(2,2): Range("D4") làm chuẩn, nên trong hệ quy chiếu này Rang("D4") tương đương cột mốc chính. Nên Cells(2,2) lúc này sẽ phải tính từ Range("D4") (Giống như ta dùng sheets("Sheet1").Cells(2,2), lúc này sheets("sheet1") là hệ quy chiếu, gốc của nó mặc định là A1 vậy!)
 
Upvote 0
Dear Anh
+ Với Test 1 thì ô được chọn là F6, và msgbox là $F$6

Với Test 2 thì ô được chọn là E5, và msgbox sẽ ghi là $E$5

ở test 2 này em thấy hay ở chỗ là tuy ghi là cells(2,2) nhưng lại thành E5

Anh chỉ thêm
 
Upvote 0
Cãm ơn Ca_dafiST-Lu! đã góp vui
Nhưng... chưa chắc những cái 2 bạn nói là đáp án đâu
Thế mới là ĐỐ VUI chứ (vì code đã có, chỉ việc copy và paste vào là chạy ---> Đâu có đơn giãn thế)
He... he...
 
Upvote 0
Anh ơi
Em thấy test 1 còn hiểu (đối với em). Nhưng Test 2 không biết giải thích thế nào.

Em chịu rồi
 
Upvote 0
Anh ơi
Em thấy test 1 còn hiểu (đối với em). Nhưng Test 2 không biết giải thích thế nào.

Em chịu rồi
Cái này giống hàm INDEX của công thức Excel ấy!
Ví dụ:
PHP:
Set Rng = Range("F5:I10")
Rng(2,2).Select
Có nghĩa là chọn dòng 2, cột 2 của Rng, tức chọn G6
===> Rng(1,1) = F5
===> Rng(0,0) = E4
===> Gần giống với Offset nhưng lệch với Offset 1 đơn vị
Đoạn code này:
PHP:
Sub Test2()
  With Range("D4")
    .Cells(2, 2).Select
    MsgBox Selection.Address
  End With
End Sub
viết rõ ra sẽ là vầy:
PHP:
Sub Test2()
    Range("D4")(2, 2).Select
    MsgBox Selection.Address
End Sub
(cứ nghĩ Range("D4") chính là Rng tôi ví dụ ở trên, bạn sẽ hiểu ngay)
 
Upvote 0
Gửi các bạn file đáp án! Xem thử bên trong nó nói cái gì nha!
Thí nghiệm này muốn nói với các bạn rằng:
- Một bài toán tưởng chừng đơn giản nhưng vẫn có thể ko đơn giãn như ta đã nghĩ
- Offset Properties có vẽ mang ý nghĩa "vật lý" hơn.... Nếu tính toán gì đó trên "giấy tờ" dựa vào Offset thì hãy coi chừng... sa bẫy (tôi đã từng bị như thế)..
- Hay nói cụ thể hơn: Range("A1").Offset(1,1) chưa chắc là cell B2 đâu nha
 

File đính kèm

Upvote 0
Gửi các bạn file đáp án! Xem thử bên trong nó nói cái gì nha!
Thí nghiệm này muốn nói với các bạn rằng:
- Một bài toán tưởng chừng đơn giản nhưng vẫn có thể ko đơn giãn như ta đã nghĩ
- Offset Properties có vẽ mang ý nghĩa "vật lý" hơn.... Nếu tính toán gì đó trên "giấy tờ" dựa vào Offset thì hãy coi chừng... sa bẫy (tôi đã từng bị như thế)..
- Hay nói cụ thể hơn: Range("A1").Offset(1,1) chưa chắc là cell B2 đâu nha
Cám ơn Bác nhiều, nhờ đó mới để ý dùng offset nhớ kiểm tra merge cell. Cái này Thầy Long lúc viết Code sort với hơn 3 côt có bẫy mà không để ý.
 
Upvote 0
Thanks anh Tuấn,

Theo em vấn đề ở đây không phải do offset hay cells quyết định. Mà nguyên nhân bị sai là do Select. Nhưng thế mơi thấy cần phải nghiên cứu rõ trường hợp select này.

Hi vọng có thể tham gia tiếp các câu đố sau của anh.
 
Upvote 0
Chào mọi người! Tôi có 1 câu hỏi...
Đây cũng không hẳn là câu đố vui nhưng tình huống của nó thì tôi nghĩ chúng ta rất thường gặp
- Có 1 danh sách nằm ở A1:C35
- Cột C chứa dử liệu: DL1, DL2... đến DL15 ( nằm lộn xộn)
- Cell E2 dùng Validation để chọn điều kiện
- Dùng Advanced Filter lọc ra kết quả đặt tại I1 theo điều kiện ở E2
Vấn đề là Advanced Filter trong file này làm việc không chính xác! Khi chọn điều kiện = DL1 thì nó lọc luôn DL10, DL11...
===> Vậy nếu bắt buộc phải dùng Advanced Filter thì phải làm cách nào
(Đương nhiên AutoFilter không bị tình trạng này)
Xin hãy xem file và cho biết giãi pháp
 

File đính kèm

Upvote 0
Bác xem thử cái này nhé.

[Highlight=VB]Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim SL
If Target.Address = "$E$2" Then
Application.EnableEvents = False
SL = [E2]
[E2] = "=""=" & SL & """"
[I1].CurrentRegion.Clear
[A1].CurrentRegion.AdvancedFilter 2, [E1:E2], [I1]
[E2] = SL
Application.EnableEvents = True
End If
End Sub[/highlight]
 
Upvote 0
Advance Filter with Criteria is Text

Trước hết bạn có thể đọc cái này
PHP:
All items that begin with that text are filtered. For example, if you type the text Dav as a criterion, Microsoft Excel finds "Davolio," "David," and "Davis." To match only the specified text, type the following formula, where text is the text you want to find. =''=text''

và kiểm tra lại file đính kèm.

Thân!
 

File đính kèm

Upvote 0
Bác xem thử cái này nhé.

[highlight=VB]Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim SL
If Target.Address = "$E$2" Then
Application.EnableEvents = False
SL = [E2]
[E2] = "=""=" & SL & """"
[I1].CurrentRegion.Clear
[A1].CurrentRegion.AdvancedFilter 2, [E1:E2], [I1]
[E2] = SL
Application.EnableEvents = True
End If
End Sub[/highlight]
Hay ghê...
Mấu chốt nằm ở chổ:
Nếu tôi không cho công thức này vào code thì tôi có thể đặt nó ở 1 cell phụ nào đó...
Tuyệt!
Trước hết bạn có thể đọc cái này
PHP:
All items that begin with that text are filtered. For example, if you type the text Dav as a criterion, Microsoft Excel finds "Davolio," "David," and "Davis." To match only the specified text, type the following formula, where text is the text you want to find. =''=text''
và kiểm tra lại file đính kèm.

Thân!
Thì ra nó nằm trong Help ---> Vậy mà không chịu xem... Hic...
Cảm ơn bạn!
 
Lần chỉnh sửa cuối:
Upvote 0
Các Anh ơi
Application.EnableEvents = False
có tương tự với
Application.volatile (false)

Không ạ

[A1].CurrentRegion.AdvancedFilter 2, [E1:E2], [I1]

Em đã record lại macro nhưng chữa hiểu số 2 ở trên ??

Các anh chỉ giúp
Xin cám ơn
 
Lần chỉnh sửa cuối:
Upvote 0
Application.Volatile
Dùng trong khai báo hàm của người dùng (UDF), nếu đặt True (mặc định là False) thì hàm sẽ tự tính lại khi có sự tính toán trong 1 ô bất kỳ trên bảng tính có chứa hàm.
(The function will be recalculated whenever calculation occurs in any cells on the worksheet on which this function appears.)
Application.EnableEvents = True/False
Thiểt lập hoặc hủy bỏ bộ xử lý sự kiện của E. Thường được dùng trong các sub xử lý sự kiện để tránh tình trạng bị gọi lại trong khi chưa xử lý xong (sẽ tạo vòng lặp vô hạn)

Riêng chữ số sau AdvancedFilter là giá trị trong hằng xlFilterAction: xlFilterInPlace (=1) (lọc và đặt tại chỗ), hằng còn lại là xlFilterCopy (=2), lọc và copy đến vị trí khác.
 
Upvote 0
Bác xem thử cái này nhé.

[Highlight=VB]Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim SL
If Target.Address = "$E$2" Then
Application.EnableEvents = False
SL = [E2]
[E2] = "=""=" & SL & """"
[I1].CurrentRegion.Clear
[A1].CurrentRegion.AdvancedFilter 2, [E1:E2], [I1]
[E2] = SL
Application.EnableEvents = True
End If
End Sub[/highlight]
[E2] = "=""=" & SL & """"

Các anh ơi sao lắm "=" thế? giúp em hiểu được không?

Tks
 
Upvote 0
[E2] = "=""=" & SL & """"

Các anh ơi sao lắm "=" thế? giúp em hiểu được không?

Tks
Đưa chuổi công thức vào... 1 chuổi ---> Cái này sẽ rắc rối khi trong công thức có dấu "
Vì lẽ đó, đôi khi muốn dể nhìn người ta sẽ thay " thành Chr(34)
Hảy làm 1 cuộc thí nghiệm sau:
PHP:
Sub Test()
    Dim SL
    SL = "NDU"
    MsgBox "=""=" & SL & """"
End Sub
Xem nó ra cái gì ---> Từ đó suy ra ý nghĩa của những dấu "
 
Upvote 0

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

Back
Top Bottom