从一个单元格中提取 2 次并放入两个不同的列中?
Extract 2 times from a cell and put into two different columns?
我有一个这样的电子表格:
B 列:
The Auditor arrived at 9am and left at 2pm
The Auditor arrived 09:00, left 16:00
我想提取审计员到达的开始时间并将其放入 C 列,如下所示:
C 列
9
9
然后提取结束时间并将其放入D列。
D 列
2
4
然后在 E 列中我想计算审核员在现场的小时数:
E 列
5
7
目前我正在使用这个公式来确定单元格中第一个数字的位置:
这是我用来尝试检索数字的 C 列中的公式:
=MID(B18,MIN(FIND({0,1,2,3,4,5,6,7,8,9},B18&"0123456789")),1)
我的问题是这仅在开始时间是一位而不是两位或更多时才有效,所以上午 9 点不是 09:00。
有人可以告诉我最好的方法吗?
你能试试这个可怕的公式吗?将其放在 C18
单元格...
=24*IF(OR(IFERROR(FIND("am";MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);1);0)>0;IFERROR(FIND("pm";MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);1);0)>0)=TRUE;TIMEVALUE(MID(MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);1;MIN(FIND({"am";"pm"};MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5)&"ampm";1)-1))&" "&MID(MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);MIN(FIND({"am";"pm"};MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5)&"ampm";1));2));TIMEVALUE(MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5)))
这是一个 VBA 解决方案。即使您没有要求 VBA,用于此目的的 UDF(用户定义函数)编写起来也相对简单,将来也可以更改。我用了一个正则表达式来识别时间。
可接受的时间格式包括您示例中显示的时间格式,数字和 am/pm 之间有或没有 space,以及 2:00 下午或类似时间。如有必要,可以轻松添加其他时间格式。
要输入此用户定义函数 (UDF),alt-F11 打开 Visual Basic 编辑器。
确保您的项目在 Project Explorer window 中突出显示。
然后,从顶部菜单 select Insert/Module 和
将下面的代码粘贴到打开的 window 中。
要使用此用户定义函数 (UDF),请输入类似
的公式
=ExtrTm(B1)
=ExtrTm(B1,1)
=ExtrTm(B1,2)
在某个单元格中。
第二个参数(如果省略则默认为一个)决定是否从字符串中提取第 1 次或第 2 次(如果有更多则为第 n 次)。
编辑: 编辑代码以提供正则表达式,允许可选地使用 dot
(.
) 作为时间分隔符。
Option Explicit
Function ExtrTm(S As String, Optional tmIndex As Long = 1) As Date
Dim RE As Object, MC As Object
'Const sPat As String = "\d+(?::\d+)?\s*(?:am|pm)?"
'To allow for optional use of dot as a time separator, use
Const sPat As String = "\d+(?:[:.]\d+)?\s*(?:am|pm)?"
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.Pattern = sPat
.ignorecase = True
If .test(S) = True Then
Set MC = .Execute(S)
ExtrTm = CDate(MC(tmIndex - 1))
End If
End With
End Function
结果是 Excel 时间,是一天的一小部分。如果将结果格式化为时间,您将以人类可读的方式查看结果。如果您需要以小数小时表示(例如乘以小时费率),只需将返回值乘以 24。
我有一个这样的电子表格:
B 列:
The Auditor arrived at 9am and left at 2pm
The Auditor arrived 09:00, left 16:00
我想提取审计员到达的开始时间并将其放入 C 列,如下所示:
C 列
9
9
然后提取结束时间并将其放入D列。
D 列
2
4
然后在 E 列中我想计算审核员在现场的小时数:
E 列
5
7
目前我正在使用这个公式来确定单元格中第一个数字的位置:
这是我用来尝试检索数字的 C 列中的公式:
=MID(B18,MIN(FIND({0,1,2,3,4,5,6,7,8,9},B18&"0123456789")),1)
我的问题是这仅在开始时间是一位而不是两位或更多时才有效,所以上午 9 点不是 09:00。
有人可以告诉我最好的方法吗?
你能试试这个可怕的公式吗?将其放在 C18
单元格...
=24*IF(OR(IFERROR(FIND("am";MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);1);0)>0;IFERROR(FIND("pm";MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);1);0)>0)=TRUE;TIMEVALUE(MID(MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);1;MIN(FIND({"am";"pm"};MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5)&"ampm";1)-1))&" "&MID(MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5);MIN(FIND({"am";"pm"};MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5)&"ampm";1));2));TIMEVALUE(MID(B18;MIN(FIND({0;1;2;3;4;5;6;7;8;9};B18&"0123456789"));5)))
这是一个 VBA 解决方案。即使您没有要求 VBA,用于此目的的 UDF(用户定义函数)编写起来也相对简单,将来也可以更改。我用了一个正则表达式来识别时间。
可接受的时间格式包括您示例中显示的时间格式,数字和 am/pm 之间有或没有 space,以及 2:00 下午或类似时间。如有必要,可以轻松添加其他时间格式。
要输入此用户定义函数 (UDF),alt-F11 打开 Visual Basic 编辑器。 确保您的项目在 Project Explorer window 中突出显示。 然后,从顶部菜单 select Insert/Module 和 将下面的代码粘贴到打开的 window 中。
要使用此用户定义函数 (UDF),请输入类似
的公式=ExtrTm(B1)
=ExtrTm(B1,1)
=ExtrTm(B1,2)
在某个单元格中。
第二个参数(如果省略则默认为一个)决定是否从字符串中提取第 1 次或第 2 次(如果有更多则为第 n 次)。
编辑: 编辑代码以提供正则表达式,允许可选地使用 dot
(.
) 作为时间分隔符。
Option Explicit
Function ExtrTm(S As String, Optional tmIndex As Long = 1) As Date
Dim RE As Object, MC As Object
'Const sPat As String = "\d+(?::\d+)?\s*(?:am|pm)?"
'To allow for optional use of dot as a time separator, use
Const sPat As String = "\d+(?:[:.]\d+)?\s*(?:am|pm)?"
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.Pattern = sPat
.ignorecase = True
If .test(S) = True Then
Set MC = .Execute(S)
ExtrTm = CDate(MC(tmIndex - 1))
End If
End With
End Function
结果是 Excel 时间,是一天的一小部分。如果将结果格式化为时间,您将以人类可读的方式查看结果。如果您需要以小数小时表示(例如乘以小时费率),只需将返回值乘以 24。