大量データの一括投入 — setValueArray / setFormulaArray
level: intermediate / verified: 2026-10-01 / 4言語タブ対応 / English
やりたいこと
何千・何万セルもの値や数式を、セルごとに getRange() するのではなく 配列にまとめて一度に投入する。あわせて相対参照を行ごとにずらした数式を一括入力する。
| やり方 | 使うもの |
|---|---|
| セルごとに投入 | ws.getCells(r, c).setNumberValue(...) |
| 値を一括投入 | ws.setValueArray(Array<dto.InputValueObject>) |
| 数式を一括投入 | ws.setFormulaArray(Array<dto.InputFormulaObject>) |
対象クラス
dto.InputValueObject
| メソッド | 説明 |
|---|---|
setStringValue(A1C1, val, numberFormat?) | 文字列値を設定します。 |
setNumberValue(A1C1, val, forceString?, numberFormat?) | 数値を設定します。 |
setBooleanValue(A1C1, val, forceString?, numberFormat?) | 真偽値を設定します。 |
setDateTimeValue(A1C1, val, forceString?, numberFormat?) | 日付時刻値を設定します。 |
setEmptyVal(A1C1) | セル範囲を空に設定します。 |
getA1C1() / getInputType() / getStringValue() / getNumberValue() / getBooleanValue() / getDateTimeValue() / getNumberFormat() / getForceString() | 設定内容の取得。 |
dto.InputFormulaObject
| メソッド | 説明 |
|---|---|
setA1C1(A1C1) | 対象セルを設定します。 |
setFormula(formula) | 数式を設定します(先頭に = は付けない)。 |
getA1C1() / getFormula() | 設定内容の取得。 |
コード
実行結果:
// bulk-input.js — 値と数式の一括投入、セルごと投入との速度比較
const { nodeosbxl, dto } = require("nodeosbxl");
const app = new nodeosbxl.App();
const wb = app.createWorkBook("bulk-input.xlsx");
const ws = wb.openWorkSheet("Sheet1");
// ---------- 1. いろいろな型を一度に投入する ----------
const date = new dto.DateTimeObject();
date.setYMD(2024, 3, 20);
const values = [];
const addString = (a1, val) => {
const o = new dto.InputValueObject();
o.setStringValue(a1, val);
values.push(o);
};
// 末尾の省略可能引数は undefined のまま渡せます(省略として扱われます)
const addNumber = (a1, val, fmt) => {
const o = new dto.InputValueObject();
o.setNumberValue(a1, val, false, fmt);
values.push(o);
};
addString("A1", "商品名");
addNumber("B1", 1234.5);
addNumber("C1", 0.25, "0.0%");
// 日付: 書式を省略すると既定書式が自動設定されます(Range.setDateValue と同じ)
const dateVal = new dto.InputValueObject();
dateVal.setDateTimeValue("D1", date, false, "yyyy-mm-dd"); // 書式を明示
values.push(dateVal);
const dateVal2 = new dto.InputValueObject();
dateVal2.setDateTimeValue("D2", date); // 省略 → 自動
values.push(dateVal2);
ws.setValueArray(values);
console.log("[1] 型混在の一括投入");
for (const a1 of ["A1", "B1", "C1", "D1", "D2"]) {
const r = ws.getRange(`${a1}:${a1}`);
console.log(` ${a1}: 表示値=${JSON.stringify(r.getValue()[a1])} 書式=${JSON.stringify(r.getNumberFormat()[a1])}`);
}
// ---------- 2. 空にするのも一括投入 ----------
ws.getRange("A2:A2").setValue("いったん入力");
const empty = new dto.InputValueObject();
empty.setEmptyVal("A2");
ws.setValueArray([empty]);
console.log("[2] setEmptyVal 後 A2 =", JSON.stringify(ws.getRange("A2:A2").getValue()["A2"]));
// ---------- 3. 相対参照を行ごとにずらした数式を一括入力 ----------
// Range.setFormula() では相対参照が展開されないので、こちらを使う
for (let r = 1; r <= 3; r++) ws.getRange(`F${r}:F${r}`).setNumberValue(r * 10);
const formulas = [];
for (let r = 1; r <= 3; r++) {
const f = new dto.InputFormulaObject();
f.setA1C1(app.convertFromRowColNumber(r, 7)); // G1, G2, G3
f.setFormula(`F${r}*2`); // 行ごとに異なる相対参照
formulas.push(f);
}
ws.setFormulaArray(formulas);
console.log("[3] setFormulaArray 後");
console.log(" 数式 =", JSON.stringify(ws.getRange("G1:G3").getFormula()));
console.log(" 値 =", JSON.stringify(ws.getRange("G1:G3").getValue(true)));
// ---------- 4. 速度比較(2,000 行 x 5 列 = 10,000 セル)----------
const ROWS = 2000, COLS = 5;
const wsCell = wb.addWorkSheet("CellByCell");
let t = Date.now();
for (let r = 1; r <= ROWS; r++) {
for (let c = 1; c <= COLS; c++) wsCell.getCells(r, c).setNumberValue(r * 100 + c);
}
const msCell = Date.now() - t;
const wsBulk = wb.addWorkSheet("Bulk");
const bulk = [];
t = Date.now();
for (let r = 1; r <= ROWS; r++) {
for (let c = 1; c <= COLS; c++) {
const o = new dto.InputValueObject();
o.setNumberValue(app.convertFromRowColNumber(r, c), r * 100 + c);
bulk.push(o);
}
}
const msBuild = Date.now() - t;
t = Date.now();
wsBulk.setValueArray(bulk);
const msApply = Date.now() - t;
console.log(`[4] ${ROWS * COLS} セルの投入`);
console.log(` セルごと getCells().setNumberValue() : ${msCell} ms`);
console.log(` setValueArray (構築${msBuild} + 投入${msApply}) : ${msBuild + msApply} ms`);
const a = wsCell.getRange("E2000:E2000").getValue(true)["E2000"];
const b = wsBulk.getRange("E2000:E2000").getValue(true)["E2000"];
console.log(`[検証] 両方式とも E2000 = ${a === b ? a : `不一致 ${a} / ${b}`}`);
wb.save();
wb.close();
[1] 型混在の一括投入
A1: 表示値="商品名" 書式="General"
B1: 表示値="1234.5" 書式="General"
C1: 表示値="25.0%" 書式="0.0%"
D1: 表示値="2024-03-20" 書式="yyyy-mm-dd"
D2: 表示値="2024/3/20" 書式="yyyy/m/d;@"
[2] setEmptyVal 後 A2 = ""
[3] setFormulaArray 後
数式 = {"G1":"F1*2","G2":"F2*2","G3":"F3*2"}
値 = {"G1":"20","G2":"40","G3":"60"}
[4] 10000 セルの投入
セルごと getCells().setNumberValue() : 102 ms
setValueArray (構築18 + 投入58) : 76 ms
[検証] 両方式とも E2000 = 200005
[4] の ms は実行のたびに変わります(上記は 1 回の実行例)。
解説
速度
| セル数 | セルごと getCells().setNumberValue() | setValueArray() | 差 |
|---|---|---|---|
| 10,000(2,000 行 x 5 列) | 約 110 ms | 76 ms(構築 18 + 投入 58) | 約 1.4 倍 |
| 100,000(20,000 行 x 5 列) | 1,390 ms | 770 ms(構築 130 + 投入 640) | 約 1.8 倍 |
いずれも osbxl 1.5.0 / Node.js v21 での 1 回の実測例で、環境と実行のたびに変わります。 傾向としてセル数が増えるほど差が開きます。 JavaScript 側で InputValueObject を組み立てる時間も無視できないので、 上記では「構築」と「投入」を分けて計測しています。 数万セルを超えるなら setValueArray() を使ってください。
使いどころ
setValueArray()— 配列や CSV、DB の結果など「まとめて入れたい値」があるとき。
型(文字列 / 数値 / 真偽値 / 日付)を 1 つの配列に混在させられます。setFormulaArray()— 行ごとに異なる相対参照の数式を入れるとき。
Range.setFormula()では相対参照が展開されない(概要の注意点参照)ため、 計算列を作るならこちらが正解です。- セル数が数十程度なら、可読性を優先して
getCells(r, c)/getRange("A1:A1")で十分です。
注意点
- 素のオブジェクトリテラルは渡せません。
dto.InputValueObject/dto.InputFormulaObjectの インスタンスを作る必要があります。// ✗ 例外: Invalid argument ws.setValueArray([{ cell: "A1", value: 100 }]); // ✓ const o = new dto.InputValueObject(); o.setNumberValue("A1", 100); ws.setValueArray([o]); setDateTimeValue()は表示書式を自動設定します(Range.setDateValue()と対称)。
numberFormatを省略すると内容に応じてyyyy/m/d;@(日付のみ)/h:mm:ss;@(時刻のみ)/yyyy/m/d h:mm:ss;@(日付+時刻)が自動で付きます。
特定の書式にしたいときだけ第4引数で渡します。setDateTimeValue("D2", date) → 表示値 "2024/3/20" 書式 "yyyy/m/d;@" setDateTimeValue("D1", date, false, "yyyy-mm-dd") → 表示値 "2024-03-20" 書式 "yyyy-mm-dd"- 同じセルを複数回指定すると、配列の後ろの要素が勝ちます(実測)。
意図しない上書きが起きないよう、投入前に A1C1 の重複が無いことを確認してください。 InputFormulaObjectはsetA1C1()が必須。 数式だけ設定してもセルが指定されていなければ反映されません。setFormulaArray()の数式にも先頭の=は付けません。f.setFormula("F1*2")です。undefinedは「末尾の」省略可能引数にだけ渡せます(省略として扱われます)。
途中の位置のundefinedやnullはunsupported arguments例外になります。これは osbxl 全体(// ✓ 末尾 undefined = 省略 o.setNumberValue("A1", 100, false, undefined); // ✗ 例外: 途中の undefined o.setNumberValue("A1", undefined, false, "#,##0"); // ✗ 例外: null は省略として扱われない o.setNumberValue("A1", 100, null);Rangeの setter など含む)に共通の仕様です。
関連
- 目次
- 前: 行・列・セル範囲の操作
- 概要 — オブジェクトモデルと基本の流れ / 値と数式を入れて表を作る
- API リファレンス