a new handle code

Apr 12, 2013 at 4:56 PM
Hi Keith,

hope you are doing well. i wrote a new handle implementation which seems to be not leaking as profously as the implentation you have. it is completely based on what you have. these are the features:
1> maps a cell location to a pointer.
2> does not leak when you cut and paste a handle to another location.
2> if the cell is empty deletes underlying pointer.
3> does not leak if you f2 from the same cell or from function wizard.

i am just 6 months old to the concept of c++ and excel sdk, not as experienced as you are so there may be somethings i have overlooked but seems like everthying is good. i am giving the code below and if you want you can use it.

also i use boost to convert between strings and numbers. but i guess you do not want to use any additional dependencies in which case you can modify the part (which converts between string and numbers) using some other code.

// handle.h - simple handle class

pragma once

include <set>

include <memory>

include "oper.h"

include <boost/lexical_cast.hpp>

include <boost/algorithm/string.hpp>

namespace xll {
    template<class T, class D = std::default_delete<T>>
class handle {
        public:
            typedef typename std::map<std::string,std::unique_ptr<T,D> > handle_map;

            static handle_map& handle_map_get(void)
            {
                static handle_map h_;

                return h_;
            }
        private:

            static void insert(std::string name,T* p, D d)
            {
                handle_map& h(handle_map_get());
                // loop to delete any empty cell
                for(handle_map::iterator it=h.begin();it!=h.end();++it)
                {

                    std::wstring cell = strings::mbstowcs(it->first);
                    cell.erase(cell.end()-1);
                    OPERX loc = ExcelX(xlfTextref,OPERX(cell.c_str()) ,OPERX(false));
                    OPERX cell_content = ExcelX(xlCoerce,loc); 
                    if(cell_content.xltype == xltypeNil)
                    {
                        h.erase(it);
                        break;
                    }

                }
                // delete any existing handles
                handle_map::iterator it=h.find(name);
                if(it != h.end()) h.erase(it);
                h.insert(std::pair<std::string,std::unique_ptr<T,D> >(name,std::unique_ptr<T,D>(p,d)));

            }
            std::pair<std::string, T*> p_;
        public:
            // Called as handle<T> h(new T(...));
            // in constructor. Must be uncalced.
            handle(T* p = 0, D d = std::default_delete<T>())
            {
                if (p) 
                {                       
                    OPERX xCaller = ExcelX(xlfCaller);
                    OPERX xSName = ExcelX(xlSheetNm,xCaller);
                    std::wstring SName_ws(xSName.val.str + 1, xSName.val.str[0]);
                    std::string name = strings::wcstombs(SName_ws);
                    // take out the book name
                    name = name.substr(name.find_last_of("]")+1);
                    name.erase(name.end()-1);
                    std::string row = boost::lexical_cast<std::string>(xCaller.val.sref.ref.rwFirst+1);             
                    std::string col = boost::lexical_cast<std::string>(xCaller.val.sref.ref.colFirst+1);
                    name.append("!").append("R").append(row).append("C").append(col);
                    insert(name,p, d);
                    p_ = std::pair<std::string, T*>(name,p);
                }
            }
            handle(OPERX xname, bool checked = true)
            {
                handle_map& h_map(handle_map_get());
                std::string name = strings::wcstombs(std::wstring((xname).val.str + 1, (xname).val.str[0]));
                p_ = std::pair<std::string,T* >(name,(h_map.find(name)->second).get()); 
            }

            ~handle(){ }

            // std::string get() const
            OPERX get() const
            {
                OPERX handleName= OPERX((strings::mbstowcs(p_.first)).c_str());
                return handleName;
                //return p_.first;
            }
            T* ptr()
            {
                return p_.second;
            }
            operator T*()
            {
                return p_.second;
            }
            const T* operator->() const
            {
                return p_.second;
            }
            T* operator->()
            {
                return p_.second;
            }
            T& operator*()
            {
                return *p_.second;
            }

            const T& operator*() const
            {
                return *p_.second;
            }


};
}// namespace xll
Coordinator
Apr 12, 2013 at 5:25 PM
Thanks for your effort. You may want to take a look at locus.h for more efficient means of associating pointers with cells.

Why are you unnecessarily dragging in boost? Use std::to_string.

The best way to convince me is to find other users that adopt your code and give it a positive review. You seem to be the only person fetishizing over "profuse" leaking.
Apr 12, 2013 at 7:16 PM
i wasn't aware of std::to_string. that function is nice only problem is i am writing vs2010 and std::to_string supports only 3 types and "int" is not among them. but that is not a real problem as i static_cast to <long long>.

i was worrying about the leak issue because underlying the function i run monte carlo simulation and store huge amount of data. many time i use the fx button or just calculate not moving out from the cell. this was causing excel to build up handles. but now that i am using new handle implementation the issue is not there.

also on a side note. is there any place where i can get an example of how you are using "document.h/document.cpp" i know you have a nice way to write documentation but if i can get an example to learn about its usage it would be very kind of you.
Coordinator
Apr 12, 2013 at 7:56 PM
Have you read http://xll.codeplex.com/wikipage?title=AddIn ?

If you are doing Monte Carlo simulation in Excel you might want to check out http://tukhi.com. No need to store data, it calculates statistics on the fly.