Tìm số lượng công nhân tăng, giảm hàng tháng

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

tam8678

Đời Xá Chi
Tham gia
30/4/09
Bài viết
417
Được thích
301
Nghề nghiệp
Kế toán
Mong các anh, em trên GPE xem và hướng dẩn giúp, tìm số lượng tăng giảm công nhân hàng tháng.
Cụ thể trong file đính kèm
 

File đính kèm

Upvote 0
Hai trong 1 đây, xin mời mại zô!

PHP:
Option Explicit
Sub SoTangGiam()
 Dim tRng As Range, sRng As Range, Clls As Range, Rng0 As Range, xRng As Range
 Dim jJ As Byte
  
 Set sRng = Range([c4], [c65500].End(xlUp))
 Set tRng = Range([b4], [b65500].End(xlUp))
 For jJ = 1 To 2
   Set xRng = Choose(jJ, [D4], [e4])
   Range(xRng, xRng.End(xlDown)).ClearContents
   For Each Clls In Choose(jJ, sRng, tRng)
      Set Rng0 = Choose(jJ, tRng, sRng).Find(Clls.Value, , xlFormulas, xlWhole)
      If Rng0 Is Nothing Then _
         Choose(jJ, [D65500], [e65500]).End(xlUp).Offset(1).Value = Clls.Value
   Next Clls
 Next jJ
End Sub
 
Upvote 0
Đến : Anh ChanhTQ@
Hơn 1 lần nhấn nút " Cám Ơn "
Đọc mà không hiểu thì mong anh hướng dẩn.
 
Upvote 0
PHP:
Option Explicit
Sub SoTangGiam()
 Dim tRng As Range, sRng As Range, Clls As Range, Rng0 As Range, xRng As Range
 Dim jJ As Byte
 
 Set sRng = Range([c4], [c65500].End(xlUp))
 Set tRng = Range([b4], [b65500].End(xlUp))
 For jJ = 1 To 2
   Set xRng = Choose(jJ, [D4], [e4])
   Range(xRng, xRng.End(xlDown)).ClearContents
   For Each Clls In Choose(jJ, sRng, tRng)
      Set Rng0 = Choose(jJ, tRng, sRng).Find(Clls.Value, , xlFormulas, xlWhole)
      If Rng0 Is Nothing Then _
         Choose(jJ, [D65500], [e65500]).End(xlUp).Offset(1).Value = Clls.Value
   Next Clls
 Next jJ
End Sub
-----------
Nếu được thì nhờ anh xem và sửa giúp 1 lần nửa.
Đính kèm file
 

File đính kèm

Upvote 0
-----------
Nếu được thì nhờ anh xem và sửa giúp 1 lần nửa.
Đính kèm file
Thử code này xem:
PHP:
Sub Compare2List()
  Dim List1 As Range, List2 As Range, Cll1 As Range, Cll2 As Range
  Dim Dic1, Dic2, Dic3
  Set Dic1 = CreateObject("Scripting.Dictionary")
  Set Dic2 = CreateObject("Scripting.Dictionary")
  Set Dic3 = CreateObject("Scripting.Dictionary")
  Set List1 = Range([B4], [B65536].End(xlUp))
  Set List2 = Range([C4], [C65536].End(xlUp))
  Range("D4:F60000").ClearContents
  With Application.WorksheetFunction
    For Each Cll1 In List1
      If .CountIf(List2, Cll1) Then
        Dic1.Add Cll1, Cll1
      Else
        Dic3.Add Cll1, Cll1
      End If
    Next Cll1
    For Each Cll2 In List2
      If .CountIf(List1, Cll2) = 0 Then
        Dic2.Add Cll2, Cll2
      End If
    Next Cll2
    Range("D4").Resize(Dic1.Count) = .Transpose(Dic1.Keys)
    Range("E4").Resize(Dic2.Count) = .Transpose(Dic2.Keys)
    Range("F4").Resize(Dic3.Count) = .Transpose(Dic3.Keys)
  End With
End Sub
Add toàn bộ những gì tìm được vào Dictionary Object, sau đó "quăng ra" bảng tính 1 lần duy nhất ---> Tôi nghĩ cách này cho tốc độ nhanh hơn (thay vì tìm đến đâu, "quăng" đến nấy)
 

File đính kèm

Upvote 0
To : NDU
Rất cám ơn sự nhiệt tình của bạn. Ý tôi là như thế này:
Code của anh ChanhTQ tôi đọc còn hiểu lờ mờ chút đỉnh, của NDU thì....mù tịt.
Bạn giúp tôi ( xin phép anh ChanhTQ trước ) thêm, sửa trên đoạn code của anh ChanhTQ để tôi: trước mắt xử dụng cho công việc, sau đó ( so sánh trước và sau ) để học, để có thể áp dụng vào việc khác ( không lẽ mỗi chút mỗi hỏi ).
Mong tin bạn.
 
Upvote 0
To : NDU
Rất cám ơn sự nhiệt tình của bạn. Ý tôi là như thế này:
Code của anh ChanhTQ tôi đọc còn hiểu lờ mờ chút đỉnh, của NDU thì....mù tịt.
Bạn giúp tôi ( xin phép anh ChanhTQ trước ) thêm, sửa trên đoạn code của anh ChanhTQ để tôi: trước mắt xử dụng cho công việc, sau đó ( so sánh trước và sau ) để học, để có thể áp dụng vào việc khác ( không lẽ mỗi chút mỗi hỏi ).
Mong tin bạn.
Vì bài trước bạn yêu cầu khác: Từ 2 list lọc ra 2 list nên sư phụ dùng hàm CHOOSE để gôm lại (cho gọn)
Bây giờ hơi khác 1 chút: Từ 2 list lọc ra 3 list nên không thể CHOOSE được, phải dùng 2 vòng lập riêng biệt
Tôi sửa trên code của sư phụ cho bạn đây:
PHP:
Sub SoTangGiam()
 Dim tRng As Range, sRng As Range, Clls As Range
 Set tRng = Range([B4], [B65500].End(xlUp))
 Set sRng = Range([C4], [C65500].End(xlUp))
 Range("D4:F65000").ClearContents
 For Each Clls In sRng
   If tRng.Find(Clls.Value, , xlFormulas, xlWhole) Is Nothing Then
      [E65500].End(xlUp).Offset(1).Value = Clls.Value
    Else
      [D65500].End(xlUp).Offset(1).Value = Clls.Value
    End If
  Next Clls
  For Each Clls In tRng
   If sRng.Find(Clls.Value, , xlFormulas, xlWhole) Is Nothing Then
      [F65500].End(xlUp).Offset(1).Value = Clls.Value
    End If
  Next Clls
End Sub
Thật ra thuật toán của tôi và sư phụ là giống nhau, chỉ khác về chi tiết quá trình:
- Sư phụ dùng Find để tìm, tôi dùng COUNTIF
- Khi tìm được, sư phụ cho nó vào cell luôn (tức tìm đến đâu ra kết quả đến nấy)... Còn tôi thì cho giá trị tìm được vào Dictionary Object (như thêm từ điển vậy)... Đến cuối quá trình mới cho toàn bộ vào bảng tính
 
Upvote 0
Vẫn cố đấm ăn sôi đây, xin mời tham khảo

PHP:
Option Explicit
Sub SoTangGiam()
 Dim tRng As Range, sRng As Range, Clls As Range, Rng0 As Range, xRng As Range
 Dim jJ As Long
  
 Set sRng = Range([c4], [c65500].End(xlUp))
 Set tRng = Range([b4], [b65500].End(xlUp))
 jJ = sRng.Rows.Count + tRng.Rows.Count
 [D4].Resize(jJ, 3).ClearContents
 For jJ = 1 To 2
   Set xRng = Choose(jJ, [E4], [F4])
   For Each Clls In Choose(jJ, sRng, tRng)
      Set Rng0 = Choose(jJ, tRng, sRng).Find(Clls.Value, , xlFormulas, xlWhole)
      If Rng0 Is Nothing Then
         Choose(jJ, [e65500], [F65500]).End(xlUp).Offset(1).Value = Clls.Value
      Else
         If jJ = 1 Then _
            [D65500].End(xlUp).Offset(1).Value = Clls.Value
      End If
   Next Clls
 Next jJ
End Sub

Thật ra thuật toán của tôi và sư phụ là giống nhau, chỉ khác về chi tiết:
- Dùng Find / COUNTIF
- Khi tìm được, sư cho nó vào cell luôn (tức tìm đến đâu ra kết quả đến nấy)... Còn tôi thì cho giá trị tìm được vào Dictionary Object (như thêm từ điển vậy)... Đến cuối quá trình mới cho toàn bộ vào bảng tính

Chưa thực nghiệm có quyền chưa tin 'Ai nhanh hơn ai!" :-= --=0 --=0
 
Upvote 0
Chưa thực nghiệm có quyền chưa tin 'Ai nhanh hơn ai!" :-= --=0 --=0
Em chắc ăn 100% vì đã thử nghiệm rồi:
- Find chậm hơn COUNTIF và MATCH
- Cho dử liệu tìm được vào mãng, sau đó mới ra kết quả ở cuối quá trình sẽ nhanh hơn so với cách tìm và ra kết quả ngay
- Có người nói rằng MATCH nhanh hơn COUNTIF ---> Em thí nghiệm trên vài chục ngàn dòng, thấy chẳng khác gì
 
Upvote 0
Mong các anh, em trên GPE xem và hướng dẩn giúp, tìm số lượng tăng giảm công nhân hàng tháng.
Cụ thể trong file đính kèm
Tôi vừa phát hiện ra 1 cách cực kỳ đơn giàn, dùng Advanced Filter... Bạn làm như sau:
1> Chỉnh lại bảng tính như hình dưới đây

attachment.php


Tức xóa công thức ở dòng 3 và gõ vào tiêu đề cột
2> Công thức của ĐK1, ĐK2ĐK3 là:
PHP:
=COUNTIF($C$4:$C$18,$B4)>0
PHP:
=COUNTIF($B$4:$B$16,$C4)=0
PHP:
=COUNTIF($C$4:$C$18,$B4)=0
3> Dùng Advanced Filter, Lọc List1 theo DK1... Lọc List2 theo DK2lọc List1 theo DK3
Vậy là xong!
Nếu không muốn làm bằng tay, ta cũng có thể viết code dựa trên cách làm này
PHP:
Sub Compare2List()
  Dim List1 As Range, List2 As Range
  Dim Dk1 As Range, Dk2 As Range, Dk3 As Range
  Set List1 = Range([B3], [B65536].End(xlUp))
  Set List2 = Range([C3], [C65536].End(xlUp))
  Set Dk1 = Range("H3:H4")
  Set Dk2 = Range("I3:I4")
  Set Dk3 = Range("J3:J4")
  List1.AdvancedFilter 2, Dk1, [D3]
  List2.AdvancedFilter 2, Dk2, [E3]
  List1.AdvancedFilter 2, Dk3, [F3]
End Sub
Bảo đảm ĐƠN GIẢN và NHANH
 

File đính kèm

Upvote 0
Trích NDU:
Tôi vừa phát hiện ra 1 cách cực kỳ đơn giàn, dùng Advanced Filter...
Rất trân trọng ý kiến của bạn .
Còn tôi cũng vừa phát hiện ra 1 lỗi cũng cực kỳ đơn giản:
- Trong trường hợp số thẻ (ST) vừa tăng, xong rồi lại giảm trong cùng 1 kỳ. Cụ thể là ST vào ngày 2, nghĩ vào ngày 20 chẳng hạn thì làm gì có trong bảng lương tháng ?
- Ghi chú:
* Lương nghỉ việc thanh toán 1 tháng 2 lần vào các ngày 15 và 2
* Lương bình thường vào ngày 5 của tháng sau
* ST : được đánh liên tục từ thấp đến cao.
Bạn có cao kiến gì không ? ( mời bạn uống cafe nhé )
 
Upvote 0
Trích NDU:
Tôi vừa phát hiện ra 1 cách cực kỳ đơn giàn, dùng Advanced Filter...
Rất trân trọng ý kiến của bạn .
Còn tôi cũng vừa phát hiện ra 1 lỗi cũng cực kỳ đơn giản:
- Trong trường hợp số thẻ (ST) vừa tăng, xong rồi lại giảm trong cùng 1 kỳ. Cụ thể là ST vào ngày 2, nghĩ vào ngày 20 chẳng hạn thì làm gì có trong bảng lương tháng ?
- Ghi chú:
* Lương nghỉ việc thanh toán 1 tháng 2 lần vào các ngày 15 và 2
* Lương bình thường vào ngày 5 của tháng sau
* ST : được đánh liên tục từ thấp đến cao.
Bạn có cao kiến gì không ? ( mời bạn uống cafe nhé )
Giải thuật dựa trên cơ sơ dử liệu thật mà ra... Vì vậy, để có được cách tính toán chính xác tôi cần dử liệu nhập của bạn, cụ thể phải có những trường hợp đặc biệt như bạn vừa nói trong file ---> Từ đó nghiên cứu và tìm giải thuật chính xác!
 
Upvote 0
Giải thuật dựa trên cơ sơ dử liệu thật mà ra... Vì vậy, để có được cách tính toán chính xác tôi cần dử liệu nhập của bạn, cụ thể phải có những trường hợp đặc biệt như bạn vừa nói trong file ---> Từ đó nghiên cứu và tìm giải thuật chính xác!
--------
Đã soát, xét lại quá trình nhập liệu.Nhờ các anh em GPE xem giúp ( lại phiền đến NDU)
Đính kèm file ( lần thứ 3 )
 

File đính kèm

Upvote 0
--------
Đã soát, xét lại quá trình nhập liệu.Nhờ các anh em GPE xem giúp ( lại phiền đến NDU)
Đính kèm file ( lần thứ 3 )
Theo như những gì bạn trình bày trong file thì:
- Ta chỉ cần tìm những số thể ổn định và số thẻ tăng
- Số thẻ giảm chính là cột D (số thể nghỉ việc)
Đúng không?
Tôi đề xuất code này:
PHP:
Sub Compare2List()
  Dim List1 As Range, List2 As Range, List3 As Range
  Dim Cll1 As Range, Cll2 As Range, Dic1, Dic2
  On Error Resume Next
  Set Dic1 = CreateObject("Scripting.Dictionary")
  Set Dic2 = CreateObject("Scripting.Dictionary")
  Set List1 = Range([B4], [B65536].End(xlUp))
  Set List2 = Range([C4], [C65536].End(xlUp))
  Set List3 = Range([D4], [D65536].End(xlUp))
  Range("E4:G60000").ClearContents
  With Application
    For Each Cll1 In List1.SpecialCells(2)
      If .CountIf(List2, Cll1) Then Dic1.Add Cll1, Cll1
    Next Cll1
    For Each Cll2 In List2.SpecialCells(2)
      If .CountIf(List1, Cll2) = 0 Then Dic2.Add Cll2, Cll2
    Next Cll2
    Range("E4").Resize(Dic1.Count) = .Transpose(Dic1.Keys)
    Range("F4").Resize(Dic2.Count) = .Transpose(Dic2.Keys)
    List3.SpecialCells(2).Copy: Range("G4").PasteSpecial 3
    .CutCopyMode = False
  End With
End Sub
Ngoài ra bạn vẫn có thể áp dụng Advanced Filter để tìm số thẻ ổn định và số thẻ tăng, riêng số thẻ giảm ta vẫn dùng cách copy từ cột D sang cột G
Ghi chú: Tôi dùng SpecialCells(2) với mục đích chỉ duyệt qua các cell có dử liệu (bỏ qua các cell rổng) ---> Như vậy sẽ tăng tốc độ làm việc cho code
 
Upvote 0
To: NDU
Có gì không phải thì RẤT MONG bạn bỏ qua.
Tôi xin nói thẳng : tôi là dân học kế toán, học excel cùa các trung tâm ( Biên Hòa ) được 1 tháng, Code trước của bạn dùng 2 vòng lặp thì tôi hiểu được ít nhiều ( rất quý ), bạn tuần tự thì tôi theo được ( dù rằng code có chậm nhưng tôi vẫn thích, tôi chấp nhận tôi dốt, nhưng tôi hiểu vấn đề), bạn cao quá thì tôi thua (đọc không nổi ), bạn viết tầm tầm thôi để tôi còn thở, bạn có thể xử dụng hàm find để giải quyết vấn đề này được không ?
Trích:
- Ta chỉ cần tìm những số thể ổn định và số thẻ tăng => chính xác
- Số thẻ giảm chính là cột D (số thể nghỉ việc) => Chính xác, nhưng có thể sắp xếp cùng 1 Số thẻ thì cùng 1 dòng được không bạn nhỉ ( như trong file đính kèm, vì việc này liên quan đến phân tích dữ liệu : lý do tại sao vừa nhận việc lại nghĩ..., từ số thẻ còn liên quan đến các tổ, mức độ ổn định của các tổ sản xuất ....)

Tôi thật sự rất trân trọng sự nhiệt tình của bạn và anh ChanhTQ@, không phải diển đàn nào cũng có được những thành viên như thế.
Có gì không phải thì RẤT MONG bạn bỏ qua.
 
Upvote 0
To: NDU
Có gì không phải thì RẤT MONG bạn bỏ qua.
Tôi xin nói thẳng : tôi là dân học kế toán, học excel cùa các trung tâm ( Biên Hòa ) được 1 tháng, Code trước của bạn dùng 2 vòng lặp thì tôi hiểu được ít nhiều ( rất quý ), bạn tuần tự thì tôi theo được ( dù rằng code có chậm nhưng tôi vẫn thích, tôi chấp nhận tôi dốt, nhưng tôi hiểu vấn đề), bạn cao quá thì tôi thua (đọc không nổi ), bạn viết tầm tầm thôi để tôi còn thở, bạn có thể xử dụng hàm find để giải quyết vấn đề này được không ?
Trích:
- Ta chỉ cần tìm những số thể ổn định và số thẻ tăng => chính xác
- Số thẻ giảm chính là cột D (số thể nghỉ việc) => Chính xác, nhưng có thể sắp xếp cùng 1 Số thẻ thì cùng 1 dòng được không bạn nhỉ ( như trong file đính kèm, vì việc này liên quan đến phân tích dữ liệu : lý do tại sao vừa nhận việc lại nghĩ..., từ số thẻ còn liên quan đến các tổ, mức độ ổn định của các tổ sản xuất ....)

Tôi thật sự rất trân trọng sự nhiệt tình của bạn và anh ChanhTQ@, không phải diển đàn nào cũng có được những thành viên như thế.
Có gì không phải thì RẤT MONG bạn bỏ qua.
Vâng! Không có gì đâu bạn à, vì trước đây tôi cũng vậy thôi: Chỉ áp dụng cái nào ta hiểu được, cái gì không hiểu sẽ không áp dụng... Ẹc... Ẹc...
Có điều tôi thấy cái Dictionary Object này nó quá đơn giản và dùng nó xử lý mãng là vô địch ---> Vì thế mà áp vào bài này (tôi đọc Help và hiểu được nguyên lý, tôi nghĩ bạn chắc cũng sẽ thừa hiểu)
Về vấn đề bạn yêu cầu:
nhưng có thể sắp xếp cùng 1 Số thẻ thì cùng 1 dòng được không bạn nhỉ
Nếu vậy thật sự quá đơn giản nếu ta dùng công thức:
Ví dụ:
PHP:
E4 =IF(COUNTA(B4:C4)=2,B4,"")
PHP:
F4 =IF(AND(B4="",C4<>""),C4,"")
PHP:
G4 =IF(D4="","",D4)
Bạn nghĩ sao?
-------------------
Tôi xin nói thẳng : tôi là dân học kế toán, học excel cùa các trung tâm ( Biên Hòa )
Vậy chắc nhà bạn ở Biên Hòa?
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy chắc nhà bạn ở Biên Hòa?
Đúng vậy, tôi dân BH,ở BH, không biết NDU ở đâu ?
Tôi đã kiểm tra code của NDU, chắc có lẻ do tôi trình bày trong file không được rỏ ràng nên code NDU viết kết quả không được như mong muốn. Các số thẻ vừa tăng, vừa giảm chỉ ra được kết quả giảm mà không có tăng ( khi có kết quả thì có thể sắp xếp những trường hợp này cùng 1 dòng được không ?)
Đính kèm file
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Vậy chắc nhà bạn ở Biên Hòa?
Đúng vậy, tôi dân BH,ở BH, không biết NDU ở đâu ?
Tôi đã kiểm tra code của NDU, chắc có lẻ do tôi trình bày trong file không được rỏ ràng nên code NDU viết kết quả không được như mong muốn. Các số thẻ vừa tăng, vừa giảm chỉ ra được kết quả giảm mà không có tăng ( khi có kết quả thì có thể sắp xếp những trường hợp này cùng 1 dòng được không ?)
Đính kèm file
Tôi đã hiểu ý bạn rồi ---> Mấu chốt nằm ở chổ các số thẻ giống nhau nằm trên 1 hàng, vì thế mà tôi đưa ra công thức
Nếu bạn muốn dùng code, tôi đề xuất:
PHP:
Sub Test()
  With Range([C4], [C65536].End(xlUp))
    .Offset(, 2).Value = "=IF(COUNTA(RC[-3]:RC[-2])=2,RC[-3],"""")"
    .Offset(, 3).Value = "=IF(AND(RC[-4]="""",RC[-3]<>""""),RC[-3],IF(AND(RC[-4]="""",RC[-2]<>""""),RC[-2],""""))"
    .Offset(, 4).Value = "=IF(RC[-3]="""","""",RC[-3])"
    With .Offset(, 2).Resize(, 3)
      .Value = .Value
    End With
  End With
End Sub
Đơn giản là tôi cho công thức ấy vào code
Bạn test lại thử
(Tôi cũng ở Biên Hòa luôn ---> Có thể uống cafe được đấy... ẹc... ẹc...)
 

File đính kèm

Upvote 0
Viết sao cho NDU hiểu. Bạn cố gắng giúp tôi vậy thì hãy mường tượng như thế này NDU hởi :
- Mở file " Số công nhân tăng giảm lần 3 "
- Các cột từ B4 đến B...,C4 đến C..., D4 đến D...là khu vực nhập liệu, các số thẻ không nằm ngay ngắn và theo thứ tự từ thấp đến cao, không có khoảng trắng
- Tôi trình bày trong file trước là đã sắp xếp cho dể hiểu thôi
File đính kèm
( Số thẻ đến thời điểm này là 900 - không dùng hàm choose được phải không ?)
(Tôi cũng ở Biên Hòa luôn ---> Có thể uống cafe được đấy... ẹc... ẹc...)
NDU ở phường nào ? Sao lại có thể uống cafe ? , bình thường thôi
Chúc mệt mà vui ( đừng có nổi quạo nhé)
 

File đính kèm

Upvote 0
Web KT

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

Back
Top Bottom