#excel #vba #date
#excel #vba #Дата
Вопрос:
ниже приведен VBA, при запуске которого я получаю код ошибки «Ошибка времени выполнения»13: несоответствие типов». Раньше это работало отлично для общего формата « dd mmm yyyy hhmm
«. После нескольких других VBA теперь это в пользовательском формате « dd mmm yyyy hhmm
«. Конечная цель состоит в том, чтобы вставить пустую строку, в которой пропущена дата, и поместить «БЕЗ ОТСТУПОВ» в пустой столбец строки A, а для столбцов B и C указать «N / A», а для столбца D введите недостающую дату в « dd mmm yyyy 0000
«. При отладке выделяется строка, начинающаяся с d1= cdate … .
Sub Missing_date()
Dim d1 As Date, d2 As Date
r = 1
start:
If Cells(r 1, "D") = "" Then Exit Sub
d1 = CDate(Split(Cells(r, "D"), " ")(1) amp; ", " amp; Split(Cells(r, "D"), " ")(0) amp; " " amp; Split(Cells(r, "D"), " ")(2))
d2 = CDate(Split(Cells(r 1, "D"), " ")(1) amp; ", " amp; Split(Cells(r 1, "D"), " ")(0) amp; " " amp; Split(Cells(r 1, "D"), " ")(2))
If d2 - d1 >= 2 Then
Rows(r 1).Insert shift:=xlDown
Cells(r 1, "D") = Format(d1 1, "dd mmm yyyy 0000")
Cells(r 1, "A") = "NO DEPARTURES"
Cells(r 1, "B") = "N/A"
Cells(r 1, "C") = "N/A"
End If
r = r 1
GoTo start
End Sub
Комментарии:
1. Редактирование вашего вопроса с примером ваших данных в текстовой форме, которые можно скопировать / вставить в рабочий лист; наряду с скриншотами желаемых результатов (и данными, если это добавит ясности), будет иметь большое значение для разработки подходящего решения.
Ответ №1:
У вас будет очень много проблем, пытаясь обрабатывать даты по-своему, а не так, как хотелось бы Excel. Я взял на себя смелость предположить, что у вас не было намерения объявлять войну Excel. Пожалуйста, попробуйте этот код.
Option Explicit
Sub InsertMissingDates()
' 111
Dim NextDate As Variant
Dim CellVal As Variant
Dim R As Long ' loop counter: Rows
R = Cells(Rows.Count, "D").End(xlUp).Row
NextDate = CellDate(Cells(R, "D"))
If NextDate = vbError Then Exit Sub
' bottom rows must be inserted before top rows
For R = R - 1 To 2 Step -1
CellVal = CellDate(Cells(R, "D"))
If CellVal = vbError Then Exit For ' exit if date can't be recognised
Do While Int(CDbl(CellVal)) < Int(CDbl(NextDate - 1))
Rows(R 1).Insert Shift:=xlDown
With Cells(R 1, "D")
.Value = Int(CDbl(NextDate - 1))
.NumberFormat = "dd mmm yyyy hhmm"
.HorizontalAlignment = xlLeft
End With
Cells(R 1, "A").Value = "NO DEPARTURES"
Cells(R 1, "B").Value = "N/A"
Cells(R 1, "C").Value = "N/A"
NextDate = NextDate - 1
Loop
NextDate = CellVal
Next R
End Sub
Private Function CellDate(Cell As Range) As Variant
' 111
' return vbError if cell's value couldn't be converted to a date
Dim Fun As Variant ' function return value
Dim CellVal As Variant
Dim Sp() As String
CellVal = Cell.Value
If IsDate(CellVal) Then
Fun = CDate(CellVal)
Else
Sp = Split(CellVal, " ")
If UBound(Sp) = 3 Then
Sp(3) = Right("0000" amp; Sp(3), 4)
Sp(3) = Left(Sp(3), 2) amp; ":" amp; Right(Sp(3), 2)
On Error Resume Next
Fun = CDate(Join(Sp))
End If
End If
If VarType(Fun) <> vbDate Then
MsgBox """" amp; CellVal amp; """ in row " amp; Cell.Row amp; vbCr amp; _
"couldn't be converted to a date.", _
vbInformation, "Data format error"
Fun = vbError
End If
CellDate = Fun
End Function
Дело в том, что Excel принимает дату за целое число, например 44135. Завтра будет 44136. Следовательно, каждый день = 1 и, следовательно, каждый час = 1/24. 44135.0 — это 12 утра, а 43135.5 — 12 вечера. Чтобы отобразить эти числа, например, 31 октября 2020 года 1200, вы не форматируете число, а форматируете ячейку. Это то, что делает мой код.
Теперь у вас на рабочем листе будут ячейки с текстом, который выглядит как дата (ваши записи), и датами, которые выглядят как текст (записи, сделанные моим кодом). Рассмотрите возможность создания процедуры, которая просматривает NumberFormat
каждую ячейку и изменяет ее значение на правильную дату, если это текст, одновременно применяя требуемый формат. Вы можете использовать строки кода из моих приведенных выше процедур, чтобы собрать их вместе. Тогда функция CellDate
устареет, потому что ее единственная задача — посредничать между вашими текстовыми датами и намерениями Excel.
Комментарии:
1. Большое вам спасибо, однако он вставляет строку для всех дат, даже для дней, когда у нас есть рейсы. Это намного ближе, чем когда-либо прежде. Я надеюсь, что это всего лишь небольшая настройка, необходимая для ее исправления. По крайней мере, мы знаем, что это работает. Кроме того, можем ли мы удалить окно сообщения, поскольку мы знаем, что оно работает? люди, использующие это, запутаются. Я хочу, чтобы они нажали кнопку и получили расписание своих рейсов. Этот VBA составляет около двух третей от 24 VBA, которые у меня есть. (Это последний). Спасибо.
2. Действительно, это было неточное программирование, и поэтому его легко исправить. Я добавил
NextDate = CellVal
в нижней части процедуры. Пожалуйста, измените свой код, чтобы добавить эту строку.3. MsgBox не следует удалять. В заголовке указано «Ошибка формата данных». Решение не в том, чтобы стрелять в messenger. Предполагается,
CellDate
что функция может считывать ваши даты в текстовом формате. Сообщение о ошибке будет показано только в том случае, если попытка завершится неудачей. Поэтому у вас есть два варианта. Один из них заключается в том, чтобы избавиться от текстовых дат, которые делают функцию устаревшей, а другой — улучшить функцию, чтобы она могла читать те, которые она сейчас, похоже, не может прочитать.4. Можно изменить «спагетти-код» OP, подобный циклическому программированию; * возможно, было бы полезно настаивать на полных ссылках на диапазоны 🙂
5. Доброе утро, спасибо за быстрый ответ, я попытался поместить NextDate = CellVal в нижней части частной функции, и на самом деле ничего не произошло. Я вижу, что это уже в первой части VBA. Я скопировал и вставил снова вашу формулу, если я что-то пропустил. Также действительно ли имеет значение, есть ли у меня option explicit? Это не позволит мне получить его, так как это происходит после многих других VBA. Еще раз спасибо. Это так сложно, что я занимаюсь этим уже почти неделю.