Rút gọn hàm Getpivotdata thành một hàm tự tạo

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài

DanVanPhoto

Thành viên chính thức
Tham gia
29/11/22
Bài viết
51
Được thích
-4
Chào tất cả GPE. em vì tính chất công việc em thường xuyên làm việc với hàm Getpivotdata. sử dụng để lồng rất nhiều. khi viết rất dài dẫn đến sửa đổi cũng mất nhiều thời gian. nên em có ý tưởng là rút gọn hàm lại và em đã thử viết một hàm tự tạo nhưng em không hiểu sai xót ở đâu nhờ các GPE giải đáp và gỡ rối giúp ạ. em có file đính kèm bên trong em cũng có mô tả trước và sau khi hoàn thành.
 

File đính kèm

Chào tất cả GPE. em vì tính chất công việc em thường xuyên làm việc với hàm Getpivotdata. sử dụng để lồng rất nhiều. khi viết rất dài dẫn đến sửa đổi cũng mất nhiều thời gian. nên em có ý tưởng là rút gọn hàm lại và em đã thử viết một hàm tự tạo nhưng em không hiểu sai xót ở đâu nhờ các GPE giải đáp và gỡ rối giúp ạ. em có file đính kèm bên trong em cũng có mô tả trước và sau khi hoàn thành.
Làm theo ý hiểu của bản thân.
Mã:
Function GetPivot(ByVal Rng As Range)
Dim lr&, i&, j&, k&, col&, t&
Dim res(), KQ()
lr = Rng.Rows.Count
col = Rng.Columns.Count
ReDim res(1 To lr, 1 To 3)

For j = 3 To col Step 2
    For i = 2 To lr
        If Rng(i, j) <> "" And IsNumeric(Rng(i, j)) Then
            k = k + 1
            'ReDim Preserve Res(1 to k, 1 to 3)
            res(k, 1) = Rng(1, j - 1)
            res(k, 2) = Rng(i, 1)
            res(k, 3) = Rng(i, j)
        End If
    Next
Next
ReDim KQ(1 To k, 1 To 3)
For i = 1 To k
If res(i, 1) <> 0 Then
    t = t + 1
    KQ(t, 2) = res(t, 2)
    KQ(t, 1) = res(i, 1)
    KQ(t, 3) = res(i, 3)
End If
Next i

GetPivot = KQ
End Function
Cú pháp:
M14=GetPivot(Vùng dữ liệu)
Ví dụ M14=GetPivot(A3:I18) ----> Enter để được kết quả.
 
Bảng A
Mã liệu
Sản phẩm 1​
Sản phẩm 2​
Sản phẩm 3​
Sản phẩm…n​
SFSLg
A1Sản phẩm 1A1={DataTable(A3:I18)}
B4Sản phẩm 1D2
C7Sản phẩm 1I3
D2Sản phẩm 2B4
ESản phẩm 2F.5
F0.5Sản phẩm 2M6
GSản phẩm 3C7
HSản phẩm 3I8
I38Sản phẩm 3K.9
JSản phẩm 3O10
K0.9
L
M6
N
O10

PHP:
Function DataTable(Rng As Range)
 Dim Arr()
 Dim J As Long, W As Integer, Col As Integer
 Dim SF As String
 
 Arr() = Rng.Value
 ReDim aKQ(1 To Rng.Cells.Count, 1 To 3) As String
 For Col = 3 To UBound(Arr(), 2) Step 2
    SF = Arr(1, Col - 1)
    For J = 2 To UBound(Arr())
        If Arr(J, Col) > 0 Then
            W = W + 1:              aKQ(W, 1) = SF
            aKQ(W, 2) = Arr(J, 1):  aKQ(W, 3) = Str(Arr(J, Col))
        End If
    Next J
 Next Col
 DataTable = aKQ()
End Function
 
Cảm ơn anh đã xem file. do kích thước của mảng KQ không đủ chứa.
Redim 10 ngàn nhiều quá, mà nếu dữ liệu 3 ngàn dòng thì vẫn không đủ
Redim 1 to lr * col / 2 là vừa vặn,
ReDim aKQ(1 To Rng.Cells.Count, 1 To 3) As String
Ngược lại, code này redim không chỉ hơi dư mà là quá dư (gấp đôi mức cần thiết). Kết quả thì không chém bớt nên lúc nào cũng dư cả cây số.

Trong phạm vi hàm chiếm chỗ, cấm xâm phạm. Lão ct lỡ xảy chân bước 1 bước vào trong hàng rào kẽm gai xanh liền sinh ra lỗi #Spill!

1693234639637.png
 
Lần chỉnh sửa cuối:
Redim 10 ngàn nhiều quá, mà nếu dữ liệu 3 ngàn dòng thì vẫn không đủ
Redim 1 to lr * col / 2 là vừa vặn,

Ngược lại, code này redim chỉ hơi dư (gấp đôi mức cần thiết). Kết quả thì không chém bớt nên lúc nào cũng dư.

Trong phạm vi hàm chiếm chỗ, cấm xâm phạm. Lão ct lỡ xảy chân bước 1 bước vào trong hàng rào kẽm gai xanh liền sinh ra lỗi #Spill!

View attachment 294330
Trân trọng cảm ơn anh đã khai sáng.
 
dạ cảm ơn nhưng có lẽ em diễn đạt mông lung. ý em là kết quả như hàm getpivotdata ấy ạ.
=GETPIVOTDATA("Sum of INPUT",$A$1,"Day",20230703,"Hour",1,"ID","KKK")
cú pháp vẫn như hàm này nhưng được rút gọn đi thôi .
=hamtutao(ngày,giờ,line,ID).1693236969589.png
bảng pivot của em vẫn là pivot của excel em muốn hàm tự tạo của mình có chức năng tương tự như hàm getpivotata nhưng đơn giản hơn rút gọn đi
 
Lần chỉnh sửa cuối:
dạ cảm ơn nhưng có lẽ em diễn đạt mông lung. ý em là kết quả như hàm getpivotdata ấy ạ.
=GETPIVOTDATA("Sum of INPUT",$A$1,"Day",20230703,"Hour",1,"ID","KKK")
Bạn thử điền K2 = 2230703, L2 = 1, M2 = KKK
Rồi công thức là:
N2 =GETPIVOTDATA("Sum of INPUT",$A$1,"Day",K2,"Hour",M2,"ID",L2)
Lúc này công thức có thể kéo xuống rồi.
 
Redim 1 to lr * col / 2 là vừa vặn,

(1) Ngược lại, code này redim không chỉ hơi dư mà là quá dư (gấp đôi mức cần thiết). Kết quả thì không chém bớt nên lúc nào cũng dư cả cây số.
ReDim aKQ(1 To Rng.Cells.Count, 1 To 3) As String
(2) Trong phạm vi hàm chiếm chỗ, cấm xâm phạm. Lão ct lỡ xảy chân bước 1 bước vào trong hàng rào kẽm gai xanh liền sinh ra lỗi #Spill!

(1) Thì chia hết cho 2 là được & chuyện đó giành chủ bài đăng biết & phải lo chuyện tối ưu thôi;
Mã:
ReDim aKQ(1 To Rng.Cells.Count\2, 1 To 3) As String

(2) Với hàm mảng tự tạo thì khi chọn vùng để ấn định hàm thì tôi làm vùng đó có màu nền khác xung quanh nó là được;
Cũng giống như rào 1 mảnh vườn trên trang tính í mà!
 
Bạn thử điền K2 = 2230703, L2 = 1, M2 = KKK
Rồi công thức là:
N2 =GETPIVOTDATA("Sum of INPUT",$A$1,"Day",K2,"Hour",M2,"ID",L2)
Lúc này công thức có thể kéo xuống rồi.
vâng điều này thì em biết. nhưng khi em viết lồng với nhiều hàm và còn lặp lại nên rất dài và rối mắt. em muôn rút gọn lại cho dễ quản lý
 
Dùng hàm count của excel hoặc tạo vòng for đếm số dòng kết quả trước
Cảm ơn anh đã xem bài và chỉ dẫn.
Trong code đã có biên k để đếm số lần thỏa 9 chính là số dòng của mảng thu được. Tuy nhiên tôi lại bí chỗ biến kết quả ấy thành giá trị của UDF. (đã sử dụng khai báo tăng kích thước mảng res theo biến k nhưng không hiểu bản chất nên vẫn không được). Đành dùng 1 vòng lặp nữa để loại bỏ các dòng có giá trị bằng 0, và đưa mảng vừa thu được này thành giá trị của UDF.
 
vâng điều này thì em biết. nhưng khi em viết lồng với nhiều hàm và còn lặp lại nên rất dài và rối mắt. em muôn rút gọn lại cho dễ quản lý
Bạn thử xem file của bạn có cái pivot table nào không? Có công thức mẫu nào cần chuyển sang hàm VBA không? Mấy bài bên trên là làm chơi cho vui chứ câu hỏi của bạn hoàn toàn không có gì để trả lời.
 
Cảm ơn anh đã xem bài và chỉ dẫn.
Trong code đã có biên k để đếm số lần thỏa 9 chính là số dòng của mảng thu được. Tuy nhiên tôi lại bí chỗ biến kết quả ấy thành giá trị của UDF.
Ý anh HieuCD là đếm hoặc dùng vòng lặp để có số k trước, sau đó resize mảng kết quả k dòng thì vừa, không cần vòng lặp chém zero (thực chất là chém empty)
Tuy nhiên:
- Nếu đếm bằng hàm Count thì phải đếm chỉ những cột lẻ, và bao nhiêu cột lẻ cũng chưa biết. Thế là cũng phải lặp
- Nếu chạy vòng lặp để đếm thì cũng bằng 1 vòng lặp của bạn lúc chém empty.

Có 1 cách khác đó là xoay ngang mảng kết quả rồi Redim Preserve tăng dần theo k, cuối cùng Transpose cho ra kết quả cuối của hàm. Cách này sẽ bị giới hạn của hàm Transpose, quá giới hạn số phần tử (số dòng nhân số cột) thì bị lỗi.

(2) Với hàm mảng tự tạo thì khi chọn vùng để ấn định hàm thì tôi làm vùng đó có màu nền khác xung quanh nó là được;
Cũng giống như rào 1 mảnh vườn trên trang tính í mà!
Anh rào vườn dư tức là xâm phạm quỹ đất công. Vì vẫn có những trường hợp số lượng dòng kết quả ít hơn số lượng ô chia hai.
 
Theo tôi hiểu thì thớt chỉ muốn một cách viết hàm người dùng để giảm thgieeur tham số của hàm GETPIVOTDATA.

Có hai cách:

1. Nếu là phiên bản 365 thì viết một Lambda làm việc này. Cách thức tương tự như cách 2 bên dưới.

2. Đặt một HAMPIVOTDATA(byval ngay as Date, byval gio as Time, byval dong as Long, byval aiDi as string)

HAMPIVOTDATA = Application.GETPIVOTDATA("Sum of INPUT",$A$1,"Day",ngay,"Hour",gio,"ID",aiDI)
 
Bạn thử xem file của bạn có cái pivot table nào không? Có công thức mẫu nào cần chuyển sang hàm VBA không? Mấy bài bên trên là làm chơi cho vui chứ câu hỏi của bạn hoàn toàn không có gì để trả lời.
em xin lỗi em gửi nhầm file ạ. em không sửa được bài #1. nên em xin phép gửi lại file tại đây ạ
Theo tôi hiểu thì thớt chỉ muốn một cách viết hàm người dùng để giảm thgieeur tham số của hàm GETPIVOTDATA.

Có hai cách:

1. Nếu là phiên bản 365 thì viết một Lambda làm việc này. Cách thức tương tự như cách 2 bên dưới.

2. Đặt một HAMPIVOTDATA(byval ngay as Date, byval gio as Time, byval dong as Long, byval aiDi as string)

HAMPIVOTDATA = Application.GETPIVOTDATA("Sum of INPUT",$A$1,"Day",ngay,"Hour",gio,"ID",aiDI)
 

File đính kèm

em xin lỗi em gửi nhầm file ạ. em không sửa được bài #1. nên em xin phép gửi lại file tại đây ạ
Mã:
Function UseGetPivotData(ByVal rng As Range, ByVal Dayz&, ByVal Hourz&, ByVal Line&, ByVal ID$)
   UseGetPivotData = rng.pivotTable.GetPivotData("Sum of INPUT", "Day", Dayz, "Hour", Hourz, "line", Line, "ID", ID)
End Function
Công thức ngoài sheet .
Mã:
H13
=UseGetPivotData(Sheet3!$A$1,F13,F14,F15,F16)
 
Mã:
Function UseGetPivotData(ByVal rng As Range, ByVal Dayz&, ByVal Hourz&, ByVal Line&, ByVal ID$)
   UseGetPivotData = rng.pivotTable.GetPivotData("Sum of INPUT", "Day", Dayz, "Hour", Hourz, "line", Line, "ID", ID)
End Function
Công thức ngoài sheet .
Mã:
H13
=UseGetPivotData(Sheet3!$A$1,F13,F14,F15,F16)
vâng được rồi ạ. em cảm ơn bác, nhân tiện cho em hỏi là mình muốn khi nhập giá trị trong hàm tự tạo mà nó hiện cái đề xuất hướng dẫn giống hàm của excel thì làm như thế nào vậy ạ
1693403227994.png
 

File đính kèm

  • 1693403222771.png
    1693403222771.png
    2.2 KB · Đọc: 1
vâng được rồi ạ. em cảm ơn bác, nhân tiện cho em hỏi là mình muốn khi nhập giá trị trong hàm tự tạo mà nó hiện cái đề xuất hướng dẫn giống hàm của excel thì làm như thế nào vậy ạ
View attachment 294398
Cách làm khá phức tạp, bạn tìm trên diễn đàn có bài nói về vấn đề nầy
Theo mình đề xuất hướng dẫn các tham số không có cũng không thành vấn đề, vì đây là hàm tự tạo có tính cá biệt cao chỉ dùng cho file nầy không dùng cho trường hợp khác, nếu cần có thể nhấn "fx" trên thanh công thức công thức sẽ thấy các tham số của hàm tự tạo
 
Web KT

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

Back
Top Bottom