Как я могу принудительно вызвать NumberFormat для функции VBA из функции VBA? - PullRequest
2 голосов
/ 09 марта 2020

Попытка преобразовать метки времени, которые даны в секундах после первого января 1970 года. Я написал небольшую функцию в Excel VBA для преобразования в формат даты Excel. Это прекрасно работает в том смысле, что оно преобразуется в число, которое при правильном форматировании дает понятную метку времени, но мне приходится каждый раз форматировать вызовы вручную. Я попытался решить проблему несколькими способами, но либо она ничего не делает с числом, либо приводит к ошибке: "#VALUE." Функция называется Sec2TS, и если я использую: 1502569847 в качестве ввода возвращает: 42959.8547106481, что правильно, но я бы хотел увидеть: 2017 Aug 12 20:30:47. Я добавил код:

   Function Sec2TS(Secs As Double) As Date

If Secs > 0 Then
    Sec2TS = 25569 + (Secs / 86400)
Else
    Sec2TS = 0
End If

ActiveCell.NumberFormat = "yyyy mmm dd hh:mm:ss"

End Function

Что с этим не так? Я пытался установить диапазон для выбора и переключения приложений, но безрезультатно.

Ответы [ 2 ]

1 голос
/ 09 марта 2020

Если бы формула могла изменить форматирование на листе, это привело бы к совершенно безумным эффектам для всех пользователей, потому что они не знали бы, почему все эти странные вещи действительно случаются. Вероятно, это основная причина, по которой формула / UDF не может ничего изменить на рабочем листе, она может только возвращать значение.

В качестве обходного пути вы можете использовать событие Worksheet_Change для форматирования права ячейки после того, как вы ввели формулу, которая содержит Sec2TS. Итак, сначала мы проверяем, какие ячейки измененного диапазона (Target) содержат формулы (Target.SpecialCells(xlCellTypeFormulas)), а затем проверяем, содержит ли любая ячейка в этом диапазоне "Sec2TS" в своей формуле, чтобы .NumberFormat эта ячейка.

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim CellsWithFormulas As Range
    On Error Resume Next
    If Target.Cells.CountLarge > 1 Then
        Set CellsWithFormulas = Target.SpecialCells(xlCellTypeFormulas)
    ElseIf Target.HasFormula Then
        Set CellsWithFormulas = Target
    End If
    On Error GoTo 0

    If CellsWithFormulas Is Nothing Then Exit Sub

    Dim Cell As Range
    For Each Cell In CellsWithFormulas.Cells
        If InStr(1, Cell.Formula, "Sec2TS") > 0 Then
            Cell.NumberFormat = "yyyy mmm dd hh:mm:ss"
        End If
    Next Cell
End Sub

Обратите внимание, что проверка Target.Cells.CountLarge > 1 необходима, поскольку при применении SpecialCells только к одной ячейке VBA автоматически применяет ее к всем ячейкам рабочего листа , что делает код очень медленным.

0 голосов
/ 09 марта 2020

Если вам не нужно численно обрабатывать значения, вы можете использовать String вместо Date в качестве выходной функции:

Function Sec2TS(Secs As Double) As String
    Dim D As Double

    If Secs > 0 Then
        D = CStr(25569# + (Secs / 86400#))
    Else
        D = CStr(0)
    End If

    Sec2TS = Format(D, "yyyy mmm dd hh:mm:ss")
End Function

enter image description here

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