Получить матрицу из excel в c++ xll, изменить ее и вернуть

Я закодировал функцию xll, получающую матрицу из excel, изменяя ее и возвращая:

__declspec(dllexport) LPXLOPER12 WINAPI ZZZZUpdateArray1(LPXLOPER12 arrayin)
{
    if (arrayin->xltype == xltypeMulti | xlbitDLLFree)
    {
        double ScaleFactor = 2.0;
        int rows = arrayin->val.array.rows;
        int cols = arrayin->val.array.columns;
        static XLOPER12 xlArray;
        xlArray.val.array.lparray = reinterpret_cast<LPXLOPER12>(::new XLOPER12[rows * cols] /*::malloc(rows * cols * sizeof(XLOPER12))*/);
        for (int r = 0; r<rows; r++)
        {
            for (int c = 0; c<cols; c++)
            {
                if ((arrayin->val.array.lparray + ((r* cols) + c))->xltype == xltypeNum)
                {
                    XLOPER12* var = xlArray.val.array.lparray + ((r* cols) + c);
                    var->xltype = xltypeNum;
                    var->val.num = ScaleFactor*(arrayin->val.array.lparray + ((r* cols) + c))->val.num ;
                }
            }
        }
        return static_cast<LPXLOPER12>(&xlArray);
    }
    return arrayin;
}

но он падает на

if ((arrayin->val.array.lparray + ((r* cols) + c))->xltype == xltypeNum)

Если я, например, беру матрицу 5 * 5 из Excel, при отладке я вижу, что она имеет 19 строк и 20 столбцов, что произошло!?

Возможно, это потому, что когда я получаю LPXLOPER12 arrayin, он представляет собой диапазон Excel, намного более сложный, чем матрица 5 * 5. Как тогда получить доступ к матрице 5 * 5, которую она содержит?


person Olorin    schedule 13.04.2017    source источник
comment
if (arrayin->xltype == xltypeMulti | xlbitDLLFree) всегда оценивается как true. Наверняка не то, что вы хотите. Ваш компилятор, вероятно, предупредил вас об этом. Кроме того, использование распределителя стандартной библиотеки C++ (operator new), безусловно, не соответствует ожиданиям Excel.   -  person IInspectable    schedule 13.04.2017
comment
@IInspectable Дополнительный вопрос (чтобы узнать, стоит ли нам открывать специальный вопрос): возможно, вы знаете, как создавать функции xll, возвращающие или имеющие дескрипторы в качестве параметров?   -  person Olorin    schedule 14.04.2017
comment
@IInspectable Целью if (arrayin->xltype == xltypeMulti | xlbitDLLFree) было просто проверить, что arrayin действительно представляет собой двумерный массив.   -  person Olorin    schedule 14.04.2017
comment
Тем не менее, вы не соблюдаете приоритет оператора C++. Независимо от ввода, выражение всегда оценивается как true. Какой бы ни была цель, код не достигает ее.   -  person IInspectable    schedule 14.04.2017


Ответы (2)


  • Используйте код Excel Q для регистрации входного аргумента.
  • Вам нужно правильно объявить возвращаемую переменную:

    // initialize the return variable
    xlArray.val.array.rows = rows;
    xlArray.val.array.columns = cols;
    xlArray.xltype = xltypeMulti | xlbitDLLFree;
    
person Malick    schedule 13.04.2017
comment
В чем смысл использования malloc вместо new? Поскольку вы передали флаг xlbitDLLFree, вы можете использовать любой распределитель, который считаете нужным. Или я что-то упускаю? - person IInspectable; 13.04.2017
comment
@IInspectable Вы правы. Если вы используете удаление, чтобы освободить его, вы можете использовать его. Вы ничего не упускаете, но я думал, что ОП использует бесплатно. см. stackoverflow.com/questions/43375114/ . Я только что удалил свое замечание о malloc и new. - person Malick; 13.04.2017
comment
@Malick Это действительно работает с Q вместо U для входного аргумента, спасибо. (В остальном я слишком глуп.) - person Olorin; 13.04.2017
comment
@IInspectable Лучше использовать new, потому что это не вызовет проблем при компиляции релиза x64, тогда как malloc вызовет. - person Olorin; 13.04.2017
comment
@Malick Побочный вопрос (чтобы узнать, стоит ли нам открывать специальный вопрос): возможно, вы знаете, как создавать функции xll, возвращающие или имеющие дескрипторы в качестве параметров? - person Olorin; 13.04.2017
comment
@ujs: new звонит malloc. Если malloc вызывает проблемы, вызов new тоже. Дело в том, что если вы передаете xlbitDLLFree, управление памятью будет приватным для вашего модуля. Вы можете использовать любой распределитель, включая mallov/free. - person IInspectable; 13.04.2017
comment
@ujs: нет, я действительно не знаю, я думаю, вам нужно поддерживать все дескрипторы в фоновом режиме и просто возвращать / принимать ключ (например, двойной), который ссылается на дескриптор. - person Malick; 14.04.2017
comment
@Malick Странно, моя функция не работает для одной переданной ей ячейки Excel ... - person Olorin; 14.04.2017
comment
@ujs: этого следовало ожидать. Одна ячейка не является матрицей. - person IInspectable; 15.04.2017
comment
И да, и нет, потому что VARIANT может быть одноклеточным без проблем. - person Olorin; 15.04.2017

Я взял код ujsgeyrr1f0d0d0r0h1h0j0j_juj, чтобы сделать его для тестирования моего приложения. Я думаю, это может быть полезно. Я также использовал коды из других ссылок.

    __declspec(dllexport) LPXLOPER12 WINAPI Array_In_Out(LPXLOPER12 ExMatriz)

{

     static XLOPER12 xlMatriz;  // variável de retorno


try
{

    int rows = ExMatriz->val.array.rows;
    int cols = ExMatriz->val.array.columns;
    xlMatriz.xltype = xltypeMulti | xlbitDLLFree;
    xlMatriz.val.array.rows = rows;
    xlMatriz.val.array.columns = cols;


    // ======= VERIFICACAO DOS DADOS DE ENTRADA ==============


    if (ExMatriz->xltype != xltypeRef       &&
        ExMatriz->xltype != xltypeSRef  &&
        ExMatriz->xltype != xltypeMulti)
    {
        xlMatriz.xltype = xltypeErr;
        xlMatriz.val.err = xlerrValue;

        return (LPXLOPER12)&xlMatriz;
    }



    static XLOPER12 MatrizMulti, tempTypeMulti;
    LPXLOPER12 Matrizptr;

    tempTypeMulti.xltype = xltypeInt;
    tempTypeMulti.val.w = xltypeMulti;

    if (xlretUncalced ==
        Excel12(xlCoerce, (LPXLOPER12)&MatrizMulti, 2, (LPXLOPER12)ExMatriz,
        (LPXLOPER12)&tempTypeMulti))
    {
        return 0;
    }


    Matrizptr = MatrizMulti.val.array.lparray;

    // verify that the entire ExMatriz are nums

    for (int r = 0; r < rows; r++)
    {
        for (int c = 0; c < cols; c++)
        {


            if ((Matrizptr + ((r* cols) + c))->xltype != xltypeNum)  // verifica se os valores são numericos
            {


                if (Matrizptr->xltype == xltypeErr)
                {

                    xlMatriz.xltype = xltypeErr;
                    xlMatriz.val.err = Matrizptr->val.err;

                    return (LPXLOPER12)&xlMatriz;
                }
                else
                {

                    xlMatriz.xltype = xltypeErr;
                    xlMatriz.val.err = xlerrValue;

                    return (LPXLOPER12)&xlMatriz;
                }

            }


        }
    }



    xlMatriz.val.array.lparray = reinterpret_cast<LPXLOPER12>(::new XLOPER12[rows * cols]); //new XLOPER12[rows*cols];


    for (int r = 0; r < rows; r++)
    {

        for (int c = 0; c < cols; c++)
        {

            xlMatriz.val.array.lparray + ((r* cols) + c);

            ExMatriz->val.array.lparray + ((r* cols) + c);

            xlMatriz.val.num = ExMatriz->val.num;         // coloca os valores de entrada na variável de saída !!!

        }
    }



    return static_cast<LPXLOPER12>(&xlMatriz);


    //return (LPXLOPER12)&xlMatriz;

}
catch (std::exception& e)
{
    xlMatriz.xltype = xltypeErr;
    xlMatriz.val.err = xlerrNA;
    return  (LPXLOPER12)&xlMatriz;
}

}

person Horacimar Pinheiro Cotrim    schedule 02.07.2018