根据正文标准修改和连接标题标题

时间:2018-03-10 02:19:33

标签: excel excel-formula excel-2013

我有以下用于计算加班时间的Excel表格。

enter image description here

我希望自动生成最后两列,最好使用公式,以便用户可以看到员工在哪些日期工作OT。

Bob的示例输出是:

Dates worked Normal OT : "2nd, 3rd, 4th, 5th, 10th & 12th"

Dates worked Double OT : "6th, 7th & 13th"

请注意,我没有Excel 2016,因此无法使用TEXTJOIN()。另请注意,第1周和第2周的日期以数字格式存储,而不是日期格式,因此也无法使用WEEKDAY()

P.S。我已经尝试了TextJoin UDF,但它似乎没有用,因为我在公式中有很多标准。

Excel 2016中TEXTJOIN的工作公式为:

=TEXTJOIN(", ",TRUE,IF(WEEKDAY($B$3:$O$3,2)<6,IF($B5:$O5>0,TEXT($B$3:$O$3,"dd/mm/yyyy"),""),""))

这是使用日期格式。 UDF似乎不适用于这些参数。

1 个答案:

答案 0 :(得分:0)

我在问题的最后忽略了PS中的所有内容,因为Jeeped是正确的,因为它与主体和屏幕截图相矛盾。

不使用UDF,公式太复杂了。别担心,我已经提供了我自己的基本TEXTJOIN() UDF,绝对有效。

以下所有公式都需要&#34;数组输入&#34; (通过按 Ctrl + Shift + 输入)在单个单元格中,然后复制/填充。 (请记住复制起始{}

两个公式的唯一区别在于,一个使用比较<5,而另一个使用>=5,每一个都使用适当的&#34;否。 of Days&#34;细胞。


第一个公式需要在数组中输入T5(Bob&#39; Dates Worked Normal OT&#34;)然后填写:

{=SUBSTITUTE(TEXTJOIN(", ", TRUE, IF((MOD(COLUMN($B5:$O5)-COLUMN($B5), 7)<5)*($B5:$O5>0), $B$3:$O$3 & CHOOSE(IF($B$3:$O$3<4, $B$3:$O$3, IF($B$3:$O$3<21, 4, IF($B$3:$O$3<24, $B$3:$O$3-20, IF($B$3:$O$3<31, 4, 1)))), "st", "nd", "rd", "th"), "")), ", ", " & ", MAX(1, S5-1))}

以上公式的扩展,易于阅读的版本(如果你复制粘贴它也会有效):

{=
SUBSTITUTE(
  TEXTJOIN(
    ", ",
    TRUE,
    IF(
      (MOD(COLUMN($B5:$O5)-COLUMN($B5), 7)<5)*($B5:$O5>0),
      $B$3:$O$3
      &
      CHOOSE(
        IF($B$3:$O$3<4, $B$3:$O$3, IF($B$3:$O$3<21, 4, IF($B$3:$O$3<24, $B$3:$O$3-20, IF($B$3:$O$3<31, 4, 1)))),
        "st", "nd", "rd", "th"
      ),
      ""
    )
  ),
  ", ",
  " & ",
  MAX(1, R5-1)
)}



第二个公式需要在数组U5(Bob&#39; Dates Worked Double OT&#34;)中进行数组输入,然后填写:

{=SUBSTITUTE(TEXTJOIN(", ", TRUE, IF((MOD(COLUMN($B5:$O5)-COLUMN($B5), 7)>=5)*($B5:$O5>0), $B$3:$O$3 & CHOOSE(IF($B$3:$O$3<4, $B$3:$O$3, IF($B$3:$O$3<21, 4, IF($B$3:$O$3<24, $B$3:$O$3-20, IF($B$3:$O$3<31, 4, 1)))), "st", "nd", "rd", "th"), "")), ", ", " & ", MAX(1, S5-1))}

上述公式的扩展版本是:

{=
SUBSTITUTE(
  TEXTJOIN(
    ", ",
    TRUE,
    IF(
      (MOD(COLUMN($B5:$O5)-COLUMN($B5), 7)>=5)*($B5:$O5>0),
      $B$3:$O$3
      &
      CHOOSE(
        IF($B$3:$O$3<4, $B$3:$O$3, IF($B$3:$O$3<21, 4, IF($B$3:$O$3<24, $B$3:$O$3-20, IF($B$3:$O$3<31, 4, 1)))),
        "st", "nd", "rd", "th"
      ),
      ""
    )
  ),
  ", ",
  " & ",
  MAX(1, S5-1)
)}

注意:

  • 如上所述,公式依赖于&#34; No。的可用性/准确性。 of Days&#34;细胞才能正常工作。
  • 这些公式非常简单:
    • (MOD(COLUMN($B5:$O5)-COLUMN($B5), 7)>=5)*($B5:$O5>0)只是一种编码AND((…), (…));
    • 的数组公式友好方式
    • 唯一偷偷摸摸的事情是使用CHOOSE()函数和四个嵌套IF()来选择序数指标。
  • 不要忘记在开始时包含{,在复制粘贴时包含公式末尾的}。这些仅用于显示需要输入数组的公式。


我的TEXTJOIN UDF版本:

'============================================================================================
' Module     : <any standard module>
' Version    : 0.1.0
' Part       : 1 of 1
' References : Optional - Microsoft VBScript Regular Expressions 5.5   [VBScript_RegExp_55]
' Source     : https://stackoverflow.com/a/49218794/1961728
'============================================================================================
Public Function TEXTJOIN( _
                                     ByRef delimiter As String, _
                                     ByRef ignore_empty As Boolean, _
                                     ByRef text1 As Variant _
                        ) _
       As String
       Dim ƒ As Excel.WorksheetFunction: Set ƒ = Excel.WorksheetFunction

  Const DELIMITER_ As String = "#"
  Const PATTERN_ As String = "^(?:#)+|(?:#)+$|(#){2,}"

  Static rexDelimiterEscaper As Object ' VBScript_RegExp_55.RegExp ' ## Object
  Static rexEmptyIgnorer As Object ' VBScript_RegExp_55.RegExp ' ## Object
  If rexEmptyIgnorer Is Nothing _
  Then
    Set rexEmptyIgnorer = CreateObject("VBScript.RegExp") ' New VBScript_RegExp_55.RegExp ' ## CreateObject("VBScript.RegExp")
    With rexEmptyIgnorer
      .Global = True
      .Pattern = PATTERN_ ' Replacement = "$1"
    End With
    Set rexDelimiterEscaper = CreateObject("VBScript.RegExp") ' New VBScript_RegExp_55.RegExp ' ## CreateObject("VBScript.RegExp")
    With rexDelimiterEscaper
      .Global = True
      .Pattern = "(.)" ' Replacement = "\$1"
    End With
  End If

  Dim varText1 As Variant
  Select Case TypeName(text1)
    Case "Range":
      varText1 = ƒ.Transpose(text1.Value2)
      If text1.Rows.Count = 1 Then
        varText1 = ƒ.Transpose(varText1)
        If text1.Columns.Count = 1 Then varText1 = Array(varText1)
      End If
    Case "Variant()":
      varText1 = text1
    Case Else:
      varText1 = Array(text1)
  End Select
  If ignore_empty _
  Then
    With rexEmptyIgnorer
      .Pattern = Replace(PATTERN_, DELIMITER_, rexDelimiterEscaper.Replace(delimiter, "\$1"))
      TEXTJOIN = .Replace(Join(varText1, delimiter), "$1")
    End With
  Else
    TEXTJOIN = Join(varText1, delimiter)
  End If

End Function

注意:

  • 这是正确的填充:
    • 前两个参数不是可选的;
    • 如果您不想使用分隔符,则必须传递一个空字符串作为第一个参数。
    • 只允许另外一个(也是必需的)参数。
  • 您可以为第三个参数传递任何内容,除了多维数组/范围。这样做会导致#VALUE!错误。
  • 它应该非常快,特别是对于大输入,因为它不使用任何循环。如果你不忽略空值,那就会很快。忽略它们会因为几个正则表达式而变慢,并且还必须使用额外的字符串操作。