はじめに
悪戦苦闘した挙句、過去にも同じようなところでひっかかったな…という自省から備忘録として残しておくことにします。
専門職ではありませんので、技術的不足は平にご容赦ください。
用意したOfficeScripts(抜粋)
const TARGET_WORD = "★★"; // 対象シート名に含まれる文字
const targetSheets = workbook.getWorksheets()
.filter(ws => ws.getName().includes(TARGET_WORD)); // TARGET_WORDを含むシートのみ
発生したエラー
実際のエラーメッセージ(抜粋):
HTTPステータスコード: 400 Bad Request
メッセージ: 実行中に Office スクリプトでエラーが発生し、完了しませんでした。
ランタイム エラー: Line 19: _e.sent(...).filterAsync is not a function
どこで出た?
Power Automateの「スクリプトの実行」アクションでOffice Scriptを呼び出したとき。
試したこと
戻り値をオブジェクトにラップ
JSON.stringifyで返す
Base64化して返す
結果
どれもダメ。エラーは変わらず。
調査でわかったこと
こちらの質問と回答が大変ためになりました。多謝。
Power Automateはfilterやfindを検出すると、内部で「Async版」を探す。
→ でもOffice ScriptにはfilterAsyncなんてない
→ エラー
ということなのでしょうか…?
解決策
filterやfindを使わない。
forEach()やfor...ofで書き換えると正常動作。
修正版コード
function main(workbook: ExcelScript.Workbook): { sheet: string; checkEmpty: boolean; commentEmpty: boolean }[] {
const CHECK_ROW_INDEX = 28;
const COMMENT_ROW_INDEX = 4;
const TARGET_WORD = "★★";
const targetMonth = ((new Date().getMonth() + 11) % 12) + 1;
const { checkColIndex, commentColIndex } = getColumnIndices(targetMonth);
const allSheets = workbook.getWorksheets();
const results: { sheet: string; checkEmpty: boolean; commentEmpty: boolean }[] = [];
for (const sheet of allSheets) {
if (!sheet.getName().includes(TARGET_WORD)) continue;
const checkCell = safeGetCell(sheet, CHECK_ROW_INDEX, checkColIndex);
const commentCell = safeGetCell(sheet, COMMENT_ROW_INDEX, commentColIndex);
const checkEmpty = isCellEmpty(checkCell);
const commentEmpty = isCellEmpty(commentCell);
if (checkEmpty || commentEmpty) {
results.push({ sheet: sheet.getName(), checkEmpty, commentEmpty });
}
}
return results;
}
まとめ
Office Script × Power Automateでは、配列メソッド(filter, find, …)は避けたほうがいい?
安定動作には同期的なループを使う。