воскресенье, 27 ноября 2011 г.

Урок 25. База данных потерялась?


В предыдущем уроке я остановился на том, что показал один из способов наведения порядка в отображаемой интерфейсом программы таблице, т.е. показал один из способов сортировки получаемых из базы данных записей.
Сегодня мне хотелось бы остановиться вот на каком вопросе: испытания собственной программы я произвожу сам, поэтому сам нахожу ее удобные и не очень места. И вот одним из таких подводных камней мне видится смена буквы съемного носителя. Да-да, мой уважаемый читатель, программу можно носить с собой везде, разместив ее на USB, скажем, носителе, поскольку программа, как Вы уже знаете, использует для собственных настроек файл ini, что многие могут посчитать старомодным, а не реестр операционной системы. Использование реестра ОС - модно и современно, но требует написания инсталлятора. Оставим этот вопрос на будущее. А сейчас попробуем разобраться с такой бедой: сменный диск, подключенный к одному компьютеру, имеет, скажем, букву “Е”, а на другом он становится “F”. Но в строке подключения к базе данных, если кто обратил внимание:
ConnectionString=Provider=Microsoft.Jet.OLEDB.4.0;Data Source=X:\Lessons\...\Les 25\Расходы\Rashod.mdb;...
четко прописана буква диска в абсолютном пути (Data Source=X:).
Как быть? Править вручную файл ini перед использованием программы - занятие скучное и неблагодарное.
Тогда предлагаю использовать следующий алгоритм:
- прочитать строку подключения из файла ini,
- попробовать подсоединиться к базе данных,
- при неудачном подсоединении дать возможность оператору выбрать расположение базы данных, используя стандартное окно диалога,
- записать в файл ini новую строку подключения.
Последую примеру героя М.М. Жванецкого: “Если вопросов нет, я начну”.
Добавьте на форму MainFrm компонент TOpenDialog с палитры компонентов, с вкладки “Dialogs”.
Создайте новую процедуру следующего содержания:
procedure TMainFrm.SetDisk(); // Установка диска с БД
Var
ini: TIniFile;
ConnectionString: String;
MyDir: String;
begin
MyDir:=GetCurrentDir; // Запомнить в переменную путь к текущему директорию
OpenDialog1.Filter:='Файлы базы данных|*.mdb'; // Фильтр для диалога выбора файла (показывать только файлы баз данных Access
// Выбор файла
If not OpenDialog1.Execute // Открытие окна диалога
then // Отмена выбора
begin
exit; // Выход из подпрограммы
end;
ini:=TiniFile.Create(MyDir + '\Rashod.ini'); // Подключение к файлу настроек
MySelect.MySel_Dir:=ExtractFilePath(OpenDialog1.FileName); // Извлечение абсолютного пути к выбранному файлу
ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+MySelect.MySel_Dir+'Rashod.mdb;Persist Security Info=False'; // Конструирование строки подключения
Ini.WriteString('General','ConnectionString',ConnectionString); // Запись строки подключения в файл настроек
// Ini.WriteString('General','TempConnectionString',ConnectionString);
ini.Free; // Освобождение памяти
SetCurrentDir(MyDir); // Возврат программы к текущему каталогу
end;
Один тонкий момент есть в этой процедуре, который мне хотелось бы пояснить. Дело в том, что компонент TOpenDialog, устанавливает текущий директорий по понятиям операционной системы. Поэтому, если Вы выбрали какую-то папку с базой данных, отличную от рабочей папки программы, то работа программы нарушится. Следовательно, необходимо запомнить в строковой переменной положение указателя на текущую папку до начала всего действия:
MyDir:=GetCurrentDir;,
а по окончании действия, вернуть его на место:
SetCurrentDir(MyDir);
Не забудьте дать объявление новой процедуры в секции Private описания интерфейса:
procedure SetDisk();
Где должна сработать новая процедура? Конечно же, при создании формы, при обработке события onCreate:
If Not TestConnection
then
SetDisk();
Теперь для тестирования измените вручную путь к базе данных, прописанный в файле ini.
Удачи.

Что же дальше?
На следующем уроке я планирую рассказать, как производится очистка базы данных, удаление всех записей из таблиц или присвоение отдельным полям стартовых (нулевых) значений.


четверг, 17 ноября 2011 г.

Урок 24. Сортировка записей в таблице



Не в альтернативу предыдущему уроку, где я довольно долго рассказывал о том, как создать форму для таблицы справочника, данный урок получился очень коротким. Случилось это вот как. Намереваясь составить очередной урок, я открыл проект на том этапе, на котором оставил его в последний раз, запустил программу и увидел очевидное неудобство: при выборе мемориального ордера самый нужный - последний как раз и оказался в конце списка. Это очевидное неудобство: оператор всегда вводит записи в текущий месяц, редко обращаясь к записям предыдущих периодов. Я решил сразу исправить эту ошибку интерфейса, а начинающим программистам - еще раз напомнить: создавая интерфейс всегда ставьте себя на место будущего пользователя, задумывайтесь почаще: что ему будет удобно, а что - нет.
Все инструкции к этому уроку можно свести к следующему:
в свойство IndexFieldNames компонента ADOTableMOs впишите ID DESC.
Вот так все просто?
Нет, не просто. Это - лишь один из нескольких способов задать сортировку.  Другие мы рассмотрим позже.
PS Постфикс DESC задает обратный (от "я" до "а") порядок сортировки.
Наглядный видео урок Вы можете посмотреть или скачать.


Что же дальше?
А в следующем уроке я предлагаю решить вопрос: а как должна вести себя программа, если база данных хранится на съемном носителе, а при подсоединении к компьютеру, съемному диску присвоена неизвестная доселе буква?