|
07.11.2008, 13:21 | #1 |
Moderator
|
э-хе-хе...
Испытываю возобновление интереса к теме и вот в связи с чем. ADODB.Recordset имеет полезнейшие свойства Filter и Sort, которыми можно эффективно пользоваться, фильтруя исходный набор или изменяя порядок записей исходного Recordset'а и далее перебирая в цикле нужные записи в нужном порядке.
Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки. Увы, при управлении Excel из Аксапты этого не происходит: X++: static void Job103(Args _args) { #CCADO ComExcelDocument_RU doc = new ComExcelDocument_RU(); COM rst = new COM('ADODB.Recordset'); COM xlApp; COM wbook; COM activeSheet; COM range; COM flds,fld; int i; ; doc.NewFile('',false); wbook = doc.getComDocument(); xlApp = wbook.Parent(); activeSheet = xlApp.ActiveSheet(); flds = rst.Fields(); flds.Append('myField1', #adVarChar, 50); flds.Append('myField2', #adInteger); rst.Open(); for (i=1;i<=1000;i++) { rst.AddNew(); fld = flds.Item(0); fld.Value(int2str(i)); fld = flds.Item(1); fld.Value(i*2); rst.Update(); } rst.Filter("myField1 Like '*24*'"); rst.Sort('myField1 DESC'); rst.MoveFirst(); range = activeSheet.Range('A1'); range.CopyFromRecordset(rst, 300); range = activeSheet.Range('A1000'); range.CopyFromRecordset(rst, 300); doc.visible(true); // чтобы показать, что набор действительно фильтруется и сортируется rst.MoveFirst(); while (! rst.EOF()) { info(strFmt('%1 --- %2', new CCADOField( flds.Item(0) ).value(), new CCADOField( flds.Item(1) ).value())); rst.MoveNext(); } } Но этого не происходит. Вместо этого - и начиная с ячейки A1, и начиная с ячейки A1000 - одинаково выводятся первые 300 записей исходного набора. А хотелось бы, чтобы вывелись только 20 записей с ячейки A1, т.е. те записи, которые пример выводит в окно Infolog. Возможно мои претензии необоснованы и CopyFromRecordset должен себя вести именно так, как ведет себя в этом примере? Я уже было засомневался, вернее, почти отказался от своих "претензий", но решился на еще одну проверку - в самом Excel на VBA: Код: Sub Job103_VBA() Dim i As Integer Dim rst As Object Dim flds As Object Dim xlApp As Excel.Application Set rst = CreateObject("ADODB.Recordset") 'я сознательно создал rst через CreateObject, а не как New ADODB.Recordset, 'чтобы не искать ссылку на ADO через Tools\References Set flds = rst.Fields flds.Append "myField1", 200, 50 '200 = adVarChar flds.Append "myField2", 3 '3 = adInteger rst.Open For i = 1 To 1000 rst.AddNew rst.Fields(0).Value = i rst.Fields(1).Value = i * 2 rst.Update Next i rst.Filter = "myField1 Like '*24*'" rst.Sort = "myField1 DESC" rst.MoveFirst 'Set xlApp = New Excel.Application Set xlApp = Application xlApp.Workbooks.Add xlApp.Range("A1").CopyFromRecordset rst, 300 xlApp.Range("A1000").CopyFromRecordset rst, 300 xlApp.Visible = True End Sub Код: Set xlApp = New Excel.Application 'Set xlApp = Application Есть ли у кого какие-нибудь соображения? Может, кто-нибудь интересующийся продвинуто заглянет какими-нибудь крутыми вьюерами в тайны происходящих процессов COM-автоматизации? Может быть удастся победить ситуацию использованием каких-нибудь COMDispFunction? P.S. Проделал даже такой финт. Создал шаблон xlt, в который зашил VBA-процедуру: Код: Sub myCopyFromRecordset(ByVal rng As Range, ByVal rst As ADODB.Recordset, ByVal maxRows As Integer) rng.CopyFromRecordset rst, maxRows End Sub X++: xlApp.Run('myCopyFromRecordset', range, rst, 300); |
|
07.11.2008, 20:12 | #2 |
Administrator
|
Цитата:
Я удивлен другим. Я удивлен - что CopyFromRecordset все-таки может копировать с учетом фильтрации - но об этом видимо "помнит" только текущее приложение - т.е. поддержка реализована не на уровне "ядра" ADO
__________________
Возможно сделать все. Вопрос времени |
|
Теги |
ado, comvariant, excel, faq, odbc, sql, интеграция, прямой доступ, формат дат, экспорт, экспорт в excel |
|
|