Уважаемые коллеги, насобирав ссылки для ветки
Класс ODBCConnection , а также вооружившись информацией из других источников, решил сам немного поэкспериментировать с темой ADO в Аксапте. Результаты мне понравились. В качестве примера выкладываю свой демоджоб.
Джобик делает следующее:
- Аксапта выполняет запрос к БД (у меня – Oracle); запрос – непосредственно к базе, на «нормальном» SQL, не на аксаптовском «диалекте».
- Результаты запроса (некоторые поля таблицы «Список сотрудников») помещаются в новую рабочую книгу Excel; для вставки данных на рабочий лист используется метод CopyFromRecordset объекта Range.
- Книга сохраняется, Excel закрывается (Excel невидим на протяжении всего процесса, книгу можно посмотреть по окончании в соответствующей заданной Вами папке).
- Далее Аксапта открывает эту новую книгу Excel уже не «как Excel c ячейками А1», а так, как если бы это была полноценная таблица БД (открывает - как ADO-шный Recordset).
- Строки этой таблицы считываются в Аксапту и выводятся в info-окне.
Перед запуском джоба необходимо:
1. Прописать Вашу папку для сохранения тестовой рабочей книги Excel;
2. Прописать параметры подключения к Вашей БД в зависимости от БД: SQL Server или Oracle, раскомментировав одно и закомментировав соответственно другое.
X++:
static void Job_TestADO_1(Args _args)
{
// НЕОБХОДИМО ПЕРЕД ЗАПУСКОМ:
// 1. прописать Вашу тестовую папку
str filePath = "C:\\Gustav\\ADOtest\\";
// 2. прописать Ваши параметры ConnectionString,
// раскомментировав нужное и закомментировав ненужное
// ЛИБО для Oracle:
str dbCnnString = "Provider=MSDAORA;" +
"Password=" + "yourpassword" + ";" +
"User ID=" + "youruserid" + ";" +
"Data Source=" + "yourdatasource";
// ЛИБО для SQL Server:
//str dbCnnString = "Provider=SQLOLEDB;" +
// "DATABASE=" + "yourdatabase" + ";" +
// "SERVER=" + "yourserver" + ";" +
// "UID=" + "youruserid" + ";" +
// "PWD=" + "yourpassword";
COM xlApp; // Excel.Application
COM wbks, wbk; // Workbooks, Workbook
COM wkss, wks; // Worksheets, Worksheet
COM rng, cell, rngCR; // все Range
COM font; // Range.Font
COM cnnDB, rstDB; // ADO: Connection, Recordset
COM cnnExcel, rstExcel; // ADO: Connection, Recordset
COM flds, fld; // ADO: Fields, Field
int i, iMax;
str strSQL, strInfo;
// ============================================================================
// СНАЧАЛА ДВЕ ВЛОЖЕННЫЕ ФУНКЦИИ
// ----------------------------------------------------------------------------
// функция преобразует полученное через ADO вариантное значение из Excel
// в значение, пригодное к дальнейшему использованию в Axapta
// (в данном демо-джобе не используется - она сама по себе демо :-) )
anytype adoValueFromExcel(COMVariant _val, int _type)
{
switch (_type)
{
// список констант соответствует типам данных, распознаваемых ADO для Excel
case 5: return _val.double(); // adDouble
case 6: return _val.currency(); // adCurrency
case 7: return _val.date(); // adDate
case 11: return _val.boolean(); // adBoolean
case 202, 203: return _val.bStr(); // adVarWChar, adLongVarWChar("memo")
}
return '';
}
// ----------------------------------------------------------------------------
// функция преобразует полученное через ADO вариантное значение из Excel
// в СТРОКОВОЕ значение, пригодное к использованию в INFO-окне Axapta
// (используется в данном демо-джобе)
str adoInfoValFromExcel(COMVariant _val, int _type)
{
switch (_type)
{
case 5: return num2str(_val.double(),-1,-1,1,0);
case 6: return num2str(_val.currency(),-1,-1,1,0);
case 7: return date2str(_val.date(),123,2,2,2,2,4);
case 11: return int2str(_val.boolean());
case 202, 203: return _val.bStr();
}
return '';
}
// ============================================================================
// ТЕПЕРЬ ОСНОВНОЙ ПРОЦЕСС
// готовим информацию БД для передачи в Excel
cnnDB = new COM("ADODB.Connection");
cnnDB.connectionString(dbCnnString);
cnnDB.Open();
strSQL = "SELECT Name, PhoneLocal, EmplId, CellularPhone, UserId, BirthDate, RecId " +
"FROM EmplTable " +
"ORDER BY Name";
rstDB = new COM("ADODB.Recordset");
rstDB.open(strSQL, cnnDB);
// готовим новую рабочую книгу Excel для приема данных из БД:
xlApp = new COM("Excel.Application");
wbks = xlApp.Workbooks();
wbk = wbks.Add();
wkss = wbk.Worksheets();
wks = wkss.Item(1);
wks.Name("AdoTestSheet");
rng = wks.Range("A1");
// выводим строку имен полей (1-я строка листа Excel)
flds = rstDB.Fields();
iMax = flds.Count() - 1;
for (i = 0; i <= iMax; i += 1)
{
fld = flds.Item(i);
cell = rng.Offset(0, i);
cell.Value2(fld.Name());
}
rngCR = rng.CurrentRegion();
font = rngCR.Font();
font.Bold(true); // делаем выведенные заголовки жирным шрифтом
// выводим данные, начиная со 2-й строки листа Excel - больше было подготовки! :-)
cell = rng.Offset(1, 0);
cell.CopyFromRecordset(rstDB); // вот она, "изюминка"!
// сохраняем книгу и закрываем Excel
if (WinAPI::fileExists(filePath + "AdoTestBook.xls"))
WinAPI::deleteFile(filePath + "AdoTestBook.xls");
wbk.SaveAs(filePath + "AdoTestBook.xls");
wbk.Close();
xlApp.Quit();
rstDB.Close();
cnnDB.Close();
// ----------------------------------------------------------------------------
// открываем через ADO ранее сохраненную книгу Excel как-будто таблицу БД !
// (сейчас нет ячеек типа A1 и B1, а есть "настоящая" таблица с полями и записями)
cnnExcel = new COM("ADODB.Connection");
cnnExcel.connectionString("Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + filePath + "AdoTestBook.xls;" +
"Extended Properties='Excel 8.0;HDR=Yes'");
cnnExcel.Open();
rstExcel = new COM("ADODB.Recordset");
rstExcel.Open("SELECT * FROM [AdoTestSheet$]", cnnExcel);
// выводим в Info строку заголовков из Excel
flds = rstExcel.Fields();
iMax = flds.Count() - 1;
strInfo = '';
for (i = 0; i <= iMax; i += 1)
{
fld = flds.Item(i);
strInfo = strInfo + fld.Name() + " -- ";
}
info(strInfo);
info("----------------------------------------------------------------");
// выводим в Info данные из Excel
while (!rstExcel.EOF())
{
strInfo = '';
for (i = 0; i <= iMax; i += 1)
{
fld = flds.Item(i);
strInfo = strInfo + adoInfoValFromExcel(fld.Value(), fld.Type()) + " -- ";
}
info(strInfo);
rstExcel.MoveNext();
}
rstExcel.Close();
cnnExcel.Close();
}