Tập hợp HÀM TỰ TẠO để làm thư viện Hàm

Liên hệ QC

Ếch Xanh

Thành viên tích cực
Tham gia
12/8/09
Bài viết
865
Được thích
1,572
Topic này tôi mở ra mục đích là tập hợp những hàm tự tạo hay của diễn đàn, để về sau nếu ai có khả năng tổng hợp thành Addins toàn tập thì dễ dàng lấy nguồn tại đây.

Tôi cũng hy vọng, các thành viên nào có những hàm hay hoặc thấy những hàm hay trên diễn đàn Giải pháp Excel hoặc diễn đàn khác, xin vui lòng post lên đây, và vui lòng trích nguồn từ link nào để tiện theo dõi.

Bài viết này, với tôi trình độ còn yếu kém, cho nên cách đặt tên hàm cũng như cách sử dụng hàm cũng chưa chính xác, vậy xin các thành viên bổ sung, góp ý, phản biện để các hàm của chúng ta trở nên mạnh hơn, hiệu quả hơn, chất lượng hơn, nhanh hơn đặc biệt chính xác hơn.

THAM KHẢO THÊM: Mỗi ngày một hàm VBA tại đây:
http://www.giaiphapexcel.com/forum/showthread.php?31-Mỗi-tuần-một-hàm-VBA&

Dưới đây là mở đầu một vài hàm:

1) Hàm Thay đổi kích thước mảng 2 chiều (ptm0412)

PHP:
Function resizeArr(ByVal SourceArr, ByVal NewC As Long)
  Dim OldR As Long, OldC As Long, NewR As Long, iR As Long, iC As Long
  Dim ArrKQ, iKQ, jKQ, SArr
  SArr = SourceArr
  iKQ = 1: jKQ = 1
  OldR = UBound(SArr, 1)
  OldC = UBound(SArr, 2)
  NewR = Int(OldR * OldC / NewC)
  If (OldR * OldC) Mod NewC > 0 Then NewR = NewR + 1
  ReDim ArrKQ(1 To NewR, 1 To NewC)
  For iC = 1 To OldC
    For iR = 1 To OldR
      ArrKQ(iKQ, jKQ) = SArr(iR, iC)
      iKQ = iKQ + 1
      If iKQ > NewR Then iKQ = 1: jKQ = jKQ + 1
    Next
  Next
  resizeArr = ArrKQ
End Function

Nguồn: http://www.giaiphapexcel.com/forum/...về-mảng-trong-VBA-(Array)&p=309679#post309679

-------------------------------------------------------------------------------


2) Hàm SORT mảng 1 chiều: (ndu96081631)

PHP:
Function Sort1DArray(ByVal Arr, Optional ByVal isText As Boolean = False, Optional ByVal isDESC As Boolean = False)
  Dim sCommand As String
  sCommand = "('" & Join(Arr, vbBack) & "').split('" & vbBack & "').sort("
  If isText Then
    sCommand = sCommand & ")"
  Else
    sCommand = sCommand & "function(a,b){return (a-b)})"
  End If
  If isDESC Then sCommand = sCommand & ".reverse()"
    sCommand = sCommand & ".join('" & vbBack & "')"
  With CreateObject("MSScriptControl.ScriptControl")
    .Language = "JavaScript"
    Sort1DArray = Split(.Eval(sCommand), vbBack)
  End With
End Function


Nguồn: http://www.giaiphapexcel.com/forum/...về-mảng-trong-VBA-(Array)&p=320811#post320811

-------------------------------------------------------------------------------

3) Hàm tính diện tích tam giác (ndu96081631)

PHP:
Function TriArea(ByVal x1 As Double, ByVal x2 As Double, ByVal x3 As Double, _
                 ByVal y1 As Double, ByVal y2 As Double, ByVal y3 As Double) As Double
  Dim dA As Double, dB As Double, dC As Double, dP As Double
  dA = Sqr((x2 - x1) ^ 2 + (y2 - y1) ^ 2) '<--- Chieu dai canh A
  dB = Sqr((x3 - x2) ^ 2 + (y3 - y2) ^ 2) '<--- Chieu dai canh B
  dC = Sqr((x1 - x3) ^ 2 + (y1 - y3) ^ 2) '<--- Chieu dai canh C
  dP = (dA + dB + dC) / 2 '<--- nua chu vi
  TriArea = Sqr(dP * (dP - dA) * (dP - dB) * (dP - dC))
End Function

Nguồn: http://www.giaiphapexcel.com/forum/...khi-biết-toạ-độ-trên-exel&p=319887#post319887

CÒN TIẾP, SẼ BỔ SUNG SAU...
 
Lần chỉnh sửa cuối:
Topic này là Tập hợp các Hàm tự tạo để làm thư viện. Thiết nghĩ những bài post vào topic này nên là những thuật toán tối ưu hoặc ít nhất là hiện tại chưa có thuật toán nào hay hơn. Có như thế thì mới mong thực hiện được mục tiêu của topic này là tập hợp hàm tự tạo để lập một thư viện.
Nếu cái gì cũng post vào đây thì không khéo sau một thời gian ta lại phải tập hợp những Hàm tự tạo hay từ những cái đã "tập hợp" ở đây.

Vài dòng chia sẻ theo quan điểm cá nhân. Nếu có gì không phải xin các anh chị và các bạn bỏ qua.

Ý của huuthang_bd rất là hay, nhưng tôi lại nghĩ, mỗi người có hàm gì thì cứ post vào đây, mục đích là để phản biện, để phân tích, để đánh giá chất lượng; sau đó chúng ta tạo một topic khác tổng hợp lại những hàm có chất lượng cao. Vậy có được không ạ?
 
Upvote 0
như vậy thì mình gởi lại Hàm kiểm tra số nguyên tố chạy nhanh hơn một tí
Function Isprime_number(n As Long) As Boolean
Dim i As Long
Dim tam As Boolean
i = 2
tam = True
Do While (i <= Sqr(n))
If (n Mod i = 0) Then
Isprime_number = False
Exit Function
End If
i = i + 1
Loop
Isprime_number = tam
End Function
 
Upvote 0
Hàm nội suy 1 chiều cho cả ngang và dọc (Ptm0412):

PHP:
Option Base 1
Function Noisuy(XNum As Double, XRng As Range, YRng As Range) As Double
  If XNum = 0 Then Noisuy = 0: Exit Function
  Dim KnownX, KnownY, i, k
  k = 1
  ReDim KnownX(1 To XRng.Count)
  ReDim KnownY(1 To XRng.Count)
  For Each Cll In XRng
    KnownX(k) = Cll.Value
    k = k + 1
  Next
  k = 1
  For Each Cll In YRng
    KnownY(k) = Cll.Value
    k = k + 1
  Next
  For i = 1 To XRng.Count
    If KnownX(i) <= XNum And KnownX(i + 1) >= XNum Then
      Noisuy = KnownY(i) + ((XNum - KnownX(i)) * _
      (KnownY(i + 1) - KnownY(i))) / (KnownX(i + 1) - KnownX(i))
      Exit Function
    End If
  Next
End Function

Nguồn: http://www.giaiphapexcel.com/forum/...g-thức-tính-hệ-số-nội-suy&p=324510#post324510
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Hàm tính bảng chấm công (Sa_DQ):

PHP:
Option Explicit
Function THCong(Cong As Range, LCg As String) As Variant
  Dim Cls As Range: Const DC As String = "/"
  For Each Cls In Cong
    Select Case UCase(LCg)
      Case "X"
        If Weekday(Cells(7, Cls.Column).Value) > 1 Then
          If UCase(Left(Cls.Value, 1)) = "X" Then
            THCong = THCong + 1
          ElseIf Cls.Value = "1/2" Then
            THCong = THCong + 0.5
          End If
        End If
      Case "P", "KP", "O", "L"
13      If UCase(Cls.Value) = "P" And LCg = "P" Then THCong = THCong + 1
        If UCase(Cls.Value) = "KP" And LCg = "KP" Then THCong = THCong + 1
15      If UCase(Cls.Value) = "O" And LCg = "O" Then THCong = THCong + 1
        If UCase(Cls.Value) = "L" And LCg = "L" Then THCong = THCong + 1
      Case "TG"
        If Weekday(Cells(7, Cls.Column).Value) = 1 Then
          If UCase(Cls.Value) = "X" Then
            THCong = THCong + 1
          ElseIf Cls.Value = "1/2" Then
            THCong = THCong + 0.5
          End If
        End If
      Case "TC"
        On Error Resume Next
        If Len(Cls.Value) >= 2 And InStr(Cls.Value, DC) < 1 Then
          THCong = THCong + CDbl(Right(Cls.Value, 1))
        End If
    End Select
  Next Cls
End Function

Nguồn: http://www.giaiphapexcel.com/forum/...-các-loại-công-dị-thường.&p=324663#post324663
 
Upvote 0
Hàm này dài dòng, và không tổng quát ở dòng
If XNum = 0 Then Noisuy = 0: Exit Function
sẽ sai, vì có trường hợp cần nội suy x=0?
Tôi không định đưa hàm này vào danh sách hàm đưa vào thư viện vì viết cho trường hợp cụ thể là file của anhTrung Chinh. Nhưng đã có nhận xét nên tôi sẽ giải thích như sau:
- File của anh Trung Chinh cần nội suy ra hệ số cho 1 giá trị vốn đầu tư. Vốn đầu tư = 0 thì cần tính hệ số làm gì, nên tôi cho hệ số = 0, anh Trung Chinh không phản hồi gì nên tôi không sửa. Hoặc anh ấy tự sửa được. Nếu dùng cho tổng quát, chỉ cần xoá dòng đó đi là xong.
- Thông thường bảng số liệu để tra nằm dọc theo cột, nhưng anh Trung Chinh để nằm theo dòng, nên tôi viết cho cả 2 trường hợp. Nếu chỉ viết cho 1 trường hợp dữ liệu nằm ngang, code chỉ cần ngắn như bài này: http://www.giaiphapexcel.com/forum/...g-thức-tính-hệ-số-nội-suy&p=324479#post324479
- Code này dài, dài vì phải gán giá trị vào mảng, đoạn code chính chỉ có 1 dòng lệnh bên trong vòng lặp For - Next.
- Cuối cùng, tuy code dài nhưng vì dùng mảng nên chắc chắn 1 điều là nó sẽ chạy rất nhanh.

Nếu Learning muốn sưu tầm, thì nên ghi rõ là nội suy 1 chiều cho cả dữ liệu ngang và dọc.
 
Lần chỉnh sửa cuối:
Upvote 0
Hàm này dài dòng, và không tổng quát ở dòng

sẽ sai, vì có trường hợp cần nội suy x=0
?
Câu lệnh:
Mã:
If [COLOR=#0000bb]XNum [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]0 Then Noisuy [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]0[/COLOR][COLOR=#007700]: Exit Function [/COLOR]
này hoàn toàn đúng trong phạm vi yêu cầu của đề bài.
Nó đã thoả mãn điều kiện khi dự án <= 5 tỷ thì chi phí này sẽ là 0.64%
Thế 0.64% * 0 = ? ; cần gì xét nữa.
Mình nghĩ rằng code (cùng một người viết) càng dài thì càng tổng quát vì người viết đã xét nhiều trường hợp, và chương trình chạy càng nhanh.
 
Lần chỉnh sửa cuối:
Upvote 0
Cái dzà... mấy cái này có từ đời nào rồi ---> Code của bạn đúng là cho tốc độ rất chậm đấy
Ít ra cũng phải vầy:
PHP:
Function Isprime_number(n As Long) As Boolean
  Dim i As Long
  Isprime_number = True
  For i = 2 To Int(Sqr(n))
    If n Mod i = 0 Then Isprime_number = False: Exit Function
  Next
End Function

Em mới viết ra hàm kiểm tra số nguyên tố anh ndu xem thử nó có tối ưu hơn hay không nha, hi hi

PHP:
Function ISPRIME_NUMBER(n As Long, Optional i As Long = 2) As Boolean
      If (n < 2) Then
                           ISPRIME_NUMBER = False
                   Exit Function
      ElseIf ((n < 4) Or (i > Sqr(n))) Then
                           ISPRIME_NUMBER = True
                   Exit Function
      ElseIf (n Mod i = 0) Then
                          ISPRIME_NUMBER = False
                  Exit Function
      Else
                      ISPRIME_NUMBER = ISPRIME_NUMBER(n, i + 1)
   End If
End Function
ví dụ
ISPRIME_NUMBER(9) = FALSE
ISPRIME_NUMBER(5)=TRUE
 
Lần chỉnh sửa cuối:
Upvote 0
Câu lệnh:
Mã:
If [COLOR=#0000bb]XNum [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]0 Then Noisuy [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]0[/COLOR][COLOR=#007700]: Exit Function [/COLOR]
này hoàn toàn đúng trong phạm vi yêu cầu của đề bài.
Nó đã thoả mãn điều kiện khi dự án <= 5 tỷ thì chi phí này sẽ là 0.64%
Thế 0.64% * 0 = ? ; cần gì xét nữa.
Mình nghĩ rằng code (cùng một người viết) càng dài thì càng tổng quát vì người viết đã xét nhiều trường hợp, và chương trình chạy càng nhanh.

Oh, quan trọng ở đây đưa vào hàm tổng quart và tiêu đề là hàm nội suy, vậy là sai bạn ah,
Càng dài càng tổng quát - lại sai nữa,
Nếu đúng như a ptm0412 nói tức là chỉ đúng với trường hợp cụ thế bài toán đó thôi
 
Upvote 0
Em mới viết ra hàm kiểm tra số nguyên tố anh ndu xem thử nó có tối ưu hơn hay không nha, hi hi

Không tối ưu bạn ah,
Đây là hình thức đệ quy cũng ra soát theo đệ quy từng số từ 1 - sqr(n) luôn (khi số đó là nguyên tố chẳng hạn)
Hơn nữa, mà thực tế người ta nói rằng nên Dùng vòng lặp để Trốn đệ quy - cái này bạn là GV TH chắc hiểu rõ hơn,

Ngoài ra thuật toán rà tìm này hảy còn chưa tối ưu,
 
Upvote 0
Oh, quan trọng ở đây đưa vào hàm tổng quart và tiêu đề là hàm nội suy, vậy là sai bạn ah,
Càng dài càng tổng quát - lại sai nữa,
Nếu đúng như a ptm0412 nói tức là chỉ đúng với trường hợp cụ thế bài toán đó thôi
Ở trên tôi có nói: nếu cần tổng quát thì xóa bỏ dòng lệnh If XNum = 0 Then Noisuy = 0: Exit Function
Và tôi cũng có nói: Hàm này có thể tính cho 2 vùng dữ liệu cả ngang và dọc, ở vị trí bất kỳ, theo ý bạn cũng vẫn chưa gọi là tổng quát, vậy thế nào có thể gọi là tổng quát?
Tiêu đề "hàm nội suy" là sai, vậy "hàm nội suy" thật sự đúng nó như thế nào? Bạn có thể cho biết không?

Nhân tiện, xin nhờ bạn và các cao thủ góp ý và viết cho 1 hàm "nội suy" thật sự đúng và thật sự tổng quát.
Xin cám ơn.
 
Upvote 0
Oh, quan trọng ở đây đưa vào hàm tổng quart và tiêu đề là hàm nội suy, vậy là sai bạn ah,
Càng dài càng tổng quát - lại sai nữa,
Nếu đúng như a ptm0412 nói tức là chỉ đúng với trường hợp cụ thế bài toán đó thôi
Bạn hãy giải bài toán theo ý của bạn để mọi người học hỏi, còn không thì phải chấp nhận người có giải pháp hay nhất trong trường hợp này. Nếu bạn chỉ nói suông thì chẳng ma nào tin.
Muốn tổng quát và chính xác thì quan hệ giữa các đại lượng (ở đây là tổng mức đầu tư và một chi phí nào đó) phải là một hàm số (y = f(x)).
Còn ở đây quan hệ kiểu bảng tra (toán đồ) mà đòi tổng quát là không thể, đòi hỏi sự chính xác càng không luôn vì khi ta nội (ngoại) suy là chấp nhận mối quan hệ tuyến tính trong từng đoạn mà thực tế cái tổng thể thì không phải vậy (không phải hàm bậc nhất, còn hàm gì thì không biết).
 
Lần chỉnh sửa cuối:
Upvote 0
Hàm kiểm tra khối ô có chứa Merge Cells hay không (minhthien321):

PHP:
Function MergeCheck(Rng As Range) As Boolean
  On Error GoTo MerCls
  MergeCheck = Rng.MergeCells: Exit Function
MerCls:
  MergeCheck = True
End Function


Thủ tục dưới đây làm cho khối ô Merge hoặc UnMerge:

PHP:
Sub MergeAndUnMerge()
  With Selection
    If MergeCheck(Selection) = True Then
      .UnMerge: .HorizontalAlignment = xlGeneral
    Else
      .Merge: .HorizontalAlignment = xlCenter
    End If
  End With
End Sub

Nói thêm là, tại sao ta làm cái thủ tục này, bởi vì có những lúc ta ProtectSheet mà đã bảo vệ thì Excel lại không cho Merge Cells, vì vậy nếu muốn sử dụng thủ tục này, đầu thủ tục ta cho UnProtect trước, cuối thủ tục ta lại Protect nó lại.
 
Lần chỉnh sửa cuối:
Upvote 0
Hàm lấy tên cột từ chỉ số cột trong Excel
Mã:
Function CotABC(ColIndex As Long) As String ' ham lay ten tu chi so cot
    CotABC = Replace(Cells(1, ColIndex).Address(0, 0), 1, "")
End Function
 
Upvote 0
Hàm lấy tên cột từ chỉ số cột trong Excel
Mã:
Function CotABC(ColIndex As Long) As String ' ham lay ten tu chi so cot
    CotABC = Replace(Cells(1, ColIndex).Address(0, 0), 1, "")
End Function
Đúng ra hàm này nên có 1 cái Optional, để khi ta chẳng gõ đối số ColIndex thì nó sẽ ngầm hiểu mặc định đang nói đến cột hiện hành (vì chắc gì đã nhớ biết được ta đang ở cột nào)
 
Upvote 0
Đúng ra hàm này nên có 1 cái Optional, để khi ta chẳng gõ đối số ColIndex thì nó sẽ ngầm hiểu mặc định đang nói đến cột hiện hành (vì chắc gì đã nhớ biết được ta đang ở cột nào)

Nhớ có lần thầy NDU có hướng dẫn về vụ này như sau:
PHP:
Function ColLetter(ByVal Cel As Range) As String
  ColLetter = Replace(Cells(1, Cel.Column).Address(0, 0), 1, "")
End Function

Không biết có phải ý thầy là vậy?
 
Upvote 0
Đúng ra hàm này nên có 1 cái Optional, để khi ta chẳng gõ đối số ColIndex thì nó sẽ ngầm hiểu mặc định đang nói đến cột hiện hành (vì chắc gì đã nhớ biết được ta đang ở cột nào)
Bạn ndu nói gì mình không hiểu, mình nghỉ chỉ cần thêm điều kiện về chỉ số cột cho các phiên bản Excel thôi.
Ví dụ mình áp dụng:

Dim iCol As Long
iCol = 50 ' thực tế tìm được từ code
MsgBox CotABC(iCol) '---> AX
 
Upvote 0
Bạn ndu nói gì mình không hiểu, mình nghỉ chỉ cần thêm điều kiện về chỉ số cột cho các phiên bản Excel thôi.
Ví dụ mình áp dụng:

Dim iCol As Long
iCol = 50 ' thực tế tìm được từ code
MsgBox CotABC(iCol) '---> AX
Tức là thế này:
- Với hàm của anh, nếu em gõ vào bảng tính công thức =CotABC(100) thì nó sẽ cho kết quả = CV, đúng không?
- Giả định em muốn biết cột hiện hành là tên gì thì làm sao? Em đang đứng ở cột CV, làm sao em biết cột này có số thứ tự =100 để mà điền vào hàm đây?
- Vậy sẽ cải tiến lại hàm sao cho nếu em gõ =CotABC() không có đối số thì ngầm định là đang nói đến cột tại ActiveCell
---------------
Em nghĩ sửa thành vầy sẽ ổn hơn:
PHP:
Function CotABC(Optional ColIndex) As String
  If IsMissing(ColIndex) Then ColIndex = Application.ThisCell.Column
  CotABC = Replace(Cells(1, ColIndex).Address(0, 0), 1, "")
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Tức là thế này:
- Với hàm của anh, nếu em gõ vào bảng tính công thức =CotABC(100) thì nó sẽ cho kết quả = CV, đúng không?
- Giả định em muốn biết cột hiện hành là tên gì thì làm sao? Em đang đứng ở cột CV, làm sao em biết cột này có số thứ tự =100 để mà điền vào hàm đây?
- Vậy sẽ cải tiến lại hàm sao cho nếu em gõ =CotABC() không có đối số thì ngầm định là đang nói đến cột tại ActiveCell
---------------
Em nghĩ sửa thành vầy sẽ ổn hơn:
PHP:
Function CotABC(Optional ColIndex) As String
  If IsMissing(ColIndex) Then ColIndex = Application.ThisCell.Column
  CotABC = Replace(Cells(1, ColIndex).Address(0, 0), 1, "")
End Function

Bị lỗi ndu à, nhưng sửa câu:
If IsMissing(ColIndex) Then ColIndex = Application.ThisCell.Column
thành:
If IsMissing(ColIndex) Then ColIndex = ActiveCell.Column
thì hết lỗi!
 
Upvote 0
Web KT

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

Back
Top Bottom