Visual Basic, .NET, ASP, VBScript
 

   
 
Описание для автора не найдено
 
     
   
 

 Использование True DBgrid при создании приложений для управления базами данных на Visual Basic 6.0 (Часть1)

 

Введение

Visual Basic (здесь и далее, если не указано иначе, имеется в виду Visual Basic 6.0) является весьма удобным и относительно простым средством для разработки приложений для управления базами данных. Причем размер БД особой роли не играет, и VB одинаково эффективно справится с любым. Мой, почти восьмилетний опыт работы с VB показывает, что практическая любая область человеческой деятельности может быть оптимизирована при помощи базы данных. На сегодняшний день приложения для управления БД являются лидирующими в прикладном программировании, и они крайне необходимы во всех предприятиях и организациях.

 

Почему не VB.NET?

VB.NET, без сомнения, является современной и крайне эффективной платформой. Во многих случаях результат программирования на VB.NET превосходит результат, полученный, при помощи VB 6.0. Однако сейчас говорить о массовом переходе на платформу NET, во всех ее проявлениях, вряд ли приходится. Возможно с переходом на Windows 2003 (хотя 2003 и не позиционируется как система для настольного компьютера) или на ожидаемый Longhorn, платформа NET придет на компьютеры массового пользователя. Тогда программисты будут вынуждены перейти на платформу NET, но до этого пройдет еще лет 5 (не меньше).

 

Что такое True DbGrid?

Понятно, что наиболее эффективный способ представления структурированной информации – это таблица. Не зря ведь электронные таблицы, в свое время, произвели фурор в информационном сообществе. Чаще всего и данные из БД представляют в виде, очень похожем на электронные таблицы. Всю эту и многую другую функциональность предоставляют так называемые  Grid. В комплекте с Visual Studio поставляются достаточно удобные GridMSFlexGrid и DataGrid. При создании простого приложения целесообразнее использовать именно их. (Обычно используют MSFlexGrid). Подавляющее большинство Grid, наряду со стандартными возможностями, обладают всякими «вкусностями»: начиная от возможности раскрашивания столбцов, строк и ячеек, и, заканчивая, возможностями помещения в ячейки рисунков, импорт/экспорт данных и так далее. Часто необходима возможность редактирования данных непосредственно в самом Grid, прямо на форме.

 

Примечание. Раз уж речь зашла о редактировании данных прямо в Grid, то хотелось бы высказаться по этому поводу.  Вообще-то я не приветствую непосредственное редактирование данных. Проблема в том, что контроль над их целостностью и качеством выполнить в таком случае весьма затруднительно. Правильность ввода приходится проверять мгновенно, возможно даже накладывая ограничения на уровне БД. При этом вполне может возникнуть ситуация, когда пользователь ввел неверные данные и получил сообщение об этом, но вот беда отказаться от их ввода можно только по нажатию клавиши ESC. Любая другая попытка покинуть ячейку, с неверно введенными данными, будет пресечена бдительными процедурами проверки, и сообщение появится вновь. С этим можно и смириться, но как-то не аккуратно, не по-современному. Гораздо лучше, если редактирование строки (читай записи БД) выполняется в отдельной форме, которая вызывается по нажатию специальной кнопки на форме (можно по двойному щелчку мыши по нужной строке). Тут есть простор для творчества программиста, а самое главное, пользователь вполне может закрыть форму и отказаться от применения изменений, не вызывая функций проверки целостности. Понятно, что такая функциональность программы целиком и полностью лежит на плечах программиста, что не может не сказаться на сложности программы, но игра стоит свеч. Программный продукт, построенный таким образом, приобретает профессиональные черты, которые пользователь, без сомнения, оценит.

Есть и другая сторона медали у непосредственного редактирования данных в Grid. Практика программирования показывает, что, как правило, данные, которые пользователь видит в Grid, основаны на достаточно сложной, НЕОБНОВЛЯЕМОЙ инструкции Select. Поэтому редактировать непосредственно такой Grid не представляется возможным.

 

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

True DbGrid изначально создавался компанией APEX, однако с 2000 года он выпускается по маркой компании CompontOne (в которую также вошла компания VideoSoft, о компонентах которой речь еще впереди). На сегодня True DbGrid существует в версии 8.0, но я использую версию 7.0. Предполагаю, что большинство приведенного в данной статье vb-кода c успехом будет работать и в версии 8.0. Возможности True DbGrid настолько обширны, что нет ни одной задачи, которой мне не удалось бы решить с его помощью. Еще один плюс заключается в том, что в комплекте с True DbGrid поставляется большое количество примеров на VB. Их изучение сильно облегчает процесс привыкания и эффективного использования компонентов.

 

*.MDB или MS SQL Server?

Вопрос о выборе формата БД – вечный вопрос. На эту тему написано много книг и статей и по-прежнему однозначного ответа нет. И все же что выбрать? Мой опыт показывает: если приложение однопользовательское, или если пользователей не много, например три, если объем данных (записей в БД) не превышает 50000 строк можно смело выбрать формат MDB. Работать с ним приятно и удобно. Никаких серьезных трудностей при этом нет.

Если количество пользователей у БД три и более, если количество записей исчисляется сотнями тысяч, то однозначный выбор в пользу MS SQL Server.

Примечание. В мире есть еще ряд платформ типа клиент-сервер. Oracle и Informix – две наиболее известные из них. Для обеих выпускаются драйверы доступа к данным для VB. Informix для России экзотика, выбирать эту платформу стоит только при крайней необходимости и только тогда, когда нужно подключаться из VB к уже существующей базе данных.  Oracle сейчас используется, по-моему, в структуре «Сбербанка».  На этом список систем клиент-сервер не заканчивается, но в связке с VB логично использовать MS SQL Server.

Хочу обратить ваше внимание на то, что MS SQL Server существует в нескольких вариантах. Более подробно об этом можно почитать на www.microsoft.com. В принципе, если объем данных относительно небольшой и нет специально выделенного сервера, есть смысл присмотреться к MSDE. Это урезанный вариант MS SQL Server, зато абсолютно бесплатный. Он имеет ограничение на размер БД – 2 Гбайта. Во многих случаях этого хватит, тем более что для его запуска не нужна серверная версия Windows. Кроме того, имеются также версии: standard и evaluation. Они также вполне способны обеспечить потребности пользователей и программистов в подавляющем большинстве случаев. Версия Enterprise Edition, активно распространяющая хакерами, применяется только для обработки очень больших объемов данных и показывает наивысшую производительность только на многопроцессорных машинах (максимум 32), под управлением кластерными системами Windows. Во всех остальных случаях ее эксплуатация на обычном ПК, даже под управлением Windows 2000 Server будет пустым расточительством ресурсов.

 

Работаем с True DbGrid

В процессе рассмотрения вопросов использования TrueDbGgrid мы будем создавать реальное приложение, работающее с реальной базой данных. Вопросы о том, как создать приложение на VB я, естественно, пропускаю. Это вы должны уже знать.

TrueDbGgrid существует в нескольких реализациях, для подключения через разных провайдеров.

 

TDBG7.OCX

Built-In Data Control

Remote Data Control

TODBG7.OCX (OLE DB)

ADO Data Control

Data Environment

Remote Data Services

Tabular Data Control

True Data Control

 

Из всех перечисленных провайдеров наиболее применим на практике OLEDB в связке с ADO (ActiveX Data Object). Работать с ними удобно, в Интернете можно найти много статей по их использованию, а профессиональные авторы написали немало книг. OLE DB и ADO – это современные интерфейсы программирования доступа к данным.

 

Для использования TrueDbGgrid нужно поставить соответствующую галочку в окне Components, которое вызывается нажатием правой кнопки мыши на панели TollBox. Также следует включить True Data Control Lite и Microsoft ADO Data Control.


 

 

Далее необходимо поставить ссылку на ADO. Для этого следует выполнить Project-References:

 

 

 

 


 

Вы вполне можете использовать не ADO, а, например, DAO (или любой другой подходящий интерфейс доступа), но тогда вам придется переработать код, приведенный в статье под эту платформу.

Какую версию ADO выбирать для работы? Ответ один – самую последнюю. Кстати, на www.microsoft.com ADO можно скачать абсолютно бесплатно. Искать следует mdac_typ.exe. Не стоит забывать, что в нашей БД будут использовать национальные символы (кириллица), а это, как известно, может вызывать проблемы сортировки, выборки и так далее. С каждой версией ADO подобные ошибки исправляются, впрочем, появляются и новые.

 

Предварительный этап закончен. Теперь осталось только выбрать БД для работы. Все примеры в данной статье будут работать с БД MS Access. Естественно нового я ничего создавать не буду. Воспользуюсь готовой базой телефонных номеров, которая у меня есть и уже используется. Описание таблиц БД смотрите в приложении. Понятно, что у вас такой БД нет в наличии, но ее можно создать, в соответствии с описанием, и «забить» подходящими данными.

 


Расположите на форме элементы управления TrueDbGgrid, как вам это будет удобно, а также ADODC и TDataLite.

 

 

 

По-моему получилось неплохо!

 

«Ресайзинг» TrueDbGgrid

Теперь приложение можно запустить.



Понятно, что объекты ADODC и TDataLite отображаться не должны. Точнее они могут отображаться и их можно использовать для навигации (как в ACCESS), но на практике так делают редко. Поэтому устанавливаем каждому объекту свойство Visible=False. Кстати у TDataLite, кроме кнопок навигации, имеется много других кнопок

 

Их набор можно менять, если вызвать свойство Custom объекта.


 

Назначение большинства кнопок очевидно. Средства поиска и постановки закладок не применимы в российских условиях, так как вызывают окна, интерфейс которых выполнен по-английски. Эти средства, если они нужны конечному пользователю, придется разрабатывать вручную. Нам же наиболее интересен режим Query Mode. Собственно ради него мы и используем TDataLite. Это встроенные средства поиска (фильтрации) данных в TrueDbGgrid. Использовать его крайне удобно, кроме того, такой режим поиска применяется во многих профессиональных БД, разработанных за рубежом.

 

После запуска приложения мы уже столкнулись с первой проблемой, связанной с TrueDbGgrid. При изменении размеров формы, размеры TrueDbGgrid не меняются. Это очень неудобно. Добавим соответствующий код в модуль формы VB.

 

Private Sub Form_Resize()

On Error Resume Next

If Me.Width < 3500 Or _

Me.Height < 3500 Then

            Me.Height = 3600

            Me.Width = 3600

             Exit Sub

End If

 

Me.TDBGrid1.Width = Me.Width - 570

Me.TDBGrid1.Height = Me.Height - 1700

 

End Sub

 

Обратите внимание, что внизу формы я преднамеренно оставил место, здесь в будущем появятся кнопки управления.

У приложения появляются профессиональные черты, но до Microsoft нам еще далеко. Следующий момент, связанный с «ресайзингом», это запоминание последнего размера и местоположения окна. Эта проблема легко решается средствами VB.

 

Private Sub Form_Unload(Cancel As Integer)

    Dim i As Integer

 

 

    If Me.WindowState <> vbMinimized Then

        SaveSetting "slugba2004", "Settings", "MainLeft", Me.Left

        SaveSetting "slugba2004", "Settings", "MainTop", Me.Top

        SaveSetting "slugba2004", "Settings", "MainWidth", Me.Width

        SaveSetting "slugba2004", "Settings", "MainHeight", Me.Height

    End If

   

       'закрываем все открытые окна

    For i = Forms.Count - 1 To 1 Step -1

        Unload Forms(i)

    Next

End Sub

 

 

 

 

Private Sub Form_Load()

 

On Error Resume Next

 

    Me.Left = GetSetting("slugba2004", "Settings", "MainLeft", 1000)

    Me.Top = GetSetting("slugba2004", "Settings", "MainTop", 1000)

    Me.Width = GetSetting("slugba2004", "Settings", "MainWidth", 6500)

    Me.Height = GetSetting("slugba2004", "Settings", "MainHeight", 6500)

 

End Sub

 

Первая процедура записывает текущие размеры и положение окна на момент закрытия. Вторая – восстанавливает, записанные в реестр, значения при запуске приложения. Честно говоря, я пока и слова не написал собственно про БД и TrueDbGgrid. Все что рассмотрено выше относится к фундаментальным основам VB, но и их повторить не грех!

Подключение к данным и связывание элементов управления

Чтобы приложение правильно заработало, необходимо последовательно связать элементы управления на форме. Источником данных (собственно объект Connection) является ADODC, возвращающая Recordset, который мы должны передать объекту TDataLite. Для этого свойству DataSource объекта TDataLite присваиваем значение Adodc1, его можно выбрать из раскрывающего списка. Напомню, что TDataLite мы используем только для режима Query Mode, который нам в дальнейшем понадобиться. Кстати, полная версия TDataLite, называемая True Data (TD) имеет все необходимое для установления связи с данными, что позволяет отказаться от Adodc.

Понятно, что TDataLite также возвращает объект Recordset, который необходимо передать в TrueDbGgrid. Для этого свойству DataSource объекта TrueDbGgrid необходимо присвоить значение TDataLite1. Обратите внимание, что выбрать можно не только TDataLite1, но и Adodc1, это еще раз подтверждает, что эти объекты, грубо говоря, работают с объектом Recordset и его же возвращают.


 

Линейка связей построена, теперь необходимо выполнить подключение объекта Adodc1 непосредственно к данным. Здесь следует иметь в виду, что принципиально бывает два вида подключений к БД. Первый – это подключение, выполненное на этапе разработки, необходимое лишь для удобства программиста и второй – подключение, выполненное в режиме Run-Time, то есть в процессе работы программы. В первом случае программист сам вручную, на этапе разработки указывает тип БД (провайдера) и путь к ней. Понятно, что у реального пользователя путь может быть любым (в том числе и тип БД, но это, как правило, жестко оговаривается). Поэтому в качестве пути к БД можно использовать данные, которые ранее были записаны, например, в конфигурационный файл, реестр или этот путь каждый раз (или единожды) запрашивается у пользователя. Выбор здесь огромен, я не буду на этом останавливаться, и буду считать, что путь у меня всегда один и тот же.


Для правильной настройки подключения следует вызвать свойство Custom объекта Adodc1. 

 

Выбираем пункт Use Connection String. Строка подключения имеет стандартный синтаксис. В принципе, нажав на кнопку Build, можно последовательно построить ее, выбирая необходимые пункты. С другой стороны, на практике проще запомнить основные строки подключения к наиболее распространенным форматам данных.

 

В нашем случае для БД в формате ACCESS используем следующую строку:

 

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\kross\krossav.mdb;Persist Security Info=False

 

Если необходима аутентификация пользователей (что в принципе для формата MDB применяется редко) используем следующее:

 

Provider=Microsoft.Jet.OLEDB.4.0;Password=111;User ID=User;Data Source=C:\kross\krossav.mdb;Persist Security Info=True

 

Если значение Password не передавать, то при подключении к источнику, будет выскакивать соответствующее окно аутентификации, где пароль нужно будет вводить вручную.

 

При подключении к SQL Server используем следующую строку:

"PROVIDER=SQLOLEDB" & _

        ";SERVER=" & "tel" & _

        ";DATABASE=CDR_SI" & _

        ";TRUSTED_CONNECTION=YES"

 

Понятно, что в каждом конкретном случае значения параметров будет разное. Прочитать полное описание формата ConnectionString можно на сервере www.msdn.microsoft.com.

 

Перейдем на вкладку RecordSourse.


Если на первом этапе мы указали тип БД и путь к ней, то теперь пришло время указать конкретные данные, которые необходимо показать в TrueDbGgrid. Adodc может получать данные непосредственно из таблицы, для этого в Command Type выбираем пункт 2-adCmdTable, а в списке Table or Stored Procedure Name выбираем таблицу. Обратите внимание на то, что если строка Connection String сформирована неверно, то таблицы в списке не появляются.

Практика показывает, что данные, выводимые на обозрение пользователя, формируются на основе нескольких таблиц. Делается это средствами языка SQL. (Имеется ввиду конструкция JOIN (LEFT, RIGHT, INNER).

 

Я хочу связать две таблицы: tblKross (с данными по кабельному распределению абонента) и tblNSIAbonent (в которой указаны наименование абонента и его адрес). Связь между таблицами выполним по полю Nomer (номер абонента). Так как в обеих таблицах имеется ограничение уникальности по полю Nomer можно воспользоваться конструкцией INNER JOIN. SQL запрос будет выглядеть так:

 

SELECT tblKross.Nomer, tblKross.Skaf, tblKross.Polosa, tblKross.Raspred, tblNSIAbonent.Abonent, tblNSIAbonent.Address

FROM tblKross INNER JOIN tblNSIAbonent ON tblKross.Nomer = tblNSIAbonent.Nomer;

 

Примечание. Вы можете создавать запросы средствами ACCESS, а затем просто переносить их в код VB. Более того, сложные запросы можно сохранять в файле MDB, а затем связывать с ними Adodc. С точки зрения ADO, запросы на выборку, сохраненные в файле MDB – это тоже таблицы. Используя этот механизм можно создавать сложные запросы с вычисляемыми полями, возложив их обработку целиком и полностью на ADO, а в программе писать короткие запросы на выборку из них.

 

Чтобы в качестве источника данных указать SQL запрос, в списке Command Type выбираем 1-adCmdText, а в качестве значения Command Text указываем SQL запрос.

 

Подключение к БД можно осуществить и в режиме Run-Time. Для этого следует свойству ConnectionString объекта Adodc1 присвоить соответствующее значение, а свойству RecordSource присвоить вышеуказанный запрос SQL.  Код можно добавить в процедуру Form_Load, но при необходимости подключение можно выполнить в любом другом месте программы. Кстати, если вы используете подключение в режиме Run-Time, то после завершения этапа программирования, лучше удалить и строку подключении и SQL запрос, которые мы внесли в форму свойств объекта Adodc1. В противном случае возможна ситуация, когда Adodc1 будет генерировать ошибку до того как будет выполнено программное подключение к БД.

 

Me.Adodc1.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data “ & _

“Source=C:\kross\krossav.mdb;Persist Security Info=False"

 

В качестве значения параметра «Sourсe» нужно передать реальный путь к БД.

 

Me.Adodc1.RecordSource = "SELECT tblKross.Nomer, tblKross.Skaf, “ & _

"tblKross.Polosa, tblKross.Raspred, tblNSIAbonent.Abonent, “ & _

“tblNSIAbonent.Address " & _

"FROM tblKross INNER JOIN tblNSIAbonent ON tblKross.Nomer = “ & _

“tblNSIAbonent.Nomer"

 

Me.Adodc1.Refresh

 

В дальнейшем, когда мы запрограммируем таймер, строку с Refresh можно (и даже нужно) удалить.

 

Все, приложение можно запустить.

 

 


Приложение заработало. Обратите внимание на то, что данные в таблице можно редактировать, и они успешно записываются в БД. Чтобы запретить редактирование достаточно просто в Adodc1 изменить свойство LockType на 1-adLockReadOnly.

Свойство LockType, кроме значения 1-adLockReadOnly может принимать следующее значения:

 

4 – adLockBatchOptimistic

Оптимистическая блокировка с пакетным обновлением

3 – adLockOptimistic

Оптимистическая

2 – adLockPessimistic

Пессимистическая

-1 – adLockUnspecified

Без блокировки, используется для клонированных Recordset

 

Немного о блокировках. С точки зрения разработчика организовать пессимистическую блокировку гораздо проще. Ее суть состоит в том, что при открытии курсора (в нашем случае Recordset) строки обновляемого набора данных блокируются для монопольного доступа и остаются заблокированными до тех пор, пока курсор не выйдет из блокировки. Такая блокировка неудобна для пользователей, поскольку одна и более строк, необходимых пользователю, могут оказаться надолго заблокированными другим пользователем. Оптимистическая блокировка более удобна пользователю, но ее сложнее реализовать. Эта технология основывается на предположении, что другие пользователи, скорее всего, не будут пытаться обновить строку, с которой работает текущий пользователь. Поэтому на запись блокировка не устанавливается. В тоже время, все же существует вероятность, что другой пользователь обновит строку. В таком случае приложение должно само проверить, не произошло ли изменение строки, перед ее сохранением. Реализовать программно это достаточно сложно, но на радость программистов, фирма ComponetOne, создавая TrueDbGgrid, уже обо все этом позаботилась. Работает TrueDbGgrid (точнее не TrueDbGgrid, а TDataLite),  по умолчанию, в режиме оптимистической блокировки (может это и не блокировка вовсе) и в случае необходимости выводит сообщение об ошибке. Обратите внимание, что и у TDataLite, и у Adodc имеются свойства для установки типов блокировок. Очень желательно устанавливать для них одинаковое значение. Практика показывает, что можно смело выставить оптимистическую блокировку. Компоненты все сами сделают и сгенерируют ошибку, которую можно перехватить и обработать.

Не стоит забывать, что ошибка генерируется при попытке сохранить запись. И продолжить процесс сохранения без обновления состояния Recordset невозможно. В тоже время обновление приведет к потере изменений, которые пользователь сделал, но еще не сохранил. Поэтому, правильно, при появлении ошибки блокировки, сохранять обновляемую запись, например, в буфер обмена, как это предлагает делать Access. Из всего этого следует, что лучше записи непосредственного в TrueDbGgrid не редактировать. Об этом я и ранее говорил и сейчас повторяюсь.

 

Теперь поговорим про свойство CursorType в Adodoc. Объект Recordset в Adodc представляет собой результирующий набор строк, полученный в результате выполнения запроса к БД. И он бывает четырех типов, так называемых  курсоров: adOpenForwardOnly, adOpenKeyset, adOpenDynamic, adOpenStatic.

 

Курсор adOpenForwardOnly

            С последовательным доступом. Он допускает обновление данных, но только в текущей строке. Никакие изменения, вносимые пользователями в базовые таблицы, в объекте Recordset не отображаются.

 

Курсор adOpenStatic

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

 

Курсор adOpenKeyset

            Курсор типа Keyset создает локальный набор ключей, индексирующий результирующий набор строк запроса. Recordset, основанный на курсоре Keyset допускает обновление данных, но после заполнения строками никакие изменения, вносимые в таблицы уже более не отображаются.

 

Курсор adOpenDynamic

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

 

 

Какой тип курсора выбрать? В случае с БД в формате MDB, выбирать можно любой, так как ни один из них не будет обновляться динамически. Статический курсор из-за чрезмерной потребности в ресурсах лучше не использовать. В принципе оптимальным выбором будет динамический курсор.

 

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

 

Обновление TrueDbGgrid

При работе с БД состояние Recordset постоянно меняется, текущий пользователь изменяет, удаляет и добавляет записи. Другие пользователи сети также выполняют различные действия над данными. Как я уже сказал, даже динамический курсор в связке с MDB не выполняет автоматическое обновление Recordset. Более того, связка Adodc и TDataLite, даже при клиент-серверном подключении не всегда корректно выполняет обновление отображаемых данных. Для верности, программисту приходится вручную выполнять обновление TDataLite. Это одно из самых больших неудобств и еще один большой плюс в пользу True Data.

 

Примечание. True Data имеет все необходимые средства для автоматического обновления Recordset. Более того, имеются средства для фонового обновления, чтобы не отвлекать и не передергивать пользователя.

При использовании TDataLite я настоятельно рекомендую с обновлением Adodc выполнять программное обновление TDataLite, это сразу избавит вас от многих проблем, особенно если вы будете использовать специфическое оформление строк TrueDbGgrid, в зависимости от их содержимого (об этом дальше).

 

Наиболее просто выполнять обновление состояние Recordset по таймеру. Для этого воспользуемся соответствующим объектом и расположим его на форме. Свойство Interval установим равным 10000 (10 секундам).

Добавим следующий код к модуль формы:

 

Public Sub Timer1_Timer()

Dim book As Variant

Dim coll As Integer

 

On Error Resume Next

 

book = Me.Adodc1.Recordset.Bookmark

coll = Me.TDBGrid1.Col

 

           Me.Adodc1.Refresh

Me.TDataLite1.Refresh

 

Me.Adodc1.Recordset.Bookmark = book

Me.TDBGrid1.Col = coll

 

End Sub

Собственно, само обновление выполняется методом Refresh. Этот метод вызывает, кроме обновления Recordset, сброс текущего положения курсора в TrueDbGgrid, что, по меньшей мере, вызывает раздражение у пользователей. Проблема решается легко. Сначала запоминаем текущую строку в Recordset, а затем текущий столбец в TrueDbGgrid. Запоминать нужно именно строку в Recordset, а не в TrueDbGgrid. Так как новые строки в Recordset могут попасть выше текущего положения в TrueDbGgrid и оно, соответственно, сдвинется вверх.

Для определения текущего положения в Recordset воспользуемся свойством Bookmark. Единственный недостаток этого свойства заключается в том, что оно возвращает значение типа Variant. Придется с этим смириться. После обновления Adodc и TDataLite, восстановим текущее положение пользователя. Вот собственно и все.

 

Примечание. В ADO нет свойства OrdinalPosition, поэтому для определения текущего положения приходится пользоваться свойством Bookmark. Если нужно определить абсолютное положение курсора (имеется в виду курсора ввода данных), то необходимо, предварительно обновив Recordset, воспользоваться свойствами Row и Col TrueDbGgrid.

 

Обновление TrueDbGgrid выполняется автоматически.

 

Столбцы в  TrueDbGgrid

Если вы последовательно выполняли все действия, описанные в статье, то программа должна успешно запускаться и нормально работать. Думаю, что вы также обратили внимание на то, что TrueDbGgrid достаточно интеллектуальный компонент. Он сам добавляет столбцы, чтобы правильно отобразить нашу выборку. Вот только одно «но», столбцы имеют специфические названия, такие, какие возвращает инструкция Select. Все это выглядит не профессионально. Приведем TrueDbGgrid к привычному для пользователя виду.

Для этого вызываем свойство Custom TrueDbGgrid и перейдем на вкладку Columns. Здесь имеются три кнопки и дерево столбцов. Первая кнопка добавляет новый столбец в текущем месте, вторая – в конец списка столбцов, третья – предназначена для удаления выделенного столбца.

Для изменения заголовка столбца, его придется связать с соответствующим полем в БД (точнее с полем, которое возвращает инструкция Select), присвоив соответствующее значение свойству DataField.

 

 

 

 

 

 

 

 

 

 

 

 

 


Для изменения заголовка столбца следует изменить свойство Caption.


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

В режиме Run-Time все это тоже можно сделать. Проходим циклом по всем столбцам и в зависимости от значения свойства DataField присваиваем необходимые значения свойству Caption. Реализуется это на VB так:

 

For i = 0 To Me.TDBGrid1.Columns.Count - 1

    Select Case Me.TDBGrid1.Columns.Item(i).DataField

        Case "Nomer"

            Me.TDBGrid1.Columns(i).Caption = "Номер"

    End Select

   

Next i

 

Примечание. Как только вы меняете состояние столбца, TrueDbGgrid из автоматического режима переходит в ручной. Все столбцы добавляются и связываются с данными вручную. Чтобы вернуть автоматический режим, просто щелкните объект TrueDbGgrid на форме правой кнопкой мыши и выберите пункт Clear Fields.

 

 

На практике такой код, изменяющий названия столбцов TrueDbGgrid в режиме Run-Time используется редко. Гораздо проще все подготовить в режиме конструирования. Даже если в дальнейшем придется добавлять новые столбцы, то в обоих случаях программа потребует равнозначной переделки. И все же способ избежать ручного (программного) изменения названия столбцов есть. Делается это при помощи специального слова As в SQL запросе. Перепишем наш запрос на выборку данных и приведем его к следующему виду:

 

SELECT tblKross.Nomer As Номер, tblKross.Skaf As Шкаф, tblKross.Polosa As Полоса, tblKross.Raspred As Распределение, tblNSIAbonent.Abonent As Абонент, tblNSIAbonent.Address As Адрес

FROM tblKross INNER JOIN tblNSIAbonent ON tblKross.Nomer = tblNSIAbonent.Nomer;

 

Теперь этот запрос будет возвращать поля: Номер, Шкаф, Полоса, Распределение, Абонент, Адрес. Для корректной работы также необходимо выполнить перенастройку TDataLite (вот и еще один плюс в пользу True Data). Для этого откройте свойство Custom объекта TDataLite1. Перейдите на вкладку Fields и нажмите на кнопку Retrieve Fields. Теперь все столбцы будут называться так, как мы указали в запросе SQL. Как вы понимаете, при нажатии Retrieve Fields, все настройки полей пропадают и возвращаются к стандартным. Понятно, что это не очень удобно. Избежать этого можно только одним способом – определиться заранее, в самом начале этапа программирования, выбрав единый стиль: либо используем As, либо вручную добавляем столбцы и изменяем свойство Caption, либо делаем это в режиме Run-Time.

В конце концов, и SQL Server и Access позволяют в названии полей использовать кириллицу. Это последний и самый простой способ.

 

Примечание. Думаю, что нигде вы не найдете рекомендации называть поля в БД по-русски. До недавнего времени это было совсем невозможно. Профессиональные программисты никогда не позволяли себе таких вольностей. Наученный горьким опытом, я тоже никогда не называю поля по-русски. Впрочем, последние версии ADO очень корректно с ними работают, но ведь все может случиться и например, другой драйвер может отказаться с ними работать. С другой стороны, лучше ADO пока ничего нет.

 

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

Раскрывающий список в TrueDbGgrid

Для программирования раскрывающихся списков в комплекте с TrueDbGgrid поставляется дополнительная компонента TDBDropDown. Она будет просто незаменима, если в раскрывающемся списке нужно сделать несколько колонок. Таких ситуаций в жизни программирования я не встречал. Признаюсь честно. Если вам позарез необходимо сделать такой список, то я отправляю вас примеру №26 (Tutorial 26), который поставляется вместе с TrueDbGgrid. Использование TDBDropDown ничем не отличается от стандартного TrueDbGgrid, все свойства его те же самые. Для связывания столбца TrueDbGgrid с TDBDropDown достаточно изменить свойство DropDown для соответствующего столбца, выбрав подходящий TDBDropDown из списка. Чтобы в TrueDbGgrid сразу отображалось подходящее значение из списка, а не его ключевой элемент (это может быть как цифра, так и текст) просто включите флажок ValueTranslate в свойствах TDBDropDown.

 

Как я уже сказал, использовать TDBDropDown рекомендуется только в редких, исключительных случаях. Во всех остальных с легкостью можно воспользоваться свойством Values TrueDbGgrid.

 

Свойство Values позволяет, не только отображать список, но и рисунки в ячейке, а также RadioButton и CheckBox. В примере №7 (Tutorial 7) показывается использование раскрывающегося списка.

 

 

 

Основное преимущество свойства Values заключается в очень простом механизме изменения его в режиме Run-Time. Покажу это на примере, хотя к нашей программе это не относится. Для добавления значений в список используется следующий простой код:

 

 

 

Dim Item As New TrueOleDBGrid70.ValueItem

 

Переключаемся в режим раскрывающегося списка

TDBGrid1.Columns(2).ValueItems.Presentation = dbgComboBox

 

‘очищаем список

TDBGrid1.Columns(2).ValueItems.Clear

 

for i=1 to 5

    With TDBGridSkaf.Columns(2).ValueItems

         Item.Value = i

         Item.DisplayValue = i+10

         .Add Item

    End With

Next i

 

‘включаем режим автоматического выбора значения из списка в зависимости от ‘значения в ячейке

 

      TDBGrid1.Columns(2).ValueItems.Translate = True

 

‘включаем режим автоматического завершения набираемого текста, как в Excel

TDBGrid1.Columns(2).AutoCompletion = True

 

Добавим этот код в процедуру Form_Load.

 

В нашем случае раскрывающийся список не нужен, но его ключевое значение 2 совпало со значением в одной из ячеек и так как свойство Translate = True, то значение 2, как и положено, было заменено на 12, при этом сам ключевой столбец в раскрывающемся списке не отображается. Понятно, что список можно заполнять любыми значения, в том числе и основанными на любом объекте Recordset. Другие возможности свойства Value смотрите в справе к TrueDbGgrid в разделе Automatic Data Translation with ValueItems.

 

Поиск в TrueDbGgrid

Мы не закончили работать с интерфейсом TrueDbGgrid. Но сейчас переключимся на другую задачу, которая не менее важна, - поиск данных. Вспомним, что именно для этого вы расположили на форме объект TDataLite1. Давайте воспользуемся его весьма удобными и мощными средствами поиска.

Поиск в TDataLite организован по принципу предварительного запроса. Другими словами, при переходе в режим запроса, данные с сетки TrueDbGgrid исчезают (они не пропадают, они просто скрываются), а пользователь вносит в сроку необходимые данные для выполнения фильтрации. При переключении в нормальный режим просмотра данные в TrueDbGgrid предстают уже в отфильтрованном виде. Вообще слово «Поиск» здесь не совсем уместно, правильнее говорить фильтрация. Применительно к базам данных «Поиск», как таковой, это не очень удобное средство, так как данных в таблице очень много, и указать какой либо уникальный признак, для однозначной идентификации записи, весьма трудно, поэтому и была придумана фильтрация, позволяющая достаточно легко выйти из положения.

Добавим на форму элемент управления CheckBox (Check1). Свойство Style переключим в режим 1-Graphical. Флажок превратиться в кнопку, которая умеет «залипать». Также следует, рядом с кнопкой, расположить надпись Label1. В модуль формы добавляем следующий код:

 

Private Sub Check1_Click()

On Error Resume Next

 

‘проверяем в каком режиме мы находимся

If Me.TDataLite1.QueryMode = False Then

в режиме нормального отображения данных

 

переключаемся в режим запроса

    Me.TDataLite1.QueryMode = True

 

‘ информируем об этом пользователя

    Me.Label1.Caption = "Запрос..."

    Me.Label1.ToolTipText = "Сброс фильтра"

    Me.Label1.Enabled = True

 

‘ выполняем сброс Recordset

    Me.Adodc1.Refresh

    Me.TDataLite1.Refresh

 

останавливаем таймер

    Me.Timer1.Enabled = False

   

 

Else

‘ в режиме запроса

 

‘ переключаемся в режим нормального отображения данных

Me.TDataLite1.QueryMode = False

 

выполняем сброс Recordset

   Me.Adodc1.Refresh

   Me.TDataLite1.Refresh

 

переключаем состояние кнопки

        Me.Check1.Value = 0

 

        If Me.TDataLite1.QueryFilter <> "" Then

               ‘ если значение фильтра было установлено

              

   ‘ информируем об этом пользователя

  

   Me.Label1.Caption = "Фильтр!!!"

               Me.Label1.ToolTipText = "Сброс фильтра"

 

   ‘ запускаем таймер

               Me.Timer1.Enabled = True

        Else

               ‘ если значение фильтра не было установлено, пользователь

                     ‘ ничего не ввел

 

   ‘ снимаем все сообщения о фильтре          

               Me.Label1.Caption = ""

               Me.Label1.ToolTipText = ""

               Me.Check1.Enabled = True

               Me.Label1.Enabled = False

 

   ‘ выполняем сброс Recordset

               Me.Adodc1.Refresh

               Me.TDataLite1.Refresh

 

 

  ‘ запускаем таймер

              Me.Timer1.Enabled = True

        End If

End If

 

  ‘ вызываем корректное обновление

  ‘ Recordset, как сделано в таймере

 

Call Timer1_Timer

 

End Sub

 

На первый взгляд количество Refresh несколько избыточно, но практика показала, что в некоторых случаях TrueDbGgrid ведет себя не всегда корректно. В первую очередь это связано с длинной цепочкой передачи Recordset по объектам. Поэтому, можно сказать, опытным путем, «через тернии к звездам», была подобрана подходящая комбинация Refresh. Кстати, в нашем случае, везде, где выполняется Refresh Recordset, можно вставить строку Call Timer1_Timer, но на практике в событии таймера могут быть запущены другие операции, которые не желательно выполнять при включенном режиме фильтра.

 

При изменении размеров формы кнопка «Фильтр» не будет перемещаться вниз. Добавим соответствующий код в процедуру Form_Resize.

 

Me.Check1.Top = Me.Height - 1300

Me.Label1.Top = Me.Height - 1200 

 

Для фильтрации записей, нажимаем на кнопку Фильтр, вводим нужные значения в соответствующие поля и снова нажимаем кнопку Фильтр.

 

И вот что у нас получится, если в качестве значения фильтрации в столбец «Шкаф» ввести единицу:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Как отказаться от фильтрации? Это можно сделать просто еще раз нажав на кнопку «Фильтр» и удалить введенные ранее значения. И снова нажать на кнопку «Фильтр». Жизнь пользователю можно облегчить. Добавим следующий код в модуль формы:

 

Private Sub Label1_Click()

Dim i As Long

On Error Resume Next

 

обновление Recordset

Me.Adodc1.Refresh

Me.TDataLite1.Refresh

 

переключаемся в режим запроса

Me.TDataLite1.QueryMode = True

 

‘пробегаем все поля и удаляем значения фильтра

For i = 0 To TDataLite1.Fields.Count - 1

    Me.TDataLite1.Fields(i) = ""

Next i

 

 

удаляем сообщения о фильтре

Me.Label1.Caption = ""

 

 

‘ возвращаем на место кнопку

If Me.Check1.Value = 0 Then

           

Else

            Me.Check1.Value = 0

End If

 

‘ переключаемся в режим нормального отображения данных

Me.TDataLite1.QueryMode = False

 

вызываем процедуру таймера

Call Timer1_Timer

 

End Sub

 

Теперь, если пользователь щелкнет мышью Label1, когда в нем отображается «Фильтр!!!» или «Запрос…», то Recordset обновляется и фильтр сбрасывается. Пользователь увидит содержимое TrueDbGgrid в первозданном виде.

Почему Componentone не ввела функцию очистки фильтр, остается только гадать? Если вы внимательно изучили код, то, наверное, обратили внимание, что эта функциональность TrueDbGgrid, представляет собой, удобный способ задания строки для свойства TDataLite1.QueryFilter, которая, в свою очередь, передается свойству Filter ADO. Метод Refresh вызывает сброс фильтра, но только у ADO, поэтому для сброса фильтра в TDataLite1 приходится программно «пробегать» по полям TrueDbGgrid, и очищать их от введенных значений.

 

По-моему получилось очень неплохо.

 

Задание свойств для режима фильтрации

В приведенном выше примере данные фильтровались на полное соответствие значению фильтрации. Это удобно для числовых полей. Для строковых данных удобнее фильтровать на соответствие начала строки или любого вхождения. TDataLite обладает всеми необходимыми настройками. Откройте свойство Custom  объекта TDataLite (черт возьми, ведь нет такого свойства «Custom», но как еще опишешь, что нужно открыть?). Перейдите на вкладку Fields. В списке полей выберите поле «Abonent», в списке Query Operation выберете условие “starts with”. Нажмите кнопку ОК. Теперь фильтрация в режиме Query Mode по столбцу Абонент будет осуществляться по началу содержимого колонки. Если выбрано условие «contains» - ищется любое вхождение образца. Работа других условий очевидна.

 

Примечание. Нажатие на кнопку Retrieve Fields приведет к сбросу всех настроек полей.

 

Условия фильтрации на этапе конструирования

TDataLite предоставляет программисту возможность на этапе конструирования формы указать фиксированные фильтры данных. Изменять эти фильтры, в режиме Run-Time, невозможно, но их можно программно включить и выключить. Параметров фильтрации может быть сколь угодно много (ограничения накладываются только синтаксисом SQL) и связываются они между собой условием AND.

Чтобы добавить условие фильтрации снова откройте свойство Custom и перейдите на вкладку Filters. Нажмите кнопку New. После этого вызовите построитель выражений (как в Access) поля Filter Expression (кнопка с троеточием). Постройте следующее выражение (его можно просто от руки ввести в поле Filter Expression) Skaf  = 1. На вкладке General включите флажок Filtered. Приложение можно запустить. Значение свойства Filtered можно менять в режиме Run-time.

По-моему результат очевиден. Собственно, у TDataLite имеется много подобных средств, предназначенных для того, чтобы не писать сложных инструкций SQL вручную. Часто на SQL это сделать проще, а пользоваться средствами TDataLite следует только в том случае, если в процессе работы с приложением необходимо оперативно переключаться между двумя режимами просмотра данных.

 

Оформление строк в TrueDbGgrid

Основная проблема стандартных Grid заключается в относительно слабых средствах визуального оформления строк, в зависимости от их содержимого. Например, необходимо выделить цветом строки, которые должны наиболее сильно привлекать внимание пользователя. TrueDbGgrid имеет достаточно мощные средства для оформления строк. Наиболее простой вариант оформления – это чередование строк разных цветов. Этот режим часто применяют для длинных списков. Для включения этого режима вызовите свойство Custom TrueDbGgrid, на вкладке Splyts поставьте галочку свойству AlternatingRowStyle (для изменения состояния флажка можно дважды щелкнуть строку свойства). Для изменения внешнего вида строк нужно изменить свойства узлов EvenRowStyle и OddRowStyle. Менять можно практически все. В нашем примере изменим для узла EvenRowStyle свойство BackColor, на… любой!

Как видите, свойств, которые можно изменять очень много. В случае с чередованием строк все это можно сделать в режиме конструирования формы, но подавляющее большинство изменений требуется вносить в процессе выполнения программы, в режиме Run-Time. Об этом и пойдет речь дальше. А пока приложение можно запустить.

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Понятно, что красный фон – это не самый удачный выбор, но для примера этого достаточно.

Следующий этап, гораздо более сложный, это раскрасить строки в зависимости от условия и сделать это в режиме Run-Time. Поставим себе задачу: в строках, где поле «Шкаф» имеет значение 1, шрифт сделать синим. При этом, при изменении номера шкафа, строка должна возвращаться к нормальному стилю отображения и снова становиться синей, если изменить номер шкафа на 1. Чересстрочную раскраску при этом отменим, сняв галочку AlternatingRowStyle.

Принцип применения индивидуального стиля к строкам заключается в том, что TrueDbGgrid «умеет» генерировать событие при прорисовке каждой строки и передавать в него текущую позицию в Recordset. Событие генерируется только для строк, которые будут видны в данный момент в TrueDbGgrid. Это увеличивает производительность применения стилей. Событие будет сгенерировано вновь, если в TrueDbGgrid нужно отобразить новую строку или группу строк. И все же, при отображении длинных списков, не следует загружать процедуру обработки события прорисовки, сложным VB-кодом, чтобы производительность программы осталась на приемлемом уровне. Достаточно объемно эта функциональность TrueDbGgrid рассмотрена в примере №11 (Tutorial 11), но мы, конечно, уделим этому вопросу немного внимания.

Для того, чтобы, соответствующее, событие прорисовки, «зажигалось» на вкладке Splits окна свойства Custom TrueDbGgrid включите флажок у свойства FetchRowStyle. Теперь можно программировать.

Вначале программно создадим дополнительные стили оформления.

Определим следующие переменные на уровне модуля формы

 

Private OneOn As New TrueOleDBGrid70.Style

Private nonOne As New TrueOleDBGrid70.Style

Private RSClone As ADODB.Recordset

 

Добавим в процедуру Load_Form следующий код

 

    ‘ создаем новый стиль OneOn
    ‘ это будет синий шрифт

    Set OneOn = TDBGrid1.Styles.Add("OneOn")

    OneOn.ForeColor = vbBlue

 

 

    ‘ создаем новый стиль NonOne
    ‘ это будет черный шрифт (то есть вернуть все назад)

    Set nonOne = TDBGrid1.Styles.Add("NonOne")

    nonOne.ForeColor = vbBlack

 

      Call Timer1_Timer

 

Мы создали два новых стиля. Сделали это программно. Собственно говоря, это можно было сделать в режиме конструирования, но так интереснее.

Для обработки события прорисовки добавим следующий код:

 

Private Sub TDBGrid1_FetchRowStyle(ByVal Split As Integer, Bookmark As Variant, ByVal RowStyle As TrueOleDBGrid70.StyleDisp)

On Error Resume Next

‘ не будем применять стили если TrueDbGgrid наход. в режиме запроса

If Me.TDataLite1.QueryMode = True Then Exit Sub

 

‘ переходим на соответствующую запись в Recordset

    RSClone.Bookmark = Bookmark

 

‘ проверяем значение поля Шкаф и в зависимости от его содержимого применяем

стиль

    If RSClone("Skaf").Value = "1" Then

       RowStyle = OneOn

    Else

       RowStyle = nonOne

    End If

End Sub

 

В процедуру обработки события таймера добавим следующую строку. Строку следует добавить после всех методов Refresh. В нашем случае проще всего добавить в конец процедуры.

 

    клонируем Recordset Adodc1, так как FetchRowStyle корректно работает

    ‘ только с клонами

 

    Set RSClone = Me.TDataLite1.Recordset.Clone

 

Как это ни странно, но программу можно запустить!


Вуаля! Все получилось. Теперь при изменении номера шкафа, произойдет и изменение оформления строки. Все не так уж и сложно, но при практическом программировании вы обязательно столкнетесь с проблемами. Функция эта, хоть и полезная, но, часто, трудно реализуемая.

 

Примечание. Будьте очень внимательны при применении методов Refresh для Adodc и TDataLite. Обязательно выполняйте обновление клона Recordset после вызова этого метода, а для Adodc и TDataLite, метод Refresh обязательно вызывайте для обоих объектов сразу.

 

Перехват ошибок в Adodc, TrueDbGgrid и TDataLite

Перехват ошибок в TrueDbGgrid и Adodc реализован хорошо и удобно. Для перехвата ошибок в Adodc используется процедура обработки события Error.

 

Private Sub Adodc1_Error(ByVal ErrorNumber As Long, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, fCancelDisplay As Boolean)

 

Большинство параметров данной процедуры очевидно. Чтобы подавить сообщение, которое генерируется и выводится на экран подсистемой ADO, добавьте следующую строку в процедуру обработки ошибок.

 

    fCancelDisplay = True

 

Ситуация с TrueDbGgrid очень похожа. Для обработки ошибок в TrueDbGgrid используется следующая процедура:

 

Private Sub TDBGrid1_Error(ByVal DataError As Integer, Response As Integer)

 

Параметр Response аналогичен параметру fCancelDisplay, если он равен 0, то сообщение об ошибке, генерируемое самим TrueDbGgrid не появится на экране и, наоборот, появится, если параметр равен 1.

 

Обработка ошибок в TDataLite также осуществляется механизмом событий и обрабатывается процедурой

 

Private Sub TDataLite1_Error(ByVal ErrorNumber As Long, Description As String, ByVal Scode As Long, ByVal FieldName As String, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, fCancelDisplay As Boolean)

 

Рассмотрим следующую проблему: запустите приложение, перейдите в режим запроса и в качестве значения для поля Шкаф введите, например, «www». Попробуйте применить данный фильтр кнопкой «Фильтр».  На экране появится сообщение об ошибке.

Напоминающее о том, что полю Skaf возможны только числовые значения.

Для профессионального приложения так не пойдет. Давайте перехватим ошибку и выведем свое сообщение. Для этого добавьте в модуль формы следующую процедуру:

 

Private Sub TDataLite1_Error(ByVal ErrorNumber As Long, Description As String, ByVal Scode As Long, ByVal FieldName As String, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, fCancelDisplay As Boolean)

Select Case ErrorNumber

    Case 2003

        MsgBox "Неверный формат ввода"

End Select

    fCancelDisplay = True

End Sub

 

Теперь попробуйте выполнить те же действия, и вы получите сообщение об ошибке, которое вы введете в строке с функцией MsgBox.

Резюме

Все ли мы рассмотрели? Боюсь, что нет! TrueDbGgrid обладает настолько широкими возможностями, что в рамках одной статьи обо всем просто невозможно рассказать. Более того, многое из того, что я рассказал, можно сделать другим, более эффективным, способом. Программирование БД – очень непростая задача. Так как приложение должно быть не только функциональным, но еще и удобным пользователю. То, что на профессиональном языке называется «юзабилити». Достичь определенных высот в этом помогает опыт программирования, который приобретается годами и практикой прикладного программирования.

Что же мы рассмотрим в следующий раз? Мы обязательно остановимся на сохранении параметров TrueDbGgrid и восстановлении их при, следующем запуске программы, на сортировке данных в TrueDbGgrid и отображении информативной стрелки направления сортировки. Мы точно посмотрим, как можно выполнить экспорт и импорт данных средствами TrueDbGgrid и ADO. Попробуем избавиться от компонента Adodc. А также обязательно остановимся на печати табличных данных при помощи самого TrueDbGgrid и при помощи компоненты VSView.

 

Приложение

Таблица NSIAbonent

Codr (ключевое поле)

Длинное целое

4

Nomer

Длинное целое

4

Abonent

Текстовый

150

Address

Текстовый

150

Date

Дата/время

8

Mesto

Текстовый

150

Tip

Длинное целое

4

 

Таблица tblKross

Nomer

Длинное целое

4

Skaf

Длинное целое

4

Polosa

Текстовый

10

Raspred

Текстовый

10

KA

Длинное целое

4

Prim

Текстовый

255

 

 
     

   
   
     
  VBNet рекомендует