Цитата:
Сообщение от
macklakov
Лучше в аксовскую базу со стороны не лезть. Получишь блокировки, в самый напряженный момент.
Однако, нашёлся «рояль в кустах». Теперь лезем не стороны, а изнутри!
На мой взгляд – просто чума…
Recordset в оперативной памяти (как массив)! Без объекта Connection! Сам по себе, без привязки к источнику данных. При этом обладает свойствами обычного Recordset-а (работают всякие MoveLast, MoveFirst и т.п. – конечно, надо потестировать, но MoveFirst работает точно – см. джоб ниже). Можно добавлять записи, редактировать их. Состав полей тоже определяем сами.
В качестве примера – джоб ниже, опять-таки выводящий в Excel список сотрудников. Ничего предварительно настраивать не надо, просто запускайте.
X++:
static void Job_TestADO_2(Args _args)
{
// ----------------------------------------------------------------------------
// ADODB.Recordset в оперативной памяти без привязки к источнику данных
// ----------------------------------------------------------------------------
EmplTable emplTable;
COM rstAxa; // ADO: Recordset
COM flds, fld; // ADO: Fields, Field
COM xlApp; // Excel.Application
COM wbks, wbk; // Workbooks, Workbook
COM wkss, wks; // Worksheets, Worksheet
COM rng, cell, rngCR; // все Range
COM font; // Range.Font
COM entCol; // Range.EntireColumn
COM actWin; // Excel.Application.ActiveWindow
int i, iMax;
// ============================================================================
// СНАЧАЛА ВЛОЖЕННАЯ ФУНКЦИЯ
// ----------------------------------------------------------------------------
// функция для задания типа поля нашего Recordset-а в оперативной памяти
// в данном демо-джобе используется для наглядности
// для простоты используем всего 3 типа данных: число, строка и дата
int adoTypeToExcel(str _type)
{
switch (_type)
{
// используются значения констант перечисления DateTypeEnum из топика TypeProperty (ADO)
// (см. справку по ADO в файле ADO210.CHM - можно поискать на своем компе)
case 'num' : return 5; // adDouble
case 'str' : return 8; // adBSTR
case 'date': return 133; // adDBDate
}
return 8;
}
// ============================================================================
// ТЕПЕРЬ ОСНОВНОЙ ПРОЦЕСС
// Recordset создается в оперативной памяти - без Connection!
rstAxa = new COM('ADODB.Recordset');
// формируем структуру нашего Recordset-а в "мозгах"
flds = rstAxa.Fields();
flds.Append('Name' , adoTypeToExcel('str' ));
flds.Append('PhoneLocal' , adoTypeToExcel('str' ));
flds.Append('EmplId' , adoTypeToExcel('str' ));
flds.Append('CellularPhone', adoTypeToExcel('str' ));
flds.Append('UserId' , adoTypeToExcel('str' ));
flds.Append('BirthDate' , adoTypeToExcel('date'));
flds.Append('RecId' , adoTypeToExcel('num' ));
// и наконец открываем его
rstAxa.Open();
// ----------------------------------------------------------------------------
while select emplTable order by Name
{
// бежим по таблице "Список сотрудников" Axapta
// и добавляем записи (выбранные поля) в Recordset в оперативной памяти
rstAxa.AddNew();
fld = flds.Item('Name' ); fld.Value(emplTable.Name );
fld = flds.Item('PhoneLocal' ); fld.Value(emplTable.PhoneLocal );
fld = flds.Item('EmplId' ); fld.Value(emplTable.EmplId );
fld = flds.Item('CellularPhone'); fld.Value(emplTable.CellularPhone);
fld = flds.Item('UserId' ); fld.Value(emplTable.UserId );
fld = flds.Item('BirthDate' ); fld.Value(emplTable.BirthDate );
fld = flds.Item('RecId' ); fld.Value(emplTable.RecId );
rstAxa.Update();
}
// к этому моменту в оперативной памяти сформирована НАША таблица "Список сотрудников"
// ----------------------------------------------------------------------------
// перед выгрузкой в Excel встанем на первую запись НАШЕЙ ТАБЛИЦЫ В ПАМЯТИ
// и изменим имя сотрудника, дату его рождения и ID
// НЕ БОЙТЕСЬ!!! Аксаптовская таблица EmplTable при этом НЕ ЗАТРАГИВАЕТСЯ!!! :)))
rstAxa.MoveFirst();
fld = flds.Item('Name' ); fld.Value('Самый молодой cотрудник с очень длинным именем');
fld = flds.Item('BirthDate'); fld.Value(1\3\2006); // 1-е марта 2006 года
fld = flds.Item('EmplId' ); fld.Value('000333');
// потом обратите внимание, что в Excel ведущие нули у 000333 сохранятся!
rstAxa.Update();
// ----------------------------------------------------------------------------
// готовим новую рабочую книгу Excel для приема данных из Axapta:
xlApp = new COM('Excel.Application');
xlApp.Visible(true);
wbks = xlApp.Workbooks();
wbk = wbks.Add();
wkss = wbk.Worksheets();
wks = wkss.Item(1);
wks.Name('AdoTestSheet');
rng = wks.Range('A1');
// ----------------------------------------------------------------------------
// выводим строку имен полей (1-я строка листа Excel)
flds = rstAxa.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(rstAxa);
// ----------------------------------------------------------------------------
// подгоняем ширину столбцов Excel
rngCR = rng.CurrentRegion();
entCol = rngCR.EntireColumn();
entCol.AutoFit();
// замораживаем строку заголовков Excel
cell.Select();
actWin = xlApp.ActiveWindow();
actWin.FreezePanes(true);
// ----------------------------------------------------------------------------
rstAxa.Close();
}