Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Работа с данными

Страница: 1 |

 

  Вопрос: Как связать List с определенной колонкой в DBGrid Добавлено: 17.08.05 01:57  

Автор вопроса:  Walther
Ребята, помогите доктору, плиз!
Заранее прошу простить за наверное дилетантский вопрос, но так как я и есть пока дилетанат, то... :)

Имеется база данных по визитам пациентов[Report.mdb].
В данном случае у нас участвуют две связанные таблицы:
[PacientData] - данные пациента (номер пациента, имя, возраст, пол и т.д.)
[PacientVisit] - ВСЕ визиты ВСЕХ пациентов(номер пациента, дата визита, диагноз, назначения и пр.)
таблицы связаны через поле (PacNo)-номер пациента
На форме есть контрол Data1 и связанные с ним текстбоксы txtFields(7) - тут выводятся данные пациента,
Data1 связан с [PacientData],
также есть контрол Data2 и связанный с ним DBGrid1,
Data2 связан с Data1 через SQLзапрос (str1)
соответственно DBGrid1 показывает все визиты ТОЛЬКО ДАННОГО пациента
Это то, что мы имеем

Теперь, что нужно - собственно вопрос:
Я добавил на форму List1.
Нужно - привязать его к столбцу DateVisit в DBGrid1, чтобы в List1 отображались даты визитов ТОЛЬКО ДАННОГО пациента, а DBGrid1 показывал ТОЛЬКО ОДНУ строку соответствующую выбранному в List1 визиту.

Существующий кусок кода:
Option Explicit
Dim DBName As String
Dim tblName As String

Private Sub Form_Load()
 DBName = "REPORT.MDB"
 tblName = "PacientData"
  With Data1
    .DatabaseName = App.Path + DBName
    .RecordsetType = vbRSTypeDynaset
    .RecordSource = tblName
    .Refresh
  End With
End Sub

Public Sub Data1_Reposition()
Dim str1 As String
'В txtFields(0) отображается PacNo,
  If txtFields(0).Text = Empty Then
     txtFields(0).Text = "0"
  End If
str1 = "SELECT * FROM PacientVisit WHERE PacNo=" & txtFields(0).Text
  With Data2
    .DatabaseName = App.Path + DBName
    .RecordsetType = vbRSTypeDynaset
    .RecordSource = str1
    .Refresh
  End With
 DBGrid1.ReBind 'DBGrid1 привязан к Data2
End Sub

Самое главное - можно-ли решить задачу без ADO?
Т.е. иcпользуя уже имеющиеся Data1, Data2 и DBGrid1
Заранее спасибо

Ответить

  Ответы Всего ответов: 15  

Номер ответа: 1
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #1 Добавлено: 17.08.05 13:05
я бы не советовал использовать Data1 2... Лучше юзать если не ADO то DAO это одно и тоже токо без контролов.

от пример отображения в ListView определённой таблицы (DAO)


Public Sub WritetoListView(ListView As ListView, DBPath$, Password$, Table$) '+
'Отображает базу в ListView
Dim Db As Database, rs As Recordset
ListView.View = lvwReport

Set Db = OpenDatabase(DBPath$, False, False, "MS Access;pwd=" & Password$)
Set rs = Db.OpenRecordset("select * from [" & Table$ & "]";)

For i = 0 To rs.Fields.Count - 1 'Создаём столюцы
ListView.ColumnHeaders.Add , , rs.Fields(i).Name
Next

If rs.EOF = False Then
'Заполняем значениями столбцы

    While Not rs.EOF
Set lvItm = ListView.ListItems.Add(, , IIf(IsNull(rs(0)), "", rs(0)))
        For i = 1 To rs.Fields.Count - 1
            lvItm.SubItems(i) = IIf(IsNull(rs(i)), "", rs(i))
        Next
        sno = sno + 1
        DoEvents
        rs.MoveNext
    Wend
End If
End Sub

Ответить

Номер ответа: 2
Автор ответа:
 Walther



Вопросов: 2
Ответов: 12
 Профиль | | #2 Добавлено: 18.08.05 02:17
Спасибо уважаемый HACKER, но...
1.Нужна связь не ListView с таблицей, а List с определенной колонкой DBGrid, согласитесь это несколько разные задачи.

2. Вы пишете /я бы не советовал использовать Data1 2... / , к сожалению, по определенным причинам (долго объяснять, да это никому и неинтересно) я не могу отказаться от использования Data1,2

3.Если Вы обратили внимание (я не случайно привел существующий код) - база уже открыта.
Можно ли встроиться сюда, или необходимо снова открывать базу через /Set Db=OpenDatabase/
Может я что-то непонимаю?


Ответить

Номер ответа: 3
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #3 Добавлено: 18.08.05 17:28
Ставишь свойство List - DataSource в Data2, a свойство List - DataField в нужное тебе поле даты,
Только после того как зальешь Data2 по SQL запросу. Т.е. DataSource можно прямо в редакторе свойств поставить, а DataField в коде после
str1 = "SELECT * FROM PacientVisit WHERE PacNo=" & txtFields(0).Text
  With Data2
    .DatabaseName = App.Path + DBName
    .RecordsetType = vbRSTypeDynaset
    .RecordSource = str1
    .Refresh
  End With

Потом у List есть событие Change (кажется) - выбор определенной строки. По нему строй запрос и заливай скажем Data3, к которому цепляй DBGrid.

Ответить

Номер ответа: 4
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #4 Добавлено: 18.08.05 21:47
уважаемый Walther, я конечно понимаю что я не кинул готовый кусок кода который будет полностью удовлетворять ваш вопрос, но...


    While Not rs.EOF
Set lvItm = ListView.ListItems.Add(, , IIf(IsNull(rs(0)), "", rs(0)))
        For i = 1 To rs.Fields.Count - 1
            lvItm.SubItems(i) = IIf(IsNull(rs(i)), "", rs(i))
        Next
        sno = sno + 1
        DoEvents
        rs.MoveNext
    Wend


представте что RS это и есть ваш Data1 или 2... тогда цикл While - Wend перебирает все строки в таблице, а цикл For - Next все колонки. В итоге если в For - Next "ловить" нужную Вам колонку и вместо ListView конечно использовать List то получится как раз заполнение List определённой колонкой.
-------------
Вобщем говоря на русском:

Эта хрень накиданная в том моём примере, отображает в ListView все колонки и строки, и доделывать и/или переделывать чтобы она отображала определённую колонку не в листвьюве а в обычном - несколько мин, даже если не открывать заново, а теми же Data 1 ...

Ответить

Номер ответа: 5
Автор ответа:
 Walther



Вопросов: 2
Ответов: 12
 Профиль | | #5 Добавлено: 18.08.05 23:22
Спасибо уважаемый АНДРЕЙ, Вы пишете Т.е. DataSource можно прямо в редакторе свойств поставить, а DataField в коде после,
но в этом как раз и вопрос.
То, что DataSource можно прямо в свойствах поставить, я знаю, а DataField сам VB не даст в свойствах поставить - будет ругаться /You need to fill in the RecordSource property of the Data control to get a list of field names/, потому, что свойства Data2 мы ставим в коде.
Весь фокус как этот блин List1.DataField поставить?
Код то какой?
Насколько я понимаю, там цикл должен быть?

Мне вот тут по мылу советовали такой код, через ADO, только не смогли сказать, как без ADO сделать.
'Список надо будет загружать вручную. Примерно так:
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Set rs.ActiveConnection = <cnn>
rs.Open ";DiagnosValue"
List1.Clear
Do Until rs.EOF
  List1.AddItem rs.Fields("Name";).Value
  List1.ItemData(List1.NewIndex) = rs.Fields("ID";).Value
  rs.MoveNext
Loop
rs.Close
Set rs = Nothing
'Затем, при выборе элемента списка, обновлять грид:
Private Sub List1_Click()
Dim ID As Long
If List1.ListIndex >= 0 Then ID = List1.ItemData(List1.ListIndex)
If ID = 0 Then
  Grid1.Filter = vbNullString
Else
  Grid1.Filter = "[ID] = " & Trim$(Str$(ID))
End If
Grid1.Requery
End Sub
'Это примерный код, я его не проверял.

Но тут ADO и Grid, а у меня ведь Data и DBGrid, а у него нет такого фильтра как Grid1.Filter
Чего делать то?

Уважаемый HACKER пока готовил ответ АНДРЕЮ появилось Ваше сообщение. Спасибо. Попробую разобраться. Отвечу позже, что получилось.

Ответить

Номер ответа: 6
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #6 Добавлено: 19.08.05 11:22
Насколько я понимаю, там цикл должен быть?
Я наверное плохо понял проблему, Вы не знаете имя поля? Если знаете то
List1.DataField ="имя_поля_в_базе"

Ответить

Номер ответа: 7
Автор ответа:
 Walther



Вопросов: 2
Ответов: 12
 Профиль | | #7 Добавлено: 20.08.05 00:28
List1.DataField ="имя_поля_в_базе"

???
Может имя поля в таблице?
По моему там все-таки цикл должен быть

Ответить

Номер ответа: 8
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #8 Добавлено: 25.08.05 11:04
Уважаемый доктор. Залить List1 нужными Вам датами не так уж сложно. Да, Вы были правы. Без цикла обойтись не получается.
После того как Вы залили Data2.

  ;Data2.Recordset.MoveFirst
  Do
    List1.AddItem Data2.Recordset!DateVisit
    ;Data2.Recordset.MoveNext
  Loop Until Data2.Recordset.EOF

Теперь Вам понадобится еще один элемент Data3 с которым надо связать DBGrid1, а сам Data3 заливать так же запросом, но по List1_Click.
Здесь начинаются сложности с провайдером доступа к базе, сами увидите какие.
Запрос примерно такой
"select * from datviz where DateVizit=" & Left(List1.List(List1.ListIndex), Len(List1.List(List1.ListIndex)))

Ответить

Номер ответа: 9
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #9 Добавлено: 25.08.05 11:08
Ой, таблица конечно не datviz, а Ваша PacientVisit.

Ответить

Номер ответа: 10
Автор ответа:
 Walther



Вопросов: 2
Ответов: 12
 Профиль | | #10 Добавлено: 27.08.05 02:48
Спасибо уважаемый АНДРЕЙ, Ваш пример в первой части помог.
Список заполняется.
Правда пришлось еще добавить
List1.Clear
перед циклом, без этого список почему-то заполнялся данными несколько раз.
А вот во второй части Вы оказались правы - сложности.
Код такой (на основе Вашего)
Private Sub List1_Click()
Dim str2 As String
str2 = "select * from PACIENT_VISIT where DateVisit=" & Left(List1.List(List1.ListIndex), Len(List1.List(List1.ListIndex)))
  With Data3
    .DatabaseName = App.Path + "\DBASE\" + DBName
    .RecordsetType = vbRSTypeDynaset
    .RecordSource = str2
    .Refresh
  End With
End Sub

Когда кликаешь на произвольную позицию в списке (например дата визита была 14.06.2005) - пишет Run-time ошибку '3075':
Syntax error in number in query expression 'DateVisit=14.06.2005'
Вы не знаете, что это значит?
Что за синтаксическая ошибка в номере выражения запроса?
Ругается зараза на
.Refresh
, т.е. не дает обновить.
Data3 заливается копией кода заливки Data2(он парой строк выше), только естественно запрос другой, вот и вся разница - так там на
.Refresh
не ругается.
В чем дело то?

Ответить

Номер ответа: 11
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #11 Добавлено: 27.08.05 13:08
Дело все в том, что DAO как то по другому работает с датами нежели ADO. Там этот запрос проходит на ура, если саму дату ограничить апострофами. Зайдите сюда
http://www.vbrussian.com/conf/default.asp
там мы давно это обсуждаем в теме SQL.
А про Clear я просто забыл, надо конечно очищать список перед новым заполнением, ведь метод AddItem просто добавляет новый элемент в конец списка.

Ответить

Номер ответа: 12
Автор ответа:
 Walther



Вопросов: 2
Ответов: 12
 Профиль | | #12 Добавлено: 28.08.05 21:21
Спасибо уважаемый АНДРЕЙ, после внимательного изучения по Вашему совету темы SQL, код принял следующий вид
Private Sub List1_Click()
Dim str2 As String
Dim L As String
L = CLng(DateValue(List1.List(List1.ListIndex)))

str2 = "select * from PACIENT_VISIT where DateVisit=" & Left(L, Len(L))
  With Data3
    .DatabaseName = App.Path + "\DBASE\" + DBName
    .RecordsetType = vbRSTypeDynaset
    .RecordSource = str2
    .Refresh
  End With
DBGrid1.ReBind
End Sub

Все вроде-бы заработало, в Grid1 стали отображаться записи, правда связь получилась такая - в List1 отображаются все визиты ТОЛЬКО данного пациента (что и требовалось), а в Grid1 отображается не уникальная строка соответсвующая ТОЛЬКО этому визиту пациенту, а все визиты разных пациентов, которые были в день выбранный в List1. Но это я думаю вылечить, просто нужно наверное усовершенствовать запрос.

Тут получилась другая странная вешь - когда пытаешься добавить новый визит, в саму базу данных новые данные вносятся, в List1 тоже появляется новая стока, а в Grid1 почему новая строка не отображалась (вернее отображается пустая).
Мучился целый день - и так и эдак, в конце концов обратил внимание, что в момент клика в List1, грид прежде чем отобразиться, как то странно мигает один раз. Пригляделся - в поле DateVisit мелькает не дата, а число.
Попробовал прописать явно формат поля DateVisit кодом
Format(имя переменной, "dd.mm.yy";)
- все заработало.
Хотя в свойствах таблицы в базе данных тип поля уже был определен, как "Краткий формат даты".
Странно это, господа :)
глюки, глюки...

Спасибо еще раз!
Неужели наконец сдвинусь с места. :)

Ответить

Номер ответа: 13
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #13 Добавлено: 28.08.05 22:14
а в Grid1 отображается не уникальная строка соответсвующая ТОЛЬКО этому визиту пациенту, а все визиты разных пациентов, которые были в день выбранный в List1. Но это я думаю вылечить, просто нужно наверное усовершенствовать запрос.

Вы абсолютно правы. В запрос надо добавить второе условие (через and) c ID пациента.Т.е примерно так

str2 = "select * from PACIENT_VISIT where (DateVisit=" & Left(L, Len(L)) & ";) and (PacNo=" & txtFields(0).Text & ";)"

Насчет глюков Вы не правы. VB совсем не обязательно знать, что Вы там в Access установили.

Ответить

Номер ответа: 14
Автор ответа:
 AndreyMp



ICQ: 237822510 

Вопросов: 28
Ответов: 1182
 Профиль | | #14 Добавлено: 28.08.05 22:19
Да и гриду надо делать рефрешь или ребилд, не помню точно, давно со стандартными гридами не работал (слабоваты они - мало возможностей).

Ответить

Номер ответа: 15
Автор ответа:
 Walther



Вопросов: 2
Ответов: 12
 Профиль | | #15 Добавлено: 31.08.05 22:57
Спасибо АНДРЕЙ, именно такой запрос я сделал. Все работает.

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам