如何在添加到计数器之前检查行之前的单元格是否相同

时间:2017-10-14 23:01:47

标签: arrays excel excel-vba with-statement vba

我正在制作一张时间表,用于计算每位员工每周观看的小时数。我已经实施了一些代码,用于确定员工是否属于公司的一部分,未付假期,是离开公司,还是已经离开公司。

我想要做的是创建一个表格,告诉我加入者,离职者和那些按周休假的人数。

应用代码对数据进行排序后,它看起来像这样:

Data table 我用更有意义的描述替换之前存在的随机值。

我想创建一个表,该表在行中第一次添加到joiner计数器时值为No Joined'所以我不重复计数。例如,身份证1,我不想在第2周到第5周将该人计为加入者,仅在第2周。

到目前为止,这是我的代码,我在查看每列的行数,然后再转到下一列:

Dim LastCol As Long
Dim LastRow As Long
Dim I As Long
Dim Z As Long
Dim Q As Long
Dim Joined As Integer
Dim ws As Worksheet

'set worksheet to use
Set ws = Sheets("Sheet1")

With ws
  'Find last col and row for range
   LastCol = ws.Cells(3, Columns.Count).End(xlToLeft).Column
   LastRow = ws.Cells(Rows.Count, D).End(xlUp).Row

For I = 3 To LastCol
    NotJoined = 0
        For Z = 4 To LastRow
            'check if cell is > 0
            If ws.Cells(Z, I).Value > 0 Then
                Joined = Joined + 1
            End If
        Next Z
    'Find last row and add value to row below
    Q = ws.Cells(Rows.Count, I).End(xlUp).Row
    ws.Cells(Q + 1, I).Value = Joined
Next I
End With

如何在任何给定的行中添加一种只计算一个木匠(从未加入到任何其他值)/ leaver(从任何值到x)的方法,但每周都会找到这些值。我正在努力建立如下表:

Resulting table from data

提前致谢!

1 个答案:

答案 0 :(得分:1)

我完成了一半的工作。请完成剩下的工作。这是我得到的。将代码粘贴到标准代码模块中,并将工作表的名称从“Tony”更改为您正在测试的任何内容。

Option Explicit

Enum Nst                            ' Status
    ' 15 Oct 2017
    NstNone = -3
    NstNotJoined
    NstOnLeave
    NstLeft
    NstPresent
End Enum

Enum Nix                            ' Array index
    ' 15 Oct 2017
    NixPresent = 1
    NixJoined
    NixLeft
    NixUnpaid
End Enum

Sub HeadCount()
    ' 15 Oct 2017

    Dim Arr() As Integer                ' Result
    Dim Wk As Long, Ix As Nix           ' Arr() indices
    Dim Ws As Worksheet
    Dim LastCol As Long
    Dim LastRow As Long
    Dim StatusArr As Variant
    Dim R As Long, C As Long            ' Row / Column
    Dim Stat As Nst, NewStat As Nst     ' status

    'set worksheet to use
    Set Ws = Sheets("Tony")
    StatusArr = Array(NstNotJoined, NstOnLeave, NstLeft, NstPresent)

    With Ws
        ' prefix a period to refer to object in With statement
        LastCol = .Cells(3, .Columns.Count).End(xlToLeft).Column
        LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
        ReDim Arr(1 To (LastCol - 3), 1 To NixUnpaid)

        For R = 4 To LastRow
            Stat = NstNone                  ' unable to determine changes in Wk 1
            For C = 4 To LastCol
                Wk = C - 3
                NewStat = StatusArr(Application.Match(Val(.Cells(R, C).Value), StatusArr, 1) - 1)
                If NewStat <> Stat Then     ' count changes
                    ' Count joiners
                    If (Stat = NstNotJoined) And (NewStat = NstPresent) Then
                        Arr(Wk, NixJoined) = Arr(Wk, NixJoined) + 1
                    End If
                    ' count leavers
                    If (Stat <> NstLeft) And (NewStat = NstLeft) Then
                        Arr(Wk, NixLeft) = Arr(Wk, NixLeft) + 1
                    End If
                End If

                Stat = NewStat
                If Stat = NstOnLeave Then Arr(Wk, NixUnpaid) = Arr(Wk, NixUnpaid) + 1
                If Stat = NstPresent Then Arr(Wk, NixPresent) = Arr(Wk, NixPresent) + 1
            Next C
        Next R

        .Cells(20, "D").Resize(UBound(Arr, 2), UBound(Arr, 1)).Value = Application.Transpose(Arr)
    End With
End Sub

我在你的记录中引入了以下逻辑。

  1. -2表示“尚未加入”
  2. -1表示“休假”(可能是未付款)
  3. 0或空白表示“不工作”(可能是左)
  4. 任何其他正数表示工作时间(假定工作时间)
  5. 请在工作表上使用这些数字,而不是您目前拥有的文本。如果需要,可以编写代码来翻译它们。在代码中,这些数字在Enum Nst中表示。 NstNone在本周开始时使用。我认为你的系统在这一点上存在缺陷,因为你不知道有多少人在不知道以前的状态的情况下加入或离开了。 NstNone填补了这一空白。

    最后一行代码确定输出将写入找到数据的同一工作表的D20:H23范围内。现有数据将被覆盖。请确保在员工ID下方的A列中不写任何内容,因为宏使用A列来确定要评估的员工人数。

    结果将包含与上周相同数量的列。它将由Enum Nix确定为4行,这意味着员工在场,加入,离开和休无薪假。我们的想法是,您可以将此列表粘贴到一个表中,其中包含您想要的标题和格式。您可以通过修改Enum Nix来更改序列。请务必将值= 1指定给名字。 (不要乱搞Enum Nst!)

    我的号码与您的结果中的号码不符。那是因为我不明白你的结果。但是,我认为这些数字是存在的,如果你需要额外的数字,它们将很容易整合到已建立的系统中。