Beispiel #1
0
// function Excel4 calls always as using XLOPER12 seem problematic
int xlw::XlfFuncDesc::RegisterAs(const std::string& dllName, const std::string& suggestedHelpId, double mode_) const
{
    // alias arguments
    XlfArgDescList& arguments = impl_->arguments_;

    int nbargs = static_cast<int>(arguments.size());
    std::string args(returnTypeCode_);
    std::string argnames;

    // the synchronous part of an asynchronous function returns void
    if (XlfExcel::Instance().excel14() && impl_->Asynchronous_)
    {
        args = ">";
    }

    XlfArgDescList::const_iterator it = arguments.begin();
    while (it != arguments.end())
    {
        argnames += (*it).GetName();
        args += (*it).GetType();
        ++it;
        if (it != arguments.end())
            argnames+=", ";
    }
    
    // When the arguments add up to more then 255 char is problematic. the functions
    // will not register see  see BUG ID: 2834715 on sourceforge - nc
    if(argnames.length() > 255)
    {
        argnames = "Too many arguments for Function Wizard";
    }

    // the synchronous part of an asynchronous function have an extra 
    // bigdata xloper on the end containing the handle
    if (XlfExcel::Instance().excel14() && impl_->Asynchronous_)
    {
        args += "X";
    }
    if (impl_->recalcPolicy_ == xlw::XlfFuncDesc::Volatile)
    {
        args+="!";
    }
    if (XlfExcel::Instance().excel12() && impl_->Threadsafe_)
    {
        args+="$";
    }
    if (XlfExcel::Instance().excel14() && impl_->ClusterSafe_)
    {
        args+="&";
    }
    if (impl_->MacroSheetEquivalent_)
    {
        args+="#";
    }

    args+='\0'; // null termination for C string

    std::vector<LPXLOPER> argArray(10 + nbargs);
    LPXLOPER *px = &argArray[0];
    std::string functionName(GetName());

    // We need to have 2 functions exposed one for less than
    // version 14 and that it the normal function, we also need
    // the Synchronous part that returns void and takes an extra int
    // By convension this is the same as the normal function but with 
    // Sync on the end
    if (XlfExcel::Instance().excel14() && impl_->Asynchronous_)
    {
        functionName += "Sync";
    }

    (*px++) = XlfOper4(dllName);
    (*px++) = XlfOper4(functionName);
    (*px++) = XlfOper4(args);
    (*px++) = XlfOper4(GetAlias());
    (*px++) = XlfOper4(argnames);
    (*px++) = XlfOper4(mode_);
    (*px++) = XlfOper4(impl_->category_);
    (*px++) = XlfOper4(""); // shortcut
    // use best help context
    if(!helpID_.empty() && helpID_ != "auto")
    {
        (*px++) = XlfOper4(helpID_);
    }
    else
    {
        (*px++) = XlfOper4(suggestedHelpId); 
    }
    (*px++) = XlfOper4(GetComment());
    int counter(0);
    for (it = arguments.begin(); it != arguments.end(); ++it)
    {
        ++counter;
        if(counter < nbargs)
        {
            (*px++) = XlfOper4((*it).GetComment());
        }
        else
        {
            // add dot space to last comment to work around known excel bug
            // see http://msdn.microsoft.com/en-us/library/bb687841.aspx
            (*px++) = XlfOper4((*it).GetComment() + ". ");
        }
    }

    if(XlfExcel::Instance().excel12())
    {
        // total number of arguments limited to 255
        // so we can't send more than 245 argument comments
        nbargs = std::min(nbargs, 245);
    }
    else
    {
        // you can't send more than 30 arguments to the register function
        // in up to version 2003, so just only send help for up to the first 20 parameters
        nbargs = std::min(nbargs, 20);
    }

    XlfOper4 res;
    int err = XlfExcel::Instance().Call4v(xlfRegister, res, 10 + nbargs, &argArray[0]);
    if(err == xlretSuccess && res.IsNumber())
    {
        funcId_ = res.AsDouble();
    }
    else
    {
        funcId_ = InvalidFunctionId;
    }

    return err;
}
Beispiel #2
0
int xlw::XlfOper4::ConvertToCellMatrix(CellMatrix& output) const
{

    if (lpxloper_->xltype == xltypeMissing || lpxloper_->xltype == xltypeNil )
    {

        CellMatrix tmp(1,1);
        output = tmp;

        return xlretSuccess;
    }

    if (lpxloper_->xltype == xltypeNum)
    {
        CellMatrix tmp(1,1);

        tmp(0,0) = lpxloper_->val.num;

        output = tmp;



        return xlretSuccess;
    }

    if (lpxloper_->xltype == xltypeBool)
    {
        CellMatrix tmp(1,1);

        tmp(0,0) = (lpxloper_->val.xbool >0);

        output = tmp;


        return xlretSuccess;
    }

    if (lpxloper_->xltype == xltypeErr)
    {
        CellMatrix tmp(1,1);

        tmp(0,0) = CellValue(lpxloper_->val.err,true);

        output = tmp;

        return xlretSuccess;
    }

    if (lpxloper_->xltype == xltypeStr)
    {
        CellMatrix tmpCell(1,1);

        unsigned long len = *((*lpxloper_).val.str);

        std::string tmp;
        tmp.resize(len);


        for(unsigned long k=0; k<len; ++k)
            tmp[k]= ((*lpxloper_).val.str)[k+1];


        tmpCell(0,0) = tmp;

        output = tmpCell;

        return xlretSuccess;
    }


    if (lpxloper_->xltype == xltypeMulti)
    {
        unsigned long rows = lpxloper_->val.array.rows;
        unsigned long columns = lpxloper_->val.array.columns;
        CellMatrix result(rows,columns);

        for (unsigned long i=0; i < rows; i++)
            for (unsigned long j=0; j < columns; j++)
            {
                unsigned long thisType = (*lpxloper_).val.array.lparray[i*columns+j].xltype;
                if (thisType == xltypeNum)
                {
                    double x = (*lpxloper_).val.array.lparray[i*columns+j].val.num;
                    result(i,j) = x;
                }
                else
                {
                    if (thisType==xltypeStr)
                    {
                          unsigned long len = *((*lpxloper_).val.array.lparray[i*columns+j].val.str);

                          std::string tmp;
                          tmp.resize(len);

                          for(unsigned long k=0; k<len; ++k)
                            tmp[k]=
                            ((*lpxloper_).val.array.lparray[i*columns+j].val.str)[k+1];

                          result(i,j) = tmp;
                    }

                    else
                        if (thisType == xltypeBool)
                        {
                            result(i,j) = ((*lpxloper_).val.array.lparray[i*columns+j].val.xbool > 0);
                        }
                        else
                            if (thisType== xltypeErr)
                            {
                                result(i,j) = CellValue(((*lpxloper_).val.array.lparray[i*columns+j].val.err),true);
                            }
                            else
                                if (thisType!=xltypeMissing && thisType != xltypeNil)
                                    throw("cell contains neither number nor string nor boolean nor empty");
                }

            }

        output= result;


        return xlretSuccess;


    }

    XlfRef ref;
    int xlret = ConvertToRef(ref);
    if (xlret != xlretSuccess)
        return xlret;

    unsigned long nbRows = ref.GetNbRows();
    unsigned long nbCols = ref.GetNbCols();

    output = CellMatrix(nbRows,nbCols);
    for (unsigned long i = 0; i < nbRows; ++i)
    {
        for (unsigned long j = 0; j < nbCols; ++j)
        {
            XlfOper4 element = ref.element<XlfOper4>(static_cast<WORD>(i), static_cast<BYTE>(j));
            unsigned long type = element.lpxloper_->xltype;

            if (type == xltypeRef)
            {
                XlfRef xlrefij;

                int xlretij = element.ConvertToRef(xlrefij);

                if (xlretij != xlretSuccess)
                    return xlretij;

                XlfOper4 refElement = xlrefij.element<XlfOper4>(0UL,0UL);
                type = refElement.lpxloper_->xltype;

                if (type == xltypeNum)
                {
                    double tmp;
                    xlret = refElement.ConvertToDouble(tmp);

                    output(i,j) = tmp;

                    if (xlret != xlretSuccess)
                        return xlret;
                }
                else
                    if (type == xltypeErr)
                    {
                        WORD tmp;

                        xlret = refElement.ConvertToErr(tmp);

                        output(i,j) = CellValue(tmp,true);

                        if (xlret != xlretSuccess)
                            return xlret;
                    }
                    else
                    if (type == xltypeBool)
                    {
                        bool tmp;

                        xlret = refElement.ConvertToBool(tmp);

                        output(i,j) = tmp;

                        if (xlret != xlretSuccess)
                            return xlret;
                    }
                    else
                    {
                        if (type == xltypeStr || type == xltypeSRef)
                        {
                            char* tmp;
                            xlret = refElement.ConvertToString(tmp);
                            output(i,j) = std::string(tmp);

                            if (xlret != xlretSuccess)
                                return xlret;
                        }
                        else
                        {

                            if (type != xltypeMissing)
                                return xlretInvXloper;

                        }

                    }

            }
            else
                if (type == xltypeNum)
                {
                    double tmp;
                    xlret = element.ConvertToDouble(tmp);

                    output(i,j) = tmp;

                    if (xlret != xlretSuccess)
                        return xlret;
                }
                else
                {
                    if (type == xltypeStr || type == xltypeSRef)
                    {
                        char* tmp;
                        xlret = element.ConvertToString(tmp);
                        output(i,j) = std::string(tmp);

                        if (xlret != xlretSuccess)
                            return xlret;
                    }
                    else
                    {
                        if (element.lpxloper_->xltype != xltypeMissing)
                            return xlretInvXloper;

                    }

                }
        }

    }
    return xlret;

}
Beispiel #3
0
/*!
Registers the command as a macro in excel.
\sa XlfExcel, XlfFuncDesc.
*/
int xlw::XlfCmdDesc::DoRegister(const std::string& dllName, const std::string& suggestedHelpId) const
{
    XlfArgDescList arguments = GetArguments();

    // 2 = normal macro, 0 = hidden command
    double type = hidden_ ? 0 : 2;

    int nbargs = static_cast<int>(arguments.size());
    std::string args("A");
    std::string argnames;

    XlfArgDescList::const_iterator it = arguments.begin();
    while (it != arguments.end())
    {
        argnames += (*it).GetName();
        args += (*it).GetType();
        ++it;
        if (it != arguments.end())
            argnames+=", ";
    }

    // When the arguments add up to more then 255 char is problematic. the functions
    // will not register see  see BUG ID: 2834715 on sourceforge - nc
    if(argnames.length() > 255)
    {
        argnames = "Too many arguments for Function Wizard";
    }

    std::vector<LPXLOPER> argArray(10 + nbargs);
    LPXLOPER *px = &argArray[0];

    (*px++) = XlfOper4(dllName);
    (*px++) = XlfOper4(GetName());
    (*px++) = XlfOper4(args);
    (*px++) = XlfOper4(GetAlias());
    (*px++) = XlfOper4(argnames);
    (*px++) = XlfOper4(type);
    (*px++) = XlfOper4("");
    (*px++) = XlfOper4("");
    (*px++) = XlfOper4("");
    (*px++) = XlfOper4(GetComment());
    int counter(0);
    for (it = arguments.begin(); it != arguments.end(); ++it)
    {
        ++counter;
        if(counter < nbargs)
        {
            (*px++) = XlfOper4((*it).GetComment());
        }
        else
        {
            // add dot space to last comment to work around known excel bug
            // see http://msdn.microsoft.com/en-us/library/bb687841.aspx
            (*px++) = XlfOper4((*it).GetComment() + ". ");
        }
    }

    if(XlfExcel::Instance().excel12())
    {
        // total number of arguments limited to 255
        // so we can't send more than 245 argument comments
        nbargs = std::min(nbargs, 245);
    }
    else
    {
        // you can't send more than 30 arguments to the register function
        // in up to version 2003, so just only send help for up to the first 20 parameters
        nbargs = std::min(nbargs, 20);
    }

    XlfOper4 res;
    int err = XlfExcel::Instance().Call4v(xlfRegister, res, 10 + nbargs, &argArray[0]);
    if(err == xlretSuccess && res.IsNumber())
    {
        funcId_ = res.AsDouble();
    }
    else
    {
        funcId_ = InvalidFunctionId;
    }
    return err;
}