Ark SiteFor Developers Arkアーキテクチャ
TOP プラグイン作成講座 CalcArk編 第5回




みなさんこんにちは。ワークシート関数プラグイン担当のHです。
今回で、ワークシート関数プラグインのレッスンは最後ですが、今までのレッスンに比べ、ボリューム的にもその重要さからも大事なものですので、是非、理解してください。頂上まであと少しです・・・
それでは、最後までよろしくお願いします

Lesson7では、セル範囲参照を引数に取った場合に、そのセル範囲内の各セルデータへのアクセス方法について説明します。
このLessonが終われば、SUM関数等の実装がどのようにされているのかが理解できます。
今まで同様、サンプルとして用意している関数で説明します。
三四郎にはSumStep関数という便利な関数があり、この関数は「3つ以上の引数をとり、第1引数を列ステップ数、第2引数を行ステップ数、第3引数以降に数値やセル範囲を指定して、数値の合計を返す」というものです。ただし、「引数がセル範囲の場合は、列ステップ数や行ステップ数で指定された数の分だけセルを飛ばして計算します。」



今回は、サンプルということもあり、引数の個数は3つに限定し、第3引数はセル(範囲)参照のみとして実装しています。
では、実装を見てみましょう。ちょっと長くなったので、途中で半分に分割しています。

リスト1SumStep.javaの抜粋
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041

      
import	jp.co.justsystem.choco.model.CellAccess;
import	jp.co.justsystem.choco.model.CellData;
import	jp.co.justsystem.choco.model.Value;
import	jp.co.justsystem.choco.model.ValueException;
import	jp.co.justsystem.choco.model.expr.ExprValue;
import	jp.co.justsystem.choco.model.function.FuncArg;
import	jp.co.justsystem.choco.model.function.FunctionArg3;

public class SumStep extends FunctionArg3 {
	public void call( FuncArg arg, ExprValue result ) throws ValueException {
		// 列方向のステップ数を取得する
		int	col_step = arg.castIntArg( 0 );
		
		(略。col_step に対するエラー処理)

		// 行方向のステップ数を取得する
		int	row_step = arg.castIntArg( 1 );

		(略。row_step に対するエラー処理)
		
		ExprValue		range = arg.getArg( 2 );

		(略。range に対するエラー処理)
		
		// セル範囲内アクセスコールバック用のクラスを作成する
		Access	access = new Access( col_step, row_step, range.getRmin(), range.getCmin() );
		
		// セル範囲内にアクセスする
		boolean	success = range.accessRange( access );
		if( success ) {
			// セル範囲内にエラー値等がなかった
			result.setNumber( access.getTotal() );
		} else {
			// セル範囲内にエラー値があった
			result.setError( access.getError() );
		}
	}
	
	public String getName() {
		return	"SumStep";
	}
      

9行目を見るとFunctionインターフェースを実装するのではなくて、FunctionArg3というクラスを派生していることが分かりますね。これは、続く「付録」でも説明しますが、3つの引数をとる関数の抽象的な実装をしてくれているクラスです。SumStepの実装を見ても分かるように、getMinArgc、getMaxArgc、getTypeメソッドがなく、これらをFunctionArg3xが実装してくれています。

10行目からが、実際の関数実装です。
12行目から21行目までで、第1引数の列ステップ数、第2引数の行ステップ数、そして第3引数の計算対象のセル範囲を取得しています。

そして、26行目で、取得した行列ステップ数とセル範囲を元にしてAccessクラスを作成しています。
ちょっと説明が前後しますが、Accessクラスは45行目のCellAccessインターフェースを実装したクラスで、これをExprValueクラスのaccessRangeメソッドの引数に渡すと(29行目)、各セル毎にaccessメソッド(62行目)がコールバックされる仕組みになっています。
そして、対象セル範囲内の全てのセルに問題なくアクセスできた場合はtrueを返し、途中で中断された場合はfalseを返します。ここでは、対象セル範囲内にエラー値を見つけた場合に、それ以降のアクセスを中断しています。(79行目)

リスト2SumStep.javaの抜粋
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098

      
	/**
	 * セルアクセス用のクラス
	 */
	private class Access implements CellAccess {
		private int	col_step_;
		private int	row_step_;
		private int	rmin_;
		private int	cmin_;
		private int	error_;
		private double	sum_;
		
		Access( int col_step, int row_step, int rmin, int cmin ) {
			col_step_ = col_step + 1;
			row_step_ = row_step + 1;
			rmin_ = rmin;
			cmin_ = cmin;
			error_ = Value.ERROR_NO_ERROR;
			sum_ = 0;
		}

		public boolean access( CellData cell, int row, int col ) {
			if( (( row - rmin_ ) % row_step_) != 0 ) {
				// 集計対象外の位置
				return	true;
			}
			if( (( col - cmin_ ) % col_step_) != 0 ) {
				// 集計対象外の位置
				return	true;
			}

			Value	val = cell.getValue();
			switch( val.getType() ) {
			case Value.TYPE_NUMBER:
				sum_ += val.getNumber();
				break;
			case Value.TYPE_ERROR:
				error_ = val.getError();
				return	false;
			}
			return	true;
		}

		/**
		 * 合計を返します
		 */
		double getTotal() {
			return	sum_;
		}

		/**
		 * セル範囲内で見つかったエラー値を返します
		 */
		int getError() {
			return	error_;
		}
	}
}
      

残りは、Accessクラスの説明です。

先ほどと説明が重複しますが、CellAccessインターフェースは62行目のaccessメソッドのみからなっていて、これをAccessクラスが実装することで、各セル毎の処理がコールバックされます。

63行目から70行目で、SumStepのステップ処理について実装しています。

72行目で、セルデータの値(val)を取得し、その型が数値であれば数値の和をとり(74〜76行目)、エラー値であればそのエラー値を覚えておき、falseを返すことでセル範囲アクセス処理を中断しています。(77〜79行目)
エラー値以外の場合は、trueを返すことでセル範囲アクセスを続行します。(81行目)

いかがでしたか?
要は、ExprValueクラスのaccessRangeメソッドと、CellAccessインターフェースを実装すればいいということです。CalcArkが標準で提供している組み込みワークシート関数プラグインに含まれるSUMやAVERAGE関数等は、おおよそこの手法で実装されています。

おわりに
以上、4回に渡りワークシート関数プラグインの作成方法を見てきました。

表計算アプリケーションでは、ワークシート関数を上手に使うことで、基本的な帳票は十分作成できます。使い方によっては、本来の使われ方以上の威力も発揮することが可能です。そして、そのワークシート関数を自分の好みによって作成することができるとなると、これほど面白いことはないでしょう。使い方によっては、2次方程式の解を求める関数等、教材としても利用できるのではないでしょうか。
みなさん、いろいろ試して楽しんでみてください。

ソースファイル
圧縮ファイル
プラグインソースダウンロードへ

各ソースファイル
SumStep.java

jp.co.justsystem.choco.model パッケージ
CellAccess
CellData
Value

jp.co.justsystem.choco.model.expr パッケージ
ExprValue

jp.co.justsystem.choco.model.function パッケージ
FuncArg
Function


<<その3へ   付録へ>>


TOP プラグイン作成講座 CalcArk編 第5回