Difference between revisions of "Calc/Add-In/CompleteAddIn"

From Apache OpenOffice Wiki
< Calc‎ | Add-In
Jump to: navigation, search
(See also)
Line 262: Line 262:
 
*Constructing Components http://perso.wanadoo.fr/moutou/MyUNODoc_HTML/UNOCppAPI13.html
 
*Constructing Components http://perso.wanadoo.fr/moutou/MyUNODoc_HTML/UNOCppAPI13.html
 
*All my UNO/C++ document is available here http://perso.wanadoo.fr/moutou/MyUNODoc_HTML/UNOCppAPI.html
 
*All my UNO/C++ document is available here http://perso.wanadoo.fr/moutou/MyUNODoc_HTML/UNOCppAPI.html
 +
 +
[[Category:Calc issues]]

Revision as of 17:31, 17 April 2006

In this article under construction a complete and simple add-in in C++ is presented.

Introduction

We start from an example of SDK slightly modified : <OpenOffice.org1.1_SDK>/examples/DevelopersGuide/Components/CppComponent

This example contains two files but I only use one file (and one service).

IDL File

Here is the corresponding IDL file :

// IDL
#include <com/sun/star/uno/XInterface.idl>
#include <com/sun/star/lang/XInitialization.idl>
#include <com/sun/star/lang/XServiceName.idl>
#include <com/sun/star/lang/XLocalizable.idl>
#include <com/sun/star/sheet/XAddIn.idl>
module my_module
{
  interface XSomething : com::sun::star::uno::XInterface
{ // our four methods
  string methodOne( [in] string val );
  string methodTwo( [in] string val );
  long methodThree( [in] sequence< sequence< long > > aValList );
  sequence< sequence< long > > methodFour( [in] sequence< sequence< long > > aValList );
};
service MyService2
{
interface XSomething;
interface com::sun::star::lang::XInitialization;
interface com::sun::star::lang::XServiceName;
interface com::sun::star::sheet::XAddIn;
};
};

Four method named methodOne, methodTwo, methodThree and methodFour will be implemented.

Implementing in C++ the corresponding four Methods

We first give the C++ code of the four method presented in IDL file.

The two first Methods

The two first methods are similar :

OUString MyService2Impl::methodOne( OUString const & str )
throw (RuntimeException)
{
  return OUString( RTL_CONSTASCII_USTRINGPARAM(
    "called methodOne() of MyService2 implementation: ") ) + m_arg + str;
}

OUString MyService2Impl::methodTwo( OUString const & str )throw (RuntimeException)
{
  return OUString( RTL_CONSTASCII_USTRINGPARAM(
    "called methodTwo() of MyService2 implementation: ") ) + m_arg + str;
}

They only take a string (from a OOoCalc Cell) and add a message and put all the message+string in the result cell.

The third Method

The third method is more complicated : it returns a value calculed from a cell range (the sum).

sal_Int32 MyService2Impl::methodThree(const Sequence< Sequence< sal_Int32 > > &aValList )
throw (RuntimeException)
{ sal_Int32 n1, n2;
  sal_Int32 nE1 = aValList.getLength();
  sal_Int32 nE2;
  sal_Int32 temp=0;
  for( n1 = 0 ; n1 < nE1 ; n1++ )
  {
    const Sequence< sal_Int32 > rList = aValList[ n1 ];
    nE2 = rList.getLength();
    const sal_Int32* pList = rList.getConstArray();
    for( n2 = 0 ; n2 < nE2 ; n2++ )
    {
      temp += pList[ n2 ];
    }
  }
  return temp;
}

The fourth Method

The goal of the fourth method is to show how we can implement a matrix function : starting from a cell range and obtaining a celle range.

//It's a matrix operation should be called like : {=METHODFOUR(A1:B4)}
Sequence< Sequence< sal_Int32 > > MyService2Impl::methodFour(const Sequence< Sequence< sal_Int32 > > &aValList )
throw (RuntimeException)
{ sal_Int32 n1, n2;
  sal_Int32 nE1 = aValList.getLength();
  sal_Int32 nE2;
  Sequence< Sequence< sal_Int32 > > temp = aValList;
  for( n1 = 0 ; n1 < nE1 ; n1++ )
  {
    Sequence< sal_Int32 > rList = temp[ n1 ];
    nE2 = rList.getLength();
    for( n2 = 0 ; n2 < nE2 ; n2++ )
    {
      rList[ n2 ] += 4;
    }
    temp[n1]=rList;
  }
  return temp;
}

What is done by this example is not great : only add four to every cells of the cell range.

The code is not complete with this four method. If you want to create a component you have to add code, if you want to make a scriptable component you still add more code and if you want to create an AddIn you have to add more.

The XAddIn Interface

Every add-in have to implement the XAddIn interface. As usual it is described by an IDL file :

// IDL
module com { module sun { module star { module sheet {
interface XAddIn: com::sun::star::lang::XLocalizable
{
  string getProgrammaticFuntionName( [in] string aDisplayName );
  string getDisplayFunctionName( [in] string aProgrammaticName );
  string getFunctionDescription( [in] string aProgrammaticName );
  string getDisplayArgumentName(
  [in] string aProgrammaticFunctionName,
  [in] long nArgument );
  string getArgumentDescription(
  [in] string aProgrammaticFunctionName,
  [in] long nArgument );
  string getProgrammaticCategoryName( [in] string aProgrammaticFunctionName );
  string getDisplayCategoryName( [in] string aProgrammaticFunctionName );
};
}; }; }; };

The corresponding C++ code is given now without explanation (for the moment)

// XAddIn
OUString SAL_CALL MyService2Impl::getProgrammaticFuntionName( const OUString& aDisplayName ) throw( uno::RuntimeException )
{
// not used by calc
// (but should be implemented for other uses of the AddIn service)
  return OUString();
}

OUString SAL_CALL MyService2Impl::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException )
{ // a nested if implementation would be better
  OUString aProgName, aRet;
  aProgName = aProgrammaticName;
  if (aProgName.equalsAscii("methodOne")) aRet = OUString::createFromAscii("method1");
  if (aProgName.equalsAscii("methodTwo")) aRet = OUString::createFromAscii("method2");
  if (aProgName.equalsAscii("methodThree")) aRet = OUString::createFromAscii("method3");
  if (aProgName.equalsAscii("methodFour")) aRet = OUString::createFromAscii("method4");
  return aRet;
}

OUString SAL_CALL MyService2Impl::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException )
{ // a nested if implementation would be better
  OUString aRet;
  if (aProgrammaticName.equalsAscii("methodOne"))
    aRet = OUString::createFromAscii("methodOne() : 1st try");
  if (aProgrammaticName.equalsAscii("methodTwo"))
    aRet = OUString::createFromAscii("methodTwo() : 1st try");
  if (aProgrammaticName.equalsAscii("methodThree"))
    aRet = OUString::createFromAscii("methodThree() : 1st try");
  return aRet;
}

OUString SAL_CALL MyService2Impl::getDisplayArgumentName(
const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException )
{
  OUString aRet;
  if (aProgrammaticName.equalsAscii("methodOne")||aProgrammaticName.equalsAscii("methodTwo"))
    aRet = OUString::createFromAscii("a string");
  if (aProgrammaticName.equalsAscii("methodThree")||aProgrammaticName.equalsAscii("methodFour"))
    aRet = OUString::createFromAscii("a Cell Range");
  return aRet;
}

OUString SAL_CALL MyService2Impl::getArgumentDescription(
const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException )
{
  OUString aRet;
  if (aProgrammaticName.equalsAscii("methodOne")||aProgrammaticName.equalsAscii("methodTwo"))
    aRet = OUString::createFromAscii("method1/2:a string or a cell with a string is required");
  if (aProgrammaticName.equalsAscii("methodThree")||aProgrammaticName.equalsAscii("methodFour"))
    aRet = OUString::createFromAscii("method3/4:a cell range is required");
  return aRet;
}

OUString SAL_CALL MyService2Impl::getProgrammaticCategoryName(const OUString& aProgrammaticName ) throw( uno::RuntimeException )
{
  OUString aRet( RTL_CONSTASCII_USTRINGPARAM("Add-In"));
  return aRet;
}

OUString SAL_CALL MyService2Impl::getDisplayCategoryName(const OUString& aProgrammaticName ) throw( uno::RuntimeException )
{
  return getProgrammaticCategoryName( aProgrammaticName );
}

The XServiceName Interface

Again the corresponding IDL file indicates what we have to do :

// IDL
module com { module sun { module star { module lang {
interface XServiceName: com::sun::star::uno::XInterface
{
  string getServiceName();
};
}; }; }; };

This interface is simple : one method :

// XServiceName
OUString SAL_CALL MyService2Impl::getServiceName() throw( uno::RuntimeException )
{
// name of specific AddIn service
  return OUString::createFromAscii( "my_module.MyService2" );
}

The XServiceInfo Interface

This Interface may be avoided. You have to implement it only if you want that your add-in is also scriptable : you can call it from OOoBasic for instance.

// XServiceInfo implementation
OUString MyService2Impl::getImplementationName()
throw (RuntimeException)
{
// unique implementation name
  return OUString( RTL_CONSTASCII_USTRINGPARAM("my_module.my_sc_impl.MyService2") );
}

sal_Bool MyService2Impl::supportsService( OUString const & serviceName )
throw (RuntimeException)
{
// this object only supports one service, so the test is simple
  if (serviceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("my_module.MyService2") ))
    return true;
  if (serviceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.sheet.AddIn") ))
    return true;
  else return false;
}

Sequence< OUString > MyService2Impl::getSupportedServiceNames()
throw (RuntimeException)
{
  return getSupportedServiceNames_MyService2Impl();
}

Reference< XInterface > SAL_CALL create_MyService2Impl(Reference< XComponentContext > const & xContext)
SAL_THROW( () )
{
  return static_cast< lang::XTypeProvider * >( new MyService2Impl() );
}

See also

This article is under construction and if you want to go further, for the moment have a look to the following references :

Personal tools