Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Visual Basic 6

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9

Открыть новую тему     Написать ответ в эту тему

jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
dneprcomp
Вот, немного начинаю разбираться с БД. Спасибо.
 
А насчет использования транзакций не просветите? Я решил их использовать, т.к. информация, для хранения и обработки которой я делаю прогу, для меня очень ценна (это научный материал). Вот фрагмент кода:

Код:
Private Sub Form_Load()
 
    BasePath = "D:\Библиография\"           'путь к файлу БД
    BaseName = "MainBase.mdb"                'файл БД
 
    Set wks = DBEngine.Workspaces(0)                                    
    Set db = wks.OpenDatabase(BasePath + BaseName)
    Set rsetSurname = db.OpenRecordset("Sprav_Authors", dbOpenDynaset)
 
End Sub
 
Private Sub Command1_Click()
 
    wks.BeginTrans                                                   'начало транзакции
    rsetSurname.AddNew                                           'начало формирования записи
    rsetSurname!Surname = Text1.Text                      'добавление данных из текстового окна "Фамилия" (Text1)
    rsetSurname!Name = Text2.Text                           'добавление данных из текстового окна "Имя" (Text2)
    rsetSurname!Patronymic = Text3.Text                   'добавление данных из текстового окна "Отчество" (Text3)
    rsetSurname.Update                                             'добавление сформированной записи в БД
    rsetSurname.MoveNext                                         'переход на след. запись
    wks.CommitTrans                                                'конец транзакции
 
End Sub

 
Я так понимаю, что до начала занесения каких-либо данных в БД надо использовать метод .BeginTrans, а после их занесения - использовать метод .CommitTrans (см. код)? А если начало и конец транзакции делать, соответственно, в начале и в конце ВСЕЙ программы?
 
Dneprcomp, вопрос состоит в том, когда будет правильным начинать транзакцию, а когда правильным будет ее закончить?

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 20:55 24-07-2009 | Исправлено: jek1976, 21:04 24-07-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976
По логике кода все верно. Кроме строки rsetSurname.MoveNext. Она здесь  не к месту.  
 
Transaction нужны когда изменения происходят в нескольких table и важно сохранять данные в связи. К примеру, делаем update 2-x table последовательно. Первый прошел нормально. А вот на втором ошибка - данные не сохранились. Вот тут и сработает transaction и сделает undo всем изменениям в базе.  
Возвращаясь к коду, в нем нехватает механизма on error. И wks.RoolbackTrans

Цитата:
А если начало и конец транзакции делать, соответственно, в начале и в конце ВСЕЙ программы?  
Transaction используется только для работы с DB. Делать как в вопросе, все равно что начинать солить суп, когда в кастрюле не то, что супа, а еще воды то нет.
Цитата:
когда будет правильным начинать транзакцию, а когда правильным будет ее закончить?
А вот как сделал в коде, так и правильно. Как начинаем изменять данные в базе, так и пора BeginTrans. Как закончили данное конкретное изменение - CommitTrans. Как ошибка - RoolbackTrans.
В данном случае т.к. изменение происходит только в одном table, я бы не использовал транзакцию, а просто поставил бы errorhandler. До rsetSurname.Update  изменений в базе еще нет. После - уже все записалось и без ошибки. Нет смысла в использовании  транзакции.

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 21:51 24-07-2009 | Исправлено: dneprcomp, 21:53 24-07-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
ОК, спасибо!

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 00:20 25-07-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
dneprcomp
Еще такая ситуация.
Допустим, я добавил запись, состоящую из трех полей - Фамилия, Имя и Отчество, в таблицу БД методом .AddNew. Добавилась эта запись, конечно, в самый конец БД.
Но при таком добавлении происходит естественное нарушение сортировки фамилий в БД.
Как здесь поступить? Сортировать записи внутри самой БД (методом .Sort) или же отсортировать записи как-либо иначе?

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 01:47 26-07-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976
Нет такого понятия как естественная сортировка. И запси далеко не всегда дбавляются в конец.
Физическое раположение в базе и представление данных на скрине или в репорте - совершенно разные и никак не связанные вещи. В 99% совершенно не интересно, как именно физически данные расположены в базе. Метод .Sort тоже не перемещает данные физически.
Сортируем или в рекордсете(order by field1, field2) или свойствами некоторых контролов(dropdownlist, grid)

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 04:36 26-07-2009 | Исправлено: dneprcomp, 04:40 26-07-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Понятно, спасибо.
 
Dneprcomp, я сделал вот таким образом:

Код:
Public wks As Workspace
Public db As Database
Public rsetSurname As Recordset
Public rsetSurname1 As Recordset
Public rsetName As Recordset
Public КоличествоЗаписейТаблицы_Sprav_Authors As Long
 
Private Sub Form_Load()
 
    BasePath = "D:\[Библиография]"
    BaseName = "MainBase.mdb"
 
    Set wks = DBEngine.Workspaces(0)
    Set db = wks.OpenDatabase(BasePath + "\" + BaseName)
    Set rsetSurname = db.OpenRecordset("Sprav_Authors", dbOpenDynaset)
 
End Sub
 
Private Sub Command1_Click()
    Dim i As Long
 
    rsetSurname.AddNew
    rsetSurname!Surname = Text1.Text
    rsetSurname!Name = Text2.Text
    rsetSurname!Patronymic = Text3.Text
    rsetSurname.Update
   'выполняем сортировку записей внутри БД
    Set rsetSurname1 = db.OpenRecordset("SELECT * " & "FROM Sprav_Authors ORDER BY Surname, Name", dbOpenDynaset)
 
   Set rsetSurname = rsetSurname1

 
  'обновление таблицы с "ФИО" на форме из таблицы "Sprav_Authors" БД:
  'определяем кол-во записей в табл. "Sprav_Authors"
   КоличествоЗаписейТаблицы_Sprav_Authors = rsetSurname.RecordCount
  'устанавливаем кол-во строк в таблице на форме равным кол-ву записей
  'в табл. "Sprav_Authors" (плюс одна строка для учета строки заголовка таблицы)
   VSFlexGrid1.Rows = rsetSurname.RecordCount + 1
  'переходим на первую запись в таблице "Sprav_Authors"
   rsetSurname.MoveFirst
  'перебираем все записи таблицы "Sprav_Authors"
   For i = 1 To КоличествоЗаписейТаблицы_Sprav_Authors
      'выводим номер текущей строки таблицы в нулевую (фиксированную) колонку
       VSFlexGrid1.TextMatrix(i, 0) = Str(i)
      'читаем фамилию из записи БД и переносим ее в таблицу на форме
       VSFlexGrid1.TextMatrix(i, 1) = rsetSurname!Surname
      'читаем имя из записи БД и переносим его в таблицу на форме
       VSFlexGrid1.TextMatrix(i, 2) = rsetSurname!Name
      'читаем отчество из записи БД и переносим его в таблицу на форме
       VSFlexGrid1.TextMatrix(i, 3) = rsetSurname!Patronymic
      'переходим на следующую запись в таблице "Sprav_Authors"
       rsetSurname.MoveNext
   Next i

 
Покритикуйте.

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 14:11 26-07-2009 | Исправлено: jek1976, 14:14 26-07-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976
В целом все верно.  
1.Нехватает механизма обработки ошибок. К примеру, что будет с программой, если любое поле = Null ?
2. Нет смыла в строке rsetSurname.MoveFirst . Если никто recordset не трогал, он и так стоит на первой строке.
3.Гонять recordsrt movefirst, movelast cчитаеся не очень правильным с точки зреия потери ресурсов. Хорошо, база маленькая. Можно ведь и по другому:

Код:
Do while not rsetSurname.eof
   VSFlexGrid1.Rows = VSFlexGrid1.Rows + 1
   VSFlexGrid1.TextMatrix(i, 2) = rsetSurname!Name  
 ну и т.д.
 
Loop
 

4.

Цитата:
 Set rsetSurname = rsetSurname1  

А это зачем?
5. dbOpenDynaset применяют если надо изменять данные(update,insert). Для только чтения можно dbReadOnly
Тогда даже случайно никто базу не изменит
 
6.Для чего на load открывается recordset?
7.Eсли не планируется использовать recordset дальше, считается хорошим тоном закрывать его после использования.

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 21:15 26-07-2009 | Исправлено: dneprcomp, 21:23 26-07-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
К примеру, что будет с программой, если любое поле = Null ?

Null или "" ? Ведь поля-то текстовые!
 

Цитата:
Нет смыла в строке rsetSurname.MoveFirst . Если никто recordset не трогал, он и так стоит на первой строке.

А если придется несколько раз добавлять записи в таблицу при разных вызовах формы? Тогда рекордсет будет изменяться и каким он окажется в нужный момент?
 

Цитата:
Код:Do while not rsetSurname.eof  
   VSFlexGrid1.Rows = VSFlexGrid1.Rows + 1  
   VSFlexGrid1.TextMatrix(i, 2) = rsetSurname!Name  
 ну и т.д.  
Loop

Этот код для того случая, когда рекордсет по умолчанию стоит на первой записи?
 

Цитата:
Цитата: Set rsetSurname = rsetSurname1
А это зачем?  

Это старые куски - пробовал по-всякому изголяться. Этого уже нет в действительности.
 

Цитата:
Для чего на load открывается recordset?

Наверное, будет лучше открывать рекордсет ПРЯМО перед использованием базы??? И затем тут же закрывать после использования.
 
 
 
 

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 00:53 27-07-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
И еще вопрос:
Вот две разных инициализации рекордсета:
 
Set БД = OpenDatabase(BasePath + "\" + BaseName)
Set Записи1 = БД.OpenRecordset("Sprav_Authors", dbOpenDynaset)
 
Set БД = OpenDatabase(BasePath + "\" + BaseName)
Set Записи2 = БД.OpenRecordset("SELECT * " & "FROM Sprav_Authors ORDER BY Surname, Name", dbOpenDynaset)
 
Не пойму, почему в первом случае кол-во записей в рекордсете Записи1 равно единице, а во втором случае, кол-во записей в рекордсете Записи2 равно реальному кол-ву записей, имеющихся в таблице "Sprav_Authors" (их там 137 штук)?

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 04:19 27-07-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976
Null это не 0. Если поле не имеет дефолтного значения и полю еще не присваивали ничего, то его значение Null.

Цитата:
А если придется несколько раз добавлять записи в таблицу при разных вызовах формы? Тогда рекордсет будет изменяться и каким он окажется в нужный момент?

А кто обещал, что после добавления recordset автоматом покажет добавленные записи? Его еще рефрешать над. Или закрывать после использования.

Цитата:
Этот код для того случая, когда рекордсет по умолчанию стоит на первой записи?  

Да.  

Цитата:
Наверное, будет лучше открывать рекордсет ПРЯМО перед использованием базы??? И затем тут же закрывать после использования.
Обычно так и делают

Цитата:
почему в первом случае кол-во записей в рекордсете Записи1 равно единице, а во втором случае, кол-во записей в рекордсете Записи2 равно реальному кол-ву записей
А потому что в первом случае просто  открыт table. Сколько в нем рекордов еще не известно. Да и вероятно будет всегда показывать 1 - т.е. текущий рекорд. Во втором же случае мы получили выборку. Количество строк тоже уже пощитано.

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 06:40 27-07-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
dneprcomp
Спасибо.
 
На данный момент - принцип работы с БД более-менее понятен.
Сейчас работаю над интерфейсом проги. Суть в том, что надо отработать методику  
Сначала возникла проблема в том, чтобы запомнить тот порядок, в каком пользователь выбирает фамилии, имена и отчества в таблице VSFlexGrid, перенесенные туда из БД. Важен именно порядок их выбора! Оказалось - это очень и очень непросто, т.к. можно выбирать как мышью, так и с помощью клавиатуры, а также в комбинации друг с другом. Кроме того, нужно учесть, что по некоторым выделенным ячейкам пользователь может щелкнуть повторно, сняв при это выделение. Эту затею с отслеживанием выделения строк мышью/клавиатурой в таблице VSFlexGrid - я оставил в покое - уж слишком много надо предусмотреть вариантов и код у меня стал очень объемным и трудночитаемым. Вместо этого пойду по другому пути.
 
Я решил преобразовать поля первой колонки таблицы VSFlexGrid в CheckBox'ы:
VSFlexGrid1.ColDataType(1) = flexDTBoolean.
Таким образом, необходимость выделения строк - отпадает и потребуется отслеживать лишь изменения состояния каждого из CheckBox'ов, связав его с соответствующей ячейкой одномерного массива (более подробнее обсуждать не буду - речь не об этом).
 
Вопрос, собственно, хочу задать совсем другой: как избавиться от точечной рамки выделения, которая появляется при щелчуе на ячейке (см. рис).
 
   
 
 

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 15:07 09-08-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Вопрос, собственно, хочу задать совсем другой: как избавиться от точечной рамки выделения, которая появляется при щелчуе на ячейке

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

Цитата:
запомнить тот порядок, в каком пользователь выбирает  
И зачем такие сложности самому себе придумывать? Даже не могу себе представить ситуацию, когда это может понадобится.
Можно попробовать добавить еще одно поле в грид и в нем ставить номер по порядку. В самом грие, а не в массиве. Порядковый номер храним в переменной и добавляем 1 по мере выделения чекбокса. При снятии выдеоения просто очищаем поле. После окончания юзером селекта, прбегаем  по гриду и заносим номера и другие данные в многомерный массив. Затем сортировка по номеру.
Полгаю что при таком подходе не понадобятся никакие алгоритмы выбора
 
PS.«Не следует множить сущее без необходимости». Ockham

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 08:34 10-08-2009 | Исправлено: dneprcomp, 08:38 10-08-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
И зачем такие сложности самому себе придумывать? Даже не могу себе представить ситуацию, когда это может понадобится.

Программа, частью которой является обсуждаемая здесь проблема, предназначена для ведения библиографического каталога печатных и электронных изданий.
Ситуация очень проста: есть таблица (сделана на основе контрола VSFlexGrid) с ФИО авторов (книг, статей и проч.), данные в которую копируются из БД. Из этой таблицы необходимо выбрать авторов, размещая их в том порядке, в каком они перечислены в оригинале, т.е. на самом издании. Список авторов удобнее всего сформировать, просто щелкая на соответствующих строках таблицы с ФИО авторов, причем, сами понимаете, результат выстраивания ФИО авторов должен соответствовать тому порядку, в котором производились щелчки в этой самой таблице. Теперь понятно?
 
 
 
 
Добавлено:

Цитата:
Можно попробовать добавить еще одно поле в грид и в нем ставить номер по порядку. В самом грие, а не в массиве. Порядковый номер храним в переменной и добавляем 1 по мере выделения чекбокса. При снятии выдеоения просто очищаем поле. После окончания юзером селекта, прбегаем  по гриду и заносим номера и другие данные в многомерный массив

Представьте себе юзера, которому надо будет так мудрить с расстановкой номеров, просто для того, чтобы выбрать список несчастных авторов!!! А если, выбрав несколько авторов путем расстановки номеров, юзер поймет, что первый автор не нужен, то ему что, заново перенумеровывать список? Ваше решение - неудачное для юзера, но простое для реализации программистом.
Что может быть проще для юзера, чем щелчки по нужным строкам в таблице авторов. Причем выстраивание авторов идет в том порядке, в котором производились щелчки - просто и понятно.
Но за такой простотой для пользователя скрывается сложность для программиста. А состоит она в том, что приходится учесть уж очень разные ситуации с выбором строк, такие как:  
1) выделение диапазона смежных строк только при помощи мыши,  
2) выделение диапазона смежных строк, производимое с нажатой клавишей Shift,  
3) выделение несмежных строк (производимое с нажатой клавишей Ctrl),  
4) неупорядоченное снятие выделения у одной или нескольких строк, включая строки, находящиеся внутри диапазона (т.к. юзер может ошибиться (промахнуться мимо) и щелкнуть не того или не тех авторов, которые нужны).  
 
Код разрастается до больших размеров и при этом еще не реализована возможность учета снятия выделения строк. Я думал, в контроле VSFlexGrid должно быть реализовано нечто подобное, ведь в нем существует же перечислитель всех выделенных строк, о котором я упомянул выше.

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 17:03 10-08-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976
Юзер не видит никаких номеров. И вообще не участвует в вычислении номера. Все делается автоматом. При условии использования чекбоксов.  
Нам ведь не нужен ряд номеров без пропусков. Для сорта пойдет массив и с пропущенными номерами.  
Кликнул - получил номер в невидимом столбце. Передумал, кликнул убрать чекбокс - удалили номер. Позже передумал, решил опять добавит - получил новый номер.
При таком подходе возможно этот "передуманный" автор окажется не на желаемом месте. Но IMHO реализация соответствует описанию.
Цитата:
Важен именно порядок их выбора!
Можно добавить ручную подсортировку, как 2-й необязательный шаг. Дать юзеру возможность менять позиции в листе(не в гриде). Как в любом download manager - передвинуть up or down  

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 21:08 10-08-2009 | Исправлено: dneprcomp, 21:10 10-08-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
При условии использования чекбоксов.

Ведь я об условии раньше уже сказал - это единственная разумная реализация поставленной задачи.
dneprcomp, вот как выглядит промежуточный рабочий вариант (значения в ячейках таблицы - с "потолка"):
 
   
 
Заодно удалось избавиться от рамки вокруг чекбокса.

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 00:38 11-08-2009 | Исправлено: jek1976, 00:42 11-08-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976
Не понял каким образом определяется очередность выбора?
 
А ведь можно сделать еще интереснее. На каждое изменение чекбокса пересортировывать лист по невидимому полю с номерами. Так что сразу будет видна очередность авторов.

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 04:35 11-08-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
А ведь можно сделать еще интереснее. На каждое изменение чекбокса пересортировывать лист по невидимому полю с номерами. Так что сразу будет видна очередность авторов.
Для этого логичнее будет перемещать записи с выбираемыми ФИО авторов - в другую таблицу. Если не сделать такого разделения на две таблицы, то будет каша...
 

Цитата:
Не понял каким образом определяется очередность выбора?
Код выложу, пока его еще не доделал.

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 04:41 11-08-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
jek1976

Цитата:
Если не сделать такого разделения на две таблицы, то будет каша...  
Не уверен, что будет. Пересортировка будет перемещать всю строку. Отсортировать можно по двум полям. Первое - по невидимому полю. Второе - по фамилии. Таким образом сверху вседа будут все отмеченные по порядку их выбора. А за ними все остальное по алфавиту.
Впрочем, хозяин - барин

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 06:10 11-08-2009 | Исправлено: dneprcomp, 06:12 11-08-2009
jek1976



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Добавил выделение цветом той строки, на которой поставлена галка в чекбоксе. В принципе - пока меня это удовлетворяет. Посмотрим далее, как это будет удобно/неудобно в работе.
 
Добавлено:
dneprcomp
Вопрос немного в сторону от темы.
Пусть имеется модуль, в котором организованы две процедуры - Proc1 и Proc2. В каждой из этих процедур объявлены (оператор Dim) по одной локальной переменной с одинаковыми именами.
Вопрос: эти две локальные переменные, находящиеся в разных процедурах, как-нибудь связаны друг с другом, то есть "знают" ли они о существовании друг друга?

Всего записей: 1057 | Зарегистр. 15-04-2005 | Отправлено: 16:33 11-08-2009
dneprcomp



Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
эти две локальные переменные, находящиеся в разных процедурах, как-нибудь связаны друг с другом, то есть "знают" ли они о существовании друг друга?

Нет, не знают

Всего записей: 3920 | Зарегистр. 31-03-2002 | Отправлено: 21:34 11-08-2009
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2 3 4 5 6 7 8 9

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Visual Basic 6


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru