06.10.2008, 17:01 | #16 |
Moderator
|
Визуальная имитация раннего связывания COM-объектов
Известно, что с COM-объектами Аксапта работает через позднее связывание. Это означает, что при портировании в Х++, например, кода VBA из Excel, нам придется расписать отдельными операторами X++ все точки, разделяющие объекты в операторах VBA.
Допустим, у нас есть такой код VBA, созданный макрорекордером и нами слегка подправленный, который в Excel записывает значение 123 в ячейку C2 активного листа активной книги, затем делает шрифт этой ячейки жирным ("болдит") и, наконец, заливает ячейку светложелтым цветом: Код: Sub Macro1() Range("C2").FormulaR1C1 = "123" Range("C2").Font.Bold = True Range("C2").Interior.ColorIndex = 36 'Light Yellow End Sub X++: { COM application; COM workbook = SysExcelApplication::construct().workbooks().add().comObject(); COM range; COM font; COM interior; ; application = workbook.Parent(); application.Visible(true); range = application.Range('C2'); range.FormulaR1C1(123); font = range.Font(); font.Bold(true); interior = range.Interior(); interior.ColorIndex(36); } Вместо нескольких таких переменных, истинный объектный смысл каждой из которых нас в данном случае мало интересует, можно использовать одну фиктивную. Обычно я называю ее comTemp - для акцентирования ее "временности" и "промежуточности". С такой "болван"-переменной можно написать операции следующим образом: X++: COM comTemp;
..........
comTemp = range.Font();
comTemp . Bold(true);
comTemp = range.Interior();
comTemp . ColorIndex(36); X++: COM::createFromObject( range.Font()).Bold( true );
COM::createFromObject( range.Interior()).ColorIndex(36); Таким образом, для реализации следующего "многоточечного" оператора VBA: Код: Application.ActiveWorkbook.Worksheets.Item(1).Cells.Item(2,3).Font.Bold = True X++: comTemp = application.ActiveWorkbook();
comTemp = comTemp.Worksheets();
comTemp = comTemp.Item(1);
comTemp = comTemp.Cells();
comTemp = COM::createFromVariant(comTemp.Item(2,3));
comTemp = comTemp.Font();
comTemp.Bold(true); В целях "борьбы" с описанным явлением я наваял совсем небольшой метод, с использованием функции runbuf, который позволяет существенно сократить количество строк код и придать вызову внешнюю похожесть на оператор VBA: X++: { COM application; COM workbook = SysExcelApplication::construct().workbooks().add().comObject(); COM range; COM comTemp; ; application = workbook.Parent(); application.Visible(true); range = application.Range('C2'); range.FormulaR1C1(123); comTemp = comEarlyBindingImitation( application, 'ActiveWorkbook()','Worksheets()','Item(1)','Cells()','~Item(2,3)','Font()'); comTemp.Bold(true); } X++: static COM comEarlyBindingImitation( COM _com0, str _com1 = '', str _com2 = '', str _com3 = '', str _com4 = '', str _com5 = '', str _com6 = '', str _com7 = '', str _com8 = '') { str myjob; str getSourcePart(str _com = '') { if (_com) if (subStr(_com,1,1) != '~') return strFmt('c=c.%1; ', _com); else return strFmt('c=COM::createFromVariant(c.%1); ', subStr(_com,2,strLen(_com)-1)); else return ''; } ; myjob = 'COM comEaBIm(COM _com0) {COM c;; c = _com0; '; myjob += getSourcePart(_com1); myjob += getSourcePart(_com2); myjob += getSourcePart(_com3); myjob += getSourcePart(_com4); myjob += getSourcePart(_com5); myjob += getSourcePart(_com6); myjob += getSourcePart(_com7); myjob += getSourcePart(_com8); myjob += 'return c; }'; return runbuf(myjob, _com0); } Интересно, что терминальные свойства (типа Bold или ColorIndex) можно тоже включить в это "раннее связывание" и тогда вообще обойтись одним оператором для одной операции. Следующие два оператора работают как надо: X++: comEarlyBindingImitation(application, 'Range("C2")','Font()','Bold(true)'); comEarlyBindingImitation(application, 'Range("C2")','Interior()','ColorIndex(36)'); |
|
|
За это сообщение автора поблагодарили: kashperuk (3), aidsua (1). |
Теги |
excel, rls, полезное, blog, axapta |
|
|