- •О.С. Зеленський
- •Розділ 9. Структура створення додатків
- •9.1. Загальна структура додатків
- •9.2. Додатки без використання архітектури «Документ-вид»
- •9.2.1. Приклад додатку реєстрації wnd-класу вікна
- •9.2.2. Створення та видалення дочірніх вікон без використання архітектури «Документ-Вид»
- •9.2.3. Створення дочірніх вікон без використання архітектури «Документ-Вид» (переключення вікон з використанням функції ShowWindow)
- •9.3. Архітектура «Документ-Вид»
- •Idr_mainframe формат строкового ресурсу.
- •9.3.1. Приклад додатку з використанням архітектури «Документ-Вид»
- •9.3.2. Види у архітектурі «Документ-Вид»
- •9.3.3. Створення видів у архітектурі «Документ-Вид» (переключення видів з використанням функції ShowWindow)
- •9.3.4. Робота з документами та видами на прикладі додатку SingleTemplate
- •9.4. Додатки mdi, робота з шаблонами
- •9.4.1. Приклад додатку mdi з одним шаблоном
- •9.4.2. Приклад додатку mdi з декількома шаблонами
- •Контрольні питання
- •Розділ 10. Робота з базами даних з використанням об'єктів ado
- •10.1.1. Ініціалізація об'єктів com з використанням директиви #import
- •10.1.2. Підтримка класів сом
- •10.2. Об'єкт Connection
- •10.3. Об'єкт Command
- •10.4. Об'єкт Recordset
- •10.5. Об'єкт Field і колекція Fields
- •10.6. Об'єкт Error і колекція Errors
- •10.8. Коротка характеристика структури мови sql
- •10.9. Синтаксис оператора вибору Select
- •10.10. Приклад програмування об'єктів ado
- •10.11. Опис розробленого навчального пакету ado6 для роботи з базами даних access та MySql
- •Int tip_bd; // тип бд 1- ms access, 2- MySql, 3 - xml
- •Void Connect_Baza(cString str);
- •Void ErrMessage(_com_error &ce);
- •If(pConn.CreateInstance("adodb.Connection"))
- •If(pRecordset.CreateInstance("adodb.RecordSet"))
- •Void cAdo6Doc::ErrMessage(_com_error &ce)
- •Void cAdo6Doc::OnMsaccess()
- •Void cAdo6Doc::OnMysql()
- •Void cAdo6Doc::OnXmlRead()
- •Void cAdo6Doc::Connect_Baza(cString str)
- •Virtual void DoDataExchange(cDataExchange* pDx);
- •Void cAdo6Dlg::DoDataExchange(cDataExchange* pDx)
- •Void cAdo6Dlg::Struct_MySql()
- •Void cAdo6Dlg::OnSelchangeListBaza()
- •Void cAdo6Dlg::OnVibor_bd()
- •Void cAdo6Dlg::AccessOpen()
- •Void cAdo6Dlg::xmlOpen()
- •Void cAdo6Dlg::Structura_bd()
- •Void cAdo6Dlg::OnSelchangeListTab()
- •Void cAdo6Dlg::show(int kod, int kod_bd)
- •Void cAdo6Dlg::Recordset_Baza(cString str)
- •Void cAdo6Dlg::OnClose()
- •10.11.2. Формування списку бд (MySql), відкриття бази даних (ms access), відкриття xml-файлу, формування списку таблиць (MySql і ms access) та полів (MySql, ms access, xml)
- •Void cAdo6Dlg::OnSelchangeListTab()
- •1. Обрану таблицю необхідно брати в зворотні лапки "`", щоб виключити помилку в тому випадку, якщо в імені таблиці будуть зустрічатися пробіли.
- •10.11.3. Робота з sql-запитами
- •Void cAdo6Dlg::OnZapros_Select()
- •If (str_query.Mid(0,6).Compare("select"))
- •If(!baza.Left(3).Compare("otl") &&
- •Void cAdo6Dlg::Recordset_Baza(cString str)
- •Void cado6Dlg::OnZapros_Make()
- •Vr_zap.Format(" Запрос выполнен за %f сек ",conec - nach);
- •10.11.4. Видалення, сортування, пошук, фільтрація, оновлення набору записів
- •Void cado6Dlg::OnZapis_Delete()
- •Void cado6Dlg::OnCheck_Sort()
- •Void cado6Dlg::OnFind()
- •0L,adSearchForward,bb);
- •Void cado6Dlg::OnFilter()
- •Void cado6Dlg::OnVozvrat()
- •10.11.5. Переходи по записах
- •Void cado6Dlg::OnButtonFirst()
- •Void cado6Dlg::OnButtonLast()
- •Void cado6Dlg::OnButtonLeft()
- •Void cado6Dlg::OnButtonRight()
- •Void cado6Dlg::OnButtonRecno()
- •Void cado6Dlg::OnButtonPgup()
- •Void cado6Dlg::OnButtonPgdn()
- •Void cado6Dlg::OnButtonBookmark()
- •10.11.6. Запис даних до xml-файлу
- •Void cAdo6Dlg::OnButtonSave()
- •10.11.7. Кнопки, призначені тільки для роботи з otl_tab
- •Void cado6Dlg::OnZapis_Add1()
- •Void cado6Dlg::OnZapis_Add2()
- •Void cado6Dlg::OnZapis_Update1()
- •Void cado6Dlg::OnZapis_Update2()
- •Void cado6Dlg::OnFormir_bd()
- •Void cAdo6Dlg::OnValues_Fields()
- •10.12. Використання у якості джерела даних електронної таблиці Excel
- •Контрольні питання
- •Завдання
- •Розділ 11. Програмування для інтернет
- •11.1. Створення броузера
- •11.3. Використання протоколу http
- •If ((pInternetSession)
- •11.4. Використання протоколу ftp
- •Контрольні питання
- •Розділ 12. Створення елементів activex
- •12.1. Створення елементів ActiveX
- •Invalidate();
- •12.2. Тестування елемента ActiveX
- •12.4. Створення елемента ActiveX на базі стандартних елементів
- •12.5. Відображення елементів ActiveX
- •Контрольні питання
- •Розділ 13. Налагодження програм
- •Int data[5];
- •Invalidate();
- •13.3. Установка точки переривання
- •13.2. Покрокове виконання програми
- •13.4. Перевірка значень змінних під час виконання програми
- •Контрольні питання
- •Список літератури
- •Додатки
Void cado6Dlg::OnZapis_Update2()
{
if(pRecordset->GetState()==0)return;
if (!pRecordset->GetRecordCount ())
{
MessageBox("Пустая таблица!!!","Увага!!!",
MB_ICONINFORMATION);
return;
}
_variant_t a;
long i;
time_t time1;
struct tm *tm1;
COleDateTime mytime(2000,1,1,0,0,0);
try
{
FieldPtr field;
for(i=0;i<fields->GetCount ();i++)
{
field = fields->GetItem ((_variant_t)i);
switch(i)
{
case 0:
time(&time1); // time 2 у секунд із 1970 р.
tm1 = localtime(&time1);
a= (long)tm1->tm_sec;
break;
case 1:
a = 20L;
break;
case 2:
a = "Привет";
break;
case 3:
a = mytime;
break;
case 4:
a = 100L;
break;
}
field->Value = a;
}
pRecordset->Update();
}
catch(_com_error &ce)
{
Doc->ErrMessage(ce);
}
}
У даній функції кожному полю за допомогою властивості Value привласнюється відповідне значення типу _variant_t. Після цього необхідно зберегти зміни поточного запису БД за допомогою методу Update(). Тут представлена робота з датою класичними засобами (структура tm), а також з використанням класу COleDateTime.
При роботі з експериментальною таблицею otl_tab часто буває потрібно сформувати її заново. У цьому зв'язку в прикладі ADO6 представлена функція OnFormir_BD() по кнопці <Формирование БД>, у якій відбувається формування таблиці заданими порціями даних. Кожна порція даних повинна бути кратна 100 записам.
Текст даної функції наведений нижче.
// Формування бази із заданими порціями записів
Void cado6Dlg::OnFormir_bd()
{
if(pRecordset->GetState()==0)return;
CString str;
m_editquery.GetWindowText (str);
long per_dob = atol(str.GetBuffer(1));
if( per_dob < 100 || per_dob > 1000000 ||
(per_dob/100. - per_dob/100) > 0.0001)
{
if (MessageBox
("Введите кол-во записей (кратных 100) для одной дополняемой порции", "Ошибка, Повторите Ввод",MB_OKCANCEL) == IDOK)
{
m_editquery.SetFocus();
GetDlgItem(IDC_STATIC3)->
SetWindowText("Введите число кратное 100");
}
else GetDlgItem(IDC_STATIC3)->SetWindowText("");
return;
}
// Видалення записів
try
{
pConn->BeginTrans();
pConn->Execute((_bstr_t)"DELETE FROM otl_tab",0,
adCmdText);
pConn->CommitTrans();
}
catch (_com_error &ce)
{
pConn->RollbackTrans();
// Прив'язка об'єкта Recordset до Datagrid
m_datagrid1.SetRefDataSource(pRecordset);
Doc->ErrMessage(ce);
return;
}
try
{
pRecordset->Requery (-1);//перечитати набір
SAFEARRAY * ar_f;
SAFEARRAY * ar_v;
_variant_t fields,values;
values.vt = VT_ARRAY|VT_VARIANT;
fields.vt = VT_ARRAY|VT_VARIANT;
// Початкова ініціалізація покажчиків
values.parray = 0;
fields.parray = 0;
long i,j,per;
SAFEARRAYBOUND rgsabound;
rgsabound.lLbound = 0;
rgsabound.cElements = 5;
ar_f = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
ar_v = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
// Відв’язування об'єкта Recordset від Datagrid
m_datagrid1.SetRefDataSource(0);
// Додавання записів заданими порціями
long povt = -1;
long kol_zapis = 0;
CString mes;
while(1)
{
povt++;
if(kol_zapis > 999000)break;
if(povt)
{
mes.Format("Будете добавлять еще %d записей\nв базе - %d записей", per_dob,pRecordset->GetRecordCount ());
if (MessageBox(mes, Внимание!!!",MB_YESNO) == IDNO)break;
}
for(j = 1+povt*per_dob;j<=per_dob*(1+povt);j++)
{
kol_zapis++;
for(i = 0; i < 5; i++)
SafeArrayPutElement(ar_f, &i, &(_variant_t)i);
i = 0;
per = pRecordset->GetRecordCount();
SafeArrayPutElement(ar_v, &i, &(_variant_t)per);
i++;
SafeArrayPutElement(ar_v, &i, &(_variant_t)j);
i++;
SafeArrayPutElement(ar_v, &i, &(_variant_t)"aaaa");
i++; // Дата
COleDateTime mytime(2000,1,1,0,0,0);
SafeArrayPutElement(ar_v, &i, &(_variant_t)mytime);
i++; // Логіка
per = 0;
SafeArrayPutElement(ar_v, &i, &(_variant_t)per);
fields.parray = ar_f;
values.parray = ar_v;
pRecordset->AddNew(fields,values);
}
}
GetDlgItem(IDC_STATIC3)->SetWindowText("");
}//end try
catch (_com_error &ce)
{
Doc->ErrMessage(ce);
}
// Прив'язка об'єкта Recordset до Datagrid
m_datagrid1.SetRefDataSource(pRecordset);
}
Спочатку в змінну per_dob типу long записується значення рядка, введене в текстове поле m_editquery. У цьому випадку для перетворення рядка в число використовується функція atol(). Входом у цю функцію є char*. Щоб зі змінної класу CString одержати вказівку на char, доцільно скористатися функцією GetBuffer(), входом у яку є мінімальна кількість символів. Якщо довжина рядка більше чим це число, то буде виведений буфер під довжину рядка, інакше він буде виведений під задану величину. Якщо повернута функцією GetBuffer() вказівка на char використовується для внесення змін у текстовий рядок, то перед тим як звертатися до будь-яких інших функцій даного класу, необхідно викликати функцію ReleaseBuffer().
У тому випадку, якщо кількість записів у порції менше 100 або більше 1000000, або введене число порції записів не кратне 100, – виведеться відповідне повідомлення про помилку та буде здійснений вихід з функції.
На наступному етапі видаляються всі записи таблиці otl_tab, використовуючи SQL-запит на видалення. Потім створюються динамічні масиви ar_f, ar_v типу VARIANT, у які будуть записуватися відповідно індекси й значення полів знову доданого запису, а також робиться відв’язування об'єкта Recordset від елемента керування Datagrid. Відразу оголошуються змінні fields та values типу _variant_t, у які будуть передані вказівки на масиви SAFEARRAY типу VARIANT.
Увага!!! При роботі із класом _variant_t при передачі вказівки на масив SAFEARRAY існує наступна особливість: після присвоєння типу масиву vt (у нашому випадку, масив варіантів – VT_ARRAY|VT_VARIANT) необхідно ініціалізувати початкові вказівки на масив нульовими значеннями. Інакше при достроковому виході з функції, якщо дані вказівки не будуть проініціалізовані, – програма спробує звільнити відповідні вказівки, у яких перебуває "бруд", і буде виведене повідомлення про помилку.
Після цього здійснюється додавання записів заданими порціями. Із цією метою введена змінна povt, що відповідає за кількість порцій даних. У вічному циклі while(1) вона постійно накопичується. До циклу їй привласнюється значення -1. Потім вона накопичується й приймає значення 0. У циклі while() розташований цикл for() за допомогою якого додаються записи однієї порції. Він виглядає наступним чином:
for(j = 1+povt*per_dob;j<=per_dob*(1+povt);j++)
{
// тіло циклу
}
У даному циклі змінна per_dob – це кількість записів у заданій порції. Так, спочатку змінна povt дорівнює нулю, тобто буде записана перша порція даних (від 1 до per_dob), потім, коли буде записуватися друга порція даних – змінна povt дорівнює 1 (від 1+per_dob до 2*per_dob) і т.д. При кожній новій порції даних, починаючи з другої, на екран буде виводитися повідомлення про виведення нової порції записів, де користувачеві надається можливість або додати чергову порцію записів, або відмовитися. При відмові буде здійснений вихід з вічного циклу while(1). Крім того, якщо кількість записів перевищить 999000, також буде здійснений вихід з вічного циклу. Всі записи в даній функції додаються за допомогою методу AddNew() з параметрами. Наприкінці виконання функції здійснюється прив'язка об'єкта Recordset до елемента керування Datagrid.
З допомогою кнопки <Значение полей> (функція відгуку OnValues_Fields()) виводяться значення полів поточного запису, а також здійснюються арифметичні операції над полями таблиці otl_tab.
Текст даної функції відгуку наведений нижче.
// кнопка <Значение полей>
// Виведення значень полів і розрахункові операції