xlladdins / xll

Excel add-in library
MIT License
104 stars 23 forks source link

Taking OPER as a function argument #17

Closed TheMichalcinOfficial closed 2 years ago

TheMichalcinOfficial commented 2 years ago

Hello, I am currently trying to learn how to use this library and I am facing some issues. I need to write a function that takes in a range of excel cells, reads them and then returns some integer output based on what was in those cells. Since I am just learning, I wanted to return the size of the range. Here is my code:

xll::AddIn xai_myfunc(
    xll::Function(XLL_LONG, "xll_myfunc", "MYFUNC")
    .Arguments({ xll::Arg(XLL_LPOPER, "timestamps", "range of cells containing timecodes") })
    .FunctionHelp("Test function")
);

xll::OPER WINAPI xll_myfunc(xll::OPER timestamps)
{
#pragma XLLEXPORT
    return timestamps.size();
}

When I try to call the function in excel and hit Enter, the process (running in debug mode) crashes and throws an exception saying that the OPER was set to nullptr. The program crashes inside the xll::type() function. I fear that I'm making a dumb mistake, but I can't figure it out...

keithtango commented 2 years ago

OPERs are passed in as pointers

xll::OPER WINAPI xll_myfunc(xll::LPOPER timestamps)
{
#pragma XLLEXPORT
    return timestamps->size();
}
TheMichalcinOfficial commented 2 years ago

It's still getting assigned to nullptr.

keithalewis commented 2 years ago

I missed that you are returning a long:

xll::AddIn xai_myfunc(
    xll::Function(XLL_LONG, "xll_myfunc", "MYFUNC")
    .Arguments({ xll::Arg(XLL_LPOPER, "timestamps", "range of cells containing timecodes") })
    .FunctionHelp("Test function")
);

LONG WINAPI xll_myfunc(xll::LPOPER timestamps)
{
#pragma XLLEXPORT
    return timestamps->size();
}
TheMichalcinOfficial commented 2 years ago

Oh yeah, that fixed it. So I just got lost with my types... One last question: can I somehow modify the multi, or return a new multi as a result? I'd like to write a function, that takes in a range of cells and then fills another range of cells with values.

keithalewis commented 2 years ago

See, e.g., https://github.com/xlladdins/xll_range/blob/946d2991ff0c984af34563a63ab686fb37d016d4/xll_range.cpp#L156

rmcrkd commented 2 years ago

You might find this identity function on a cell (or range of cells) helpful. Just replace o = *po as required, and extend xll_func's signature to include other cells, if needed.

xll::LPOPER WINAPI xll_func(xll::LPOPER po) {
#pragma XLLEXPORT
    static xll::OPER o;
    try {
        // do something more interesting
        o = *po;
    }
    catch (std::exception& e) {
        o = e.what();
    }
    return &o;
}

AddIn xai_func(
    Function(XLL_LPOPER, "xll_func", "XLL.FUNC")
    .Arguments({
                Arg(XLL_LPOPER, "po", "cells")
        })
);
keithalewis commented 2 years ago

Thanks @rmcrkd!

TheMichalcinOfficial commented 2 years ago

Thanks, all of you! :-)