Преобразовать текст Excel во время - PullRequest
0 голосов
/ 14 апреля 2020

Мне нужно преобразовать некоторый форматированный текст в время Excel, но я не смог найти решение самостоятельно.

Вот несколько примеров входного текста и способа его преобразования:

 - 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

Обратите внимание, что в некоторых случаях есть минуты и секунды, а в других - только одна минута / секунда, кроме того, в некоторых случаях вы найдете минуты (множественное число), а другие - минуты (единственное число). Наконец, некоторые знаки препинания могут быть в тексте несколько раз.

Данные находятся в столбце электронной таблицы, и я хочу извлечь время в формате Excel в другой столбец электронной таблицы.

I Я пробовал разные версии TimeValue() и DateValue() и некоторые вложенные replace () все они в формуле ячейки, но ни одна из них не работала для всех случаев.

Не могли бы вы дать мне идею или некоторые совет, как подойти к этой проблеме?

Спасибо,

Пол

Ответы [ 4 ]

1 голос
/ 14 апреля 2020

Я играл с твоим вопросом в течение дня и вижу, что другие сделали то же самое. Я восхищаюсь решением, предложенным Роном Розенфельдом с использованием Filter XML, которое я кратко рассмотрел и отбросил как слишком внушительное sh. Это не так. Но neitehr это опрятно. Для «аккуратного» взгляда не далее, чем UDF ниже. Назовите его с листа, например, =TextToTime(A1), и обязательно отформатируйте ячейку, в которую вы его поместили, как Время, возможно, как 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

Эта функция очень универсальна. Он может переводить строки типа «5 часов 10 минут 15 секунд» или «5 часов 10 минут 15 секунд» (с запятыми) или даже «5 часов 10 минут 15 секунд». Ему нужны пробелы вокруг чисел, но они не мешают лишним пробелам или опечаткам. Это терпит неудачу на "75 минутах и ​​66 секундах", но это может быть решено, если это - проблема. Основным преимуществом VBA является то, что практически все можно решить, используя всего несколько дополнительных строк кода. Функции листа не имеют такой возможности.

1 голос
/ 14 апреля 2020

Поскольку вы не включили VBA в качестве тега, вот несколько решений для формул.

Если у вас Windows Excel 2013+ с функцией FILTERXML, вы можете использовать следующее:

=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)

Если у вас нет функции FILTERXML:

  • Создайте именованную формулу:
    • FormulasDefined NamesDefine NameNew Nameseq_99 Refers 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)

Затем используйте эту формулу:

=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)

Алгоритм:

  • Найдите строку hour или min или sec
  • Верните узел перед каждой из этих строк
  • , разделите на соответствующий коэффициент для создания значение времени Excel

Примечание: Пользовательский формат столбца B: hh:mm:yy

enter image description here

Как отмечает @ScottCraner в комментариях, формулы можно сократить, создав формулу массива:

Используя 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))

без 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))

В некоторых более ранних версиях Excel Вам может понадобиться «подтвердить» эту формулу массива , удерживая нажатой ctrl + shift при нажатии , введите . Если вы сделаете это правильно, Excel поместит фигурные скобки {...} вокруг формулы, как показано в строке формул

0 голосов
/ 14 апреля 2020

Если вы решите использовать VBA и сохраните тот же формат в столбце А, вы можете использовать следующий код:

Код:

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

Вывод:

enter image description here

0 голосов
/ 14 апреля 2020

Ну, вы можете взять и отредактировать его в соответствии со своими потребностями:

enter image description here

Вот формула:

=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)

Я просто хотел, чтобы дата была конвертирована в часы, чтобы вы могли указать sh на то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...