|
|
#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 SubX++: {
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); } Тильда в строке ~Item(2,3) означает, что к Item(2,3) надо применить COM::createFromVariant. Знаю об этом из личного опыта по работе с объектами Range('...').Item(i, j) и Cells().Item(i, j).Интересно, что терминальные свойства (типа 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 |
|
|
|