Вставьте недостающие данные, затем добавьте данные в два предыдущих столбца A и B

#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. Еще раз спасибо. Это так сложно, что я занимаюсь этим уже почти неделю.