空談録

世界で5人くらいに役立ちたい

Office Add-insを使ってExcelの変更をSlackに通知したかった

できなかった
もうまじむり…

Office Add-ins(旧Apps for Office)の方は割とすんなり行けたのですがSlackのほうがこけまくりました。他の用途では使えるでしょう…
まともに記事を書ける気がしませんので適当に書きます

Excelの変更を取得する

Office Add-insでは、bindingというオブジェクトを使ってOfficeのクライアントとのデータのやり取りを行うことができます
例えばExcelであれば、Cell A1に対してbindingを作成することで、Office Add-insからA1のデータを取得、変更ができるようになります。またbindingした範囲内のデータの変更なども監視できるようになります
(データのやり取りはbindingを作成しなくてもできますがまた別の制約がかかる)

で、bindingの作成自体もいくつか手段がありますが、いろいろとモチベーションが足りないので、選択している領域からbindingを作成することにします
これはまあ現在選択している領域に対してbindingを作るので割と便利な方かなーと思います。大きさも指定できますし

やり方はbindings.addFromSelectionAsyncを呼ぶだけです。たとえばこんな感じ

	function setBinding(){
		Office.context.document.bindings.addFromSelectionAsync(Office.BindingType.Matrix, null, bindingCallback);
	}

        function bindingCallback(x) {...}

最初の引数でBindingの種類を選びます。ExcelだとMatrixかTableでしょうか。Matrixはm行n列の2次元配列となり、Tableはその最初の行がHeaderとして扱われるようになります
つまるところヘッダーがあるかないかの違いです。
今回はMatrixにします

Office Add-insではすべての関数にAsyncがついているので叫びながらcallbackを指定しましょう

bindingを作成したらbinding内のデータ変更のイベントのハンドラーを指定します
addHandlerAsyncを利用します。これはまあ戻り値を使うこともない気もするので気楽に書きましょう

さっきのbindingCallbackに書くとこんな感じ

	function bindingCallback(x)
	{
		x.value.addHandlerAsync(Office.EventType.BindingDataChanged, onBindingDataChanged);
	}

最初の引数にイベントの種類をいれて次の引数にハンドラーを入れる感じです
これでとりあえず変更は通知してもらえます

bindingから変更内容の取得

通知してもらえますって書きましたが、BindingDataChangedEventArgsは気が利かないので"変更が行われたbindingのインスタンス"しか送ってきません。
仕方がないのでbindingからgetDataAsyncを使って取得します。自動で取得する場合何かしらうまくやってください

今回はm行2列で上から順に埋まっていくものとします

// var currentRow = 0;

	function onBindingDataChanged(eventArgs) {
		eventArgs.binding.getDataAsync({coercionType: "matrix", startRow : currentRow, rowCount:1},readData)
		currentRow += 1;
	}

coercionTypeでcallbackに投げるデータの形式を指定できます。matrixはArray(of Array)の形式
columnCountなりは指定しないと全部返してくれます

readDataの中身はこんな感じ

	function readData(data){
		var s = data.value[0][0];
		s += "\n";
		s += data.value[0][1];
		// updateSlack(s);
	}

引数.valueにデータが入ります。間違えると死にます
まあ適当に
今回は超適当にやってるのでstringを結合する感じでもげもげしてます

最後のところの関数を適当に置きかえると2行の変更差分が飛ばせる気がします
(試してませんが同時に2行変更された場合BindingDataChangedの挙動はどうなるか不明)


この後Slackがよくわからなくて飛ばせませんでした
眠いしなんか時間無駄にした感じでイライラしてるので後の話は暇だったら
CORSでふんちゃらかPayload was not valid JSONか選べって言われてクソ

まあそんな感じで何かしたい方がいたら頑張ってください

この辺で