Показать сообщение отдельно
Старый 30.03.2007, 16:28   #12  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
В продолжение темы взаимодействия с Excel... Захотел я вычислять диапазон ячеек для Range в формате A1 на основании адреса левой верхней ячейки и количества строк/столбцов в диапазоне. Конечно, удобнее это делать для адресов в формате R1C1, но у Excel.Application есть чудесный метод ConvertFormula(), позволяющий в т.ч. преобразовывать адреса между форматами A1 и R1C1.
PHP код:
Function ConvertFormula_
    
<InAttribute()> ByVal Formula As Object_
    
<InAttribute()> ByVal FromReferenceStyle As XlReferenceStyle_
    
<InAttribute()> Optional ByVal ToReferenceStyle As Object_
    
<InAttribute()> Optional ByVal ToAbsolute As Object_
    
<InAttribute()> Optional ByVal RelativeTo As Object _
) As Object 
Цитата:
Parameters

Formula
Required Object. A String that contains the formula you want to convert. This must be a valid formula, and it must begin with an equal sign.
FromReferenceStyle
Required XlReferenceStyle. The reference style of the formula.
XlReferenceStyle can be one of these XlReferenceStyle constants:
xlA1
xlR1C1


ToReferenceStyle
Optional XlReferenceStyle. The reference style you want returned. If this argument is omitted, the reference style isn't changed; the formula stays in the style specified by FromReferenceStyle.
Если заглянуть в Excel 11.0 Object Library (или просто нажать print xlR1C1 в отладчике Excel), то можно увидеть, что значение этой константы почему-то равно -4150 (0xffffefca). Непонятно, конечно, ну да ладно. Пишу такой вот код
X++:
#define.xlRefStyleA1    (1)
#define.xlRefStyleR1C1  (-4150)    //(0xffffefca)

// _rows, _cols - dimensions of the range area
// _bookmark    - the upper-left corner of the range
protected Bookmark getXlRangeAddress(Bookmark _bookmark, int _rows, int _cols)
{
    COM range;
    COM app;
    str strAddr;
    str strRet;
    ;
    if(!excel)              throw error("@SYS54192");
    if(_rows<1 || _cols<1)  throw error(error::wrongUseOfFunction(funcname()));
    range   = excel.my_findRange(_bookmark);
    strRet  = range.address();
    if(_rows>1 || _cols>1)
    {
        app     = range.application();
        // convert _bookmark's upper-left cell address to R1C1 format
        strAddr = app.convertFormula(strRet,  #xlRefStyleA1, #xlRefStyleR1C1);
        if(!strAddr) throw error(@"Ошибка при вызове Application.ConvertFormula!");
        strAddr = strAddr + @":R" + int2str(range.row()+_rows-1) + @"C" + int2str(range.column()+_cols-1);
        strRet  = app.convertFormula(strAddr, #xlRefStyleR1C1, #xlRefStyleA1);
    }
    return strRet;
}
Здесь excel.my_findRange() - обертка для ComExcelDocument_RU.findRange(). Но app.convertFormula() всегда возвращает пустую строку! Если просто вызвать
X++:
strAddr = app.convertFormula(strRet,  #xlRefStyleA1);
то возвращает strRet, как и положено, не преобразуя из формата A1. При всем при этом тестовый VBScript замечательно отрабатывает
PHP код:
const xlRefStyleA1      1
const xlRefStyleR1C1    = -4150
const sBmk  "$J$4"
const cRows 24
const cCols 2
set oApp    
CreateObject("Excel.Application")
strAddr     oApp.ConvertFormula(sBmkxlRefStyleA1xlRefStyleR1C1)
wscript.echo sBmk    " == " strAddr
strAddr     
strAddr ":R" & (4+cRows-1) & "C" & (10+cCols-1)
wscript.echo strAddr " == " oApp.ConvertFormula(strAddrxlRefStyleR1C1xlRefStyleA1
Код:
$J$4 == R4C10
R4C10:R27C11 == $J$4:$K$27
Пробовал дополнительно указывать значение xlAbsolute (1) параметра ToAbsolute - эффект нулевой. Я что, неправильно задаю xlRefStyleR1C1? Может, отрицательное значение надо как-то по-другому передавать?..

Последний раз редактировалось gl00mie; 30.03.2007 в 16:32.