Thống kê (đếm) theo nhiều điều kiện! (1 người xem)

  • Thread starter Thread starter Mr Joker
  • Ngày gửi Ngày gửi
Liên hệ QC

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

Mr Joker

Thành viên mới
Tham gia
17/1/11
Bài viết
40
Được thích
7
Giới tính
Nam
Chào các anh chị / các tiền bối
Em có 1 vấn đề đã tìm tòi mà chưa giải quyết được nên muốn nhờ các anh, chị giúp đỡ ạ!
Em có 1 bảng chi tiết như file đính kèm, giờ em đang muốn đếm số lượng chuyến "2 in 1" của "Type 1" đáp ứng những điều kiện sau:
_ Cùng NAME
_ Cùng TYPE (ví dụ Type 1)
_ Cùng START
_ Cùng LOCATION
_Và cuối cùng là cùng TIME, đây là vấn đề rắc rối :( vì khác TIME thì đếm là 1 chuyến như bình thường, nhưng nếu đáp ứng tất cả các điều kiện trên bao gồm cả "cùng TIME" thì lại chỉ được đếm là 1 chuyến thôi (vì do có thể 2 Type 1 trong cùng 1 lần)

Với 4 điều kiện đầu thì em có thể dùng hàm COUNTIFS để đếm được SỐ CHUYẾN theo từng tiêu chí, nhưng để đáp ứng thêm điều kiện TIME thì em chưa có cách giải quyết!
Vì đáp ứng điều kiện"cùng TIME" là bằng nhau về ngày + tháng + năm + giờ + phút - có thể bằng giây hoặc chênh lệch nhau 1 giây thì sẽ gọi là "cùng TIME"
Về định dạng và nội dung cột TIME là cố định như vậy không thay đổi.

Mong các anh chị giúp đỡ ạ ! Em cảm ơn rất nhiều
 

File đính kèm

Chào các anh chị / các tiền bối
Em có 1 vấn đề đã tìm tòi mà chưa giải quyết được nên muốn nhờ các anh, chị giúp đỡ ạ!
Em có 1 bảng chi tiết như file đính kèm, giờ em đang muốn đếm số lượng chuyến "2 in 1" của "Type 1" đáp ứng những điều kiện sau:
_ Cùng NAME
_ Cùng TYPE (ví dụ Type 1)
_ Cùng START
_ Cùng LOCATION
_Và cuối cùng là cùng TIME, đây là vấn đề rắc rối :( vì khác TIME thì đếm là 1 chuyến như bình thường, nhưng nếu đáp ứng tất cả các điều kiện trên bao gồm cả "cùng TIME" thì lại chỉ được đếm là 1 chuyến thôi (vì do có thể 2 Type 1 trong cùng 1 lần)

Với 4 điều kiện đầu thì em có thể dùng hàm COUNTIFS để đếm được SỐ CHUYẾN theo từng tiêu chí, nhưng để đáp ứng thêm điều kiện TIME thì em chưa có cách giải quyết!
Vì đáp ứng điều kiện"cùng TIME" là bằng nhau về ngày + tháng + năm + giờ + phút - có thể bằng giây hoặc chênh lệch nhau 1 giây thì sẽ gọi là "cùng TIME"
Về định dạng và nội dung cột TIME là cố định như vậy không thay đổi.

Mong các anh chị giúp đỡ ạ ! Em cảm ơn rất nhiều
Tạo 1 cột phụ cho dể làm
 

File đính kèm

@dazkangel, @hocexcel_1991, @huonglien1901 ....

Anh nghĩ với khả năng của các em, cũng với yêu cầu của chủ thớt như trên, không làm cột phụ, các em cố gắng tạo chỉ với 1 công thức cho ô I2 (rồi kéo xuống).

Đây anh chủ yếu tìm dịp chơi và học, rồi anh em cùng chia sẻ cho vui về công thức mảng, nha mấy em!

Chúc anh em ngày vui.
/-*+//-*+//-*+/

Gợi ý: trong công thức anh làm có sử dụng công thức cốt lõi của anh @HieuCD, và dùng thêm công thức tính phân đoạn MAX("Mảng") của anh @huuthang_bd...
 
@dazkangel, @hocexcel_1991, @huonglien1901 ....

Anh nghĩ với khả năng của các em, cũng với yêu cầu của chủ thớt như trên, không làm cột phụ, các em cố gắng tạo chỉ với 1 công thức cho ô I2 (rồi kéo xuống).

Đây anh chủ yếu tìm dịp chơi và học, rồi anh em cùng chia sẻ cho vui về công thức mảng, nha mấy em!

Chúc anh em ngày vui.
/-*+//-*+//-*+/

Gợi ý: trong công thức anh làm có sử dụng công thức cốt lõi của anh @HieuCD, và dùng thêm công thức tính phân đoạn MAX("Mảng") của anh @huuthang_bd...
Em dùng công thức của anh rồi sửa lại tí, thấy kết quả đúng, không biết có sai trường hợp nào không?
Mã:
=COUNT(1/(MATCH($D$2:$D$19&$E$2:$E$19&INT($C$2:$C$19),$D$2:$D$19&$E$2:$E$19&INT($C$2:$C$19),0)=ROW($1:$18))/(($A$2:$A$19=G2)*($B$2:$B$19=--RIGHT(H2))))
nhấn CSE
P/S: mấy công thức mảng em chỉ "chôm" trên mạng rồi sửa lại thôi. Chứ đụng vào mấy cái này nhức óc lắm /-*+/
 
Em dùng công thức của anh rồi sửa lại tí, thấy kết quả đúng, không biết có sai trường hợp nào không?
Mã:
=COUNT(1/(MATCH($D$2:$D$19&$E$2:$E$19&INT($C$2:$C$19),$D$2:$D$19&$E$2:$E$19&INT($C$2:$C$19),0)=ROW($1:$18))/(($A$2:$A$19=G2)*($B$2:$B$19=--RIGHT(H2))))
nhấn CSE
P/S: mấy công thức mảng em chỉ "chôm" trên mạng rồi sửa lại thôi. Chứ đụng vào mấy cái này nhức óc lắm /-*+/
Mới được cài "sườn" thôi em! cố lên! :)

Chưa chính xác, vì hàm INT($C$2:$C$19).
Do giờ phải tính đến "Giây" chỉ chênh lệch với nhau 1 giây thì xem là cùng một thời gian và loại trùng.

Cứ tập luyện suy nghĩ, đến khi có kết quả mình sẽ thấm nhiều hơn.

Thân
 
@dazkangel, @hocexcel_1991, @huonglien1901 ....

Anh nghĩ với khả năng của các em, cũng với yêu cầu của chủ thớt như trên, không làm cột phụ, các em cố gắng tạo chỉ với 1 công thức cho ô I2 (rồi kéo xuống).

Đây anh chủ yếu tìm dịp chơi và học, rồi anh em cùng chia sẻ cho vui về công thức mảng, nha mấy em!

Chúc anh em ngày vui.
/-*+//-*+//-*+/

Gợi ý: trong công thức anh làm có sử dụng công thức cốt lõi của anh @HieuCD, và dùng thêm công thức tính phân đoạn MAX("Mảng") của anh @huuthang_bd...
Thử:
Mã:
=SUMPRODUCT((A$2:A$19=G2)*(B$2:B$19=--RIGHT(H2))/MMULT(COUNTIFS(A$2:A$19,A$2:A$19,B$2:B$19,B$2:B$19,C$2:C$19,C$2:C$19+{0,1,-1}*1/86400,D$2:D$19,D$2:D$19,E$2:E$19,E$2:E$19),{1;1;1}))
 
Lần chỉnh sửa cuối:
@dazkangel, @hocexcel_1991, @huonglien1901 ....

Anh nghĩ với khả năng của các em, cũng với yêu cầu của chủ thớt như trên, không làm cột phụ, các em cố gắng tạo chỉ với 1 công thức cho ô I2 (rồi kéo xuống).

Đây anh chủ yếu tìm dịp chơi và học, rồi anh em cùng chia sẻ cho vui về công thức mảng, nha mấy em!

Chúc anh em ngày vui.
/-*+//-*+//-*+/

Gợi ý: trong công thức anh làm có sử dụng công thức cốt lõi của anh @HieuCD, và dùng thêm công thức tính phân đoạn MAX("Mảng") của anh @huuthang_bd...
Em dạo này bận công việc quá nên thời gian lên diễn đàn cũng ít. Tí nữa thử suy nghĩ cách làm thử xem. Chứ để lâu ngày đầu óc quên hết kiến thức à.
 
Thử:
Mã:
=SUMPRODUCT((A$2:A$19=G2)*(B$2:B$19=--RIGHT(H2))*MMULT(COUNTIFS(A$2:A$19,A$2:A$19,B$2:B$19,B$2:B$19,C$2:C$19,C$2:C$19+{0,1,-1}*1/86400,D$2:D$19,D$2:D$19,E$2:E$19,E$2:E$19),{1;1;1})^-1)
Công thức của em rất hay, nhưng có 1 chỗ nhược cần phải nới rộng biên:
Dùng C$2:C$19+{0,1,-1}*1/86400 sẽ bị hạn chế theo biên độ {0,1,-1} của từng giá trị theo dòng.
Ví dụ: Giả sử các giá trị tại C4, C5, C6 có chênh lệch vơi nhau 1 giây lần lượt như sau:
  • C4= 01/04/2019 8:35:03 AM -> sẽ có 3 giá trị 8:35:02 ; 8:35:03 ; 8:35:04 (Nó sẽ bị hụt mất: 05)
  • C5= 01/04/2019 8:35:04 AM -> sẽ có 3 giá trị 8:35:03 ; 8:35:04 ; 8:35:05
  • C6= 01/04/2019 8:35:05 AM -> sẽ có 3 giá trị 8:35:04 ; 8:35:05 ; 8:35:06 (Nó sẽ bị hụt mất: 03)
Thành ra sẽ có kết quả lẻ.

Gợi ý thêm 1 cách:
  • Chọn ra các giá trị chênh lệch nhau 1-2 giây (hoặc n giây), theo từng dòng dữ liệu.
  • Quy đổi thống nhất về 1 giá trị nhỏ chung nhất, theo từng dòng dữ liệu.
  • Làm được hai bước trên thì các giá trị chênh lệch nhau 1-2 giây sẽ còn thể hiện 1 ngày giờ-phút-giây thống nhất. (như ví dụ trên thì các dòng C4: C6 sẽ chỉ hiện: 01/04/2019 8:35:03 AM
  • Dựa trên kết quả đó sẽ tìm được các giá trị trùng lắp như yêu cầu đề bài, loại ra, và đếm.
Thân
 
Lần chỉnh sửa cuối:
Chào anh / chị
Trước hết em cảm ơn sự nhiệt tình của mọi người
Vấn đề này phức tạp hơn em tưởng :(
 
Công thức của em rất hay, nhưng có 1 chỗ nhược cần phải nới rộng biên:
Dùng C$2:C$19+{0,1,-1}*1/86400 sẽ bị hạn chế theo biên độ {0,1,-1} của từng giá trị theo dòng.
Ví dụ: Giả sử các giá trị tại C4, C5, C6 có chênh lệch vơi nhau 1 giây lần lượt như sau:
  • C4= 01/04/2019 8:35:03 AM -> sẽ có 3 giá trị 8:35:02 ; 8:35:03 ; 8:35:04 (Nó sẽ bị hụt mất: 05)
  • C5= 01/04/2019 8:35:04 AM -> sẽ có 3 giá trị 8:35:03 ; 8:35:04 ; 8:35:05
  • C6= 01/04/2019 8:35:05 AM -> sẽ có 3 giá trị 8:35:04 ; 8:35:05 ; 8:35:06 (Nó sẽ bị hụt mất: 03)
Thành ra sẽ có kết quả lẻ.

Gợi ý thêm 1 cách:
  • Chọn ra các giá trị chênh lệch nhau 1-2 giây (hoặc n giây), theo từng dòng dữ liệu.
  • Quy đổi thống nhất về 1 giá trị nhỏ chung nhất, theo từng dòng dữ liệu.
  • Làm được hai bước trên thì các giá trị chênh lệch nhau 1-2 giây sẽ còn thể hiện 1 ngày giờ-phút-giây thống nhất. (như ví dụ trên thì các dòng C4: C6 sẽ chỉ hiện: 01/04/2019 8:35:03 AM
  • Dựa trên kết quả đó sẽ tìm được các giá trị trùng lắp như yêu cầu đề bài, loại ra, và đếm.
Thân
Thêm 1 cách khác đỡ cộng trừ hơn, nhưng quy đổi kiểu gì thì em không biết cách làm:
Mã:
=SUMPRODUCT((A$2:A$19=G2)*(B$2:B$19=--RIGHT(H2))/COUNTIFS(A$2:A$19,A$2:A$19,B$2:B$19,B$2:B$19,C$2:C$19,"<="&C$2:C$19+1/86400,C$2:C$19,">="&C$2:C$19-1/86400,D$2:D$19,D$2:D$19,E$2:E$19,E$2:E$19))
 
Lần chỉnh sửa cuối:
Thêm 1 cách khác đỡ cộng trừ hơn, nhưng quy đổi kiểu gì thì em không biết cách làm:
Mã:
=SUMPRODUCT((A$2:A$19=G2)*(B$2:B$19=--RIGHT(H2))/COUNTIFS(A$2:A$19,A$2:A$19,B$2:B$19,B$2:B$19,C$2:C$19,"<="&C$2:C$19+1/86400,C$2:C$19,">="&C$2:C$19-1/86400,D$2:D$19,D$2:D$19,E$2:E$19,E$2:E$19))
Xem ra và cũng thú thiệt cách của em hay và gọn hơn cách của anh nghĩ ra.
Ban đầu anh tính thì gọn, tức dùng: ABS(....)<10/86399, nhưng không dè phát sinh thêm nhiều thứ nữa!
Đành, chịu thua em!

Chúc em ngày vui.
/-*+//-*+//-*+/
 
Xem ra và cũng thú thiệt cách của em hay và gọn hơn cách của anh nghĩ ra.
Ban đầu anh tính thì gọn, tức dùng: ABS(....)<10/86399, nhưng không dè phát sinh thêm nhiều thứ nữa!
Đành, chịu thua em!

Chúc em ngày vui.
/-*+//-*+//-*+/
Anh thử đưa cách quy đổi để về sau cần em có bí kíp học theo.
 
Anh thử đưa cách quy đổi để về sau cần em có bí kíp học theo.
Đem lên làm gì cho xấu hỗ em! :-)

Thiệt tình là anh ôn lại công thức của anh @huuthang_bd trong việc tìm phân đoạn MIN/MAX("Mảng"), cái này thì em biết rồi, tuy nhiên khi đem vào thì, ôi chao! nó dài quá.

Chúc em ngày vui.
/-*+//-*+//-*+/
 
Đem lên làm gì cho xấu hỗ em! :)

Thiệt tình là anh ôn lại công thức của anh @huuthang_bd trong việc tìm phân đoạn MIN/MAX("Mảng"), cái này thì em biết rồi, tuy nhiên khi đem vào thì, ôi chao! nó dài quá.

Chúc em ngày vui.
/-*+//-*+//-*+/
Cái tìm min, max 1 mảng em mất cả tuần tìm ra cách làm. Hàm min/max mảng của anh huuthang_bd em không biết cách làm ra sao ...
Nếu được anh cho em đường dẫn đến bài đó học mót co thêm kiến thức.
 
Cái tìm min, max 1 mảng em mất cả tuần tìm ra cách làm. Hàm min/max mảng của anh huuthang_bd em không biết cách làm ra sao ...
Nếu được anh cho em đường dẫn đến bài đó học mót co thêm kiến thức.
Cũng từ sự tìm tòi đặt vấn đề của @eke_rula mà có các công thức hay sản sinh:
Tính tổng Min,Max trong của các vùng dữ liệu 1 chiều trong vùng dữ liệu 2 chiều

Chúc em ngày vui.
/-*+//-*+//-*+/
 
Giả sử giờ như bên dưới thì có gọi là cùng thời gian không?
12:00:00
12:00:01
12:00:02
12:00:03
 
Giả sử giờ như bên dưới thì có gọi là cùng thời gian không?
12:00:00
12:00:01
12:00:02
12:00:03
Vụ này thì chỉ có thớt mới biết tính hay không. :)

Mấy cái giờ chênh lệch nhau 1 giây thường hay thấy trong các giao dịch thanh toán hoàn thành, để Ghi Nợ/Có tại Sổ phụ ngân hàng, như ví dụ trong file kèm.

Thân
 

File đính kèm

Chào anh em,

Rất thích chủ đề giờ chênh lệch này, vì hoàn toàn giống với thực tế đang theo dõi sổ sách tại Cty.
Nay, gửi anh em yêu cầu (mà thực tế đang làm) như sau:

Chỉ tạo bằng công thức cho cột F, trả về kết quả là các ký hiệu quy định trong bảng I1:L11, với các điều kiện sau:

1/ Nếu Phát sinh Nợ >0: Đặc điểm trên giao dịch có cùng Ngày-Giờ-Phút-Giây (chỉ lệch đúng 1 giây) thường có 3 dòng:

○ Đối với Thanh toán cho Nhà Cung Cấp (NCC), hoặc các cơ quan hữu quan (BHXH, Thuế...): thường nội dung diễn giải giống nhau
→ Giá trị lớn nhất: là Thanh toán (thường khớp đúng với giá trị đang theo dõi bên sheet "SoKTChitiet")
→ Giá trị lớn nhì: là Phí NH chuyển khoản
→ Giá trị cuối: là VAT Phí NH chuyển khoản
Lưu ý: Có vài NCC cùng chung Ngân hàng, thì chỉ có 1 dòng phát sinh giá trị thanh toán, không có 2 dòng Phí và VAT.

○ Đối với Rút Tiền gửi Ngân hàng:
→ Giá trị lớn nhất: là Rút tiền gửi ngân hàng (TGHN) nhập Qũy Tiền mặt (QTM). Diễn giải thường có chữ RTM
(thường khớp đúng với giá trị đang theo dõi bên sheet "SoKTChitiet")
→ Giá trị lớn nhì: là Phí Rút TGNH
→ Giá trị cuối: là VAT Phí rút TGNH

2/ Nếu Phát sinh Có >0: Được phân ra:
→ Bán Ngoại tệ: khi trong Diễn giải có ghi nội dung "BAN NGOAI TE"
→ Lãi tiền gửi ngân hàng: khi trong Diễn giải có ghi nội dung "Interest"
→ Hoàn tiền: khi trong Diễn giải có ghi nội dung "HOAN NHAP"
→ Số còn lại là Thu tiền

Kết quả mong muốn trả về như đã đánh tay vào cột F file kèm.

Chúc anh em tham khảo vui.
Thân
 

File đính kèm

Lần chỉnh sửa cuối:
Cảm ơn các anh / chị
Em chợt nhớ ra 1 vấn đề, cái quên này khá là quan trọng :) nhưng không rõ là có đơn giản bớt công thức mọi người đang xây dựng để đáp ứng điều kiện của bài này không nữa :)

Theo logic thì có thể bỏ qua phần xét đến tiêu chí GIÂY (bằng GIÂY hoặc lệch 1 GIÂY cũng không cần xét đến nữa), chỉ cần đáp ứng tiêu chí trùng NAME - trùng START - trùng LOCATION - và cuối cùng là trùng TIME, trong TIME chỉ cần trùng ngày - tháng - năm - giờ - phút là đủ đưa vào diện "2 chuyến nhưng ĐẾM 1 LẦN"
vì thực tế là để thực hiện xong 1 chuyến đã tốn một thời gian nhất định, thế nên không thể có trường hợp đáp ứng đầy đủ những tiêu chí trên trùng đến tận phút mà lại không phải là 1 chuyến đi đôi. Anh / chị hiểu ý em không ạ?
Ví dụ 2 "TYPE 1" (đã đáp ứng trùng NAME - START - LOCATION) có dữ liệu thời gian như sau:
01/04/2019 8:35:03
01/04/2019 8:35:04
vì trong 60 giây của phút thứ 35 này không thể có NAME nào thực hiện được 2 "TYPE 1" riêng biệt được, nên chắc chắn đây là 1 chuyến đi đôi. Vì vậy em thấy xét đến trùng phút là đủ.
 
Cảm ơn các anh / chị
Em chợt nhớ ra 1 vấn đề, cái quên này khá là quan trọng :) nhưng không rõ là có đơn giản bớt công thức mọi người đang xây dựng để đáp ứng điều kiện của bài này không nữa :)

Theo logic thì có thể bỏ qua phần xét đến tiêu chí GIÂY (bằng GIÂY hoặc lệch 1 GIÂY cũng không cần xét đến nữa), chỉ cần đáp ứng tiêu chí trùng NAME - trùng START - trùng LOCATION - và cuối cùng là trùng TIME, trong TIME chỉ cần trùng ngày - tháng - năm - giờ - phút là đủ đưa vào diện "2 chuyến nhưng ĐẾM 1 LẦN"
vì thực tế là để thực hiện xong 1 chuyến đã tốn một thời gian nhất định, thế nên không thể có trường hợp đáp ứng đầy đủ những tiêu chí trên trùng đến tận phút mà lại không phải là 1 chuyến đi đôi. Anh / chị hiểu ý em không ạ?
Ví dụ 2 "TYPE 1" (đã đáp ứng trùng NAME - START - LOCATION) có dữ liệu thời gian như sau:
01/04/2019 8:35:03
01/04/2019 8:35:04
vì trong 60 giây của phút thứ 35 này không thể có NAME nào thực hiện được 2 "TYPE 1" riêng biệt được, nên chắc chắn đây là 1 chuyến đi đôi. Vì vậy em thấy xét đến trùng phút là đủ.
Vậy hai mốc thời gian 01/04/2019 8:35:59 và 01/04/2019 8:36:00 chả nhẽ lại thành không "cùng thời gian" à :D
 
Chào anh em,

Rất thích chủ đề giờ chênh lệch này, vì hoàn toàn giống với thực tế đang theo dõi sổ sách tại Cty.
Nay, gửi anh em yêu cầu (mà thực tế đang làm) như sau:

Chỉ tạo bằng công thức cho cột F, trả về kết quả là các ký hiệu quy định trong bảng I1:L11, với các điều kiện sau:

1/ Nếu Phát sinh Nợ >0: Đặc điểm trên giao dịch có cùng Ngày-Giờ-Phút-Giây (chỉ lệch đúng 1 giây) thường có 3 dòng:

○ Đối với Thanh toán cho Nhà Cung Cấp (NCC), hoặc các cơ quan hữu quan (BHXH, Thuế...): thường nội dung diễn giải giống nhau
→ Giá trị lớn nhất: là Thanh toán (thường khớp đúng với giá trị đang theo dõi bên sheet "SoKTChitiet")
→ Giá trị lớn nhì: là Phí NH chuyển khoản
→ Giá trị cuối: là VAT Phí NH chuyển khoản
Lưu ý: Có vài NCC cùng chung Ngân hàng, thì chỉ có 1 dòng phát sinh giá trị thanh toán, không có 2 dòng Phí và VAT.

○ Đối với Rút Tiền gửi Ngân hàng:
→ Giá trị lớn nhất: là Rút tiền gửi ngân hàng (TGHN) nhập Qũy Tiền mặt (QTM). Diễn giải thường có chữ RTM
(thường khớp đúng với giá trị đang theo dõi bên sheet "SoKTChitiet")
→ Giá trị lớn nhì: là Phí Rút TGNH
→ Giá trị cuối: là VAT Phí rút TGNH

2/ Nếu Phát sinh Có >0: Được phân ra:
→ Bán Ngoại tệ: khi trong Diễn giải có ghi nội dung "BAN NGOAI TE"
→ Lãi tiền gửi ngân hàng: khi trong Diễn giải có ghi nội dung "Interest"
→ Hoàn tiền: khi trong Diễn giải có ghi nội dung "HOAN NHAP"
→ Số còn lại là Thu tiền

Kết quả mong muốn trả về như đã đánh tay vào cột F file kèm.

Chúc anh em tham khảo vui.
Thân
Hai ô ra kết quả khác, không biết có hiểu sai chỗ nào không.
216753
 
Cảm ơn các anh / chị
Em chợt nhớ ra 1 vấn đề, cái quên này khá là quan trọng :) nhưng không rõ là có đơn giản bớt công thức mọi người đang xây dựng để đáp ứng điều kiện của bài này không nữa :)

Theo logic thì có thể bỏ qua phần xét đến tiêu chí GIÂY (bằng GIÂY hoặc lệch 1 GIÂY cũng không cần xét đến nữa), chỉ cần đáp ứng tiêu chí trùng NAME - trùng START - trùng LOCATION - và cuối cùng là trùng TIME, trong TIME chỉ cần trùng ngày - tháng - năm - giờ - phút là đủ đưa vào diện "2 chuyến nhưng ĐẾM 1 LẦN"
vì thực tế là để thực hiện xong 1 chuyến đã tốn một thời gian nhất định, thế nên không thể có trường hợp đáp ứng đầy đủ những tiêu chí trên trùng đến tận phút mà lại không phải là 1 chuyến đi đôi. Anh / chị hiểu ý em không ạ?
Ví dụ 2 "TYPE 1" (đã đáp ứng trùng NAME - START - LOCATION) có dữ liệu thời gian như sau:
01/04/2019 8:35:03
01/04/2019 8:35:04
vì trong 60 giây của phút thứ 35 này không thể có NAME nào thực hiện được 2 "TYPE 1" riêng biệt được, nên chắc chắn đây là 1 chuyến đi đôi. Vì vậy em thấy xét đến trùng phút là đủ.
Theo như phân tích của hai anh trên, bạn không nên không xét đến 1 giây.

Trong bài toán này, hoàn toàn phụ thuộc vào bạn biết biên độ thời gian (giây) hạn định để phân biệt sự khác nhau giữa hai giao dịch, bạn phải tự nhận xét lấy qua việc: "thông lệ" nó xảy ra như thế nào.

Ví dụ: có thể các chuyến coi là trùng lắp, sẽ có biên độ chênh lệch nhau trong vòng 10 giây, nhưng giữa hai chuyến khác nhau phát sinh, có thể cách biệt là từ 2 phút trở lên (cái này là tôi giả dụ thôi), thì hai công thức:
  1. Bài #2 của anh @HieuCD, và
  2. Bài #6 của bạn @dazkangel
"Rất" phù hợp với yêu cầu của bạn rồi.

Trong file kèm là tôi nâng độ rộng biên của cả hai công thức tùy theo ý bạn (sau khi bạn đã nhận xét và rút ra được cái "thông lệ" phân biệt về thời gian, như trên đã đề cập). Bạn xem thử và tùy nghi áp dụng vào công việc của bạn.

Thân
 

File đính kèm

Ví dụ: có thể các chuyến coi là trùng lắp, sẽ có biên độ chênh lệch nhau trong vòng 10 giây, nhưng giữa hai chuyến khác nhau phát sinh, có thể cách biệt là từ 2 phút trở lên (cái này là tôi giả dụ thôi), thì hai công thức:
Nếu vậy thì sẽ không có trường hợp như dòng 17 và 18 trong file và không cần xét đến START và LOCATION.
 
Nếu vậy thì sẽ không có trường hợp như dòng 17 và 18 trong file và không cần xét đến START và LOCATION.
Hai dòng đó khác ngày. :)

Bởi vậy, sự phân biệt các chuyến khác nhau là do chủ thớt phải tự tìm ra, và phải khác nhau cả nhiều phút mới được.

Thân
-------------------------------------------------------------------------
Hai ô ra kết quả khác, không biết có hiểu sai chỗ nào không.
View attachment 216753
Chính xác là bị tính sai, và ký hiệu phải là "Pi" và "Pv".

Giao dịch này là chuyển "ốm đau, thai sản vào thẻ ATM" cho công nhân viên, nhưng "bị" ngân hàng "tính phí" là 55.000đ gồm thuế VAT.
Sau này, ngân hàng phải hoàn trả lại cho Cty số tiền phí này.

Thân
 
Lần chỉnh sửa cuối:
Rất cảm ơn anh / chị đã giúp đỡ :)
Ví dụ:
01/04/2019 8:35:59
01/04/2019 8:36:00

Nhận xét: Trùng phút chưa chắc đã đủ
Vậy hai mốc thời gian 01/04/2019 8:35:59 và 01/04/2019 8:36:00 chả nhẽ lại thành không "cùng thời gian" à :D
Đúng là em bỏ sót trường hợp này :)
Như vậy vẫn nên tính đến "GIÂY" là sẽ chính xác và đầy đủ nhất !
Theo như phân tích của hai anh trên, bạn không nên không xét đến 1 giây.

Trong bài toán này, hoàn toàn phụ thuộc vào bạn biết biên độ thời gian (giây) hạn định để phân biệt sự khác nhau giữa hai giao dịch, bạn phải tự nhận xét lấy qua việc: "thông lệ" nó xảy ra như thế nào.

Ví dụ: có thể các chuyến coi là trùng lắp, sẽ có biên độ chênh lệch nhau trong vòng 10 giây, nhưng giữa hai chuyến khác nhau phát sinh, có thể cách biệt là từ 2 phút trở lên (cái này là tôi giả dụ thôi), thì hai công thức:
  1. Bài #2 của anh @HieuCD, và
  2. Bài #6 của bạn @dazkangel
"Rất" phù hợp với yêu cầu của bạn rồi.

Trong file kèm là tôi nâng độ rộng biên của cả hai công thức tùy theo ý bạn (sau khi bạn đã nhận xét và rút ra được cái "thông lệ" phân biệt về thời gian, như trên đã đề cập). Bạn xem thử và tùy nghi áp dụng vào công việc của bạn.

Thân
Cảm ơn anh nhiều. Em đã hiểu vấn đề
Chúc mọi người vui vẻ !
 
Chào anh em,

Rất thích chủ đề giờ chênh lệch này, vì hoàn toàn giống với thực tế đang theo dõi sổ sách tại Cty.
Nay, gửi anh em yêu cầu (mà thực tế đang làm) như sau:

Chỉ tạo bằng công thức cho cột F, trả về kết quả là các ký hiệu quy định trong bảng I1:L11, với các điều kiện sau:

1/ Nếu Phát sinh Nợ >0: Đặc điểm trên giao dịch có cùng Ngày-Giờ-Phút-Giây (chỉ lệch đúng 1 giây) thường có 3 dòng:

○ Đối với Thanh toán cho Nhà Cung Cấp (NCC), hoặc các cơ quan hữu quan (BHXH, Thuế...): thường nội dung diễn giải giống nhau
→ Giá trị lớn nhất: là Thanh toán (thường khớp đúng với giá trị đang theo dõi bên sheet "SoKTChitiet")
→ Giá trị lớn nhì: là Phí NH chuyển khoản
→ Giá trị cuối: là VAT Phí NH chuyển khoản
Lưu ý: Có vài NCC cùng chung Ngân hàng, thì chỉ có 1 dòng phát sinh giá trị thanh toán, không có 2 dòng Phí và VAT.

○ Đối với Rút Tiền gửi Ngân hàng:
→ Giá trị lớn nhất: là Rút tiền gửi ngân hàng (TGHN) nhập Qũy Tiền mặt (QTM). Diễn giải thường có chữ RTM
(thường khớp đúng với giá trị đang theo dõi bên sheet "SoKTChitiet")
→ Giá trị lớn nhì: là Phí Rút TGNH
→ Giá trị cuối: là VAT Phí rút TGNH

2/ Nếu Phát sinh Có >0: Được phân ra:
→ Bán Ngoại tệ: khi trong Diễn giải có ghi nội dung "BAN NGOAI TE"
→ Lãi tiền gửi ngân hàng: khi trong Diễn giải có ghi nội dung "Interest"
→ Hoàn tiền: khi trong Diễn giải có ghi nội dung "HOAN NHAP"
→ Số còn lại là Thu tiền

Kết quả mong muốn trả về như đã đánh tay vào cột F file kèm.

Chúc anh em tham khảo vui.
Thân
Vấn đề của thớt xong rồi thì tới vấn đề phát sinh :P
 

File đính kèm

Vấn đề của thớt xong rồi thì tới vấn đề phát sinh :p
Cảm ơn vì đã quan tâm!
/-*+//-*+//-*+/

Dòng 103 và 104 (Ngày 26/04/2019 18:29:15) thực ra là tiền Phí Rút TGNH và VAT của khoảng rút tiền 20 Triệu (Dòng 90: 26/04/2019 14:13:17).
Trong Diễn giải (Dòng 104) của nó cũng thể hiện.

Thân
 
Dòng 103 và 104 (Ngày 26/04/2019 18:29:15) thực ra là tiền Phí Rút TGNH và VAT của khoảng rút tiền 20 Triệu (Dòng 90: 26/04/2019 14:13:17).
Trong Diễn giải (Dòng 104) của nó cũng thể hiện.

Thân
Thì tôi làm theo quy luật mà bạn mô tả mà. Cứ ráp vô quy luật nó trúng cái nào thì lấy cái đó thôi.
 
Thì tôi làm theo quy luật mà bạn mô tả mà. Cứ ráp vô quy luật nó trúng cái nào thì lấy cái đó thôi.
Mấy anh I.T thảo chương Internet banking của ngân hàng cũng vui lắm:
Giá trị rút tiền: thì ghi *RTM*
Phí rút tiền: ghi "DN - Rut tien mat VND khac tinh/TP noi mo TK"
Còn VAT bất kỳ chỉ vỏn vẹn "VAT TAX FOR VND"
Thêm vào đó, vui thì ghi cùng thời gian cho cùng giao dịch rút tiền+tính phí+VAT, "hổng dzui" thì như file làm hai thời gian cách biệt nhau.
Cũng may, việc thanh toán cho NCC thì không bị vậy.

Tội cho mấy "thằng" kế toán ngồi đó mà ghi rõ ra Phí của em nào và VAT của em nào.

Chút chia sẻ nỗi khỗ của nghề.
/-*+//-*+//-*+/
 
Lần chỉnh sửa cuối:
Theo như phân tích của hai anh trên, bạn không nên không xét đến 1 giây.

Trong bài toán này, hoàn toàn phụ thuộc vào bạn biết biên độ thời gian (giây) hạn định để phân biệt sự khác nhau giữa hai giao dịch, bạn phải tự nhận xét lấy qua việc: "thông lệ" nó xảy ra như thế nào.

Ví dụ: có thể các chuyến coi là trùng lắp, sẽ có biên độ chênh lệch nhau trong vòng 10 giây, nhưng giữa hai chuyến khác nhau phát sinh, có thể cách biệt là từ 2 phút trở lên (cái này là tôi giả dụ thôi), thì hai công thức:
  1. Bài #2 của anh @HieuCD, và
  2. Bài #6 của bạn @dazkangel
"Rất" phù hợp với yêu cầu của bạn rồi.

Trong file kèm là tôi nâng độ rộng biên của cả hai công thức tùy theo ý bạn (sau khi bạn đã nhận xét và rút ra được cái "thông lệ" phân biệt về thời gian, như trên đã đề cập). Bạn xem thử và tùy nghi áp dụng vào công việc của bạn.

Thân
Hai công thức của anh @HieuCD@dazkangel em đã áp dụng rất ok cho bài test nho nhỏ của em !
Nhưng khi áp dụng vào thực tế công việc thì do số lượng dòng dữ liệu rất nhiều, tầm trên dưới 10000 dòng / tháng - khiến công thức rất nặng và chạy rất rất lâu anh / chị ạ.
Vấn đề nữa là trong ~10000 dòng hàng (nghĩa là rất nhiều), đúng như anh nói về biên độ chênh lệch giây, rõ ràng vẫn tồn tại việc chênh nhau nhiều số giây hơn (có thể lên đến vài phút) nhưng thực tế nó đúng rơi vào trường hợp 2 in 1 bởi miễn là cùng 1 người (NAME), lấy cùng loại TYPE 1, xuất phát cùng 1 nơi (START) và đến cùng 1 chỗ (LOCATION)
Trường hợp bằng hoặc chênh nhau 1 giây là chiếm đa số để mình nhận diện 2 in 1, nhưng thực tế vẫn tồn tại 1 vài trường hợp cũng thuộc diện này nhưng lại có thể chênh nhau nhiều giây hoặc lên đến vài phút. Mình không tính nó vào là diện 2 in 1 thì sẽ bị dư chuyến và không chuẩn cho việc tính tiền phải trả :(

Và em cũng rất mong muốn ngoài thống kê được TỔNG ra thì ta có thể thống kê "đếm" chi tiết được số chuyến TYPE 1 cụ thể cho từng "TUYẾN" (vì điểm đi - điểm đến khác nhau sẽ có giá tiền cũng khác nhau) đếm được bao nhiêu chuyến 1 tuyến bất kỳ của từng cá nhân, sẽ phục vụ cho việc lên báo cáo chi tiết số tiền phải trả cho từng tuyến + cho từng NAME trong 1 khoảng thời gian tùy chọn.
Ví dụ : theo file TEST thì từ 01/04 đến 12/04/2019
01/04/2019 anh KIM đi được 1 chuyến đôi TYPE 1 từ điểm a đến điểm C
03/04/2019 anh KIM đi được 1 chuyến đơn TYPE 1 từ điểm a đến điểm C
11/04/2019 anh KIM đi được 1 chuyến đơn TYPE 1 từ điểm a đến điểm C

Như vậy tuyến a - C đi loại TYPE 1 của anh KIM đếm được tổng cộng là 3 chuyến (trong thực tế sẽ đếm trong 1 khoảng thời gian như tuần, tháng, năm,...), đây chính là cái cần thống kê. Tương tự với các tuyến khác, NAME khác, thời gian khác.

Mong anh / chị có phương án nào tối ưu hơn cho bài toán lắm yêu cầu rắc rối này thì giúp em với :( Cảm ơn mọi người rất nhiều.
 
Lần chỉnh sửa cuối:
Hai công thức của anh @HieuCD@dazkangel em đã áp dụng rất ok cho bài test nho nhỏ của em !
Nhưng khi áp dụng vào thực tế công việc thì do số lượng dòng dữ liệu rất nhiều, tầm trên dưới 10000 dòng / tháng - khiến công thức rất nặng và chạy rất rất lâu anh / chị ạ.
Vấn đề nữa là trong ~10000 dòng hàng (nghĩa là rất nhiều), đúng như anh nói về biên độ chênh lệch giây, rõ ràng vẫn tồn tại việc chênh nhau nhiều số giây hơn (có thể lên đến vài phút) nhưng thực tế nó đúng rơi vào trường hợp 2 in 1 bởi miễn là cùng 1 người (NAME), lấy cùng loại TYPE 1, xuất phát cùng 1 nơi (START) và đến cùng 1 chỗ (LOCATION)
Trường hợp bằng hoặc chênh nhau 1 giây là chiếm đa số để mình nhận diện 2 in 1, nhưng thực tế vẫn tồn tại 1 vài trường hợp cũng thuộc diện này nhưng lại có thể chênh nhau nhiều giây hoặc lên đến vài phút. Mình không tính nó vào là diện 2 in 1 thì sẽ bị dư chuyến và không chuẩn cho việc tính tiền phải trả :(

Và em cũng rất mong muốn ngoài thống kê được TỔNG ra thì ta có thể thống kê "đếm" chi tiết được số chuyến TYPE 1 cụ thể cho từng "TUYẾN" (vì điểm đi - điểm đến khác nhau sẽ có giá tiền cũng khác nhau) đếm được bao nhiêu chuyến 1 tuyến bất kỳ của từng cá nhân, sẽ phục vụ cho việc lên báo cáo chi tiết số tiền phải trả cho từng tuyến + cho từng NAME trong 1 khoảng thời gian tùy chọn.
Ví dụ : theo file TEST thì từ 01/04 đến 12/04/2019
01/04/2019 anh KIM đi được 1 chuyến đôi TYPE 1 từ điểm a đến điểm C
03/04/2019 anh KIM đi được 1 chuyến đơn TYPE 1 từ điểm a đến điểm C
11/04/2019 anh KIM đi được 1 chuyến đơn TYPE 1 từ điểm a đến điểm C

Như vậy tuyến a - C đi loại TYPE 1 của anh KIM đếm được tổng cộng là 3 chuyến (trong thực tế sẽ đếm trong 1 khoảng thời gian như tuần, tháng, năm,...), đây chính là cái cần thống kê. Tương tự với các tuyến khác, NAME khác, thời gian khác.

Mong anh / chị có phương án nào tối ưu hơn cho bài toán lắm yêu cầu rắc rối này thì giúp em với :( Cảm ơn mọi người rất nhiều.
10.000 dòng dùng SumIfS khá nặng, còn hàm mảng sẽ đơ máy. Nếu bạn chấp nhận dùng code VBA thì thiết kế tất cả báo cáo cần thiết trên sheet thật để mình viết code
 
Vấn đề của thớt xong rồi thì tới vấn đề phát sinh :p
Công thức dưới đây là công thức thực tế đang quản lý trong sổ theo dõi ngân hàng, với mục đích chỉ nhằm trao đổi cho vui về công thức mảng.

Mạn phép anh @huuthang_bd, "múa rìu qua mắt thợ" chút :), giải thích sơ bộ những chỗ lạ cho các em tham khảo thêm:
Mã:
=IF(--C4>0,CHOOSE(IFERROR(1/(1/SUM(COUNTIF(E4,{"*hoan tien*","*ban ngoai te*","*Interest*"})*{1,2,3})),4),"Ht","Bn","TL","TH"),LOOKUP(B4,AGGREGATE(15,6,$B$4:$B$150/(ABS(A4-$A$4:$A$104)<2/86399),{1,2,3}^(SUMPRODUCT(N(ABS(A4-$A$4:$A$104)<2/86399))>1)),IF(SUM(COUNTIFS($A$4:$A$150,A4+{-1,0,1}/86400+10^-12,$E$4:$E$150,{"*RTM*";"*Rut*"})),{"Rv","Rp","R"},{"Pv","Pi","TC"})))
Enter fill xuống.

Trên, chọn giải pháp LOOKUP( "Giá trị tiền", "Mảng Vectơ chỉ hướng", "Ký hiệu chọn" )
Trong đó: "Mảng Vectơ chỉ hướng" làm theo như điều kiện đặt ra, tức sẽ tìm các ngày-giờ chỉ chênh lệch nhau 1 giây. Ở đây sẽ phát sinh 3 trường hợp:
  1. Hoặc thỏa cả 3 dòng: lúc đó Mảng: {1,2,3}^(SUMPRODUCT(N(ABS(A4-$A$4:$A$104)<2/86399))>1) <=> {1,2,3}^(3>1) <=>{1,2,3}^1 = {1,2,3}. Ý sẽ lấy đủ 3 giá trị sắp theo nhỏ đến lớn.
  2. Nếu chỉ có hai giá trị thỏa: : lúc đó Mảng: {1,2,3}^(SUMPRODUCT(..'Như trên'..)>1) <=> {1,2,3}^(2>1) <=>{1,2,3}^1 = {1,2,3}. Ý sẽ lấy đủ 3 giá trị sắp theo nhỏ đến lớn. Nhưng chỉ có hai giá trị {1,2}, còn thành phần lớn nhất sẽ báo lỗi. Cái này áp dụng được cho khoản Phí và tiền thuế VAT lúc nào cũng đi chung cùng Ngày-GIờ-Phút-Giây (cl:+-1). Ví dụ: nó trả về Mảng giá trị tiền Phí và VAT: {1000,10000,#N/A!}
  3. Nếu chỉ có một giá trị thỏa: : lúc đó Mảng: {1,2,3}^(SUMPRODUCT(..'Như trên'..)>1) <=> {1,2,3}^(1>1) <=>{1,2,3}^0 = {1,1,1}. Ý sẽ lấy cùng một giá trị trả ra đủ 3 cột. Thường ứng vào các khoản thanh toán cho NCC cùng ngân hàng, hay giống như dạng Rút TGNH nhưng phân ra làm hai thời gian khi tính Phí rút và VAT của nó. Ví dụ: có 1 giá trị rút tiền mặt (dòng 90): 20Triệu, lúc đó mảng yêu cầu trả về giá trị nhỏ nhất: {1,1,1} => {20tr, 20tr, 20tr}.
  4. Do cách sắp đặt trên nên lúc nào Giá trị thanh toán hay Giá trị rút tiền mặt cũng nằm ở vị trí thứ 3 (cao nhất) trong Vectơ chỉ hướng của Lookup().
Riêng "Mảng Ký hiệu chọn" phân thành hai trường hợp: Hoặc dành cho Rút tiền mặt, hoặc không phải. Đó cũng là điều kiện đếm: SUM(COUNTIFS($A$4:$A$150,A4+{-1,0,1}/86400+10^-12,$E$4:$E$150,{"*RTM*";"*Rut*"}))
Lưu ý:
  • A4+{-1,0,1}/86400+10^-12 là mảng theo chiều ngang (cột)
  • {"*RTM*";"*Rut*"} là mảng theo chiều dọc (dòng).
Chúc anh em ngày vui.
/-*+//-*+//-*+/
 

File đính kèm

10.000 dòng dùng SumIfS khá nặng, còn hàm mảng sẽ đơ máy. Nếu bạn chấp nhận dùng code VBA thì thiết kế tất cả báo cáo cần thiết trên sheet thật để mình viết code
Vâng, nếu anh giúp được em thì thật tốt quá :) thực ra nếu dùng hàm thì em còn hiểu được đôi chút, nhưng để đáp ứng bài này thì em cũng biết hàm mảng sẽ không thể chạy nổi.
Dùng VBA thì em mù tịt, anh giúp em thì may quá. Em cảm ơn nhiều !

P/S: @Phan Thế Hiệp anh thiết kế cái báo cáo đó sang sheet khác với sheet dữ liệu giúp em nhé, vì sheet dữ liệu của em nó sẽ có tầm 10000 dòng là khá phức tạp rồi! Với thiết kế code tùy chỉnh được biên độ GIÂY để tính độ trùng thời gian được thì tốt quá ạ :)
Có 1 chút vấn đề em trình bày mong bác thiết kế VBA giúp em là trong bảng TEST cột TYPE em để là 1 hoặc 2 nhưng thực tế trong bảng dữ liệu công việc của em nó sẽ là 1xxx hoặc 2xxx, để xác định TYPE nào thì chỉ cần tách lấy ký tự đầu tiên của "1xxx hoặc 2xxx" sẽ được 1 hoặc 2 ra để thống kê là được ạ, phần xxx đằng sau không quan trọng.
 

File đính kèm

Lần chỉnh sửa cuối:
Vâng, nếu anh giúp được em thì thật tốt quá :) thực ra nếu dùng hàm thì em còn hiểu được đôi chút, nhưng để đáp ứng bài này thì em cũng biết hàm mảng sẽ không thể chạy nổi.
Dùng VBA thì em mù tịt, anh giúp em thì may quá. Em cảm ơn nhiều !

P/S: @Phan Thế Hiệp anh thiết kế cái báo cáo đó sang sheet khác với sheet dữ liệu giúp em nhé, vì sheet dữ liệu của em nó sẽ có tầm 10000 dòng là khá phức tạp rồi! Với thiết kế code tùy chỉnh được biên độ GIÂY để tính độ trùng thời gian được thì tốt quá ạ :)
Có 1 chút vấn đề em trình bày mong bác thiết kế VBA giúp em là trong bảng TEST cột TYPE em để là 1 hoặc 2 nhưng thực tế trong bảng dữ liệu công việc của em nó sẽ là 1xxx hoặc 2xxx, để xác định TYPE nào thì chỉ cần tách lấy ký tự đầu tiên của "1xxx hoặc 2xxx" sẽ được 1 hoặc 2 ra để thống kê là được ạ, phần xxx đằng sau không quan trọng.
Không có dữ liệu thật nên công thức dài dòng
Mã:
Function CountIfTime(ByVal TimeRng As Range, ByVal NameRng As Range, _
  ByVal TypeRng As Range, ByVal StartRng As Range, ByVal LocalRng As Range, _
  ByVal dTime As Double, ByVal dk As Variant)
  '=CountIfTime(Cot Time, Cot Name, Cot Type, Cot Start, Cot Location, Tieu Chuan Thoi Gian, INDEX((Dieu kien 1)*(Dieu kien 2) …  ,))
 
  Dim S, Dic As Object
  Dim i As Long, k As Long, q As Long, j As Long, n As Long
  Dim iKey As String, tmp, Test As Boolean
 
  Set Dic = CreateObject("scripting.dictionary")
  n = TimeRng.Rows.Count
  For i = 1 To n
    If dk(i, 1) Then
      iKey = NameRng(i, 1) & "#" & TypeRng(i, 1) & "#" & StartRng(i, 1) & "#" & LocalRng(i, 1)
      If Dic.exists(iKey) = False Then
        k = k + 1
        Dic.Add iKey, Array(TimeRng(i, 1).Value2)
      Else
        tmp = TimeRng(i, 1).Value2
        Test = True
        S = Dic.Item(iKey)
        q = UBound(S)
        For j = 0 To q
          If Abs(tmp - S(j)) < dTime Then Test = False: Exit For
        Next j
        If Test = True Then
          k = k + 1
          ReDim Preserve S(0 To q + 1)
          S(q + 1) = tmp
          Dic.Item(iKey) = S
        End If
      End If
    End If
  Next i
  CountIfTime = k
  Set Dic = Nothing
End Function
Xem cách dùng công thức trong File
 

File đính kèm

Không có dữ liệu thật nên công thức dài dòng
Mã:
Function CountIfTime(ByVal TimeRng As Range, ByVal NameRng As Range, _
  ByVal TypeRng As Range, ByVal StartRng As Range, ByVal LocalRng As Range, _
  ByVal dTime As Double, ByVal dk As Variant)
  '=CountIfTime(Cot Time, Cot Name, Cot Type, Cot Start, Cot Location, Tieu Chuan Thoi Gian, INDEX((Dieu kien 1)*(Dieu kien 2) …  ,))

  Dim S, Dic As Object
  Dim i As Long, k As Long, q As Long, j As Long, n As Long
  Dim iKey As String, tmp, Test As Boolean

  Set Dic = CreateObject("scripting.dictionary")
  n = TimeRng.Rows.Count
  For i = 1 To n
    If dk(i, 1) Then
      iKey = NameRng(i, 1) & "#" & TypeRng(i, 1) & "#" & StartRng(i, 1) & "#" & LocalRng(i, 1)
      If Dic.exists(iKey) = False Then
        k = k + 1
        Dic.Add iKey, Array(TimeRng(i, 1).Value2)
      Else
        tmp = TimeRng(i, 1).Value2
        Test = True
        S = Dic.Item(iKey)
        q = UBound(S)
        For j = 0 To q
          If Abs(tmp - S(j)) < dTime Then Test = False: Exit For
        Next j
        If Test = True Then
          k = k + 1
          ReDim Preserve S(0 To q + 1)
          S(q + 1) = tmp
          Dic.Item(iKey) = S
        End If
      End If
    End If
  Next i
  CountIfTime = k
  Set Dic = Nothing
End Function
Xem cách dùng công thức trong File
Em chào anh
Anh ơi, VBA em thì mù tịt nên em áp dụng đoạn code này của anh hoài mà vẫn chưa được :(
Cụ thể là em cần áp dụng cho bảng dữ liệu tầm 10000 dòng + bảng dữ liệu nằm ở 1 sheet riêng, bảng báo cáo nằm ở 1 sheet riêng (như file đính kèm), em viết rõ thiết kế và yêu cầu trong file anh giúp em hoàn thiện với nhé.
Em cảm ơn rất nhiều !
 

File đính kèm

Em chào các anh / chị
Anh chị giúp em với !
Cảm ơn anh chị đã quan tâm :)
 
Em chào anh
Anh ơi, VBA em thì mù tịt nên em áp dụng đoạn code này của anh hoài mà vẫn chưa được :(
Cụ thể là em cần áp dụng cho bảng dữ liệu tầm 10000 dòng + bảng dữ liệu nằm ở 1 sheet riêng, bảng báo cáo nằm ở 1 sheet riêng (như file đính kèm), em viết rõ thiết kế và yêu cầu trong file anh giúp em hoàn thiện với nhé.
Em cảm ơn rất nhiều !
Bạn nhập kết quả bằng tay và gởi lại file
 
10000 dòng dùng từng Function cũng khá chậm, bạn tạo sheet báo cáo đúng vị trí cột dòng mình sẽ viết sub chạy nhanh hơn
Sheet Bao Cao của em cấu trúc và vị trí sẽ giống y nguyên như trong file Test anh à!
Anh xây dựng sub theo vị trí cột dòng y như vậy là được anh nhé :)
 
Sheet Bao Cao của em cấu trúc và vị trí sẽ giống y nguyên như trong file Test anh à!
Anh xây dựng sub theo vị trí cột dòng y như vậy là được anh nhé :)
Nhập điều kiện vào các ô màu vàng code sẽ chạy, qui ước bỏ trống là lấy tất cả
Mã:
Dim sArr(), tArr(), cArr(), eRow As Long, sRow As Long
Dim Ten As String, Thang As Long

Private Sub Worksheet_Change(ByVal Target As Range)
  Dim i As Long
  If Target.Address(0, 0) = "A2" Or _
      Not Intersect(Target, Range("B13:E13")) Is Nothing Then
    With Sheets("THANG 4")
      i = .Range("D" & Rows.Count).End(xlUp).Row
      If i < 2 Then MsgBox ("Khong co du lieu"): Exit Sub
      If i <> eRow Then eRow = i: Call Create_sArr
    End With
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Ten = UCase(Range("A2").Value)
    Thang = Range("A4").Value
    If Target.Address(0, 0) = "A2" Then
      Call TongHop
      Call Chitiet
    ElseIf Not Intersect(Target, Range("B13:E13")) Is Nothing Then
      Call Chitiet
    End If
  End If
  Application.ScreenUpdating = True
  Application.EnableEvents = True
End Sub

Private Sub TongHop()
  Dim Res(1 To 9, 1 To 1), i As Long, n As Long, d As Long
  For i = 1 To sRow
    If Month(sArr(i, 7)) = Thang Then
      If Len(Ten) = 0 Or sArr(i, 3) = Ten Then
        If Mid(sArr(i, 9), 1, 1) = "1" Then d = 0 Else d = 3
        For n = 2 To 3
          If sArr(i, 1) = UCase(tArr(n, 1)) Then
            Res(n + d, 1) = Res(n + d, 1) + 1
            Res(1 + d, 1) = Res(1 + d, 1) + 1
            Exit For
          End If
        Next n
        If sArr(i, 9) = "1" Then
          Res(8, 1) = Res(8, 1) + 1
        ElseIf sArr(i, 9) = "2" Then
          Res(9, 1) = Res(9, 1) + 1
        End If
      End If
    End If
  Next i
  Range("C2:C10") = Res
End Sub

Private Sub Chitiet()
  Dim Res(1 To 1, 1 To 2), i As Long
 
  For i = 1 To sRow
    If Month(sArr(i, 7)) = Thang Then
      If Len(Ten) = 0 Or sArr(i, 3) = Ten Then
        If Len(cArr(1, 2)) = 0 Or sArr(i, 1) = cArr(1, 2) Then
          If Len(cArr(1, 3)) = 0 Or sArr(i, 5) = cArr(1, 3) Then
            If Len(cArr(1, 4)) = 0 Or sArr(i, 6) = cArr(1, 4) Then
              If (Len(cArr(1, 1)) = 0) Or (sArr(i, 9) Like cArr(1, 1) & "*") Then
                Res(1, 1) = Res(1, 1) + 1
                If Len(cArr(1, 1)) = 0 Or sArr(i, 9) = cArr(1, 1) Then Res(1, 2) = Res(1, 2) + 1
              End If
            End If
          End If
        End If
      End If
    End If
  Next i
  Range("f13:g13") = Res
End Sub

Private Sub Create_sArr()
  Dim S, Dic As Object
  Dim i As Long
  Dim Ten As String
  Const dTime As Double = 1 / 86399 '1 giay
 
  With Sheets("Bao cao")
    tArr = .Range("B2:B10").Value
    cArr = .Range("B13:E13").Value
  End With
  For i = 1 To UBound(tArr)
    tArr(i, 1) = UCase(tArr(i, 1))
  Next i
  For i = 1 To UBound(cArr, 2)
    cArr(1, i) = UCase(cArr(1, i))
  Next i
  sArr = Sheets("THANG 4").Range("D2:L" & eRow).Value2
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  For i = 1 To sRow
    sArr(i, 1) = UCase(sArr(i, 1)):    sArr(i, 3) = UCase(sArr(i, 3))
    sArr(i, 5) = UCase(sArr(i, 5)):    sArr(i, 6) = UCase(sArr(i, 6))
    sArr(i, 9) = UCase(sArr(i, 9))
    If sArr(i, 9) = 1 Then
      iKey = sArr(i, 3) & "#" & sArr(i, 5) & "#" & sArr(i, 6)
      If Dic.exists(iKey) = False Then
        Dic.Add iKey, Array(sArr(i, 7))
      Else
        tmp = sArr(i, 7)
        S = Dic.Item(iKey)
        For j = 0 To UBound(S)
          If Abs(tmp - S(j)) < dTime Then sArr(i, 9) = "11": Exit For
        Next j
        ReDim Preserve S(0 To UBound(S) + 1)
        S(UBound(S)) = tmp
        Dic.Item(iKey) = S
      End If
    End If
  Next i
  Set Dic = Nothing
End Sub
 

File đính kèm

Nhập điều kiện vào các ô màu vàng code sẽ chạy, qui ước bỏ trống là lấy tất cả
Mã:
Dim sArr(), tArr(), cArr(), eRow As Long, sRow As Long
Dim Ten As String, Thang As Long

Private Sub Worksheet_Change(ByVal Target As Range)
  Dim i As Long
  If Target.Address(0, 0) = "A2" Or _
      Not Intersect(Target, Range("B13:E13")) Is Nothing Then
    With Sheets("THANG 4")
      i = .Range("D" & Rows.Count).End(xlUp).Row
      If i < 2 Then MsgBox ("Khong co du lieu"): Exit Sub
      If i <> eRow Then eRow = i: Call Create_sArr
    End With
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Ten = UCase(Range("A2").Value)
    Thang = Range("A4").Value
    If Target.Address(0, 0) = "A2" Then
      Call TongHop
      Call Chitiet
    ElseIf Not Intersect(Target, Range("B13:E13")) Is Nothing Then
      Call Chitiet
    End If
  End If
  Application.ScreenUpdating = True
  Application.EnableEvents = True
End Sub

Private Sub TongHop()
  Dim Res(1 To 9, 1 To 1), i As Long, n As Long, d As Long
  For i = 1 To sRow
    If Month(sArr(i, 7)) = Thang Then
      If Len(Ten) = 0 Or sArr(i, 3) = Ten Then
        If Mid(sArr(i, 9), 1, 1) = "1" Then d = 0 Else d = 3
        For n = 2 To 3
          If sArr(i, 1) = UCase(tArr(n, 1)) Then
            Res(n + d, 1) = Res(n + d, 1) + 1
            Res(1 + d, 1) = Res(1 + d, 1) + 1
            Exit For
          End If
        Next n
        If sArr(i, 9) = "1" Then
          Res(8, 1) = Res(8, 1) + 1
        ElseIf sArr(i, 9) = "2" Then
          Res(9, 1) = Res(9, 1) + 1
        End If
      End If
    End If
  Next i
  Range("C2:C10") = Res
End Sub

Private Sub Chitiet()
  Dim Res(1 To 1, 1 To 2), i As Long

  For i = 1 To sRow
    If Month(sArr(i, 7)) = Thang Then
      If Len(Ten) = 0 Or sArr(i, 3) = Ten Then
        If Len(cArr(1, 2)) = 0 Or sArr(i, 1) = cArr(1, 2) Then
          If Len(cArr(1, 3)) = 0 Or sArr(i, 5) = cArr(1, 3) Then
            If Len(cArr(1, 4)) = 0 Or sArr(i, 6) = cArr(1, 4) Then
              If (Len(cArr(1, 1)) = 0) Or (sArr(i, 9) Like cArr(1, 1) & "*") Then
                Res(1, 1) = Res(1, 1) + 1
                If Len(cArr(1, 1)) = 0 Or sArr(i, 9) = cArr(1, 1) Then Res(1, 2) = Res(1, 2) + 1
              End If
            End If
          End If
        End If
      End If
    End If
  Next i
  Range("f13:g13") = Res
End Sub

Private Sub Create_sArr()
  Dim S, Dic As Object
  Dim i As Long
  Dim Ten As String
  Const dTime As Double = 1 / 86399 '1 giay

  With Sheets("Bao cao")
    tArr = .Range("B2:B10").Value
    cArr = .Range("B13:E13").Value
  End With
  For i = 1 To UBound(tArr)
    tArr(i, 1) = UCase(tArr(i, 1))
  Next i
  For i = 1 To UBound(cArr, 2)
    cArr(1, i) = UCase(cArr(1, i))
  Next i
  sArr = Sheets("THANG 4").Range("D2:L" & eRow).Value2
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  For i = 1 To sRow
    sArr(i, 1) = UCase(sArr(i, 1)):    sArr(i, 3) = UCase(sArr(i, 3))
    sArr(i, 5) = UCase(sArr(i, 5)):    sArr(i, 6) = UCase(sArr(i, 6))
    sArr(i, 9) = UCase(sArr(i, 9))
    If sArr(i, 9) = 1 Then
      iKey = sArr(i, 3) & "#" & sArr(i, 5) & "#" & sArr(i, 6)
      If Dic.exists(iKey) = False Then
        Dic.Add iKey, Array(sArr(i, 7))
      Else
        tmp = sArr(i, 7)
        S = Dic.Item(iKey)
        For j = 0 To UBound(S)
          If Abs(tmp - S(j)) < dTime Then sArr(i, 9) = "11": Exit For
        Next j
        ReDim Preserve S(0 To UBound(S) + 1)
        S(UBound(S)) = tmp
        Dic.Item(iKey) = S
      End If
    End If
  Next i
  Set Dic = Nothing
End Sub
Anh @HieuCD ơi, em đã test thử file chạy rất ok nhưng em chưa hiểu một số vấn đề sau mong anh giải đáp giúp :)
Ví dụ em có nhiều sheet "THANG 1" , "THANG 2", "THANG 3",... chứ không chỉ có mỗi "THANG 4", anh xây dựng giúp em khi em đánh số tháng cụ thể vào ô A4 sheet "BAO CAO" thì nó sẽ truy dữ liệu tại sheet có tháng tương ứng với được không anh?

Đối với đoạn TRA CỨU CHI TIẾT thì em thấy nó đã chạy và chạy đúng chuẩn với tên name là KIM, nhưng khi em đổi sang tên name khác như MINH thì nó không còn chạy cho ra kết quả nữa, anh xem giúp em ạ.

Vấn đề cuối là làm thế nào em tùy chỉnh được số giây chênh lệch phục vụ việc đếm số chuyến 2 in 1 được ạ? Hiện tại em thấy như trong sub anh để là chênh lệch 1 giây, khi em đổi tăng số giây chênh lệch lên thì sub báo lỗi ạ. Anh có thể giúp em đưa việc tùy chỉnh giây chênh lệch này vào 1 ô cụ thể như ô A6 cho thuận tiện thay đổi liệu có phức tạp không anh?

Cảm ơn anh nhiều ạ!
 

File đính kèm

Anh @HieuCD ơi, em đã test thử file chạy rất ok nhưng em chưa hiểu một số vấn đề sau mong anh giải đáp giúp :)
Ví dụ em có nhiều sheet "THANG 1" , "THANG 2", "THANG 3",... chứ không chỉ có mỗi "THANG 4", anh xây dựng giúp em khi em đánh số tháng cụ thể vào ô A4 sheet "BAO CAO" thì nó sẽ truy dữ liệu tại sheet có tháng tương ứng với được không anh?

Đối với đoạn TRA CỨU CHI TIẾT thì em thấy nó đã chạy và chạy đúng chuẩn với tên name là KIM, nhưng khi em đổi sang tên name khác như MINH thì nó không còn chạy cho ra kết quả nữa, anh xem giúp em ạ.

Vấn đề cuối là làm thế nào em tùy chỉnh được số giây chênh lệch phục vụ việc đếm số chuyến 2 in 1 được ạ? Hiện tại em thấy như trong sub anh để là chênh lệch 1 giây, khi em đổi tăng số giây chênh lệch lên thì sub báo lỗi ạ. Anh có thể giúp em đưa việc tùy chỉnh giây chênh lệch này vào 1 ô cụ thể như ô A6 cho thuận tiện thay đổi liệu có phức tạp không anh?

Cảm ơn anh nhiều ạ!
Chỉnh code, ten sheet lung tung sẽ không nhận được theo tháng
Mã:
Dim sArr As Variant, tArr(), sRow As Long
Dim Ten As String

Private Sub Worksheet_Change(ByVal Target As Range)
  'On Error Resume Next
  Application.EnableEvents = False
  Application.ScreenUpdating = False
  Ten = UCase(Range("A2").Value)
  If Target.Address(0, 0) = "A4" Then
    Call ThangArr
    If TypeName(sArr) = "Variant()" Then
      Call TongHop
      Call Chitiet
    End If
  ElseIf Target.Address(0, 0) = "A2" Then
    If TypeName(sArr) <> "Variant()" Then Call ThangArr
    If TypeName(sArr) = "Variant()" Then
      Call TongHop
      Call Chitiet
    End If
  ElseIf Not Intersect(Target, Range("B13:E13")) Is Nothing Then
    If TypeName(sArr) <> "Variant()" Then Call ThangArr
    If TypeName(sArr) = "Variant()" Then Call Chitiet
  End If
  Application.ScreenUpdating = True
  Application.EnableEvents = True
End Sub

Private Sub ThangArr()
  Dim i As Long, t As Long
  t = Range("A4").Value
  For i = 1 To Sheets.Count
    If t = Val(Right(Sheets(i).Name, 2)) Then
      Call Create_sArr(Sheets(i).Name)
      Exit Sub
    End If
  Next i
  MsgBox ("Thang: " & t & " Khong ton tai")
  sArr = Empty
End Sub

Private Sub TongHop()
  Dim Res(1 To 9, 1 To 1), i As Long, n As Long, d As Long
  For i = 1 To sRow
      If Len(Ten) = 0 Or sArr(i, 3) = Ten Then
        If Mid(sArr(i, 9), 1, 1) = "1" Then d = 0 Else d = 3
        For n = 2 To 3
          If sArr(i, 1) = UCase(tArr(n, 1)) Then
            Res(n + d, 1) = Res(n + d, 1) + 1
            Res(1 + d, 1) = Res(1 + d, 1) + 1
            Exit For
          End If
        Next n
        If sArr(i, 9) = "1" Then
          Res(8, 1) = Res(8, 1) + 1
        ElseIf sArr(i, 9) = "2" Then
          Res(9, 1) = Res(9, 1) + 1
        End If
      End If
  Next i
  Range("C2:C10") = Res
End Sub

Private Sub Chitiet()
  Dim cArr(), Res(1 To 1, 1 To 2), i As Long
  cArr = Sheets("Bao cao").Range("B13:E13").Value
  For i = 1 To UBound(cArr, 2)
    cArr(1, i) = UCase(cArr(1, i))
  Next i
  For i = 1 To sRow
      If Len(Ten) = 0 Or sArr(i, 3) = Ten Then
        If Len(cArr(1, 2)) = 0 Or sArr(i, 1) = cArr(1, 2) Then
          If Len(cArr(1, 3)) = 0 Or sArr(i, 5) = cArr(1, 3) Then
            If Len(cArr(1, 4)) = 0 Or sArr(i, 6) = cArr(1, 4) Then
              If (Len(cArr(1, 1)) = 0) Or (sArr(i, 9) Like cArr(1, 1) & "*") Then
                Res(1, 1) = Res(1, 1) + 1
                If Len(cArr(1, 1)) = 0 Or sArr(i, 9) = cArr(1, 1) Then Res(1, 2) = Res(1, 2) + 1
              End If
            End If
          End If
        End If
      End If
  Next i
  Range("f13:g13") = Res
End Sub

Private Sub Create_sArr(ByVal SheetName As String)
  Dim S, Dic As Object
  Dim i As Long, Ten As String
  Dim dTime As Double
 
  With Sheets("Bao cao")
    tArr = .Range("B2:B10").Value
    dTime = Range("A6").Value
    If IsNumeric(dTime) Then
      dTime = .Range("A6").Value / 86399
    Else
      dTime = 1 / 86399 'Mac dinh 1 giay
    End If
  End With
  For i = 1 To UBound(tArr)
    tArr(i, 1) = UCase(tArr(i, 1))
  Next i
 
  With Sheets(SheetName)
    sArr = .Range("D2:L" & .Range("D" & Rows.Count).End(xlUp).Row).Value2
  End With
  sRow = UBound(sArr)
  Set Dic = CreateObject("scripting.dictionary")
  For i = 1 To sRow
    sArr(i, 1) = UCase(sArr(i, 1)):    sArr(i, 3) = UCase(sArr(i, 3))
    sArr(i, 5) = UCase(sArr(i, 5)):    sArr(i, 6) = UCase(sArr(i, 6))
    sArr(i, 9) = UCase(sArr(i, 9))
    If sArr(i, 9) = 1 Then
      iKey = sArr(i, 3) & "#" & sArr(i, 5) & "#" & sArr(i, 6)
      If Dic.exists(iKey) = False Then
        Dic.Add iKey, Array(sArr(i, 7))
      Else
        tmp = sArr(i, 7)
        S = Dic.Item(iKey)
        For j = 0 To UBound(S)
          If Abs(tmp - S(j)) < dTime Then sArr(i, 9) = "11": Exit For
        Next j
        ReDim Preserve S(0 To UBound(S) + 1)
        S(UBound(S)) = tmp
        Dic.Item(iKey) = S
      End If
    End If
  Next i
  Set Dic = Nothing
End Sub
 

File đính kèm

Thử:
Mã:
=SUMPRODUCT((A$2:A$19=G2)*(B$2:B$19=--RIGHT(H2))/MMULT(COUNTIFS(A$2:A$19,A$2:A$19,B$2:B$19,B$2:B$19,C$2:C$19,C$2:C$19+{0,1,-1}*1/86400,D$2:D$19,D$2:D$19,E$2:E$19,E$2:E$19),{1;1;1}))
E xem mãi mới hiểu được công thức này của bác chứ đừng nói là nghĩ ra =)))
Cám ơn các bác nhé!
 

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

Back
Top Bottom