Pivot Tables — create, aggregate, change aggregation method, delete

level: advanced / verified: 2026-10-01 / tabs: Node.js・Python・Java・WebAssembly / 日本語

What you want to do

Create a pivot table from source data on a worksheet, place row and data (value) fields and aggregate. Also change the aggregation method (Sum → Average) and delete the pivot table.

StepMethod
Add a pivot tablews.getPivotTables().addPivotTable(name, sourceRange, destCell)
Get a fieldpt.getField(fieldName)
Place fieldspt.setFields(settings, layoutType, rowFields, colFields, filterFields, dataFields)
Run the aggregationpt.refreshData() → pt.refresh()
Change the aggregation methodfield.setDataFieldSubTotalsMethod(...) → setFields again → refreshData → refresh
Delete the pivot tablews.getPivotTables().removePivotTable(name)

Classes involved

PivotTables (obtained via WorkSheet.getPivotTables())

MethodDescription
addPivotTable(name, sourceRange, destCell)Adds a pivot table. sourceRange is an A1-style cell range; destCell is the top-left output cell (A1 style).
getPivotTable(name)Gets a pivot table by name. Throws if it does not exist.
removePivotTable(name)Deletes a pivot table.

PivotTable

MethodDescription
getField(fieldName)Gets a field by its source-data header name (dto.PivotFieldObject).
getFields()Returns an array of all fields.
getPivotTableSetting()Returns the settings object (dto.PivotTableSettingObject). Used as the first argument of setFields.
setFields(settings, layout, rows, cols, filters, data)Places fields and fixes the layout.
refreshData()Reloads the source data and re-aggregates.
refresh()Reflects field-layout changes and re-aggregates.
getLayoutType()Returns the current layout type (enums.XlPivotTableLayoutType).

dto.PivotFieldObject

MethodDescription
setFieldType(type)Sets the field's role (enums.XlPivotFieldType).
setDataFieldSubTotalsMethod(method)Sets the aggregation method (enums.XlPivotFieldSubtotalsMethodType). Only valid for data fields.
getCaption()Returns the field name.

Main enums

enumValueDescription
XlPivotFieldType.PivotFieldTypeRow0Row field
XlPivotFieldType.PivotFieldTypeCol1Column field
XlPivotFieldType.PivotFieldTypeData3Data (value) field
XlPivotTableLayoutType.TabularForm2Tabular form
XlPivotTableLayoutType.CompactForm0Compact form
XlPivotTableLayoutType.OutlineForm1Outline form
XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeSum1Sum
XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeAverage3Average
XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeCount2Count
XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeMax4Max
XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeMin5Min

Code

Output:

// pivot-sample.js — pivot tables: create, aggregate, change aggregation method, delete
const { nodeosbxl, enums } = require("nodeosbxl");

const app = new nodeosbxl.App();
const wb = app.createWorkBook("pivot.xlsx");
const ws = wb.openWorkSheet("Sheet1");

// ---------- 1. Source data ----------
// 10 rows of Region / Product / Quantity
const headers = ["Region", "Product", "Quantity"];
const srcData = [
  ["East", "Apple", 10], ["East", "Orange", 20], ["West", "Apple", 30],
  ["West", "Orange", 15], ["East", "Apple", 25], ["North", "Orange", 40],
  ["North", "Apple",  5], ["West", "Apple", 10], ["East", "Orange", 30],
  ["North", "Apple", 20],
];
headers.forEach((h, i) => {
  const col = String.fromCharCode(65 + i);
  ws.getRange(`${col}1:${col}1`).setValue(h);
});
srcData.forEach((row, ri) => {
  row.forEach((v, ci) => {
    const col = String.fromCharCode(65 + ci);
    const r = ri + 2;
    if (typeof v === "number") ws.getRange(`${col}${r}:${col}${r}`).setNumberValue(v);
    else ws.getRange(`${col}${r}:${col}${r}`).setValue(v);
  });
});
const srcTotal = srcData.reduce((s, r) => s + r[2], 0);
console.log(`[1] Source data: ${srcData.length} rows, quantity total = ${srcTotal}`);

// ---------- 2. Create the pivot table (rows=Region, values=Quantity sum) ----------
const pt = ws.getPivotTables().addPivotTable("SalesSummary", "A1:C11", "E1");

const rf = pt.getField("Region");
rf.setFieldType(enums.XlPivotFieldType.PivotFieldTypeRow);
const df = pt.getField("Quantity");
df.setFieldType(enums.XlPivotFieldType.PivotFieldTypeData);
df.setDataFieldSubTotalsMethod(enums.XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeSum);

pt.setFields(pt.getPivotTableSetting(), enums.XlPivotTableLayoutType.TabularForm,
             [rf], [], [], [df]);
pt.refreshData();
pt.refresh();
console.log("[2] Created PivotTable (rows=Region, values=Quantity sum, layout=tabular form)");

// ---------- 3. Read back the results and cross-check ----------
// Pivot output: E1=header, E2 onward=row labels, F2 onward=values, last row=grand total.
// The grand-total label ("総計") is written by the library itself, not by our data.
const pivotRows = {};
for (let r = 2; r <= 10; r++) {
  const label = ws.getRange(`E${r}:E${r}`).getValue()[`E${r}`];
  const val   = ws.getRange(`F${r}:F${r}`).getValue()[`F${r}`];
  if (label !== undefined && label !== "") {
    pivotRows[label] = Number(val);
    console.log(`    ${label} = ${val}`);
  }
}
const grandTotal = pivotRows["総計"];
console.log(`[3] Check: grand total ${grandTotal} === source total ${srcTotal} → ${grandTotal === srcTotal ? "OK" : "NG"}`);

// ---------- 4. Change the aggregation method to Average ----------
df.setDataFieldSubTotalsMethod(enums.XlPivotFieldSubtotalsMethodType.SubtotalsMethodTypeAverage);
pt.setFields(pt.getPivotTableSetting(), enums.XlPivotTableLayoutType.TabularForm,
             [rf], [], [], [df]);
pt.refreshData();
pt.refresh();
console.log("[4] Changed subtotal method from Sum to Average");
for (let r = 2; r <= 10; r++) {
  const label = ws.getRange(`E${r}:E${r}`).getValue()[`E${r}`];
  const val   = ws.getRange(`F${r}:F${r}`).getValue()[`F${r}`];
  if (label !== undefined && label !== "") {
    console.log(`    ${label} = ${val}`);
  }
}

// ---------- 5. Get field information ----------
const fields = pt.getFields();
console.log(`[5] getFields: ${fields.length} fields → ${fields.map(f => f.getCaption()).join(", ")}`);
console.log(`    getLayoutType = ${pt.getLayoutType()} (TabularForm=${enums.XlPivotTableLayoutType.TabularForm})`);

// ---------- 6. Delete the pivot table ----------
ws.getPivotTables().removePivotTable("SalesSummary");
try {
  ws.getPivotTables().getPivotTable("SalesSummary");
  console.log("[6] Removal failed");
} catch (e) {
  console.log("[6] removePivotTable → removal confirmed OK");
}

wb.save();
wb.close();
[1] Source data: 10 rows, quantity total = 205
[2] Created PivotTable (rows=Region, values=Quantity sum, layout=tabular form)
    East = 85
    North = 65
    West = 55
    総計 = 205
[3] Check: grand total 205 === source total 205 → OK
[4] Changed subtotal method from Sum to Average
    East = 21.25
    North = 21.66666667
    West = 18.33333333
    総計 = 20.5
[5] getFields: 3 fields → Region, Product, Quantity
    getLayoutType = 2 (TabularForm=2)
[6] removePivotTable → removal confirmed OK

Notes

Flow for creating a pivot table

  1. Prepare the source data — headers (field names) in row 1, data from row 2 onward.
  2. addPivotTable(name, sourceRange, destCell) — specify the source range (A1 style) and the top-left output cell.

When placing the pivot on the same sheet, choose a destCell that does not overlap the source. When placing it on another sheet, prefix sourceRange with the sheet name, e.g. Sheet1!A1:C11.

  1. Get fields and set their roles — get a field with pt.getField("header name") and assign

row / column / data / filter with setFieldType().

  1. Place them with setFields() — pass the settings object, the layout type and the field arrays.

The argument order is (settings, layoutType, rowFields, colFields, filterFields, dataFields).

  1. refreshData() → refresh() — reloads the source data and writes the aggregation results to the sheet.

setFields() alone does not produce results. Always call refresh().

Changing the aggregation method

The aggregation method of a data field is changed with setDataFieldSubTotalsMethod(). After changing it you must run setFields() → refreshData() → refresh() again.

enum valueNumberAggregation method
SubtotalsMethodTypeSum1Sum (default)
SubtotalsMethodTypeCount2Count
SubtotalsMethodTypeAverage3Average
SubtotalsMethodTypeMax4Max
SubtotalsMethodTypeMin5Min
SubtotalsMethodTypeProduct6Product
SubtotalsMethodTypeCountNums7Count numbers
SubtotalsMethodTypeStdDev8Sample standard deviation
SubtotalsMethodTypeStdDevP9Standard deviation
SubtotalsMethodTypeVar10Sample variance
SubtotalsMethodTypeVarP11Variance

Row × column cross-tabulation

To also use a column field, pass an array as colFields of setFields().

The output becomes a matrix of row labels (column E) × column labels (column F onward).

const cf = pt.getField("Product");
cf.setFieldType(enums.XlPivotFieldType.PivotFieldTypeCol);
pt.setFields(pt.getPivotTableSetting(), enums.XlPivotTableLayoutType.TabularForm,
             [rf], [cf], [], [df]);
pt.refreshData();
pt.refresh();

Reading back the aggregated results

Pivot table output can be read as ordinary cell values. Get aggregated values with e.g. ws.getRange("F3:F3").getValue() and cross-check them by comparing against the sum of the source data.

Deleting the pivot table

Delete with removePivotTable(name). Calling getPivotTable(name) afterwards throws.

Caveats

See also