Viết hàm tự tạo theo kiểu Excel 365

Liên hệ QC

Ngô Hải Đăng

Thành viên hoạt động
Tham gia
31/8/17
Bài viết
183
Được thích
247
Giới tính
Nam
Nghiên cứu trên diễn đàn thì phát hiện được cái Application.Caller và sau đây là ý tưởng của mình:
1. Code trên ThisWorkbook
Mã:
Option Explicit

Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
    If IsUDF Then
        SetResult
        rCaller.Formula = sFormula
    End If
End Sub

Private Sub SetResult()
    Dim r0&, c0&
    On Error Resume Next
    r0 = UBound(aResult, 1) - LBound(aResult, 1)
    c0 = UBound(aResult, 2) - LBound(aResult, 2)
    On Error GoTo 0
    If c0 = 0 Then
        rCaller.Resize(1, r0 + 1) = aResult
    Else
        rCaller.Resize(r0 + 1, c0 + 1) = aResult
    End If
End Sub

2. Code trên Module
Mã:
Option Explicit

Public IsUDF As Boolean
Public rCaller As Range
Public aResult As Variant
Public sFormula As String

Function MyUDF()
    If IsUDF Then
        MyUDF = aResult
        IsUDF = False
        Set rCaller = Nothing
        If IsArray(aResult) Then Erase aResult Else aResult = Empty
    Else
        IsUDF = True
        Set rCaller = Application.Caller
        sFormula = rCaller.Formula
        
        'Dim tmp As String: tmp = "1 GIA TRI"
        'Dim tmp: tmp = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
        Dim tmp(10, 15) As Long
        aResult = tmp
    End If
End Function

3. Gõ =MyUDF() trên Sheet để test.

Có thể thử với kết quả là 1 giá trị, mảng 1 chiều và mảng 2 chiều. Mong được học hỏi thêm kinh nghiệm từ mọi người.
 
Đã tạo một mảng mà còn xoá bớt đi là ý gì? Ngoài ý duy nhất là trình bày dữ liệu dỏm.
Tôi có hàm Frequency
10 ... 3
11 ... 5
12 ... 1
Nếu tôi có thể xoá dòng giữa, tôi còn lại:
10 ... 3
12 ... 1
Kết quả như vậy là đánh lừa người đọc.
Do đó, khi muốn trình bày kết quả kiểu khác, tôi bắt buộc phải làm cho đúng quy luật: xoá cả cụm và làm lại.
10 ... 3
12 ... 6
Mới là đúng
Excel 365 chỉ giản dị hoá công việc xoá cả cụm và làm lại cho bạn, phần nguyên tắc thì vẫn vậy. Muốn xoá dòng giữa, bạn phải vào cái mảng bên trái và delete dòng chứa 11 (nếu 2 mảng đi kề nhau), hoặc kéo cái cụm kể từ 12 lên và thâu ngắn bảng bin trong công thức (nếu hai mảng riêng biệt vùng).
 
Upvote 0
Đã tạo một mảng mà còn xoá bớt đi là ý gì? Ngoài ý duy nhất là trình bày dữ liệu dỏm.
Ý anh nói bài 100 của tôi? Thì đúng vậy. Trình bày dữ liệu dởm: Dữ liệu và mảng kết quả báo cáo nằm chung sheet, rồi chèn xoá dữ liệu (chứ không phải chèn xoá mảng kết quả), khiến cho mảng kết quả bị ảnh hưởng.
Theo thí dụ như của anh thì họ có bảng dữ liệu bên trái mảng kết quả của hàm frequency, họ chèn giữa 11 và 12 một dòng và điền thêm dữ liệu. Trước khi chèn và sau khi chèn thì Frequency vẫn giữ nguyên kết quả. Xoá 1 dòng dữ liệu cũng vậy. (Giả định là hàm Frequency nên không liên quan đến dữ liệu bên trái, thêm xoá sửa không thay đổi kết quả)

Rõ ràng rằng làm như vậy là không chuẩn về trình bày, nhưng bài 100 tôi viết mang tính mô tả đặc tính đang có (tường thuật chuyện mắt thấy tai nghe).
 
Lần chỉnh sửa cuối:
Upvote 0
...Theo thí dụ như của anh thì họ có bảng dữ liệu bên trái mảng kết quả của hàm frequency, họ chèn giữa 11 và 12 một dòng và điền thêm dữ liệu. Trước khi chèn và sau khi chèn thì Frequency vẫn giữ nguyên kết quả. Xoá 1 dòng dữ liệu cũng vậy. (Giả định là hàm Frequency nên không liên quan đến dữ liệu bên trái, thêm xoá sửa không thay đổi kết quả)

Rõ ràng rằng làm như vậy là không chuẩn về trình bày, nhưng bài 100 tôi viết mang tính mô tả đặc tính đang có (tường thuật chuyện mắt thấy tai nghe).
Ý tôi nói, công thức mảng như Frequency có cái ý nghĩa mà nó bắt buộc phải bảo tồn. Ý nghĩa ấy là "tôi là một mảng kết quả, gồm phần tử 1 ở ô đầu tiên, và 2, 3... ở các ô kế tiếp. Chúng tôi không thể đi rời". Ví dụ Excel cho phép bạn "phá vỡ" mảng (sửa xoá giữa mảng) thì sẽ xảy ra trường hợp 2 ở bài #101, tức là kết quả dỏm.
Vì vậy, dẫu có 365 thì công thức mảng vẫn là công thức mảng. Muốn bớt dữ liệu thì cũng phải theo luật giữ gìn mảng. 365 cho phép bớt công việc nhưng vẫn không thể "ăn gian" được. Bạn có thể sửa nhưng chỉ có thể sửa thằng đầu mảng (top left), hoặc chính cái thằng gây ra kích thước mảng (bin đầu vào).
 
Upvote 0
Ý tôi nói, công thức mảng như Frequency có cái ý nghĩa mà nó bắt buộc phải bảo tồn. Ý nghĩa ấy là "tôi là một mảng kết quả, gồm phần tử 1 ở ô đầu tiên, và 2, 3... ở các ô kế tiếp. Chúng tôi không thể đi rời". Ví dụ Excel cho phép bạn "phá vỡ" mảng (sửa xoá giữa mảng) thì sẽ xảy ra trường hợp 2 ở bài #101, tức là kết quả dỏm.
Vì vậy, dẫu có 365 thì công thức mảng vẫn là công thức mảng. Muốn bớt dữ liệu thì cũng phải theo luật giữ gìn mảng. 365 cho phép bớt công việc nhưng vẫn không thể "ăn gian" được. Bạn có thể sửa nhưng chỉ có thể sửa thằng đầu mảng (top left), hoặc chính cái thằng gây ra kích thước mảng (bin đầu vào).
Như vậy có gọi là phá vỡ không bác, trước giờ em chưa sài hàm này nên phải google xíu mới biết cách sài.
 
Upvote 0
Dùng hàm tự tạo để sửa lại mảng là bỏ mảng cũ và lập lại mảng mới, hoặc gầy lại dữ liệu trong mảng.
Phá vỡ mảng là làm mất đi sự liên tục của mảng hiện tại. Bằng định nghĩa, mảng là một dãy liên tục.
 
Upvote 0
Phải thực hiện trên Excel 365 mới thấy chèn và xoá dòng có ảnh hưởng đến kết quả mảng như thế nào. Clip sau cho thấy trường hợp không ảnh hưởng kết quả. Tuy nhiên việc này vẫn không nên vì:
- Data và report để chung sheet
- Nếu công thức có liên quan đến data đang xoá sửa thì kết quả bị ảnh hưởng (sum, count giảm xuống, rank thay đổi hàng loạt, hoặc dỏm như bài 101)
 
Upvote 0
Trong này cần nói rõ vụ "Không được xóa" và "Xóa không được" trong công thức trả về mảng của Excel 365 và công thức mảng nhập cho 1 vùng nhiều cells (Ctrl + Shift + Enter).

1603771361175.png

Hai cái này là khác nhau nhé, chứ không phải như trên kia đâu (mặc dù cuối cùng là kết quả mảng vẫn bảo tồn như nhau).

1/ Công thức trả về mảng kết quả của Excel 365 (và gồm cả Google Sheets): Khi xóa 1 phần kết quả (không xóa cell ghi công thức) thì vẫn xóa bình thường, ngay sau đó công thức lại ghi lại kết quả. Cứ xóa thì lại điền lại, tức là "xóa không được".

2/ Công thức mảng nhập cho 1 vùng nhiều cells (CSE): Không thể thực hiện được thao tác xóa 1 phần kết quả của mảng đó. Tức là "không được xóa".

1603771600044.png
 
Upvote 0
Upvote 0
Giờ quay lại nội dung chính của chủ topic nhé. Bạn đã làm được đến đâu rồi? Bạn đang theo cách làm nào? Mã nguồn share ra chứ các bạn khác cũng đã đưa ra mấy kiểu làm rồi. Nếu mong muốn hoàn thiện hay giống với tính năng của hàm nào thì tiếp tục.
 
Upvote 0
Giờ quay lại nội dung chính của chủ topic nhé. Bạn đã làm được đến đâu rồi? Bạn đang theo cách làm nào? Mã nguồn share ra chứ các bạn khác cũng đã đưa ra mấy kiểu làm rồi. Nếu mong muốn hoàn thiện hay giống với tính năng của hàm nào thì tiếp tục.
Em vẫn đang test thứ một số thứ. Hàm của em đơn giản chỉ là nhận vào 1 array vào rồi in ra sheet thôi. Nó sẽ kết hợp với hàm trả về mảng của những người khác tùy theo mục đích sử dụng. Chắc là sẽ sớm hoàn thành.
 
Upvote 0
Kỹ thuật lập trình không phải cứ API là làm được tất cả. Người ta phải tạo ra những thứ mà API chưa có thì mới là độc. Add-in A-Tools tạo ra hàm mảng cơ động từ cách đây hơn 10 năm, từ cái thời Excel 97 thì đương nhiên Bill chưa hề có ý tưởng về hàm mảng, mãi gần đây GoogleSheet và Excel 365 mới có đưa ra cách làm việc hàm mảng. Tuy nhiên các cách hiện nay cả trên Excel 365 và GoogleSheets đều chỉ mới chớm nở, làm giản đơn, thô chứ chưa phải linh hoạt. Còn các hàm mảng viết trên VBA hiện nay đâu đó cũng chưa đạt được yêu cầu sử dụng đâu. Cứ cho vài công thức mảng trên cùng một sheet, chèn, xóa dòng cột xem sẽ thấy ngay. Đến thời điểm này mình vẫn nói, kỹ thuật tạo hàm trả về mảng để đưa vào thực tế là rất rất khó chứ không phải dễ.
Dòng tô màu đỏ đỏ em thấy anh nói không đúng nha, Google Sheets đã có hàm mảng động từ thời mới ra mắt 2006 luôn chứ không phải như Microsoft 365 mới có năm 2020.
 
Upvote 0
Dòng tô màu đỏ đỏ em thấy anh nói không đúng nha, Google Sheets đã có hàm mảng động từ thời mới ra mắt 2006 luôn chứ không phải như Microsoft 365 mới có năm 2020.

Bác biết được chính xác năm 2006? Hay vậy? Có link nào của Google nói về việc này không? Hoặc bài viết về hàm ArrayFormula từ năm 2006?
 
Lần chỉnh sửa cuối:
Upvote 0
Dòng tô màu đỏ đỏ em thấy anh nói không đúng nha, Google Sheets đã có hàm mảng động từ thời mới ra mắt 2006 luôn chứ không phải như Microsoft 365 mới có năm 2020.
mấy ngày qua Mạnh đang viết cái lấy dữ liệu qua Internet ... đang mò cái A thì liên quan cái B xong mò cái B thì nó lại ra cái x ...

Còn Google thì Mạnh đoán thôi nhé ... đoán thì có thể = True Or False

1/ Hiện tại google Sheet đang dùng thuật toán kiểu khi ta Gõ [A1] = Sum(10,10) thì dữ liệu nó phản hồi về máy chủ của google tính toán xong thì trả kết lại cho [A1] = 20 ... ko biết có chính xác vậy không nữa ???!!!

2/ vậy liên quan tới cái mục số 1 trên thì ngày qua mạnh có lang thang đâu đó trên google tìm tài liệu như mô tả dòng đầu tiên thì vô tình phát hiện ra vào năm 2011 trên VB6 họ cũng đã viết được thuật toán tính toán như mô tả mục số 1 ===> có nghĩa từ phía Client tính toán gì đó thì nó phản hồi về máy chủ xong từ máy chủ trả lời kết quả cho Client

3/ để ứng dụng mục số 2 ta có thể viết 1 cái thư viện Tạm keo là xxxx.DLL xong ta để trên máy chủ xong các máy khác trên Internet khi cần truy xuất vào tính toán mọi cái .... kiểu gần giống như máy Chủ google sheet ấy nhỉ :p

vấn đề đáng nói ở đây là công nghệ này đã có từ xa xưa rồi mà nó có sẳn khi ta cài Windows và cái quan trọng là ta có biết gắp nó ra xài được hay không thôi ????

4/ Nếu mạnh viết trong DLL xong phán bạy là thế nọ thế kia ... thì thấy thẹn lắm :p đó là sự thật

5/ Code sau mạnh Copy của tây xong thử build lại xem thì thấy nó chạy rất tốt .... xin mời xem thử
- Mở file Server lên
- Mở file client lên xong gõ tính toán = là kết quả Server nó tính xong trả lại Client
- mặc định nó lấy IP LAN trên máy hiện tại ... nếu Qua Internet thì IP Public + Nat Port ...
- thử tắt cái Server đi xong tính toán xem = Tịt toàn tập

Hình ảnh như sau

Capture.PNG
 

File đính kèm

  • Server_Client.rar
    26.1 KB · Đọc: 11
Upvote 0
Google Sheets được Google LLC phát hành ngày 09 tháng 03 năm 2006, và hàm Query() có luôn và ngay khi phát hành. Hàm Query trả kết quả là mảng động.
 
Upvote 0
Cái cách viết code của bác này sao tớ thấy quen quen _)()(-
cái này em tìm được mà anh, tác giả là anh Nguyễn Tấn Tài có 1 bản
Bài đã được tự động gộp:

Em góp vui chút với ngôn ngữ C# hay vb.net tạo ArrayResizer có thể tìm thêm tại đây ạ:
 
Lần chỉnh sửa cuối:
Upvote 0
cái này em tìm được mà anh, tác giả là anh Nguyễn Tấn Tài có 1 bản
Bài đã được tự động gộp:

Em góp vui chút với ngôn ngữ C# hay vb.net tạo ArrayResizer có thể tìm thêm tại đây ạ:
Cái này Anh có xem lâu rồi ... nhiều khi rảnh cũng nhìn phương thức của nó chuyển code đó qua VBA Or Delphi mà chưa có làm được
Vì kỷ thuật code chưa tới khả năng đó mà :p
 
Upvote 0
Bác biết được chính xác năm 2006? Hay vậy? Có link nào của Google nói về việc này không? Hoặc bài viết về hàm ArrayFormula từ năm 2006?
Em dùng Google Sheets có thể nói là thuộc nhóm lâu nhất ở Việt Nam, nếu như trước 2014 thì Google hầu như không có cập nhật gì nhiều cho Google Sheets, chỉ tháng 11 mới có một đợt cập nhật được xem như chuyển mình thành " người lớn" như ngày nay. Về công thức mảng động ngày đầu đã có lúc đó các dòng trả về mảng thì dùng chữ Continue chứ không để trống như ngày nay. Còn về link nào nói về vấn đề này em sẽ tìm hiểu và gửi Anh xem.
 
Upvote 0
Web KT

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

Back
Top Bottom