Показать сообщение отдельно
Старый 24.04.2006, 17:53   #1  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Поговорим об ADO
Уважаемые коллеги, насобирав ссылки для ветки Класс 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();
}
За это сообщение автора поблагодарили: mazzy (5), Sada (1), alex55 (1), Kabardian (4).