Nhờ viết code VBA cộng dồn các ký tự theo điều kiện

Liên hệ QC

hoangruazbin

Thành viên mới
Tham gia
27/6/19
Bài viết
32
Được thích
3
- Nhân dịp năm mới Canh Tý, kính chúc các trong diễn đàn luôn Mạnh khỏe - Hạnh phúc - Vạn sự như ý!
- Em muốn nhờ các Anh/Chị trong diễn đàn giúp viết code VBA để tổng hợp số ngày nghỉ của từng người theo mô tả trong file đính kèm. Do mỗi tháng phải làm một file khác nhau (thông thường 1 năm có 12 file) và nhân viên thỉnh thoảng cũng có sự luân chuyển sang các bộ phận khác nhau nên việc làm bằng công thức đơn thuần đối với em rất khó khăn, Em cũng đã tìm hiểu nhiều bài viết trên diễn đàn nhưng chưa thấy nội dung nào phù hợp, rất mong các Anh/Chị giúp đỡ, em cảm ơn rất nhiều.
 

File đính kèm

Tại sao mỗi tháng phải 1 file; Sao không là 12 trang tính cho 1 năm?
 
Upvote 0
Tại sao mỗi tháng phải 1 file; Sao không là 12 trang tính cho 1 năm?
Tại mỗi tháng em có một số báo cáo chốt số liệu vào thời điểm ngày cuối cùng của tháng. Nếu làm 12 trang tính cho 12 tháng thì rất khó kiểm soát khi các báo cáo vì dữ liệu có link đến nhau (em làm chủ yếu bằng công thức, chưa biết nhiều về VBA), rất mong Anh nghiên cứu giúp em.
 
Upvote 0
Bạn tham khảo cách mình thực hiện file
Trước hết cảm ơn Anh đã quan tâm giúp đỡ, mặc dù đơn giản tuy nhiên vẫn chưa đúng theo yêu cầu của em.
Để thuận tiện cho việc viết code, em sẽ làm thủ công copy thành 12 trang tính trong 01 sheet, nhờ Anh giúp cộng dồn vào 01 trang tong_hop. Vấn đề thứ 2 là khi cộng dồn kết quả bằng số (tổng số ngày có cùng ký hiệu: VD: Nguyễn Văn A ngày 01/01/2020: F, Ngày 02/01/2020: F --> tổng hợp từ ngày 01/01 đến 02/01/2020 = 2).
Em gửi lại file đính kèm rất mong Anh giúp đỡ.
 

File đính kèm

Upvote 0
Em xin diễn giải chi tiết hơn mong các anh giúp:
- Em có 12 sheet tương ứng với 12 tháng trong năm. Trong mỗi sheet bao gồm cột tên nhân viên, cột phòng/ban/xưởng sản xuất và cột các ngày làm việc trong tháng (bắt đầu từ ngày 26 của tháng trước đến ngày 25 của tháng sau). Trong các cột ngày trong tháng sẽ theo dõi lý do vắng mặt của từng nhân viên tương ứng với các ký hiệu bằng chữ: F (Phép), O (Ốm), H (Học), TN (Tai nạn), KP (Không phép), …
- Mục tiêu tại sheet “tonghop”:
+ Tổng hợp được tổng số lần vắng mặt (bằng cách cộng dồn các ký tự nêu trên) của mỗi nhân viên trong khoảng thời gian lựa chọn (từ ngày … đến ngày …) vào các cột tương ứng, kết quả thể hiện bằng số - không phải chữ.
+ Do các nhân viên thỉnh thoảng luân chuyển đến các bộ phận khác nhau (tuy nhiên ngày điều chuyển luôn tính từ ngày đầu tháng) nên kết quả dò tìm phải thể hiện được nhân viên đó đang ở bộ phận nào vào ngày cuối cùng khi lựa chọn (bảo lưu những ngày nghỉ trước đó khi ở các bộ phận khác).
Rất mong các Anh giúp đỡ, cảm ơn rất nhiều!
 
Upvote 0
Em xin diễn giải chi tiết hơn mong các anh giúp:
- Em có 12 sheet tương ứng với 12 tháng trong năm. Trong mỗi sheet bao gồm cột tên nhân viên, cột phòng/ban/xưởng sản xuất và cột các ngày làm việc trong tháng (bắt đầu từ ngày 26 của tháng trước đến ngày 25 của tháng sau). Trong các cột ngày trong tháng sẽ theo dõi lý do vắng mặt của từng nhân viên tương ứng với các ký hiệu bằng chữ: F (Phép), O (Ốm), H (Học), TN (Tai nạn), KP (Không phép), …
- Mục tiêu tại sheet “tonghop”:
+ Tổng hợp được tổng số lần vắng mặt (bằng cách cộng dồn các ký tự nêu trên) của mỗi nhân viên trong khoảng thời gian lựa chọn (từ ngày … đến ngày …) vào các cột tương ứng, kết quả thể hiện bằng số - không phải chữ.
+ Do các nhân viên thỉnh thoảng luân chuyển đến các bộ phận khác nhau (tuy nhiên ngày điều chuyển luôn tính từ ngày đầu tháng) nên kết quả dò tìm phải thể hiện được nhân viên đó đang ở bộ phận nào vào ngày cuối cùng khi lựa chọn (bảo lưu những ngày nghỉ trước đó khi ở các bộ phận khác).
Rất mong các Anh giúp đỡ, cảm ơn rất nhiều!
Gởi lại file với các sheet tháng có đủ các cột ngày
 
Upvote 0
Em xin diễn giải chi tiết hơn mong các anh giúp:
- Em có 12 sheet tương ứng với 12 tháng trong năm. Trong mỗi sheet bao gồm cột tên nhân viên, cột phòng/ban/xưởng sản xuất và cột các ngày làm việc trong tháng (bắt đầu từ ngày 26 của tháng trước đến ngày 25 của tháng sau). Trong các cột ngày trong tháng sẽ theo dõi lý do vắng mặt của từng nhân viên tương ứng với các ký hiệu bằng chữ: F (Phép), O (Ốm), H (Học), TN (Tai nạn), KP (Không phép), …
- Mục tiêu tại sheet “tonghop”:
+ Tổng hợp được tổng số lần vắng mặt (bằng cách cộng dồn các ký tự nêu trên) của mỗi nhân viên trong khoảng thời gian lựa chọn (từ ngày … đến ngày …) vào các cột tương ứng, kết quả thể hiện bằng số - không phải chữ.
+ Do các nhân viên thỉnh thoảng luân chuyển đến các bộ phận khác nhau (tuy nhiên ngày điều chuyển luôn tính từ ngày đầu tháng) nên kết quả dò tìm phải thể hiện được nhân viên đó đang ở bộ phận nào vào ngày cuối cùng khi lựa chọn (bảo lưu những ngày nghỉ trước đó khi ở các bộ phận khác).
Rất mong các Anh giúp đỡ, cảm ơn rất nhiều!
Theo ý kiến cá nhân của mình thì bạn cần chú ý các vấn đề sau

1. Sheet tonghop phải chứa đầy đủ thông tin của tất cả nhân viên
2. Quản lý nhân viên bằng mã code chứ không được quản lý bằng tên. Nếu trùng họ tên và làm chung bộ phận nữa thì loạn corona là cái chắc

Có đủ các điều kiện trên thì việc viết code cũng đơn giản
 
Upvote 0
Theo ý kiến cá nhân của mình thì bạn cần chú ý các vấn đề sau

1. Sheet tonghop phải chứa đầy đủ thông tin của tất cả nhân viên
2. Quản lý nhân viên bằng mã code chứ không được quản lý bằng tên. Nếu trùng họ tên và làm chung bộ phận nữa thì loạn corona là cái chắc

Có đủ các điều kiện trên thì việc viết code cũng đơn giản
- Cảm ơn ý kiến của Anh, nhưng em mong muốn sheet tổng hợp lấy được sự thay đổi của nhân viên ở từng thời điểm lựa chọn (do bên em cũng hay điều động NV đi các bộ phận khác nhau).
- Em đã bổ sung mã nhân viên theo ý kiến của Anh, nhờ Anh giúp em nhé.

Gởi lại file với các sheet tháng có đủ các cột ngày
Em gửi file đã chỉnh sửa, nhờ anh xem giúp. Cảm ơn Anh!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Bạn thử kiểm 3 cột đâu (theo đơn vị cuối kỳ) xem đúng chưa nha.
Hình như chưa chuẩn, xin lỗi & sẽ tháo file
 
Lần chỉnh sửa cuối:
Upvote 0
- Cảm ơn ý kiến của Anh, nhưng em mong muốn sheet tổng hợp lấy được sự thay đổi của nhân viên ở từng thời điểm lựa chọn (do bên em cũng hay điều động NV đi các bộ phận khác nhau).
- Em đã bổ sung mã nhân viên theo ý kiến của Anh, nhờ Anh giúp em nhé.


Em gửi file đã chỉnh sửa, nhờ anh xem giúp. Cảm ơn Anh!
Code tạm thế này, còn thiếu mấy dòng tổng cộng của từng bộ phận. Bạn tham khảo nhé
 

File đính kèm

Upvote 0
- Cảm ơn ý kiến của Anh, nhưng em mong muốn sheet tổng hợp lấy được sự thay đổi của nhân viên ở từng thời điểm lựa chọn (do bên em cũng hay điều động NV đi các bộ phận khác nhau).
- Em đã bổ sung mã nhân viên theo ý kiến của Anh, nhờ Anh giúp em nhé.


Em gửi file đã chỉnh sửa, nhờ anh xem giúp. Cảm ơn Anh!
Code khá dài
Mã:
Sub TongHop()
  Dim maNV(), sArr(), Res(), Arr, Dic As Object, shMain As Worksheet, sh As Worksheet
  Dim i&, ik&, j&, jk&, sRow&, sCol&, eRow&
  Dim shName$, iKey$
  Dim fDay, eDay, Day1, Day2, iDay
  Const strCol As String = "--F--O--H--TN-KP"
 
  Set shMain = Sheets("tonghop")
  With shMain
    fDay = .Range("E2").Value
    eDay = .Range("G2").Value
    If Not (IsDate(fDay) And IsDate(eDay)) Then MsgBox ("Thoi gian khong chuan"): Exit Sub
    eRow = .Range("C" & Rows.Count).End(xlUp).Row
    If eRow > 5 Then .Range("A6:J" & eRow).ClearContents
  End With
 
  For Each sh In Sheets
    If sh.Name <> "tonghop" Then
      Day1 = sh.Range("E2").Value
      Day2 = sh.Range("G2").Value
      If IsDate(Day1) And IsDate(Day2) Then
        If fDay <= Day2 And eDay >= Day1 Then
          If iDay < Day2 Then
            iDay = Day2
            shName = sh.Name
          End If
        End If
      End If
    End If
  Next
  If shName = "" Then MsgBox ("Khong co du lieu thoa dieu kien thoi gian"): Exit Sub
  With Sheets(shName)
    eRow = .Range("D" & Rows.Count).End(xlUp).Row
    .Range("A6:D" & eRow).Copy shMain.Range("A6")
  End With
  maNV = shMain.Range("B6:B" & eRow).Value
  sRow = UBound(maNV)
  ReDim Res(1 To sRow, 1 To 5)
  Set Dic = CreateObject("scripting.dictionary")
  For i = 3 To sRow
    iKey = maNV(i, 1)
    If iKey <> "" Then
      Dic.Item(iKey) = i
    End If
  Next i
  For Each sh In Sheets
    If sh.Name <> "tonghop" Then
      Day1 = sh.Range("E2").Value
      Day2 = sh.Range("G2").Value
      If IsDate(Day1) And IsDate(Day2) Then
        If fDay <= Day2 And eDay >= Day1 Then
          eRow = sh.Range("D" & Rows.Count).End(xlUp).Row
          sArr = sh.Range("B5:AI" & eRow).Value
          sRow = UBound(sArr)
          sCol = UBound(sArr, 2)
          For i = 4 To sRow
            ik = Dic.Item(CStr(sArr(i, 1)))
            If ik > 0 Then
              For j = 4 To sCol
                If fDay <= sArr(1, j) Then
                  If eDay >= sArr(1, j) Then
                    jk = InStr(1, strCol, CStr(sArr(i, j)))
                    If jk > 2 Then
                      jk = jk / 3
                      Res(ik, jk) = Res(ik, jk) + 1
                    End If
                  End If
                End If
              Next j
            End If
          Next i
        End If
      End If
    End If
  Next
  sRow = UBound(Res)
  sCol = UBound(Res, 2)
  For i = 2 To sRow
    If maNV(i, 1) = Empty Then
      ik = i
    Else
      For j = 1 To sCol
        If Res(i, j) <> Empty Then
          Res(ik, j) = Res(ik, j) + Res(i, j)
          Res(1, j) = Res(1, j) + Res(i, j)
        End If
      Next j
    End If
  Next i
  shMain.Range("E6").Resize(sRow, sCol) = Res
End Sub
 

File đính kèm

Upvote 0
Bạn thử kiểm 3 cột đâu (theo đơn vị cuối kỳ) xem đúng chưa nha.
Hình như chưa chuẩn, xin lỗi & sẽ tháo file
Cảm ơn Anh @SA_DQ đã giúp em trong mấy ngày vừa qua.


Code tạm thế này, còn thiếu mấy dòng tổng cộng của từng bộ phận. Bạn tham khảo nhé
Cảm ơn Anh @quanghai1969 , file anh gửi em không thấy chỗ lựa chọn ngày báo cáo.


Cảm ơn Anh @HieuCD file anh gửi rất tuyệt.
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn Anh @SA_DQ đã giúp em trong mấy ngày vừa qua.



Cảm ơn Anh @quanghai1969 , file anh gửi em không thấy chỗ lựa chọn ngày báo cáo.



Cảm ơn Anh @HieuCD file anh gửi rất tuyệt.
Chỉnh lại
Mã:
Sub TongHop()
  Dim maNV(), sArr(), Res(), Arr, Dic As Object, shMain As Worksheet, sh As Worksheet
  Dim i&, ik&, j&, jk&, sRow&, sCol&, eRow&
  Dim shName$, iKey$
  Dim fDay, eDay, Day1, Day2, iDay
  Const strCol As String = ",,,,F--,O--,H--,TN-,KP-"
 
  Set shMain = Sheets("tonghop")
  With shMain
    fDay = .Range("E2").Value
    eDay = .Range("G2").Value
    If Not (IsDate(fDay) And IsDate(eDay)) Then MsgBox ("Thoi gian khong chuan"): Exit Sub
    eRow = .Range("C" & Rows.Count).End(xlUp).Row
    If eRow > 5 Then .Range("A6:J" & eRow).ClearContents
  End With
 
  For Each sh In Sheets
    If sh.Name <> "tonghop" Then
      Day1 = sh.Range("E2").Value
      Day2 = sh.Range("G2").Value
      If IsDate(Day1) And IsDate(Day2) Then
        If fDay <= Day2 And eDay >= Day1 Then
          If iDay < Day2 Then
            iDay = Day2
            shName = sh.Name
          End If
        End If
      End If
    End If
  Next
  If shName = "" Then MsgBox ("Khong co du lieu thoa dieu kien thoi gian"): Exit Sub
  With Sheets(shName)
    eRow = .Range("D" & Rows.Count).End(xlUp).Row
    .Range("A6:D" & eRow).Copy shMain.Range("A6")
  End With
  maNV = shMain.Range("B6:B" & eRow).Value
  sRow = UBound(maNV)
  ReDim Res(1 To sRow, 1 To 5)
  Set Dic = CreateObject("scripting.dictionary")
  For i = 3 To sRow
    iKey = maNV(i, 1)
    If iKey <> "" Then
      Dic.Item(iKey) = i
    End If
  Next i
  For Each sh In Sheets
    If sh.Name <> "tonghop" Then
      Day1 = sh.Range("E2").Value
      Day2 = sh.Range("G2").Value
      If IsDate(Day1) And IsDate(Day2) Then
        If fDay <= Day2 And eDay >= Day1 Then
          eRow = sh.Range("D" & Rows.Count).End(xlUp).Row
          sArr = sh.Range("B5:AI" & eRow).Value
          sRow = UBound(sArr)
          sCol = UBound(sArr, 2)
          For i = 4 To sRow
            ik = Dic.Item(CStr(sArr(i, 1)))
            If ik > 0 Then
              For j = 4 To sCol
                If fDay <= sArr(1, j) Then
                  If eDay >= sArr(1, j) Then
                    jk = InStr(1, strCol, "," & sArr(i, j) & "-")
                    If jk > 2 Then
                      jk = jk / 4
                      Res(ik, jk) = Res(ik, jk) + 1
                    End If
                  End If
                End If
              Next j
            End If
          Next i
        End If
      End If
    End If
  Next
  sRow = UBound(Res)
  sCol = UBound(Res, 2)
  For i = 2 To sRow
    If maNV(i, 1) = Empty Then
      ik = i
    Else
      For j = 1 To sCol
        If Res(i, j) <> Empty Then
          Res(ik, j) = Res(ik, j) + Res(i, j)
          Res(1, j) = Res(1, j) + Res(i, j)
        End If
      Next j
    End If
  Next i
  shMain.Range("E6").Resize(sRow, sCol) = Res
End Sub
 
Upvote 0
Upvote 0
Sau thêm 1 ngày nổ lực, mình cũng có 1 phương án giải quyết vấn đề này; Xin mới các bạn kiểm chứng giúp nha
 

File đính kèm

Upvote 0
Web KT

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

Back
Top Bottom