Viết hàm tự tạo theo kiểu Excel 365 (1 người xem)

Liên hệ QC

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

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

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
đang xài nó đấy ... hình như là cho Vĩnh viễn ... còn xài ké kiểu gì đây Mạnh chua có hiểu lắm
Không vĩnh viễn, 1 lần trả tiền xài được 1 năm, sau đó phải trả tiếp
Một Account cho phép cài đặt 5 máy, nếu không xài hết thì chia sẻ (đồng nghĩa việc chia sẻ account + pass của account)
 
Upvote 0
Không vĩnh viễn, 1 lần trả tiền xài được 1 năm, sau đó phải trả tiếp
Một Account cho phép cài đặt 5 máy, nếu không xài hết thì chia sẻ (đồng nghĩa việc chia sẻ account + pass của account)
SAO em ko thấy nó keo 1 năm Anh nhỉ
Họ cho Em keo là vĩnh viễn em cũng không Biết .... Em còn 1 cái khác nữa trên 2 năm nay mà vẫn xài tốt ... cái đó của edu tên miền trung quốc nên làm biếng xài ===> chính xác là hơi sợ tàu thôi -0-0-0-

Hình ảnh như sau ko thấy nói gì 1 năm hết
1605005262027.png
1605005286851.png
 
Upvote 0
Không vĩnh viễn, 1 lần trả tiền xài được 1 năm, sau đó phải trả tiếp
Một Account cho phép cài đặt 5 máy, nếu không xài hết thì chia sẻ (đồng nghĩa việc chia sẻ account + pass của account)
Đấy là hàng dành cho khách hàng cá nhân anh ơi.
Có nhiều gói: cho khách hàng doanh nghiệp, trường học... nữa.
 
Upvote 0
chính thức bỏ Office 2016 rồi dọn nhà qua Office 365 ... thấy giao diện rất đẹp + hiện đại -0-0-0-
mà tìm hoài không thấy dòng nào nó ghi cho xài 1 năm cả ??!!!

1605063558948.png
 
Upvote 0
Upvote 0
chính thức bỏ Office 2016 rồi dọn nhà qua Office 365 ... thấy giao diện rất đẹp + hiện đại -0-0-0-
mà tìm hoài không thấy dòng nào nó ghi cho xài 1 năm cả ??!!!

View attachment 249084

Vụ này bạn phải đăng nhập vào tài khoản của bạn trên Web của Microsoft, rồi check "Services & Subscriptions" mới thấy chứ trên ứng dụng không thấy đâu.
Bên Mac OS cũng vậy, tôi lúc trước có mua mấy app trên AppStore cũng bị tự động trừ tiền bản quyền vì không chịu kiểm tra kỹ các ứng dụng mình đã mua (Subscription) khi hết hạn.
 
Upvote 0
Vụ này bạn phải đăng nhập vào tài khoản của bạn trên Web của Microsoft, rồi check "Services & Subscriptions" mới thấy chứ trên ứng dụng không thấy đâu.
Bên Mac OS cũng vậy, tôi lúc trước có mua mấy app trên AppStore cũng bị tự động trừ tiền bản quyền vì không chịu kiểm tra kỹ các ứng dụng mình đã mua (Subscription) khi hết hạn.
Mạnh xem hết rồi không có thấy ... Mạnh còn 1 cái khác nữa tên Miền của trung Quốc tạo 2 Năm trước giờ vẫn vào OK đấy ( Có nêu mấy bài trước )

1605069608025.png
 
Upvote 0
................
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
....................
 
Lần chỉnh sửa cuối:
Upvote 0
...........................
 
Lần chỉnh sửa cuối:
Upvote 0
.....................
 
Lần chỉnh sửa cuối:
Upvote 0
........................
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Em mới thử rút cáp mạng ra thấy xài ok đó Anh
Có mạng thì Anh xài cả 2 như hình nè ...
Đang mở excel online rồi rút cáp, hay rút cáp trước khi mở Excel bằng web browser? Ngoài ra chạy offline nó cũng lưu vào thư mục one drive trên máy, sau đó khi online sẽ đồng bộ với cloud.
Anh thấy giao diện đẹp lung linh chưa ????????????
Chẳng qua là khoe hàng chứ giao diện 365 theme black nó nung ninh như nhau, tuỳ gói sẽ có thêm tab này tab kia thôi.

1605177657797.png
 
Upvote 0
................
 
Lần chỉnh sửa cuối:
Upvote 0
mới gần đây xảy ra một vụ kiện cáo xoá bài
Thật đáng buồn!

Tới giờ này các anh vẫn chưa nhìn nhận ra vấn đề, hoặc theo một hướng nào đó…

1605280721401.png

1605280724943.png

Em khẳng định là không có vụ khiếu nại, tố cáo tội phạm, kiện cáo gì cả.

--- Giải thích ---

1/ Trang web giaiphapexcel.com thuộc sở hữu của anh Bình, thông tin chi tiết lấy từ trang https://who.is/ như hình dưới. Sau đây gọi là chủ quản diễn đàn.
1605280764695.png

2/ Chủ quản diễn đàn trao quyền cho các admin/ mod theo thỏa thuận (nào đó) thực hiện các công việc quản trị diễn đàn. Gọi là ban quản trị (BQT).

3/ Sự việc thành viên X xóa các bài viết của mình có tác động gì tới diễn đàn?

- Làm mất tài sản của diễn đàn;
1605280790601.png

- Tác động tới các thành viên đã giúp đỡ trong chủ đề đó, tới các thành viên khác khi đọc chủ đề đó. Tác động tiêu cực hay tốt đẹp như nào thì các thành viên tự đánh giá, nhưng chắc chắn là không tôn trọng những người đã giúp X.

- Tạo tiền đề (xấu, tốt) cho những sự việc tương tự, hay kéo theo sau này nếu BQT không có biện pháp xử lý/ ngăn chặn phù hợp và kịp thời.

4/ Thành viên Y “tố cáo, kiện cáo” thành viên X tới BQT được gì?

- Qua sự việc vừa rồi đã phát hiện và đúc rút được một số thứ.

Còn BQT tới giờ chưa nhìn nhận ra vấn đề, hoặc theo một hướng khác.

- Không có vụ tố cáo, kiện cáo gì ở đây cả. Bởi:

Nguyên cáo là ai? Nếu thua/ thắng kiện thì được gì?

Bị cáo là ai? Đã làm tổn hại gì tới nguyên cáo?

Tòa án ở đây là ai? Là BQT chăng? Các anh/ chị BQT đang thay mặt chủ quản diễn đàn quản lý cơ mà .

Thành viên X làm ảnh hưởng tới tài sản của các anh thì các anh tự xử đi chứ. Sao lại gọi là kiện cáo gì.

Còn thành viên Y kia rảnh quá la làng lên cho các anh biết có sự việc như vậy đấy (bởi X âm thầm làm, chưa có ai biết mà). Như kiểu có kẻ thải bẩn ra cổng, có ông hàng xóm đi qua nhìn thấy và la làng lên “Có kẻ làm bẩn ra cổng nhà anh/ chị này, anh/ chị ra mà dọn đi”.

Thành viên Y thông báo, cung cấp thông tin cho BQT, phản ánh một sự việc tới BQT, chứ không có vụ kiện cáo nào cả.

1605280890556.png

5/ (Nhân tiện cho các thành viên tham khảo)

Trường hợp nếu thành viên X làm tổn hại gì đó tới thành viên Y thì:

- Thành viên Y kiến nghị tới BQT xử lý;

- Nếu BQT xử lý không thỏa đáng, hoặc không, hoặc chưa kịp thời xử lý thì thành viên Y tố cáo/ đệ đơn kiện tới cơ quan có thẩm quyền can thiệp (Cơ quan Công an, Tòa án…) với nội dung: Thành viên X làm tổn hại xyz, BQT diễn đàn xử lý sự việc không thỏa đáng, hoặc không/ chưa xử lý. Bây giờ có Luật an ninh mạng rõ ràng rồi.

----
Mong là sẽ sớm có phương án xử lý hợp lý (Tương tự như cách ngăn chặn sự việc có chiều hướng không tốt có thể xảy ra).
 
Upvote 0
Viết hàm SWITCH2003() để dùng cho Excel version thấp, như E2003
PHP:
 Option Explicit
Function SWITCH2003(Num As Double) As String
SWITCH2003 = Switch(Num <= 0, "A", Num <= 5, "B", Num <= 10, "C", Num <= 15, "D", Num > 15, "E")
End Function
:D
Mã:
Function SWITCH2003(Num As Double) As Long
SWITCH2003 = Switch(Num <= 0, 0, Num <= 5, 5, Num <= 10, 10, Num <= 15, 15, Num > 15, 20)
End Function

PHP:
Function MINIF(CSDL As Range, Ma As String) As Double
 Dim WF As Object, J As Long
 
 Set WF = Application.WorksheetFunction
 MINIF = WF.Max(CSDL(2).Resize(CSDL.Rows.Count))
 For J = 1 To CSDL.Rows.Count
    If CSDL.Cells(J, "A").Value = Ma Then
        If CSDL.Cells(J, "B").Value < MINIF Then MINIF = CSDL.Cells(J, "B").Value
    End If
 Next J
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Hồi hộp vụ gì em? Hàm trên nó chạy tốt cho Office 365, nhưng trên Office bình thường thì anh chỉ biết cho nó ra hàm mảng bình thường thôi.
Dạ hồi hộp vì chờ đợi (hóng) các sản phẩm của anh Hai Lúa ạ.
Hàm nó ra mảng hay ra gì cũng được anh miễn là một công thức một câu lệnh mà nó đỏ xuống không cần phải co kéo thêm gì cả ấy anh à, cũng thấy hay hay anh ạ.
OT cũng thấy mỗi lần các chuyên gia trao đổi và bàn luận đến chủ đề kiểu này này là lại thấy có lửa bốc lên mà hãi quá. hihi
 
Upvote 0
Upvote 0
Office 365 đã hỗ trợ các hàm mảng rồi nên chỉ cần xây dựng hàm trả về mảng là excel nó sẽ tự làm hết. Bác thử trên các phiên bản khác thì nó sẽ không làm được như vậy.
Đúng là thế, tuy nhiên đang tìm cách để cho nó giống giống với Office 365.
 
Upvote 0
Đúng là thế, tuy nhiên đang tìm cách để cho nó giống giống với Office 365.
Bác thử code này xem, tuy nhiên chỉ mới là bước đầu thôi, fill được cái mảng lên sheet.
Mã:
Option Explicit

Public rCaller As Range
Public aResult
Public nCount As Byte

Function HDFillResult(iArray, Optional iDynamic As Boolean)
    On Error GoTo Reset
    Select Case nCount
        Case Is = 0:
            nCount = 1
            If iDynamic Then Application.Volatile
            If TypeName(iArray) = "Range" Then
                Set aResult = iArray
            Else
                If IsArray(aResult) Then
                  aResult = iArray
                Else
                  aResult = iArray
                End If
            End If
            Set rCaller = Application.Caller
            HDFillResult = Evaluate(rCaller.Formula)
        Case Is = 1:
            nCount = 2
            SetResult2 rCaller, aResult
            HDFillResult = aResult
        
        Case Else:
            HDFillResult = aResult
            GoTo Reset
    End Select
    Exit Function
Reset:
    HDResetAll
End Function

Function HDResetAll() As Boolean
    HDResetAll = rCaller Is Nothing
    Set rCaller = Nothing
    If TypeName(aResult) = "Range" Then
      Set aResult = Nothing
    Else
      If IsArray(aResult) Then Erase aResult Else aResult = Empty
    End If
    nCount = Empty
End Function

Private Sub SetResult2(iCell As Range, iArray)
    Dim r0&, c0&
    GetSizeArray iArray, r0, c0
    If r0 + c0 = 2 Then Exit Sub
    Application.ScreenUpdating = False
    On Error GoTo ResetScreenUpdate
    If TypeName(iArray) = "Range" Then
        If c0 > 1 Then iCell.Resize(1, c0 - 1).Offset(0, 1) = iArray.Resize(1, c0 - 1).Offset(0, 1).Value
        If r0 > 1 Then iCell.Resize(r0 - 1, c0).Offset(1, 0) = iArray.Resize(r0 - 1, c0).Offset(1, 0).Value
    Else
        If r0 = 1 Then
            If c0 > 2 Then
                iCell.Resize(1, c0 - 1).Offset(0, 1) = iArray
                iCell.Resize(1, c0 - 2).Offset(0, 1) = iCell.Resize(1, c0 - 2).Offset(0, 2).Value
            End If
            iCell.Offset(0, c0 - 1) = Application.Index(iArray, 1, c0)
        Else
            iCell.Resize(r0 - 1, c0).Offset(1, 0) = iArray
            If r0 > 2 Then iCell.Resize(r0 - 2, 1).Offset(1, 0) = iCell.Resize(r0 - 2, 1).Offset(2, 0).Value
            If c0 > 1 Then iCell.Resize(r0 - 1, c0 - 1).Offset(0, 1) = iCell.Resize(r0 - 1, c0 - 1).Offset(1, 1).Value
            iCell.Offset(r0 - 1, 0).Resize(1, c0) = Application.Index(iArray, r0, 0)
        End If
    End If
    Exit Sub
ResetScreenUpdate:
    Application.ScreenUpdating = True
End Sub

Private Sub GetSizeArray(iArray, iRows As Long, iColumns As Long)
    If TypeName(iArray) = "Range" Then
        iRows = iArray.Rows.Count
        iColumns = iArray.Columns.Count
    Else
        iColumns = -1
        On Error Resume Next
        iRows = UBound(iArray, 1) - LBound(iArray, 1)
        iColumns = UBound(iArray, 2) - LBound(iArray, 2)
        If iColumns = -1 Then iColumns = iRows: iRows = 0
        iRows = iRows + 1: iColumns = iColumns + 1
    End If
End Sub
 
Upvote 0
Bác thử code này xem, tuy nhiên chỉ mới là bước đầu thôi, fill được cái mảng lên sheet.
Mã:
Option Explicit

Public rCaller As Range
Public aResult
Public nCount As Byte

Function HDFillResult(iArray, Optional iDynamic As Boolean)
    On Error GoTo Reset
    Select Case nCount
        Case Is = 0:
            nCount = 1
            If iDynamic Then Application.Volatile
            If TypeName(iArray) = "Range" Then
                Set aResult = iArray
            Else
                If IsArray(aResult) Then
                  aResult = iArray
                Else
                  aResult = iArray
                End If
            End If
            Set rCaller = Application.Caller
            HDFillResult = Evaluate(rCaller.Formula)
        Case Is = 1:
            nCount = 2
            SetResult2 rCaller, aResult
            HDFillResult = aResult
       
        Case Else:
            HDFillResult = aResult
            GoTo Reset
    End Select
    Exit Function
Reset:
    HDResetAll
End Function

Function HDResetAll() As Boolean
    HDResetAll = rCaller Is Nothing
    Set rCaller = Nothing
    If TypeName(aResult) = "Range" Then
      Set aResult = Nothing
    Else
      If IsArray(aResult) Then Erase aResult Else aResult = Empty
    End If
    nCount = Empty
End Function

Private Sub SetResult2(iCell As Range, iArray)
    Dim r0&, c0&
    GetSizeArray iArray, r0, c0
    If r0 + c0 = 2 Then Exit Sub
    Application.ScreenUpdating = False
    On Error GoTo ResetScreenUpdate
    If TypeName(iArray) = "Range" Then
        If c0 > 1 Then iCell.Resize(1, c0 - 1).Offset(0, 1) = iArray.Resize(1, c0 - 1).Offset(0, 1).Value
        If r0 > 1 Then iCell.Resize(r0 - 1, c0).Offset(1, 0) = iArray.Resize(r0 - 1, c0).Offset(1, 0).Value
    Else
        If r0 = 1 Then
            If c0 > 2 Then
                iCell.Resize(1, c0 - 1).Offset(0, 1) = iArray
                iCell.Resize(1, c0 - 2).Offset(0, 1) = iCell.Resize(1, c0 - 2).Offset(0, 2).Value
            End If
            iCell.Offset(0, c0 - 1) = Application.Index(iArray, 1, c0)
        Else
            iCell.Resize(r0 - 1, c0).Offset(1, 0) = iArray
            If r0 > 2 Then iCell.Resize(r0 - 2, 1).Offset(1, 0) = iCell.Resize(r0 - 2, 1).Offset(2, 0).Value
            If c0 > 1 Then iCell.Resize(r0 - 1, c0 - 1).Offset(0, 1) = iCell.Resize(r0 - 1, c0 - 1).Offset(1, 1).Value
            iCell.Offset(r0 - 1, 0).Resize(1, c0) = Application.Index(iArray, r0, 0)
        End If
    End If
    Exit Sub
ResetScreenUpdate:
    Application.ScreenUpdating = True
End Sub

Private Sub GetSizeArray(iArray, iRows As Long, iColumns As Long)
    If TypeName(iArray) = "Range" Then
        iRows = iArray.Rows.Count
        iColumns = iArray.Columns.Count
    Else
        iColumns = -1
        On Error Resume Next
        iRows = UBound(iArray, 1) - LBound(iArray, 1)
        iColumns = UBound(iArray, 2) - LBound(iArray, 2)
        If iColumns = -1 Then iColumns = iRows: iRows = 0
        iRows = iRows + 1: iColumns = iColumns + 1
    End If
End Sub
Nhìn code mà thấy hãi quá,phiền bạn có thể đính kèm ví dụ để tôi tham khảo thêm với được không?
 
Upvote 0
Cảm ơn bạn nhiều,ủa công thức vẫn phải bấm tổ hợp phím "ctrl shift enter" à bạn ? hihi :-=
Vì cái này là sẵn có của excel nên phải "Ctr Shift Enter" nó mới trả về mảng, còn nếu mình tự tạo hàm mảng riêng thì không cần.
Bạn thử gõ công thức này tại ô A20 xem
Mã:
=HDFillResult(A1:K11)
Sau đó thử với công thức =A1:K11 sẽ thấy sự khác biệt.
 
Upvote 0
Vì cái này là sẵn có của excel nên phải "Ctr Shift Enter" nó mới trả về mảng, còn nếu mình tự tạo hàm mảng riêng thì không cần.
Bạn thử gõ công thức này tại ô A20 xem
Mã:
=HDFillResult(A1:K11)
Sau đó thử với công thức =A1:K11 sẽ thấy sự khác biệt.
em test trên 365 cần ctrl+shift+365 mới ra không sẽ lỗi #SPILL!
Bài đã được tự động gộp:

Em cũng có tý hàm tự tạo gửi mọi người dùng thử:
Hướng dẫn
 
Lần chỉnh sửa cuối:
Upvote 0
Bác thử code này xem, tuy nhiên chỉ mới là bước đầu thôi, fill được cái mảng lên sheet.
Mã:
Option Explicit

Public rCaller As Range
Public aResult
Public nCount As Byte

Function HDFillResult(iArray, Optional iDynamic As Boolean)
    On Error GoTo Reset
    Select Case nCount
        Case Is = 0:
            nCount = 1
            If iDynamic Then Application.Volatile
            If TypeName(iArray) = "Range" Then
                Set aResult = iArray
            Else
                If IsArray(aResult) Then
                  aResult = iArray
                Else
                  aResult = iArray
                End If
            End If
            Set rCaller = Application.Caller
            HDFillResult = Evaluate(rCaller.Formula)
        Case Is = 1:
            nCount = 2
            SetResult2 rCaller, aResult
            HDFillResult = aResult
      
        Case Else:
            HDFillResult = aResult
            GoTo Reset
    End Select
    Exit Function
Reset:
    HDResetAll
End Function

Function HDResetAll() As Boolean
    HDResetAll = rCaller Is Nothing
    Set rCaller = Nothing
    If TypeName(aResult) = "Range" Then
      Set aResult = Nothing
    Else
      If IsArray(aResult) Then Erase aResult Else aResult = Empty
    End If
    nCount = Empty
End Function

Private Sub SetResult2(iCell As Range, iArray)
    Dim r0&, c0&
    GetSizeArray iArray, r0, c0
    If r0 + c0 = 2 Then Exit Sub
    Application.ScreenUpdating = False
    On Error GoTo ResetScreenUpdate
    If TypeName(iArray) = "Range" Then
        If c0 > 1 Then iCell.Resize(1, c0 - 1).Offset(0, 1) = iArray.Resize(1, c0 - 1).Offset(0, 1).Value
        If r0 > 1 Then iCell.Resize(r0 - 1, c0).Offset(1, 0) = iArray.Resize(r0 - 1, c0).Offset(1, 0).Value
    Else
        If r0 = 1 Then
            If c0 > 2 Then
                iCell.Resize(1, c0 - 1).Offset(0, 1) = iArray
                iCell.Resize(1, c0 - 2).Offset(0, 1) = iCell.Resize(1, c0 - 2).Offset(0, 2).Value
            End If
            iCell.Offset(0, c0 - 1) = Application.Index(iArray, 1, c0)
        Else
            iCell.Resize(r0 - 1, c0).Offset(1, 0) = iArray
            If r0 > 2 Then iCell.Resize(r0 - 2, 1).Offset(1, 0) = iCell.Resize(r0 - 2, 1).Offset(2, 0).Value
            If c0 > 1 Then iCell.Resize(r0 - 1, c0 - 1).Offset(0, 1) = iCell.Resize(r0 - 1, c0 - 1).Offset(1, 1).Value
            iCell.Offset(r0 - 1, 0).Resize(1, c0) = Application.Index(iArray, r0, 0)
        End If
    End If
    Exit Sub
ResetScreenUpdate:
    Application.ScreenUpdating = True
End Sub

Private Sub GetSizeArray(iArray, iRows As Long, iColumns As Long)
    If TypeName(iArray) = "Range" Then
        iRows = iArray.Rows.Count
        iColumns = iArray.Columns.Count
    Else
        iColumns = -1
        On Error Resume Next
        iRows = UBound(iArray, 1) - LBound(iArray, 1)
        iColumns = UBound(iArray, 2) - LBound(iArray, 2)
        If iColumns = -1 Then iColumns = iRows: iRows = 0
        iRows = iRows + 1: iColumns = iColumns + 1
    End If
End Sub
Cám ơn bạn, thật ra cũng đã khá lâu tôi cũng đã bị nó làm cho tôi thêm nhiều sợi tóc bạc.

 
Upvote 0
Trên GPE này có thành viên x gì đó lập nhiều thớt hỏi diết là File đang mở xong vô tình mở lại thì Bill thông báo ... vậy có cách gì tắt hay xử lý nó vvv
Mới vô tình mở trên Office 365 như thế xong ... thấy nó IM RE ko có thông báo gì hết => muốn mở lại chính file đó n lần ok hết
Ai đang xài office 365 thử xem có đúng không !!

Xin trân trọng thông báo với thành Viên x gì đó chuyển qua Office 365 mà xài đi khỏi đau đầu suy nghĩ cái vụ mở file rồi xong mở lại nữa vvv
trên Office 365 có rất nhiều thứ hay và hiện đại đấy ... cứ mò tiếp đi là thấy
 
Upvote 0
Trên GPE này có thành viên x gì đó lập nhiều thớt hỏi diết là File đang mở xong vô tình mở lại thì Bill thông báo ... vậy có cách gì tắt hay xử lý nó vvv
Mới vô tình mở trên Office 365 như thế xong ... thấy nó IM RE ko có thông báo gì hết => muốn mở lại chính file đó n lần ok hết
Ai đang xài office 365 thử xem có đúng không !!

Xin trân trọng thông báo với thành Viên x gì đó chuyển qua Office 365 mà xài đi khỏi đau đầu suy nghĩ cái vụ mở file rồi xong mở lại nữa vvv
trên Office 365 có rất nhiều thứ hay và hiện đại đấy ... cứ mò tiếp đi là thấy
Hình như Excel 2013 trở lên là ngon lành như vậy rồi anh.
Excel 2019 thì chắc chắn luôn.

Thành viên đó dùng Excel 2010, bởi sau khi tét trong phòng thí nghiệm các kiểu thì các phiên bản khác đều không ngon bằng. :)
 
Upvote 0
Hình như Excel 2013 trở lên là ngon lành như vậy rồi anh.
Excel 2019 thì chắc chắn luôn.

Thành viên đó dùng Excel 2010, bởi sau khi tét trong phòng thí nghiệm các kiểu thì các phiên bản khác đều không ngon bằng. :)
Sao hôm Mạnh còn xài Office 2016x64 nó vẫn còn vậy đấy . thử nhiều lần rồi file đang mở xong bấm mở lại nó báo thế

Bill thoáng kinh cho Mạnh tạo cả ngàn user đấy ... đoán thôi nhé chắc bill muốn phổ biến sâu và rộng cho ai cũng xài Office 365 hết hay sao ý

Untitled.png
Bài đã được tự động gộp:

Tự nhiên hôm trước còn là sinh viên nay Bill thăng lên chức giáo viên nhanh thế gói E3

1605792817749.png

Tiếng việt nè là giảng viên luôn mới Kinh
1605792921703.png
 
Lần chỉnh sửa cuối:
Upvote 0
Co giãn cũng tàm tạm, giờ làm cách nào để khi xóa công thức thì nó xóa nguyên cả mảng.
 
Upvote 0
Một cách lấy dữ liệu từ file đang đóng, ai sử dụng 365 có thể thử.
 
Upvote 0
Thấy người ta úp video diết cũng mới tập làm 1 cái Hàm gán dữ liệu kiểu Office 365 mà không phải lấy dữ liệu cùng File hay khác file trên cùng 1 máy

Mà lấy dữ liệu qua Internet cho nó vui vẻ chút ... tăng chút khí thế cho các bạn trẻ học code .... già như Mạnh còn mò ra mà ... các Bạn trẻ cố giắng thêm chút là ra đấy he

Cấu trúc hàm nó cũng đơn giản lắm

IP: 192.168.1.9
Port: 8181
SQL: select * from DataBaseNhap
Tiêu Đề: TRUE

Sử dụng chỉ việc gõ : A10 = SQLServer(IP,Port,SQL,true) Enter cái là xong
Nó Share nguyên 1 Folder hay 1 ổ dĩa đấy trong đó có bao nhiêu File thích lấy gì nó lấy hết ( Cái quan trọng là viết lại code chút thôi )

Xin mời ta lại xem phim
 
Upvote 0
Thấy người ta úp video diết cũng mới tập làm 1 cái Hàm gán dữ liệu kiểu Office 365 mà không phải lấy dữ liệu cùng File hay khác file trên cùng 1 máy

Mà lấy dữ liệu qua Internet cho nó vui vẻ chút ... tăng chút khí thế cho các bạn trẻ học code .... già như Mạnh còn mò ra mà ... các Bạn trẻ cố giắng thêm chút là ra đấy he

Cấu trúc hàm nó cũng đơn giản lắm

IP: 192.168.1.9
Port: 8181
SQL: select * from DataBaseNhap
Tiêu Đề: TRUE

Sử dụng chỉ việc gõ : A10 = SQLServer(IP,Port,SQL,true) Enter cái là xong
Nó Share nguyên 1 Folder hay 1 ổ dĩa đấy trong đó có bao nhiêu File thích lấy gì nó lấy hết ( Cái quan trọng là viết lại code chút thôi )

Xin mời ta lại xem phim
Giờ em mới phát hiện là nếu viết addin bằng VBA excel thì có thể lợi dụng worksheet trong addin để tính toán.
 
Upvote 0
úi dào sau 2 năm tui mới ngộ ra cách viết trên Delphi ... xong rồi mới thấy như ăn kẹo mút
ko cần sự kiện + linh tinh cua ... viết 1 cái Hàm tạm keo là ResizeArrayA thui
xong gán bất cứ cái Array nào đã tính toán xong vào đó là nó trả Array lên Range thôi
Link sau bài 1363

 
Upvote 0

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

Back
Top Bottom