Разрешение связанного ввода данных Timespan в поле Access database - PullRequest
0 голосов
/ 15 марта 2020

Я пытаюсь разрешить пользователю вводить часы и минуты в элемент управления, похожий на текстовое поле (winforms), который привязывается к набору данных, связанному с базой данных Access. В настоящее время я использую поле, в котором хранится общее количество минут, а не поле даты / времени, потому что мне нужны только часы и минуты, а не количество включенных дней.

Другими словами, я хочу, чтобы пользователь мог вводить в формате HH:mm, когда часы больше 23 (например, 100), чтобы оно выглядело как 100:30 (100 часов, 30 минут), когда они введут его, но когда он сохранится в основной таблице, это будет общее количество минут (6030). Кроме того, значение Null также должно быть разрешено.

Я гибок в отношении того, как оно хранится в базе данных, но в Access нет типа поля TimeSpan, а тип поля DateType ограничивает количество часов до 23, поэтому я выбрал значение Long Integer в минутах.

Должен быть способ сделать это, но после долгих поисков я не могу найти ничего, что дало бы мне жизнеспособное решение, которое позволяло бы часами быть больше чем 23.

Моя первоначальная мысль состояла в том, чтобы позволить пользователю вводить что-либо в обычное текстовое поле, а затем иметь код, который анализирует его в событии изменения и превращает его в минуты (если они действительны), устанавливая это значение к скрытому текстовому полю, которое на самом деле связано с датируемыми данными, но есть много проблем с анализом введенного текста, и кажется, что должно быть что-то намного проще. Я пытался использовать DateTimePicker, используя только формат времени, но он не позволяет использовать часы больше 23.

Может кто-нибудь дать мне совет, как этого добиться?

В качестве последнего средства, Я, вероятно, в итоге просто поменяю поле на Single и позволю им ввести 100.5 в течение 100 часов и 30 минут, но все равно было бы предпочтительнее, если бы оно было введено как 100:30


РЕДАКТИРОВАТЬ:

Приношу свои извинения за неполное следование ответу, но я получаю несколько ошибок о

Значение не является членом EventArgs

и

AddMinutes не является членом TimeSpan.


РЕДАКТИРОВАТЬ:

Теперь я НАМНОГО ближе ... спасибо, что научил меня чему-то очень полезному.

Мне пришлось изменить код внутри обработчиков, чтобы я мог его понять. Это не так необычно, как у вас, но работает:

Private Sub Binding_Format(sender As Object, e As ConvertEventArgs)
    If e.Value IsNot DBNull.Value Then
        Dim hours As Integer = e.Value \ 60
        Dim minutes As Integer = e.Value - (hours * 60)
        e.Value = CType(hours, String) & ":" & CType(minutes, String)
    End If
End Sub

Private Sub Binding_Parse(sender As Object, e As ConvertEventArgs)
    If e.Value IsNot DBNull.Value Then
        Dim parts As String() = e.Value.Split(":"c)
        If parts.GetUpperBound(0) = 1 Then
            If IsNumeric(parts(0)) And IsNumeric(parts(1)) And
               parts(0).ToString.Length > 0 And parts(1).ToString.Length > 0 Then
                e.Value = CInt(parts(0) * 60) + CInt(parts(1))
            End If
        End If
    End If
End Sub

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

РЕДАКТИРОВАТЬ:

Эта проблема была исправлена ​​путем перемещения кода обработчика в произойдет до того, как я заполню таблицу.

Ответы [ 2 ]

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

Просто свяжите TextBox как обычно, а затем обработайте Format и Parse события Binding. Это позволит вам конвертировать между TimeSpan и String и обратно.

Я не тестировал этот код, но, предполагая, что данные верны, я считаю, что эти обработчики событий должны работать:

Private Sub Binding_Format(sender As Object, e As ConvertEventArgs)
    Dim time = DirectCast(e.Value, TimeSpan)

    'Convert from TimeSpan to String.
    e.Value = $"{CInt(Math.Floor(time.TotalHours)):#00}:{time.Minutes:00}"
End Sub

Private Sub Binding_Parse(sender As Object, e As ConvertEventArgs)
    Dim text = CStr(e.Value)
    Dim parts = text.Split(":"c)

    'Convert from String to TimeSpan.
    e.Value = TimeSpan.FromHours(CInt(parts(0))) + TimeSpan.FromMinutes(CInt(parts(1)))
End Sub

Вы можете подключить их следующим образом:

Dim binding = timeTextBox.DataBindings.Add("Text", myDataSource, "TimeColumnOrProperty")

AddHandler binding.Format, AddressOf Binding_Format
AddHandler binding.Parse, AddressOf Binding_Parse

Вам может понадобиться вызвать binding.ReadValue() после присоединения обработчиков событий, если данные уже были записаны в элемент управления без форматирования но я этого тоже не проверял.

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

Вы все равно должны использовать дату и время, даже если вам нужны только минуты. Причина в том, что вы можете использовать все встроенные функции, чтобы получить дни, минуты, секунды. И вы можете использовать встроенные функции для добавления минут и c.

И, что еще лучше, вы можете отображать / получать время начала и время окончания, а также go после полуночи. Возможно, вам нужны ТОЛЬКО минуты и необработанное количество минут, но по моему опыту это редкая необходимость. Я имею в виду, что если бы это были ТОЛЬКО минуты, то достаточно было бы простого целочисленного столбца, и вы бы подумали об этом.

Итак, вы должны иметь (мы предполагаем) время начала и окончания.

И если пользователь ТОЛЬКО вводит минуты, то вы ВСЕГДА можете и должны использовать время начала и окончания. И тот факт, что вы имеете и можете использовать временной интервал в. net ОЧЕНЬ поддерживает эту идею.

Я не могу найти ничего, что дало бы мне жизнеспособное решение, позволяющее на несколько часов быть больше чем 23.

Почему?

Если человек вводит 5 часов, тогда у вас есть начало 0 и время окончания 5 часов.

Если они хотят ввести 200 часов, то у вас есть начало 0, а время окончания 200 часов спустя. Прелесть этого в том, что вы можете получить дни, минуты, секунды или даже недели за промежуток времени, который представляет время начала и окончания. Используя столбец даты и времени, вы можете легко охватить несколько дней.

Способ отображения пользовательского интерфейса зависит от вас. Когда вы тянете время начала и окончания, вы конвертируете его в минуты, а затем отображаете минуты в поле для редактирования пользователем. При сохранении вы конвертируете минуты обратно во время начала (0) (и дату) и время окончания в будущем (опять же, у него тоже будет часть даты). Это конечное время может быть достаточным количеством часов в течение целого года - не нужно беспокоиться об одном бите.

Преимущество вышеописанного состоит в том, что теперь все отчеты (сортировка) и даже группировка могут работать.

И Я действительно не могу представить приложение, в которое нужно ввести ТОЛЬКО 40 часов, но некоторая дата НЕ ТАКЖЕ является частью этого микса. Как я уже говорил, если вам ПРОСТО нужны минуты, используйте целочисленное поле.

Таким образом, включение даты начала здесь, кажется, еще более ценно. Это БОЛЬШЕ из беспорядка и работы, чтобы иметь дело с минутами, а также приходится иметь дело с отдельным столбцом даты.

Таким образом, столбцы даты начала и окончания (со временем) отображать не нужно. Но ваш пользовательский интерфейс может получить эти два значения, а затем создать переменную временного интервала и ваш код et c. таким образом, будет пользоваться преимуществами многих. net процедур. И в результате вы можете использовать многие функции в базе данных.

Итак, скажи, дай мне все часы на 3-ю неделю года. Этот запрос будет гораздо проще, если вы имеете дело только с двумя столбцами (время начала и окончания). Таким образом, вы можете запросить диапазон дат и время в результате. Таким образом, в то время как ваш код logi c будет стоить вам немного дороже для преобразования между столбцами начала / конца в один промежуток времени, все остальное здесь гораздо более ценно и гибко.

Так с логической точки зрения? Столбец времени начала и времени окончания, который включает дату, имеет смысл.

С физической точки зрения (отображение пользовательского интерфейса) вы можете получить два значения, получить минуты и отобразить их для редактирования / ввода пользователем. минуты. Когда вы сохраняете обратно в базу данных, вы конвертируете конвертацию обратно в столбец времени начала и окончания.

Итак, если я введу сегодня 50 часов, тогда время начала будет сегодня (0 раз), а затем закончится время будет + 50 часов (в будущем). Прелесть этого в том, что теперь я могу без кода получить / рассчитать / отобразить будущую дату только что введенных 50 часов. Итак, теперь ваше преобразование часов в будущие даты является автоматическим c и может даже отображаться в отчетах и ​​т. Д. c., Причем без дополнительного кода. Это также означает, что вы можете суммировать () минуты, используя SQL команды query + sum (и датированный) и т. Д. c.

. Ну, это означает дни, часы и т. Д. 1058 *. Поскольку временной интервал может охватывать минуты в дни и т. Д. c. Ну, хотя столбец даты и времени НЕ является просто днями, минутами, секундами, он МОЖЕТ считаться одной и той же структурой данных при преобразовании начальной даты / времени и конечной даты / времени в. net временной интервал.

Итак: Захватить столбец даты / времени начала Захватить столбец даты / времени окончания

Теперь скрыть приведенное выше время (дни, часы, минуты). Теперь отобразите, разрешите пользователю редактировать или введите 35 часов.

Теперь выполните преобразование обратно в дату начала (без времени), а затем дату / время окончания составляют + дни, часы, минуты, секунды. Таким образом, вы всегда можете получить минуты из этих двух столбцов, но они сохраняются как начальная дата (0 раз) и конечная дата в будущем. Таким образом, это позволит вам получить минуты, а также секунды, дни или что-то еще.

На концептуальном уровне у вас есть однозначное преобразование здесь. Если дата никогда не должна быть частью этого, и вам не нужно / не нужно отдельное поле даты, то вы можете просто сохранить это как простое целое число минут. Но столбец даты и времени начала / окончания позволит значительно упростить отчетность, а также имеет концептуальное преобразование один к одному в интервал времени. net (без даты).

...