26.06.2009, 10:48 | #27 |
Участник
|
Проблемы со свойствами Formula и FormulaR1C1 - в способе их вызова из Ax
Все функции из Com-объектов вызываются не напрямую, а через специальный интерфейс IDispatch, в котором реализуется пара методов IDispatch::GetIdOfNames и IDispatch::Invoke. Первый метод по имени функции возвращает ее идентификатор (DispId), а второй - вызывает по этому идентификатору функцию выполнения. В обоих этих методах в качестве входного параметра присутствует языковый идентификатор - LCID. И Excel, как многоязыковая система, использует этот идентификатор для определения используемого языка. Т.е., если вызвать Formula() с параметром языка 0x0409 (en-Us), то функция внутри будет оперировать с передаваемыми данных, считая их англоязычными, если передать 0x0419 (ru), то, соответственно, русскоязычными. Dax при вызове подставляет константу LOCALE_USER_DEFAULT, что соответствует языку интерфейса по умолчанию, что для русского интерфейса Windows аналогично вызову Invoke() с параметром 0x0419 (ru) - отсюда и проблемы с интерпретацией буфера. Excel требует вводить имена функций на русском. В VBA при вызове подставляется другая константа LOCALE_NEUTRAL (0x0000). Эту константу Excel интерпретирует как код языка по умолчанию и требует вводить английские (точнее, американские) имена функций. Фактически, свойства Formula и FormulaR1C1 позволяют использовать любой язык, поддерживаемый Excel Свойства FormulaLocal и FormulaR1C1Local игнорируют передаваемый LCID и всегда используют LOCALE_USER_DEFAULT, что и приводит к одинаковым результатам при вызове из AX всех этих свойств Ну и в заключение, я набросал небольшую DLL, с помощью которой можно делать языконезависимый вызов свойств Formula и FormulaR1C1 из Ax X++: static void ExcelFormula(Args _args) { COM xlApp; COM wbk; COM rng; COMVariant cv; int iDispatch; DLL _DLL = new DLL("ComCall.dll"); //Получение DispId для свойства Formula DllFunction FormulaDispId = new DllFunction(_dll, "FormulaDispId"); //Получение DispId для свойства FormulaR1C1 DllFunction FormulaR1C1DispId = new DllFunction(_dll, "FormulaR1C1DispId"); //Установка свойства Formula для указанного объекта Range DllFunction SetFormula = new DllFunction(_dll, "Set_Formula"); //Получение свойства Formula для указанного объекта Range //первый вызов - для получения размера используемого буфера результата DllFunction GetFormulaLen = new DllFunction(_dll, "Get_Formula"); //второй вызов - для получения свойства DllFunction GetFormula = new DllFunction(_dll, "Get_Formula"); int dispId; int dispIdR1C1; Binary buf; int len; ComVariant var; ; FormulaDispId.returns(ExtTypes::DWord); FormulaDispId.arg(ExtTypes::DWord); FormulaR1C1DispId.returns(ExtTypes::DWord); FormulaR1C1DispId.arg(ExtTypes::DWord); SetFormula.returns(ExtTypes::DWord); SetFormula.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::String); //Для получения размера буфера GetFormulaLen.returns(ExtTypes::DWord); GetFormulaLen.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::Dword); //Для получения результата буфера GetFormula.returns(ExtTypes::DWord); GetFormula.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::Pointer); xlApp = new COM ('Excel.Application'); wbk = xlApp.Workbooks(); wbk = wbk.Add(); rng = xlApp.Range('A1'); iDispatch = rng.interface(); dispId = FormulaDispId.call(iDispatch); dispIdR1C1 = FormulaR1C1DispId.call(iDispatch); SetFormula.Call(iDispatch, dispId, '=sum(B1:D1)'); cv = rng.Text(); print cv.bStr(); len = GetFormulaLen.call(iDispatch, dispId, 0); buf = New Binary(len+1); GetFormula.call(iDispatch, dispId, buf); print "dll " + buf.string(0); len = GetFormulaLen.call(iDispatch, dispIdR1C1, 0); buf = New Binary(len+1); GetFormula.call(iDispatch, dispIdR1C1, buf); print "dll R1C1 " + buf.string(0); var = rng.formula(); print "Dax " + var.bStr(); rng = xlApp.Range('A2'); rng.Formula('=sum(B1:D1)'); cv = rng.Text(); print cv.bStr(); wbk.Close(False); // чтобы не оставался скрытый экземпляр Excel xlApp.Quit(); pause; }
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: Wamr (5), tolstjak (1), ZVV (2), Antoncheg (1). |
Теги |
ado, excel, экспорт |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|