* API としてのアドイン関数 [#c2610bb4]

OpenOffice.org の API は IDL で定義されており、シート関数としてのアドイン関数はこれを利用して定義します。IDL で定義したインターフェースを備えた UNO コンポーネントがアドイン関数のコンポーネントになります。

ここでは、アドイン関数を拡張機能として作成する点を念頭において作成方法を説明します。Java で実装するのであれば Netbeans のプラグインを利用すると容易に作成できます。

#contents
** IDL による関数の定義 [#o32b8a28]
まず、アドイン関数として作成したい関数をメンバーとして持つ独自のインターフェースを定義します。このとき、各関数の引数および返り値が決められています、下記参照。IDL の定義方法については他を参照。

一例として、mytools.sheet.addin.XCellBackgroudColorRef インターフェースを定義、二つのメンバー関数を定義します。

#code(idl){{
#ifndef __mytools_sheet_addin_XCellBackgroudColorRef_idl__
#define __mytools_sheet_addin_XCellBackgroudColorRef_idl__

#ifndef __com_sun_star_uno_XInterface_idl__
#include <com/sun/star/uno/XInterface.idl>
#endif

#ifndef __com_sun_star_table_XCellRange_idl__
#include <com/sun/star/table/XCellRange.idl>
#endif

module mytools { module sheet { module addin {
	interface XCellBackgroudColorRef : ::com::sun::star::uno::XInterface
	{
		any bgColorRef( [in] ::com::sun::star::table::XCellRange xDestCellRange, 
			[in] ::com::sun::star::table::XCellRange xSourceCellRange );
		
		any bgColorRef2( [in] ::com::sun::star::table::XCellRange xDestCellRange, 
			[in] ::com::sun::star::table::XCellRange xSourceCellRange, [in] any value );
	};
}; }; };

#endif
}}

** 関数の引数 [#y7401e60]
IDL で関数を定義するときには &idlref(com.sun.star.sheet.Addin); の説明に従います。

|型|説明|h
|long|long に変換されて渡される (浮動小数点の値でも)|
|double|double に変換されて渡される|
|string|テキスト|
|long[][]|long での二次元配列|
|double[][]|double での二次元配列|
|string[][]|string での二次元配列|
|any[][]|場合に応じて double または string での二次元配列|
|any|double または string|
|&idlref(com.sun.star.table.XCellRange);|セル範囲への参照|
|&idlref(com.sun.star.beans.XPropertySet);|ドキュメントオブジェクトのプロパティへのアクセス|
|any[]|関数の最後の引数の型に指定すると、残りの全ての引数を受けとる。可変数引数用|

any 型のときのみ特殊で、与えられた引数に応じて double または string になります。セル範囲への参照を受け取りたいときには css.table.XCellRange 型を指定します。

上記以外の引数に変換できない場合、その関数は利用できません。


** 関数の返り値 [#ia8b8cac]

|型|説明|h
|long|整数値|
|double|浮動小数点値|
|string|テキスト|
|long[][]|long での二次元配列|
|double[][]|double での二次元配列|
|string[][]|string での二次元配列|
|&idlref(com.sun.star.sheet.XVolatileResult);|タイマー等での事後可変|
|any|long、double、string のどれか|

セルへの参照を返すことはできません。

返り値に利用できるものは次のものです。以下に挙げているもの以外は無視されます。
- any、enum、boolean、char、string、数値型
- &idlref(com.sun.star.sheet.XVolatileResult);
- long[][]、double[][]、string[][]、any[][]
*** IDL ファイルのコンパイル [#f536a20a]
SDK 付属の idlc を利用して IDL ファイルを URD (Uno Registry Definition) ファイルにコンパイルします。

 ~/opt/openoffice.org/basis3.3/sdk/bin/idlc \
    -I/hoge/opt/openoffice.org/basis3.3/sdk/idl XCellBackgroudColorRef.idl

作成された XCellBackgroudColorRef.urd ファイルを URE 付属の regmerge を利用して RDB (Registration DataBase) ファイルにマージします。複数の URD ファイルがあってもここで一つのタイプデータベースになります。

 ~/opt/openoffice.org/ure/bin/regmerge reg.rdb /UCR  XCellBackgroudColorRef.urd

各ツールの利用方法については SDK のツールに関するページ参照。
** コンポーネントの定義 [#vb01a1ab]
上記で定義したインターフェースを備えた UNO コンポーネントを作成してアドイン関数を提供します。

このとき、UNO コンポーネントは &idlref(com.sun.star.sheet.Addin); サービスに従って作成します。

- &idlref(com.sun.star.lang.XServiceName); コンポーネントの実装名特定
- &idlref(com.sun.star.sheet.XAddIn); アドイン関数の名前や引数の情報など
-- &idlref(com.sun.star.lang.XLocalizable); 関数の情報のローカライズ用
- &idlref(com.sun.star.sheet.XCompatibilityNames); ローカライズされた関数名提供用。(日本語向けの翻訳では en-US と同じ関数名を利用しており、最近は訳された関数名で問題が出たりしているので利用しないほうがよい)

関数を定義する際に、その関数がどのセルに入力されたかどうかを知る方法はありません。そのため、そういった情報が必要であれば、関数の引数としてセルへの参照や位置などを入れておく必要があります。

関数の引数を参照にしたときに、その引数に与えられたセルが他のセルへの参照を持っていた場合、そのセルからテキストを取得しようとしても "..." となります。
*** Python [#tf9b61f1]
一般的なコンポーネント実装と同じように行います。

以下の例ではローカライズに対応していません。
#code(python){{
# -*- coding: utf-8 -*-

import unohelper

from mytools.sheet.addin import XCellBackgroudColorRef
from com.sun.star.sheet import XAddIn
from com.sun.star.lang import XLocalizable, XServiceName, XServiceInfo
from com.sun.star.lang import Locale


class AddInBase(unohelper.Base, XAddIn, XLocalizable, XServiceName, XServiceInfo):
	
	Imple_Name = ''
	Service_Names = ('com.sun.star.sheet.AddIn', Imple_Name)
	
	functions = {}
	
	def __init__(self, ctx):
		self.locale = Locale()
	
	# XLocalizable
	def setLocale(self, locale):
		self.locale = locale
	
	def getLocale(self):
		return self.locale
	
	# XAddIn
	def getProgrammaticFuntionName(self, name):
		for k, v in self.functions:
			if name == v['DisplayName']:
				return k
		return 'unknown'
	def getDisplayFunctionName(self, name):
		return self.functions[name]['DisplayName']
	def getFunctionDescription(self, name):
		return self.functions[name]['Description']
	def getDisplayArgumentName(self, name, index):
		return self.functions[name]['Arguments'][index]
	def getArgumentDescription(self, name, index):
		return self.functions[name]['ArgumentDescriptions'][index]
	def getProgrammaticCategoryName(self, name):
		return self.functions[name]['Category']
	def getDisplayCategoryName(self, name):
		return self.functions[name]['Category']
	
	# XServiceInfo
	def getImplementationName(self):
		return self.Imple_Name
	def supportsService(self, name):
		return name in self.Service_Names
	def getSupportedServiceNames(self):
		return self.Service_Names
	
	# XServiceName
	def getServiceName(self):
		return self.Imple_Name


class SheetAddInFn(AddInBase, XCellBackgroudColorRef):
	
	Imple_Name = 'mytools.sheet.addin.CellPropertyAddInFn'
	
	functions = {
		'bgColorRef': {'DisplayName': 'BGColorRef', 
						'Arguments': ['Dest Cell', 'Source Cell'], 
						'Description': 'To get cell property value.', 
						'ArgumentDescriptions': ['The cell to set its background color', 
												'The base cell to get background color'], 
						'Category': 'Add-in'}
	}
	
	def __init__(self, ctx, *args):
		AddInBase.__init__(self, ctx)
	
	# XCellBackgroudColorRef
	def bgColorRef(self, dest, source):
		if source and dest:
			dest.setPropertyValue('CellBackColor', source.getPropertyValue('CellBackColor'))
		return ''


g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(
	SheetAddInFn, SheetAddInFn.Imple_Name, 
	('com.sun.star.sheet.AddIn',))
}}

*** Java [#h7935bb0]
Java ではまず、IDL で定義したインターフェースから abstract インターフェースのクラスファイルを生成します。

 ~/opt/openoffice.org/basis3.3/sdk/bin/javamaker \
    -BUCR -nD -Tmytools.sheet.addin.XCellBackgroudColorRef \
    ~/opt/openoffice.org/basis3.3/program/offapi.rdb reg.rdb 

ここでの例では mytools.sheet.addin.XCellBackgroudColorRef インターフェースがクラスファイルとして作成されます。コンパイル時にクラスパスに含めておく必要があります、コンポーネント配布時のクラスパスにも入れておく必要があります。

#code(java){{
package mytools.sheet.addin;

import com.sun.star.beans.XPropertySet;
import com.sun.star.lang.IndexOutOfBoundsException;
import com.sun.star.sheet.XCellRangeAddressable;
import com.sun.star.table.CellContentType;
import com.sun.star.table.CellRangeAddress;
import com.sun.star.table.XCell;
import com.sun.star.table.XCellRange;
import com.sun.star.text.XTextRange;
import com.sun.star.uno.AnyConverter;
import com.sun.star.uno.Exception;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;


public class CellBackgroudColorRef {

	public static class _CellBackgroudColorRef extends AddinBase implements XCellBackgroudColorRef 
	{

		XComponentContext m_xContext;
		public _CellBackgroudColorRef (XComponentContext xContext)
		{
			super(__implName);
		m_xContext = xContext;
			FunctionDescriptions desc = new FunctionDescriptions(
				"BGColorRef", 
				new String[]{"Dest Cell", "Source Cell"}, 
				"To get cell property value.", 
				new String[]{"The cell to set its background color", 
					"The base cell to get background color"}, 
				"Add-in");
			Descriptions.put("bgColorRef", desc);
			
			FunctionDescriptions desc2 = new FunctionDescriptions(
				"BGColorRef2", 
				new String[]{"Dest Cell", "Source Cell"}, 
					"To get cell property value.", 
				new String[]{"The cell to set its background color", 
					"The base cell to get background color"}, 
					"Add-in");
				Descriptions.put("bgColorRef2", desc2);
		}
		
		@Override
		public Object bgColorRef(XCellRange xDestCellRange, XCellRange xSourceCellRange)
		{
			Object ret = null;
			return ret;
		}
		
		@Override
		public Object bgColorRef2(XCellRange xDestCellRange, 
			XCellRange xSourceCellRange, Object value)
		{
			if (xDestCellRange != null && xSourceCellRange != null)
			{
				XPropertySet xDestProps = UnoRuntime.queryInterface(
					XPropertySet.class, xDestCellRange);
				XPropertySet xSourceProps = UnoRuntime.queryInterface(
					XPropertySet.class, xSourceCellRange);
				try {
					xDestProps.setPropertyValue("CellBackColor", 
					(int) AnyConverter.toInt(xSourceProps.getPropertyValue("CellBackColor")));
				} catch (Exception e) {
					//e.printStackTrace();
				}
			}
			System.out.println(value);
			return value;
		}
		
	}
	
	// registration
	private static final String __implName = "mytools.sheet.addin.CellPropertyAddInFn";

	public static com.sun.star.lang.XSingleComponentFactory __getComponentFactory(
			String sImplName) {
		com.sun.star.lang.XSingleComponentFactory xSingleComponentFactory = null;

		if (sImplName.equals(__implName)) {
			xSingleComponentFactory = com.sun.star.lib.uno.helper.Factory
					.createComponentFactory(CellBackgroudColorRef._CellBackgroudColorRef.class,
							new String[] { __implName });
		}
		return xSingleComponentFactory;
	}

	public static boolean __writeRegistryServiceInfo(
			com.sun.star.registry.XRegistryKey regKey) {
		return com.sun.star.lib.uno.helper.Factory.writeRegistryServiceInfo(
				__implName, 
				new String[]{"com.sun.star.sheet.AddIn"}, 
				regKey);
	}
}
}}

#code(java){{
package mytools.sheet.addin;

import java.util.HashMap;
import java.util.Map;

import com.sun.star.lang.Locale;
import com.sun.star.lang.XLocalizable;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XServiceName;
import com.sun.star.lib.uno.helper.ComponentBase;
import com.sun.star.sheet.XAddIn;

abstract class AddinBase extends ComponentBase implements XLocalizable, XServiceName, XServiceInfo, XAddIn
{
	protected String sImplName;
	protected final String[] sServiceNames;
	
	protected Locale m_Locale = null;
	
	protected Map<String, FunctionDescriptions> Descriptions;
	
	public AddinBase(String implName)
	{
		sImplName = implName;
		sServiceNames = new String[]{"com.sun.star.sheet.AddIn", sImplName};
		
		Descriptions = new HashMap<String, FunctionDescriptions>();
	}
	
	@Override
	public Locale getLocale() {
		return m_Locale;
	}

	@Override
	public void setLocale(Locale aLocale) {
		m_Locale = aLocale;
	}

	@Override
	public String getServiceName() {
		return sImplName;
	}

	@Override
	public String getImplementationName() {
		return sImplName;
	}

	@Override
	public String[] getSupportedServiceNames() {
		return sServiceNames;
	}

	@Override
	public boolean supportsService(String name) {
		for (String service : sServiceNames)
		{
			if (service.equals(name))
			{
				return true;
			}
		}
		return false;
	}

	@Override
	public String getArgumentDescription(String name, int index) {
		return Descriptions.get(name).ArgumentDescriptions[index];
	}

	@Override
	public String getDisplayArgumentName(String name, int index) {
		return Descriptions.get(name).Arguments[index];
	}

	@Override
	public String getDisplayCategoryName(String name) {
		return Descriptions.get(name).Category;
	}

	@Override
	public String getDisplayFunctionName(String name) {
		return Descriptions.get(name).DisplayName;
	}

	@Override
	public String getFunctionDescription(String name) {
		return Descriptions.get(name).Description;
	}

	@Override
	public String getProgrammaticCategoryName(String name) {
		return Descriptions.get(name).Category;
	}

	@Override
	public String getProgrammaticFuntionName(String name) {
		if (Descriptions.containsKey(name))
			return name;
		return "unknown";
	}
}
}}

#code(java){{
package mytools.sheet.addin;

public class FunctionDescriptions {

	public String DisplayName;
	public String[] Arguments;
	public String Description;
	public String[] ArgumentDescriptions;
	public String Category;
	
	public FunctionDescriptions(String sDisplayName, String[] sArguments, 
			String sDescription, String[] sArgumentDescriptions, String sCategory)
	{
		DisplayName = sDisplayName;
		Arguments = sArguments;
		Description = sDescription;
		ArgumentDescriptions = sArgumentDescriptions;
		Category = sCategory;
	}
}
}}

** 拡張機能パッケージ [#m9af677d]
拡張機能パッケージ作成方法の詳細は別ページなどを参照してください。

META-INF/manifest.xml ファイル中では RDB ファイルおよび UNO コンポーネントを実装したファイルを登録します。

 <?xml version="1.0" encoding="UTF-8"?>
 <manifest:manifest>
 <manifest:file-entry manifest:full-path="reg.rdb" 
   manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/>
 <manifest:file-entry manifest:full-path="lib.jar" 
   manifest:media-type="application/vnd.sun.star.uno-component;type=Java"/>
 </manifest:manifest>

などとします。

Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes