PDA

View Full Version : Thư viện các hàm tự lập bằng VB


PMXD
23-05-2006, 12:49 PM
Chào các anh em!
Lâu rồi không tạo chủ đề mới, tranh thủ hôm nay trời mưa, tôi post vài hàm trong VB để anh em cùng tham khảo. Cũng rất mong anh em, ai có hàm gì hay hay post lên đây thường xuyên để cũng tra đổi và học tập. Các hàm có thể đơn giản mà hiệu quả cao thì rất hoan nghênh.

1- Hàm sắp xếp các tành phần trong mảng theo thứ tự ăng dần

Sub SapXepThuTuMang(Mang)
Dim i As Long, j As Long

For i = 0 To UBound(Mang)
For j = 0 To UBound(Mang)
If i <> j And Mang(i) < Mang(j) Then
HoanVi Mang(i), Mang(j)
End If
Next j
Next i
End Sub
'=================================================


2- Hàm tìm Max của nhiều thành phần

Function TimMax(thamso As Variant)
Dim i As Integer
TimMax = -1E+50
For i = 0 To UBound(thamso)
If thamso(i) > TimMax Then
TimMax = thamso(i)
End If
Next
End Function

'=============================================
3- Hàm tìm Min của nhiều thành phần

Function TimMin(thamso As Variant)
Dim i As Integer
TimMin = thamso(LBound(thamso))
For i = LBound(thamso) To UBound(thamso)
If thamso(i) < TimMin Then
TimMin = thamso(i)
End If
Next
End Function

PhanTuHuong
23-05-2006, 02:11 PM
Chào anh Việt Anh. Anh kiểm tra lại hàm số 1 vì chưa khai báo "HoanVi".
Cám ơn anh đã post lên cho mọi người có thể tham khảo và sử dụng.

PMXD
23-05-2006, 04:20 PM
Oh, do sơ suất nên quên không post hàm HoanVi, cám ơn anh Phan Tự Hướng nhiều.


'=====================HAM HOAN VI 2 gia tri
Sub HoanVi(GiaTri1, GiaTri2)
Dim GiaTriTam
GiaTriTam = GiaTri2
GiaTri2 = GiaTri1
GiaTri1 = GiaTriTam
End Sub

phu_ho
23-05-2006, 05:46 PM
to bác PMXD: Tôi không biêt VB đâu, nhưng tôi thấy nếu sắp xếp mảng thì nên viết thế này chẳng hạn thì tính toán nó sẽ đơn giản hơn nhiều :)


Sub SapXepThuTuMang(Mang)
Dim i As Long, j As Long, N As Long

N = UBound(Mang)
For i = 0 To N-1
For j = i+1 To N
if Mang(i) < Mang(j) Then
HoanVi Mang(i), Mang(j)
End If
Next j
Next i
End Sub

Với lại đây là sắp xếp theo thứ tự giảm dần.

minhtu
23-05-2006, 06:53 PM
Em thấy đúng là hàm SapXepThuTuMang của bác PMXD là sắp xếp tăng dần đấy chứ (BubbleSort).
Nếu viết theo cách của bác phu_ho (SelectionSort) thì lại là sắp xếp giảm dần.

Tuy nhiên vòng lặp sau For j = 0 To UBound(Mang) thì hơi thừa, chỉ cần For j = 0 To i là được.

Nếu ai quan tâm đến thuật toán sắp xếp, có 1 chương trình nhỏ có 1 số thuật toán sắp xếp và so sánh tốc độ giữa chúng.
http://vbnet.mvps.org/images/gfx/sort/sortdemo.gif

Đây là hàm sưu tầm, không phải em tự lập -> Em bị lạc đề mất rồi. :eek: :eek: :eek:

PMXD
24-05-2006, 11:48 AM
Xin cảm ơn bác phu_ho và minhtu đã đóng góp ý kiến. Do đây là hàm cũng nhỏ nên tôi vẫn dùng thuật toán chưa tối ưu. Nhân đây, tôi đề xuất ý kiến nên lập ra một Box chuyên trao đổi các thuật toán (dù là đơn giản nhất) để chia sẻ các thủ thuật lập trình.

alpha_cont
29-05-2006, 09:10 PM
Cho em hỏi mấy vấn đề về macro trong excel.
1>Anh xem code VB(file kèm theo). E nhập data từ file access xuất ra từ sap 2000. Từ vùng data dung lệnh counta đếm được số hang. Anh cho e hỏi dủng lệnh gì để bảng tính chạy từ hang thứ 1 đền hang thứ counta chứ không phải đến hang thứ 10.000 (hay max 65534). Nếu chạy như vậy thì chương trình tính sẽ chậm vì nó tính cả những hàng không có phần tử?
2>Do chạy từ hang đầu tiên đến hàng thứ 10.000 (or max 645534) nên khó quản lý trang in.
3>Hạn chế của file này là chỉ cập nhật được file access trong thư mục mặc định khi viết macro, làm sao khắc phục trình trạng này?
4>Làm sao mỗi khi mở file excel lên thì các macro “deldata”, “inputdata”, “tinhthep” sẽ tự động cập nhật chứ không phải chạy thủ cong từng macro?

Em thấy mấy file người ta còn tạo mấy cái nút, để khi nhập liệu vào xong thì "bấm" cho no chạy trong excel, làm cái đó như thế nào nhi?

minhtu
29-05-2006, 11:20 PM
Cho em hỏi mấy vấn đề về macro trong excel.
1>Anh xem code VB(file kèm theo). E nhập data từ file access xuất ra từ sap 2000. Từ vùng data dung lệnh counta đếm được số hang. Anh cho e hỏi dủng lệnh gì để bảng tính chạy từ hang thứ 1 đền hang thứ counta chứ không phải đến hang thứ 10.000 (hay max 65534). Nếu chạy như vậy thì chương trình tính sẽ chậm vì nó tính cả những hàng không có phần tử?
2>Do chạy từ hang đầu tiên đến hàng thứ 10.000 (or max 645534) nên khó quản lý trang in.
3>Hạn chế của file này là chỉ cập nhật được file access trong thư mục mặc định khi viết macro, làm sao khắc phục trình trạng này?
4>Làm sao mỗi khi mở file excel lên thì các macro “deldata”, “inputdata”, “tinhthep” sẽ tự động cập nhật chứ không phải chạy thủ cong từng macro?

Em thấy mấy file người ta còn tạo mấy cái nút, để khi nhập liệu vào xong thì "bấm" cho no chạy trong excel, làm cái đó như thế nào nhi?

1. MsgBox Application.WorksheetFunction.CountA(Worksheets("DAM").Range("A1:A65536"))
Cách này cẩn thận khi có dòng dữ liệu trống xen giữa --> khi tính toán dễ gây lẫn
Có nhiều cách để xác định dòng dưới cùng có dữ liệu.
3. MsgBox Application.ActiveWorkbook.Path & "\"
4. Thuộc tính của ThisWorkbook
Private Sub Workbook_Open()
DelData
InputData
TINHTHEP
End Sub

Muốn tạo nút:
Phải chuột vào toolbar, customize...
bên tab Commands mục Categories chọn New Menu, mục Commands lôi cái New Menu ra toolbar
Phải chuột vào nút mới đó Assign Macro.
OK
Tuy nhiên nên xem phần tạo menu khi mở, xóa menu khi đóng

morpheus
30-05-2006, 03:35 AM
[QUOTE=minhtu]Em thấy đúng là hàm SapXepThuTuMang của bác PMXD là sắp xếp tăng dần đấy chứ (BubbleSort).
Nếu viết theo cách của bác phu_ho (SelectionSort) thì lại là sắp xếp giảm dần.

Tuy nhiên vòng lặp sau For j = 0 To UBound(Mang) thì hơi thừa, chỉ cần For j = 0 To i là được.

QUOTE]

:D Các bác không chuyên rồi. Thuật toán "sủi bọt" (bubble sort) này là thuật toán cơ bản nhất khi học tin. Ở đây ta nên dùng với phép lặp điều kiện thì đúng hơn là với phép lặp đếm. Điều này cho phép chủ động dừng vòng lặp khi thuật toán đã hoàn tất (chứ không nhất thiết phải thực hiện toàn bộ 2 phép lặp chồng nhau) và sẽ không sót trường hợp nào.

Dim Mang() As Double
Dim i As Integer
Dim isNotYetSorted As Boolean
Do
isNotYetSorted = False
For i = Lbound(Mang) to Ubound(Mang) - 1
If Mang(i) > Mang(i + 1) Then
HoanVi(Mang(i), Mang (i+1))
isNotYetSorted = True
End If
Next
Loop Until Not isNotYetSorted.

Các bác check lại xem nhé.

PMXD
30-05-2006, 10:49 AM
:D Các bác không chuyên rồi. Thuật toán "sủi bọt" (bubble sort) này là thuật toán cơ bản nhất khi học tin. Ở đây ta nên dùng với phép lặp điều kiện thì đúng hơn là với phép lặp đếm. Điều này cho phép chủ động dừng vòng lặp khi thuật toán đã hoàn tất (chứ không nhất thiết phải thực hiện toàn bộ 2 phép lặp chồng nhau) và sẽ không sót trường hợp nào.

Dim Mang() As Double
Dim i As Integer
Dim isNotYetSorted As Boolean
Do
isNotYetSorted = False
For i = Lbound(Mang) to Ubound(Mang) - 1
If Mang(i) > Mang(i + 1) Then
HoanVi(Mang(i), Mang (i+1))
isNotYetSorted = True
End If
Next
Loop Until Not isNotYetSorted.

Các bác check lại xem nhé.

Rất cám ơn morpheus đã đóng góp ý kiến. Ở diễn đàn cũng hầu hết là các anh em xây dựng tự lập trình nên đôi lúc cũng không tránh khỏi việc thiếu tối ưu trong thuật toán. Ở bài viết lần trước, tôi cũng đề xướng mở một chủ đề bàn về các thuật toán hay gặp khi lập trình cho các ứng dụng trong xây dựng, nhưng không thấy ai ủng hộ.

minhtu
30-05-2006, 11:09 AM
:D Các bác không chuyên rồi. Thuật toán "sủi bọt" (bubble sort) này là thuật toán cơ bản nhất khi học tin. Ở đây ta nên dùng với phép lặp điều kiện thì đúng hơn là với phép lặp đếm. Điều này cho phép chủ động dừng vòng lặp khi thuật toán đã hoàn tất (chứ không nhất thiết phải thực hiện toàn bộ 2 phép lặp chồng nhau) và sẽ không sót trường hợp nào.

Em cũng được học một ít về tin học thì được biết các bài toán mức độ tính toán phụ thuộc dữ liệu đầu vào thì không có giải thuật nào là tốt nhất. Mỗi giải thuật hay trong trường hợp này nhưng lại chưa hay trong trường hợp khác. Các bác cứ thử với 2 bộ số liệu (9,8,7,6,5,4,3,2,1,0) và (0,1,2,3,4,5,6,7,8,9) rồi dùng thử các hàm sort sẽ thấy mỗi giải thuật hay với bộ 1 nhưng chưa chắc đã hay với bộ 2 và ngược lại.

Còn giải thuật nổi bọt theo lý thuyến vẫn có 2 vòng for ***g nhau, không biết có cách 2 như bác viết không.

Ở bài viết lần trước, tôi cũng đề xướng mở một chủ đề bàn về các thuật toán hay gặp khi lập trình cho các ứng dụng trong xây dựng, nhưng không thấy ai ủng hộ
Em ủng hộ.

morpheus
30-05-2006, 11:46 AM
Rất cám ơn morpheus đã đóng góp ý kiến. Ở diễn đàn cũng hầu hết là các anh em xây dựng tự lập trình nên đôi lúc cũng không tránh khỏi việc thiếu tối ưu trong thuật toán. Ở bài viết lần trước, tôi cũng đề xướng mở một chủ đề bàn về các thuật toán hay gặp khi lập trình cho các ứng dụng trong xây dựng, nhưng không thấy ai ủng hộ.

Bác PMXD cứ lập ra đi, đồng bào nhiều khi cũng chẳng chủ động lắm đâu. Nếu lập ra một thời gian mà thấy không có hiệu quả thì ta lại đóng lo gì. Bác là mod mà, tiếp thị thêm vài bài ở các chủ đề khác thế nào chả có người quan tâm. Tôi nghĩ mục đó cũng sẽ HOT đấy. Ít nhất bác cũng đã có 2 thành viên rồi nhé.:D

PhanTuHuong
04-06-2006, 09:45 PM
Anh PMXD dạo này mải làm ăn hay sao mà ko thấy post thêm hàm nào?
Thỉnh thoảng post lên để cho mọi người học hỏi, tham khảo và bình luận cho code hoàn thiện,...
Xin chào!

PMXD
05-06-2006, 11:57 AM
Xin chào mọi người!
Lâu nay tôi cũng chẳng lập thêm được hàm nào hay ho cả, các hàm thông thường có POST lên chắc cũng không hiệu quả. Để góp vui thêm cho Box, tôi thảo luận với anh em về 1 thuật toán mà trước đây tôi thu thập được.
'========
Đề bài: Cho một tập hợp N(gồm n phần tử),. Hãy tìm trong tập hợp N phần tử thỏa mãn tính chất A.
'========
Khi đọc đề bài này, chắc ai cũng nghĩ ngay đến thuật toán "VÉT CẠN", đó là dùng vòng For chạy từ đầu đến cuối tập hợp để tìm ra phần tử có thuộc tính A. Tuy nhiên, nếu số lượng phần tử rất rất nhiều thì vòng lặp này sẽ chạy rất lâu (Đặc biệt khi dùng ngôn ngữ VB) vì số phép tính là n!.
'========
Thuật toán "CHIA ĐÔI" (tôi quên tên chính xác rồi, cứ tạm gọi như vậy):Chia đôi tập hợp ban đầu thành 2 tập hợp con N1 và N2. Dùng 1 vòng lặp For chạy trong tập hợp N1. Nếu gặp phần tử thỏa mãn thuộc tính A thì kết thúc lặp, nếu chạy hết mà không gặp phần tử đó thì xét đến tập con N2. Trong tập con N2 lại chia thành 2 tập con N21 và N22 và làm tương tự.
Cứ như vậy thì số lượng phép toán sẽ giảm đi rất nhiều, tăng tốc độ chạy chương trình.
Nếu bạn nào dùng Delphi hoặc C++ chắc cũng chẳng cần để ý đến thuật toán này, nhưng tôi làm VB, nếu cứ "VÉT CẠN" nhiều khi chạy toàn "TREO MÁY" :D
Các bạn xem có gì đóng góp ý kiến

tnlinh
05-06-2006, 01:33 PM
Mục đích của bài toán trên là lọc trong 1 tập hợp những phần tử thỏa mãn điều kiện nào đó. Theo tôi, số phép tính duyệt chỉ là n, bằng số phần tử của tập hợp, không phải là n!???

Không có cái nào tốt hơn và dễ hơn cách for i:=0 to n-1 do duyet(i)

Không cần bàn việc tối ưu ở đây, nếu bàn thì bài toán cần thêm dữ kiện.

Cuong_gt41
05-06-2006, 02:44 PM
ok. Đúng là n chứ không phải là n! . Khi cho chung chung như thế thì chỉ có cách làm for(i=1 to n). Còn khi muốn tối ưu thì phải xắp xếp theo một quy luật nhất định

tien2005
05-06-2006, 06:09 PM
Các bác cho em hỏi sử dụng hàm Redim như thế nào?
Có thể khai báo giatri=redim(i,j,k)
sau đó tìm giá trị k nào đó thì ta cũng tìm được giá trị i, j tương ứng
vd: i là phần tử, j là vị trí mặt cắt, k là giá trị moment
Cám ơn các Bác

Cuong_gt41
06-06-2006, 09:30 AM
Các bác cho em hỏi sử dụng hàm Redim như thế nào?
Có thể khai báo giatri=redim(i,j,k)
sau đó tìm giá trị k nào đó thì ta cũng tìm được giá trị i, j tương ứng
vd: i là phần tử, j là vị trí mặt cắt, k là giá trị moment
Cám ơn các Bác
Bác có thể dùng đối tượng thùng chứa của VB (Collection) Trong đó nhồi gì vào chẳng được...
Như của bác thì bác nên tạo ra một đối tượng có các thuộc tính tương ứng là i,j,k...
Rồi nhồi nó vào cái collection vừa tạo ra đấy.
(Collection : là mảng để chứa đối tượng bất kỳ Bác nên tìm hiểu cách sd nó vì nó rất hữu dụng. Chứ không cần thiết phải dùng redim đâu)

tien2005
06-06-2006, 10:56 AM
Xin chào mọi người!
Lâu nay tôi cũng chẳng lập thêm được hàm nào hay ho cả, các hàm thông thường có POST lên chắc cũng không hiệu quả. Để góp vui thêm cho Box, tôi thảo luận với anh em về 1 thuật toán mà trước đây tôi thu thập được.
'========
Đề bài: Cho một tập hợp N(gồm n phần tử),. Hãy tìm trong tập hợp N phần tử thỏa mãn tính chất A.
'========
Khi đọc đề bài này, chắc ai cũng nghĩ ngay đến thuật toán "VÉT CẠN", đó là dùng vòng For chạy từ đầu đến cuối tập hợp để tìm ra phần tử có thuộc tính A. Tuy nhiên, nếu số lượng phần tử rất rất nhiều thì vòng lặp này sẽ chạy rất lâu (Đặc biệt khi dùng ngôn ngữ VB) vì số phép tính là n!.
'========
Thuật toán "CHIA ĐÔI" (tôi quên tên chính xác rồi, cứ tạm gọi như vậy):Chia đôi tập hợp ban đầu thành 2 tập hợp con N1 và N2. Dùng 1 vòng lặp For chạy trong tập hợp N1. Nếu gặp phần tử thỏa mãn thuộc tính A thì kết thúc lặp, nếu chạy hết mà không gặp phần tử đó thì xét đến tập con N2. Trong tập con N2 lại chia thành 2 tập con N21 và N22 và làm tương tự.
Cứ như vậy thì số lượng phép toán sẽ giảm đi rất nhiều, tăng tốc độ chạy chương trình.
Nếu bạn nào dùng Delphi hoặc C++ chắc cũng chẳng cần để ý đến thuật toán này, nhưng tôi làm VB, nếu cứ "VÉT CẠN" nhiều khi chạy toàn "TREO MÁY" :D
Các bạn xem có gì đóng góp ý kiến
Theo tôi bác có thể dùng hàm Find để giải quyết công việc này sẽ tốt hơn vòng For (kinh nghiệm này có được khi tôi viết chương trình tính dự toán)

tien2005
06-06-2006, 10:59 AM
Cám ơn bác Cuong gt41, tôi sẽ tìm hiểu thêm đối tượng Collection

maikhoanam
07-06-2006, 08:05 PM
'Tim cac cap noi luc tuong ung!
'Mai Khoa Nam -STU
'1-xuat bieu do bao vat lieu sang Excel(ko xuat cac TH to hop) de lay cac gia tri min,mac
'2--xuat cac truong hop to hop sang Excel (ko xuat bieu do bao vat lieu)
'3-Tu cac gia tri min mac di tim cac gia tri noi luc tuong ung co trong cac TH to hop thong qua ham tim kiem nay
'chuc cac ban thanh cong
Public Function timMtuongung(khoangP, khoangM3 As Range, Gt As Double)
Dim i As Integer
i = 0
Do While i < khoangP.Cells.Count
i = i + 1
If khoangP(i) = Gt Then
timMtuongung = khoangM3(i)
Exit Do
End If
If khoangP(i + 1) = Gt Then
timMtuongung = khoangM3(i + 1)
Exit Do
End If
Loop
End Function
Public Function timNtuongung(khoangM3, khoangP As Range, Gt As Double)
Dim i As Integer
i = 0
Do While i < khoangM3.Cells.Count
i = i + 1
If khoangM3(i) = Gt Then
timNtuongung = khoangP(i)
Exit Do
End If
If khoangM3(i + 1) = Gt Then
timNtuongung = khoangP(i + 1)
Exit Do
End If
Loop
End Function

truongkct
04-07-2006, 09:31 AM
Các bác cho em hỏi sử dụng hàm Redim như thế nào?
Có thể khai báo giatri=redim(i,j,k)
sau đó tìm giá trị k nào đó thì ta cũng tìm được giá trị i, j tương ứng
vd: i là phần tử, j là vị trí mặt cắt, k là giá trị moment
Cám ơn các Bác
Hàm Redim dùng để cấp phát vùng nhớ cho các mảng động, ví dụn như sau:
Dim a() as Double 'Khai báo mảng động a() kiểu số thực

Redim a(1 to 100) 'cap phat vung nho 100 phan tu cho mang a()
Sao tu nhien khong viet tieng Viet duoc vay ta:confused: ?

PMXD
05-07-2006, 02:05 PM
Nếu dùng Redim Preserve Mang(0 to k) thì sẽ giữ lại được các giá trị mà mình đã Redim trước đó, nếu không nó sẽ xóa hết các giá trị cũ.

longnh
11-06-2007, 10:21 AM
Các bác cho em hỏi sử dụng hàm Redim như thế nào?
Có thể khai báo giatri=redim(i,j,k)
sau đó tìm giá trị k nào đó thì ta cũng tìm được giá trị i, j tương ứng
vd: i là phần tử, j là vị trí mặt cắt, k là giá trị moment
Cám ơn các Bác
nếu trong .NET thì OK chu VB6 ==> trước thì cẩn thận ko sai đây'
Chỉ chiều cao nhât cua arr được Redim mà thôi.

a2tiep
11-06-2007, 06:04 PM
Tôi cũng xin nói thêm về collection. Có thể coi là một danh sách liên kết các "objects".
Khi ta lập trình với Pascal thì ta trật vật tạo danh sách liên kết. Nhưng collection bao gồm toàn bộ dữ liệu và toàn bộ các object tồn tại. Cơ chế tìm kiếm và cơ chế thêm bớt rất tiện lợi.
Thời kỳ tôi làm đồ án tốt nghiệp, Nhờ một anh thế hệ trước chỉ bảo tôi. Mà tôi đã đơn giản được hàng đống code. Mà nhìn vào nó đã tôi phát ớn. Code được trình bày đơn giản rễ hiểu. Các anh em chỉ cần bật help của Vb hay VBA (Excel, AutoCAD, Word) với từ khóa collection.

Chúc anh em thành công.

a2tiep
11-06-2007, 06:14 PM
Tôi đang gặp vấn đề rất khó khăn. Mong cả nhà chỉ bảo. Tôi đang thực hiện một tool để kiểm xoát dữ liệu trong CAD bằng VBA.
Được mô tả như sau:
- Chương trình AutoCAD mở nhiều bản vẽ. Tôi có một đối tượng ở bản vẽ 1 được chuyển sang bản vẽ 2. Làm thế nào quản lý được ObjectID của nó. Bởi vì khi chuyển đối tượng đó từ 1 sang 2 thì ObjectID của nó bị thay đổi. Làm thế nào nhận ra đối tượng đó.
- Có cơ chế nào trong lập trình VBA chuyển đối tượng hay copy đối tượng từ bản vẽ 1 sang bản vẽ 2 mà vẫn kiểm xoát được ObjectID của nó không.

help me....

longnh
13-06-2007, 02:41 AM
Tôi đang gặp vấn đề rất khó khăn. Mong cả nhà chỉ bảo. Tôi đang thực hiện một tool để kiểm xoát dữ liệu trong CAD bằng VBA.
Được mô tả như sau:
- Chương trình AutoCAD mở nhiều bản vẽ. Tôi có một đối tượng ở bản vẽ 1 được chuyển sang bản vẽ 2. Làm thế nào quản lý được ObjectID của nó. Bởi vì khi chuyển đối tượng đó từ 1 sang 2 thì ObjectID của nó bị thay đổi. Làm thế nào nhận ra đối tượng đó.
- Có cơ chế nào trong lập trình VBA chuyển đối tượng hay copy đối tượng từ bản vẽ 1 sang bản vẽ 2 mà vẫn kiểm xoát được ObjectID của nó không.

help me....

theo cách thông thương nhất là phải gán một thông số cho đối tượng. khong thể dùng ObjectID được. Bạn hãy xem phần dictionary(cái này dịch qua tiếng Việt khó) của đối tượng. CAD cho phép add đủ thứ vào đây từ dạng String, Long, thậm chí BIT. Hay nữa là nó cho phép mỗi ứng dụng co' một khoảng riêng nên không sợ tranh chấp data với APP khác.