Convert Excel Text to Time

こ雲淡風輕ζ 提交于 2021-02-04 06:55:49

问题


I have to convert some formatted text to excel time, but I could not find a solution by myself.

Here are some examples of the input text and how it should be converted:

 - 1 Hour 14 minutes    ==> 01:14:00
 - 1 minute.            ==> 00:01:00
 - 1 Hour 1 minute      ==> 01:01:00
 - 2 minutes            ==> 00:02:00
 - 3 minutes 12 seconds ==> 00:03:12
 - 29 seconds           ==> 00:00:29

Observe that some times there are both minutes and seconds and some others only one of minutes/seconds, besides some times you find minutes (plural) and some others just minute (singular). Finally, some punctuation signs could be in the text some times.

The data is in a spreadsheet column and I want to extract the excel formatted time in a different column on the spreadsheet.

I've tried different versions of TimeValue() and DateValue() and some nested replace() all of them in a cell formula, but none of them worked for all cases.

Could you give me an idea or some advice on how to approach this problem?

Thanks,

Paul


回答1:


I played with your question for a day and see that others have done the same. I admire the solution offered by Ron Rosenfeld using FilterXML which I briefly considered and discarded as too outlandish. It isn't. But neitehr is it neat. For "neat" look no further than the UDF below. Call it from the worksheet with something like =TextToTime(A1) and be sure to format the cell you put this in as Time, perhaps like hh:mm:ss.

Function TextToTime(Cell As Range) As Double

    Dim Fun(2) As String
    Dim Txt() As String
    Dim Tmp As Variant
    Dim i As Integer

    Txt = Split(Cell.Value)
        For i = 1 To UBound(Txt)
            If Not IsNumeric(Txt(i)) Then
                Tmp = 0
                Tmp = InStr("HMS", UCase(Left(Trim(Txt(i)), 1)))
                If Tmp Then
                    Fun(Tmp - 1) = Val(Txt(i - 1))
                End If
            End If
        Next i

    For i = LBound(Fun) To UBound(Fun)
        If Fun(i) = "" Then Fun(i) = 0
    Next i

    TextToTime = TimeValue(Join(Fun, ":"))
End Function

This function is very versatile. It can translate strings like "5 hours 10 minutes 15 seconds" or "5 hours, 10 minutes, 15 seconds" (with commas) or even "5 hours & 10 minutes and 15 seconds". It needs the spaces around the numbers but doesn't balk at extra spaces or typos. It fails on "75 minutes and 66 seconds" but that could be dealt with if it's an issue. The key advantage of VBA is that almost anything can be dealt with using just a few extra lines of code. Worksheeet functions don't have that capability.




回答2:


Since you did not include VBA as a tag, here are some formula solutions.

If you have Windows Excel 2013+ with the FILTERXML function, you can use the following:

=IFERROR(FILTERXML("<t><s>" & SUBSTITUTE(LOWER(A1)," ","</s><s>") & "</s></t>","//s[contains(.,'hour')]/preceding-sibling::*[1]")/24,0)+
IFERROR(FILTERXML("<t><s>" & SUBSTITUTE(LOWER(A1)," ","</s><s>") & "</s></t>","//s[contains(.,'min')]/preceding-sibling::*[1]")/1440,0)+
IFERROR(FILTERXML("<t><s>" & SUBSTITUTE(LOWER(A1)," ","</s><s>") & "</s></t>","//s[contains(.,'sec')]/preceding-sibling::*[1]")/86400,0)

If you do not have the FILTERXML function:

  • Create a named formula:
    • FormulasDefined NamesDefine NameNew Nameseq_99Refers to:=IF(ROW(INDEX($A:$A,1,1):INDEX($A:$A,255,1))=1,1,(ROW(INDEX($A:$A,1,1):INDEX($A:$A,255,1))-1)*99)

Then use this formula:

=IFERROR(INDEX(TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),-1+MATCH("hour*",TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),0))/24,0)+
IFERROR(INDEX(TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),-1+MATCH("min*",TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),0))/1440,0)+
IFERROR(INDEX(TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),-1+MATCH("sec*",TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),0))/86400,0)

Algorhythm:

  • Find the string hour or min or sec
  • Return the node prior to each of those strings
  • divide by the appropriate factor to create an excel time value

Note: Custom format column B as hh:mm:yy

As pointed out by @ScottCraner in the comments, the formulas can be shortened by creating an array formula:

Using FILTERXML:

=SUM(IFERROR(FILTERXML("<t><s>" & SUBSTITUTE(LOWER(A1)," ","</s><s>") & "</s></t>","//s[contains(.,"&{"'hour'","'min'","'sec'"}&")]/preceding-sibling::*[1]")/{24,1440,8640},0))

without FILTERXML:

=SUM(IFERROR(INDEX(TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),-1+MATCH({"hour*","min*","sec*"},TRIM(MID(SUBSTITUTE(TRIM(A1)," ",REPT(" ",99)),seq_99,99)),0))/{24,1440,8640},0))

In some earlier versions of Excel, you may need to "confirm" this array-formula it by holding down ctrl + shift while hitting enter. If you do this correctly, Excel will place braces {...} around the formula as observed in the formula bar




回答3:


Well, you can take this and edit it to suit your needs:

Here is the formula :

=IF(IFERROR(FIND("da",A2,1),0)>0,LEFT(A2,FIND(" ",A2,1)-1)*24,0)+IFERROR(1*MID(A2,FIND(" ",A2,FIND(" ",A2,1)+1),FIND(" ",A2,FIND(" ",A2,FIND(" ",A2,1)+1)+1)-FIND(" ",A2,FIND(" ",A2,1)+1)),0*1)

I just wanted the date converted to hours so you can finish to what you want.




回答4:


If you decide to use VBA and you keep the same format in Column A you could use the below code:

Code:

Sub Converter()

    Dim i As Long, y As Long, LastRow As Long
    Dim arrData As Variant, arrLine As Variant
    Dim Hours As String, Minutes As String, Seconds As String

    With ThisWorkbook.Worksheets("Sheet1")

        LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

        arrData = .Range("A1:A" & LastRow)

        For i = LBound(arrData) To UBound(arrData)

            Hours = "00"
            Minutes = "00"
            Seconds = "00"

            arrLine = Split(arrData(i, 1), " ")

            For y = LBound(arrLine) To UBound(arrLine)

                If InStr(1, UCase(arrLine(y)), "HOUR") > 0 Then
                    Hours = Right("0" & arrLine(y - 1), 2)
                ElseIf InStr(1, UCase(arrLine(y)), "MINUTE") > 0 Then
                    Minutes = Right("0" & arrLine(y - 1), 2)
                ElseIf InStr(1, UCase(arrLine(y)), "SECOND") > 0 Then
                    Seconds = Right("0" & arrLine(y - 1), 2)
                End If

            Next y

            .Range("B" & i).Value = Hours & ":" & Minutes & ":" & Seconds

        Next i

    End With

End Sub

Output:



来源:https://stackoverflow.com/questions/61200039/convert-excel-text-to-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!