суббота, 31 декабря 2011 г.

Список опубликованных в 2011 году видео материалов



Название
Смотреть on-line
Ссылка для скачивания
1
Hello World с изюминкой
смотреть 1 и 2
2
Оформление проекта или то, до чего руки не доходят… (ico, компонент TMainMenu)
3
Техническое задание и алгоритм
-
-
4
Список действий и элементы управления формы (компонент TActionList)
5
Установка компонентов сторонних производителей
6
Не много ли два таймера в одной программе ?! (компонент TTimer)
7
Как запомнить настройки
смотреть 1 и 2
8
Учим таймер “петь” (компонент TMediaPlayer)
9
Создание собственного компонента (компонент TMyLabel)
10
Создание компонента сообщения (TMyMessenger)
11
Компонент гиперссылка
12
Добавление в проект формы “О программе”
13
Компонент “О программе”
14
Сохранение настроек программы
15
Финишная обработка исполняемого файла
16
Самые необходимые знания о бухгалтерии
-
-
17
Что должна уметь программа «Расходы» или ТЗ на разработку
-
-
18
Создание реляционной БД
19
Создание формы-заставки (отключаемая заставка)
20
Подключение к базе данных
21
Контейнеры и элементы управления главной формы
22
Компонент «Навигатор»
-
-
23
Очень важная последовательность действий
24
Сортировка записей в таблице
25
-
-
PS Для просмотра скачанных swf-роликов Вам понадобится flash-проигрыватель 

вторник, 27 декабря 2011 г.

Урок 28. Организация ввода и редактирования данных


В предыдущем уроке мы много говорили на тему оформления интерфейса. Теперь настало время заглянуть внутрь - организовать процедуры ввода информации в главную таблицу и редактирования ее.
Для начала, добавьте в раздел частных объявлений декларацию следующей процедуры:
Procedure TMainFrm.MyEdits();
Begin
DataEdit.Value:=ADOTableMain.FieldByName('MyDate').value;
DEdit.KeyValue:=ADOTableMain.FieldByName('D').value;
KEdit.KeyValue:=ADOTableMain.FieldByName('K').value;
SEdit.Value:=ADOTableMain.FieldByName('Summa').value;
PEdit.Text:=ADOTableMain.FieldByName('Rem').Text;
Panel3.Visible:=True;
end;
Panel3 - это верхняя панелька на главной форме, где расположены несколько элементов управления для ввода.
В этой процедуре,  элементам управления (контролам) присваиваются значения из соответствующих полей таблицы "Main".
Аналогично объявите и создайте процедуру InsEdit:
Procedure TMainFrm.InsEdit();
Begin
// Процедура подготоавливает ввод новой записи
ADOTableMain.Edit;                                // Переводит таблицу в режим редактирования
MyEdits;                                          // Вызывает процедуру, переприсваивающую данные из записи в таблице в элементы управления на форме
if DataEdit.CanFocus                              // Устанавливает фокус на первое слева поле, если это возможно
then
DataEdit.SetFocus;
DBGridEh1.Enabled:=False;                         // Делает недоступной Grid
end;




Теперь для компонента ADOTableMain необходимо прописать обработчики четырех событий:
до вставки (BeforeInsert),
до редактирования (BeforeEdit),
после записи (отправки данных в источник - AfterPost),
после вставки (AfterInsert).
Эти процедуры будут выглядеть следующим образом:

procedure TMainFrm.ADOTableMainAfterInsert(DataSet: TDataSet);
begin
// Присвоение некоторых стартовых значений полям таблицы
ADOTableMain.FieldByName('MyDate').Value:=FormatDateTime('dd/mm/yyyy',now());
ADOTableMain.FieldByName('D').Value:=1;
ADOTableMain.FieldByName('K').Value:=1;
ADOTableMain.FieldByName('MO').Value:=MySelect.MySel_IDMO;
ADOTableMain.FieldByName('MO_Name').Text:=MySelect.MySel_MOName;
// Поднять запись на верхнюю панель
InsEdit;
end;
procedure TMainFrm.ADOTableMainAfterPost(DataSet: TDataSet);
begin
DBGridEh1.ReadOnly:=True;                         // Делает Grid НЕдоступной для редактирования
end;
procedure TMainFrm.ADOTableMainBeforeEdit(DataSet: TDataSet);
begin
MyEdits;                                          // Переписывает значения из источника базы данных в поля формы
end;
procedure TMainFrm.ADOTableMainBeforeInsert(DataSet: TDataSet);
begin
DBGridEh1.ReadOnly:=False;                        // Делает Grid доступной для редактирования
end;



Пояснения я постарался задать в //комментариях :-)
Теперь настало время вспомнить про разработанный нами несколько уроков назад навигатор. Пора его "приспособить" к главной таблице. Расположите его на нижней панельке и назначьте в качестве источника данных DataSource = DataSourceMain. Не забудьте установить "якоря" (Anchors), привязывающие его справа внизу:
akRight = True;
akBottom = True,
(другие два значения = False).
Если сейчас запустить проект и нажать на навигаторе кнопку "Добавить", то возникнет следующая ошибка:





Вообще-то, о способах и методах отладки я планирую поговорить в будущем. Тема эта неисчерпаема и довольно сложна. А сейчас, просто избавимся от лишнего поля, о котором идет речь в сообщении. Откуда оно взялось? Да, Бог его знает...
удалите строку кода:
ADOTableMain.FieldByName('MO_Name').Text:=MySelect.MySel_MOName;
После запуска проекта и попытке добавить новую запись Вы обнаружите, что:





1.  Новая запись со значениями по умолчанию добавлена в таблицу Main. Ура!
2. Остается активным меню. Правильно ли это?
3. Не работают элементы управления с выпадающими списками на верхней панельке.
4. Запись невозможно сохранить.
5. Невозможно вернуть форму к стартовому виду.
Давайте добавим для начала обработчики событий для кнопок Cancel и Post навигатора




procedure TMainFrm.PrDNavigator1nbCancelClick(Sender: TObject);
begin
DBGridEh1.Enabled:=True;                // После нажатия кнопки Cancel на навигаторе, сетка должна стать доступной
Panel3.Visible:=False;                            // Верхняя панелька становится не нужна, скроем ее
end;
procedure TMainFrm.PrDNavigator1nbPostClick(Sender: TObject);
begin
// Переприсвоение значений из контролов формы в поля таблицы
ADOTableMain.FieldByName('MyDate').Value:=DataEdit.Value;
ADOTableMain.FieldByName('D').Value:=DEdit.KeyValue;
ADOTableMain.FieldByName('K').Value:=KEdit.KeyValue;
ADOTableMain.FieldByName('Summa').Value:=SEdit.Value;
ADOTableMain.FieldByName('Rem').Text:=PEdit.Text;
DBGridEh1.Enabled:=True;               // После нажатия кнопки Post на навигаторе, сетка должна стать доступной
Panel3.Visible:=False;                           // Верхняя панелька становится не нужна, скроем ее
end;

Теперь по нажатию кнопки Post (сохранить) на навигаторе, форма возвращается к первоначальному виду, а данные из полей формы переписываются в таблицу базы данных.
Разберемся с элементами управления (DEdit, KEdit), которые должны содержать списки.
Прежде всего, для каждого из них нужно задать источник строк ListSource:





Элементы управления со списками работают так, что пользователю показывается понятное ему значение из списка (ListField), а программа записывает в элемент управления (и далее - в базу данных) соответствующий ему код (KeyField).
Исправив эту некорректность, Вы получите практически работающую программу.


Останутся такие мелочи, как быстрые клавиши, обработка двойных и одинарных кликов на DBGridEh и т.п.







Урок 27. Отображение записей в Grid главной формы


В предыдущем уроке я показал как можно подготовить базу данных к работе, т.е. удалить из таблиц всю хранимую в них информацию, которая к определенному этапу становится не актуальной. В дальнейшем мы еще внесем некоторые изменения в алгоритм очистки, поскольку начинать каждый отчетный период (год) с "чистого листа", наверное, не совсем интересно и даже не правильно. Позже, когда речь пойдет об оборотной ведомости, я покажу, как можно подсчитать остатки, и тогда в алгоритм очистки базы данных нужно будет добавить несложный механизм, позволяющий перенести конечные остатки по счетам в начальные. Но, об этом чуть позже.
Давайте займемся главной формой проекта (MainFrm): пора уже научить ее отображать учетные записи.
Для этого расположите на форме два компонента:
TADOTable и TDataSource с вкладок dbGo и DataAccess соответственно.
Для начала, дайте компонентам имена: ADOTableMain и DataSourceMain.
Затем, для таблицы установите свойства:
Connection = ADOConnection1;
TableName=Main;
Щелкните дважды по компоненту ADOTableMain, и в появившемся окне с помощью правой кнопки добавьте все поля (Add all fields...).
Назначьте источник данных компоненту DataSourceMain:
DataSet = ADOTableMain;
Позаботьтесь о сортировке записей. Будет удобнее, если записи будут отображаться в порядке убывания даты, т.е. более свежие всегда вверху. Для этого в свойстве IndexFieldNames компонента ADOTableMain укажите поле сортировки MyDate с постфиксом DESC.
И последнее, что осталось сделать - указать для сетки (Grid), расположенной на форме источник отображаемых данных:
DataSource = DataSourceMain;
Если сейчас запустить проект, то после выбора МО, отобразится... опять таки пустая таблица... В чем же дело?
Очень просто: таблица Main не активна.
Разыщите процедуру:
procedure TMainFrm.TableActive(p: boolean);
begin
// Активация (деактивация таблиц)
ADOTableMOs.Active:=p;
end;
и добавьте в нее строчку кода:
ADOTableMain.Active:=p;
Аналогичные действия выполняйте при добавлении в проект новой таблицы.
Теперь, если Вы запустите проект, то увидите таблицу (я заранее внес в нее несколько записей для наглядности, ведь, с помощью механизма очистки нам теперь ничего не стоит их удалить!), но зрелище это будет мало утешительным:





Плохо - все:
1. Нужно ли пользователю видеть служебное поле счетчика? Нет.
2. Учет в нашей стране ведется в рублях и копейках, а Summa отображает как будто бы целые.
3. Мы, вроде бы, выбрали мемориальный ордер, а здесь - все записи внавал... (МО=12 и МО=13 и т.д.).
4. Если МО уже выбран, зачем вообще отображать это поле, если значение в нем всегда будет одно и тоже, пока мы не выберем другой МО?
5. Что за чуднЫе заголовки у полей?
6. Хотелось бы, чтобы поля признаков Дебета и Кредита (D и K) отображали бы удобочитаемую информацию, а не порядковые номера счетов, которые пользователь помнить не обязан.
7. Скрытый недостаток - попробуйте ввести что-то в любое поле. Скорее всего, это у Вас получится. Но, задача этой сетки - просмотр записей, а не их редактирование.
8. Хорошо бы по сумме иметь итог.
Именно поэтому я и перечеркнул вид главной формы на иллюстрации. Такой вид никуда не годится.
Давайте постепенно разбираться и исправлять.
Для начала вызовите редактор колонок сетки (дважды щелкнув на DBGridEh1). Нажмите в нем пиктограмму Add all Fields (добавить все поля).
Для полей ID и MO, отображать которые нет необходимости, установите свойство Visible в False.
Остальным полям назначьте заголовки в свойствах Title.Caption ( я записал здесь свойство через точку, это означает, что Title имеет раскрывающийся список свойств, одно из которых Caption), как показано на рисунке:



Недостатки под номерами 1, 4 и 5 устранены.
Побороть пункт 2 можно с помощью свойства DisplayFormat для колонки Summa компонента DBGridEh1, задав в нем следующее значение: "0.,00".
Для решения вопроса отображения записей только одного мемориального ордера, добавьте в процедуру ShowMOs() несколько операторов после комментария "Смена фильтра в главной форме":
procedure TMainFrm.ShowMOs();
Begin
Application.CreateForm(TMOs_Frm, MOs_Frm);  MOs_Frm.ShowMoDal;  MOs_Frm.Free;
// Смена фильтра в главной форме
ADOTableMain.Filtered:=False;
OldFilter:='MO=' + IntToStr(MySelect.MySel_IDMO);
ADOTableMain.Filter:=OldFilter;
ADOTableMain.Filtered:=True;
StatusBarUpdate;
end;
После всех этих манипуляций, главная форма уже лучше показывает записи из базы данных, но все же еще...



Для красоты и удобства (а также для возможности некоторого контроля и анализа в будущем),  необходимо организовать самосчетный подвал (футер) в Grid-е. Для этого в свойствах компонента DBGridEh1 укажите
FooterRowCount = 1;
дословно: количество строк в "подвале" - одна и
SumList.Active = True;
Затем, выберите в редакторе колонок поле Summa и укажите следующие его свойства:
Footer.DisplayFormat=0.,00;
Footer.FieldName=Summa;
Footer.ValueType=fvtSum;
Вот, уже форма приближается к нормальному виду:



Чтобы решить вопрос с отображением счетов, необходимо добавить на форму еще пару компонентов TADOTable и TDataSource, связав их, как мы уже это делали выше, с таблицей счетов (Accounts). Назовем их ADOTableAcc и DataSourceAcc соответственно.
Не забудьте добавить ADOTableAcc.Active:=p; в процедуру активации таблиц.
Вызовите конструктор полей для таблицы ADOTableMain.
По правой кнопке вызовите контекстное меню, а нем выберите New Field... (Новое поле). Заполните свойства нового поля, как показано на иллюстрации:



Таким образом Вы создадите так называемое  поле Lookup или поле с подстановкой.
Теперь нужно отобразить его в гриде.
Щелкните дважды по сетке, чтобы вызвать конструктор колонок. Воспользуйтесь еще раз кнопкой "Добавить все поля", но ВНИМАНИЕ: на вопрос "перезаписать?" ответьте отрицательно.
Затем удалите из списка повторно добавленные поля и поле "D". Перетащите на его место новое поле "D_Name". Подправьте его свойство:
Caption=Дебет;



Соответственно форма будет выглядеть совсем уже почти...



Надеюсь, что я очень подробно все описал, и Вы самостоятельно сделаете поле с подстановкой "Кредит".
Последний недостаток устраните, установив свойство DBGridEh1.Options.dgEditing = False.
В качестве бонуса конечному пользователю:
установите в свойствах DBGridEh1
OptionsEh.dghRowHighLight=True - удобно, когда строки в таблице подсвечиваются и
Options.dgAlwaysShowSelection=True - для подсветки выделенной курсором ячейки.
На этом сегодня все.
В следующем уроке я покажу как организовать ввод и редактирование данных в главной таблице.