Excel / VBA конвертирует даты в американский формат при транспонировании / вставке из VBA - PullRequest
0 голосов
/ 17 ноября 2018

Я сейчас работаю в британском контексте. Как мне кажется, я настроил их в региональных настройках (Windows 7 в корпоративном контексте, Excel 2016, версия 1803 (я думаю, что это также может быть Office 365 - что бы это ни было.)). Я пытаюсь работать с датами в VBA и вставить результаты в Excel. В начале и в конце даты обрабатываются в формате Великобритании. Но в середине Excel настаивает на преобразовании их в американские. Вставка делает: Великобритания-> США -> Великобритания.

Dim p_dtTermArray() As Date
ReDim p_dtTermArray(1 To lgNumTerms)
p_dtTermArray(1) = DateSerial(2018, 10, 1) 
p_dtTermArray(2) = DateSerial(2018, 11, 1) 

Давайте посмотрим в окне Locals:

p_dtTermArray(1)        #1/10/2018#       Date
p_dtTermArray(2)        #1/11/2018#       Date

Перед вставкой я очистил лист, как вручную с помощью Ctrl-A-A, Alt-E-A-A, так и в коде с ...UsedRange.Clear.

Ну, ситуация просто изменилась, когда я пишу это и пытаюсь что-то сделать.

Если я вставлю этот путь:

rgOutput.Offset(0, 0) = p_dtTermArray(1)
rgOutput.Offset(0, 1) = p_dtTermArray(2)

Я получаю значения Excel "1/10/2018" и "1/11/2018" с разницей в 31 день. Какой правильный.

Но если я сделаю это (массив столбцов с Transpose):

wb.Range(rgOutput.Offset(3, 6), rgOutput.Offset(2 + lgNumTerms, 6)) = Application.Transpose(p_dtTermArray)

Первые два значения: «10/01/2018» и «11/01/2018» (которые вычитают из 1). Итак, октябрь и ноябрь превратились в январь и январь. Что не так. Давайте добавим это тоже (массив строк, нет транспонирования):

wb.Range(rgOutput.Offset(3, 7), rgOutput.Offset(3, 6 + lgNumTerms)) = p_dtTermArray

Ах! Теперь они приходят как длинные !: 43374, 43405 (что опять на 31)!

Так что (частично) из-за Транспонирования! Давайте попробуем:

Dim v1, v2, v3, v4, v5
v1 = p_dtTermArray
v2 = Application.Transpose(p_dtTermArray)
v3 = Application.Transpose(v1)
v4 = Application.Transpose(v2)
v5 = Application.Transpose(Application.Transpose(v1))

В v2 до v5 тип Date превращается в тип String. И все строки правильные («1/10/2018», «1/11/2018», октябрь и ноябрь).

По какой-то причине в Excel / VBA используются неправильные региональные настройки для этих строк. Если я наберу «1/10/2018» и «1/11/2018» в двух ячейках и вычту их, я получу 31. Но когда мой транспонированный массив помещает те же две строки в две ячейки, они отображаются как «10 / 01/2018 "и" 11/01/2018 "(и вычесть до 1). Вставленные строки читаются как американские даты, а затем конвертируются в Великобританию.

Я не знаю, где еще искать что может повлиять на неправильное прочтение этих строк в одном очень специфическом контексте. Правильно ли просто избегать транспонирования с датами (и, что?, Вручную транспонировать для векторов столбцов (когда вам нужно иметь гибкость для выполнения строк или столбцов)?)?

(Во всех приведенных выше примерах даты в рабочей таблице имеют общий формат. Я пытался использовать форматы дат в ячейках как до, так и после вставки, без улучшений. В другое время и в другом месте, когда я выполнял аналогичную работу, Моя практика состояла в том, чтобы избегать использования дат в ячейках Excel и скрывать тот факт, что мои строки должны были быть датами (создавая строки в форме MMM.YY), чтобы избежать их изменения в Excel. На этот раз я подумал, что было бы неплохо просто используйте заштрихованные даты в заштрихованном Excel.)

1 Ответ

0 голосов
/ 17 ноября 2018

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

Согласно моим тестам, он автоматически распознает, когда я устанавливаю значение даты, указываю формат ячейки как Великобритания или США, а затем возвращаю значение в переменную.

В нашем регионе по умолчанию используется формат даты гггг-мм-дд.

тестовый код

Sub test()
    Dim p_dtTermArray() As Date
    Dim vR() As Long
    Dim lgnumterms As Integer
    lgnumterms = 2

    ReDim p_dtTermArray(1 To lgnumterms)
    p_dtTermArray(1) = DateSerial(2018, 10, 1)
    p_dtTermArray(2) = DateSerial(2018, 11, 1)
    ReDim vR(1 To lgnumterms)

    vR(1) = DateSerial(2018, 10, 1)
    vR(2) = DateSerial(2018, 11, 1)
    With Range("a1").Resize(1, 2)
        .Value = p_dtTermArray
        .NumberFormatLocal = "dd-mm-yyyy"
    End With

    With Range("a2").Resize(1, 2)
        .Value = vR
        .NumberFormatLocal = "mm-dd-yyyy"
    End With

    Dim vDB, vDB2
        vDB = Range("a1").Resize(1, 2)
        vDB2 = Range("a2").Resize(1, 2)

End Sub

Изображение листа

enter image description here

Окно местных жителей

enter image description here

Я обнаружил, что при переносе массива формата даты он меняется на символьный формат. Способ предотвратить это - преобразовать матрицу в код.

Sub test()
    Dim p_dtTermArray() As Date
    Dim vR() As Long
    Dim lgnumterms As Integer
    Dim r As Long, c As Long, i As Long, c As Long
    lgnumterms = 2

    ReDim p_dtTermArray(1 To lgnumterms)
    p_dtTermArray(1) = DateSerial(2018, 10, 1)
    p_dtTermArray(2) = DateSerial(2018, 11, 1)
    ReDim vR(1 To lgnumterms)

    vR(1) = DateSerial(2018, 10, 1)
    vR(2) = DateSerial(2018, 11, 1)
    With Range("a1").Resize(1, 2)
        .Value = p_dtTermArray
        .NumberFormatLocal = "dd-mm-yyyy"
    End With

    With Range("a2").Resize(1, 2)
        .Value = vR
        .NumberFormatLocal = "mm-dd-yyyy"
    End With

    Dim vDB, vDB2, vD() As Long, vD2() As Long

        vDB = Range("a1").Resize(1, 2).Value
        vDB2 = Range("a2").Resize(1, 2).Value


    r = UBound(vDB, 1)
    c = UBound(vDB, 2)

    ReDim vD(1 To c, 1 To r)
    ReDim vD2(1 To c, 1 To r)
    For i = 1 To r
        For j = 1 To c
            vD(j, i) = vDB(i, j)
            vD2(j, i) = vDB2(i, j)
        Next j
    Next i
    Range("d1").Resize(2) = vD
    Range("f1").Resize(2) = vD2


End Sub

enter image description here

...