#excel #vba #if-statement
#excel #vba #if-оператор
Вопрос:
У меня есть данные в Excel, подобные этому, один столбец:
10/15/2021 7:59:42 AM
10/15/2021 7:59:44 AM
10/15/2021 7:59:46 AM
.
.
.
10/16/2021 7:59:42 AM
10/16/2021 7:59:48 AM
10/16/2021 7:59:49 AM
Я использовал этот код в VBA для создания двух столбцов: один с датой, а другой со временем:
Sub CommandButton1_Click()
Dim rng As Range
Set rng = [A1]
Set rng = Range(rng, Cells(Rows.Count, rng.Column).End(xlUp))
rng.Texttocolumns Destination:=[B1], DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=True, Other:=False, FieldInfo:=Array(Array(1, xlMDYFormat), Array(2, xlMDYFormat), Array(3, xlGeneralFormat)), _
TrailingMinusNumbers:=True
Columns("C").Delete
Columns("E").Delete
Columns("D").Delete
End Sub
После этого у меня есть два столбца.
Моя цель — иметь один столбец с датой и временем, но иметь дату только в первый раз, когда она появляется.
Я сделал это с помощью Excel, используя IF и более поздний CONCAT.
Я скопировал первую строку, а для второй я использовал:
IF(B3=B2,"",B3)
В результате получается пустая ячейка, я просто использую CONCAT со строкой, которая содержит время.
Я бы хотел сделать это в VBA, но я не уверен, как.
Комментарии:
1. Скорее всего, ваши даты — это не текстовые строки, а реальные даты, отформатированные для отображения так, как вы видите.
TextToColumns
работает со значением в ячейке, а не с форматированным отображением. Но Excel хранит даты в виде десятичного числа, где целая часть представляет количество дней с 1 января 1900 года, а десятичная часть — часть дня (или времени). Таким образом, вам нужно разделить соответственно на целочисленную и десятичную части значения.2. Чего вы действительно хотите добиться? Чтобы исключить дублированную (идентичную) дату? Если это так, вам следует использовать одну строку кода
rng.RemoveDuplicates 1
. БезTextTocolumns
части…3. У меня нет повторяющихся данных, у меня одна и та же дата, но разное время. Я разделяю их с помощью texttocolumn, поэтому я могу применить IF и получить дату только в первый раз, когда она появляется, а в другой ячейке я получаю пустую, поэтому, когда я использую CONCAT, у меня есть дата время только в первый раз, а для других ячеек у меня есть только время. Я легко делаю это с помощью if и concat, но я хотел бы сделать это с помощью VBA
4. @RonRosenfeld все в порядке с частью TextToColumns, я получаю то, что хочу, в одном столбце дата, в одном столбце время. То, что я делаю после, важно, потому что я делаю это с помощью IF и CONCAT, и я хотел бы сделать это с помощью VBA.
5. Всегда быстрее считывать два столбца в массив VBA (см. Раздел Массивы и диапазоны в VBA ), затем перебирать его, закрывая соответствующие записи; затем записать массив обратно на рабочий лист.
Ответ №1:
Пожалуйста, попробуйте следующий способ. Он обработает начальный столбец, не разбивая его по столбцам. Предполагается, что столбец, содержащий дату, равен «A: A». Это должно быть очень быстро для больших диапазонов, с использованием массивов и работы в памяти. Он вернет обработанный массив в столбце «B: B», начиная со второй строки (в первой я предположил, что заголовок должен быть):
Sub keepFirstDateOnly_Date()
Dim sh As Worksheet, lastR As Long, arrD, arrFin
Dim firstD As String, i As Long, j As Long
Set sh = ActiveSheet
lastR = sh.Range("A" amp; sh.rows.count).End(xlUp).row
arrD = sh.Range("A2:A" amp; lastR).Value2
ReDim arrFin(1 To UBound(arrD), 1 To 1)
For i = 1 To UBound(arrD)
arrFin(i, 1) = Format(arrD(i, 1), "mm/dd/yyyy hh:mm:ss AM/PM")
Do While DateSerial(Year(arrD(i j, 1)), month(arrD(i j, 1)), Day(arrD(i j, 1))) = _
DateSerial(Year(arrD(i, 1)), month(arrD(i, 1)), Day(arrD(i, 1)))
j = j 1: If i j >= UBound(arrD) Then Exit Do
arrFin(i j, 1) = Format(TimeValue(CDate(arrD(i j, 1))), "hh:mm:ss AM/PM")
Loop
i = i j - 1: j = 0
Next i
sh.Range("B2").Resize(UBound(arrFin), 1).value = arrFin
End Sub
Это работает, только если диапазон, подлежащий обработке, отформатирован как дата, как вы указали.
Пожалуйста, протестируйте ее и отправьте отзыв.
То же самое предложение изменить «B2» на «A2», если вам нравится результат в B: B, чтобы он перезаписывал существующее содержимое A: A.
Комментарии:
1. Я тестировал, но это решение возвращает только строку, в которой у меня есть дата в первый раз, поэтому результатом после кода будет новый столбец с 4 строками, потому что у меня 4 разные даты. Но мне нужно сохранить каждую строку, а не дату в каждой строке.
2. @Ena Итак, вы хотели бы сохранить то, что показано в приведенном выше коде, но в строке они существуют изначально?
3. Итак, мои данные похожи на показанные выше, в результате мне нужно в одном столбце:
1st row: 10/15/2021 7:59:42 2nd row: 7:59:44 3rd row: 7:59:46 . . . 20th row: 10/16/2021 7:59:42 21st row: 7:59:48 22nd row: 7:59:49
То же значение строки, что и раньше, но дата отображается не каждый раз, она отображается только при первом появлении.4. ОК. Я адаптирую ее для возврата таким образом. Но я не мог понять из вашего вопроса, что вам действительно нужно, извините…
5. Я попробовал еще раз в новом Excel, и это работает. Большое спасибо!