PIVOTBY function

SpreadJS supports the PIVOTBY function, which allows you to perform data aggregations using a single formula.

The demo is being dynamically compiled to support real-time code editing... For quicker access to features, switch to the "JavaScript" tab for a smoother experience! :)
Description
app.vue
index.html
Copy to CodeMine

The PIVOTBY function allows you to create a data summary via a formula. It supports grouping along two axis and aggregating the associated values.

=PIVOTBY(row_fields,col_fields,values,function,[field_headers],[row_total_depth],[row_sort_order],[col_total_depth],[col_sort_order],[filter_array],[relative_to])
Argument Required Description
row_fields Y A column-oriented array or range contains the values used to group rows and generate row headers.
col_fields Y A column-oriented array or range that contains the values which are used to group columns and generate column headers.
values Y A column-oriented array or range of the data to aggregate.
function Y The function to summarize the grouped data.
[field_headers] N A number specifies whether the row_fields, col_fields, and values have headers and whether field headers should be returned in the results.
[row_total_depth] N Determines whether the row headers should contain totals.
[row_sort_order] N A number indicating how rows should be sorted. Numbers correspond with columns in row_fields followed by the columns in values. If the number is negative, the rows are sorted in descending/reverse order.
[col_total_depth] N Determines whether the column headers should contain totals.
[col_sort_order] N A number indicating how columns should be sorted. Numbers correspond with columns in col_fields followed by the columns in values. If the number is negative, the rows are sorted in descending/reverse order.
[filter_array] N A column-oriented 1D array of Booleans that indicate whether the corresponding row of data should be considered.
[relative_to] N Controls which values are provided to the 2nd argument of the aggregation function.

Note:

  • The PIVOTBY function is only valid when allowDynamicArray is true.
  • The array or range may contain multiple columns. If so, the output will have multiple aggregations.
  • A vector of lambda functions can be provided. If so, the output will have multiple aggregations. The orientation of the vector will determine whether they are laid out row- or column-wise.
  • When the field_headers is missing, itt will automatic assumes the data contains headers based on the values argument. If the 1st value is text and the 2nd value is a number, then the data is assumed to have headers. Fields headers are shown if there are multiple row or column group levels.
The PIVOTBY function allows you to create a data summary via a formula. It supports grouping along two axis and aggregating the associated values. Argument Required Description row_fields Y A column-oriented array or range contains the values used to group rows and generate row headers. col_fields Y A column-oriented array or range that contains the values which are used to group columns and generate column headers. values Y A column-oriented array or range of the data to aggregate. function Y The function to summarize the grouped data. [field_headers] N A number specifies whether the row_fields, col_fields, and values have headers and whether field headers should be returned in the results. [row_total_depth] N Determines whether the row headers should contain totals. [row_sort_order] N A number indicating how rows should be sorted. Numbers correspond with columns in row_fields followed by the columns in values. If the number is negative, the rows are sorted in descending/reverse order. [col_total_depth] N Determines whether the column headers should contain totals. [col_sort_order] N A number indicating how columns should be sorted. Numbers correspond with columns in col_fields followed by the columns in values. If the number is negative, the rows are sorted in descending/reverse order. [filter_array] N A column-oriented 1D array of Booleans that indicate whether the corresponding row of data should be considered. [relative_to] N Controls which values are provided to the 2nd argument of the aggregation function. Note: The PIVOTBY function is only valid when allowDynamicArray is true. The array or range may contain multiple columns. If so, the output will have multiple aggregations. A vector of lambda functions can be provided. If so, the output will have multiple aggregations. The orientation of the vector will determine whether they are laid out row- or column-wise. When the field_headers is missing, itt will automatic assumes the data contains headers based on the values argument. If the 1st value is text and the 2nd value is a number, then the data is assumed to have headers. Fields headers are shown if there are multiple row or column group levels.
<template> <div class="sample-tutorial"> <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread"> <gc-worksheet> </gc-worksheet> <gc-worksheet> </gc-worksheet> </gc-spread-sheets> </div> </template> <script setup> import '@mescius/spread-sheets-vue'; import { ref } from "vue"; import GC from "@mescius/spread-sheets"; const spreadRef = ref(null); let initSpread = function (spread) { spreadRef.value = spread; let sheet = spread.getActiveSheet(); spread.options.allowDynamicArray = true; spread.suspendPaint(); spread.suspendCalcService(); sheet.setColumnCount(30); let data = [["Year","Category","Product","Status","Sales","Rating","Profit"],[2023,"Electronics","Smart TV","Active",15000,4.5,250],[2023,"Fashion","Designer Jeans","Discontinued",8000,4.7,150],[2024,"Food","Organic Granola","Active",5000,4.8,100],[2023,"Books","Bestseller Novel","Active",12000,4.6,180],[2024,"Electronics","Laptop","Active",20000,4.9,300],[2023,"Beauty","Skincare Set","Active",7000,4.4,120],[2023,"Home & Garden","Garden Tools","Active",6500,4.3,130],[2024,"Health","Fitness Tracker","Active",9500,4.6,190],[2023,"Toys","Action Figure","Active",4800,4.7,95],[2024,"Automotive","Car Accessories","Active",3200,4.5,65],[2023,"Sports","Basketball","Active",7600,4.8,150],[2024,"Office Supplies","Notebooks","Active",11000,4.4,220],[2023,"Pet Supplies","Dog Food","Active",5600,4.6,110],[2024,"Music","Headphones","Active",13000,4.9,260],[2023,"Outdoor","Camping Tent","Active",4400,4.5,88],[2024,"Jewelry","Silver Necklace","Active",2800,4.7,56],[2023,"Tools","Power Drill","Active",3900,4.4,78],[2024,"Baby","Stroller","Active",1700,4.6,34],[2023,"Kitchen","Blender","Active",2500,4.8,50],[2024,"Clothing","Casual Shirt","Active",6200,4.5,124],[2023,"Art","Oil Paintings","Active",1900,4.7,38],[2024,"Hobbies","Model Trains","Active",3100,4.4,62],[2023,"Tech Gadgets","Smart Watch","Active",7300,4.6,146],[2024,"Travel","Luggage","Active",4600,4.8,92],[2023,"Home Decor","Wall Clock","Active",2200,4.5,44],[2024,"Fitness","Yoga Mat","Active",5700,4.7,114],[2023,"Gardening","Plant Pots","Active",3400,4.4,68],[2024,"Audio","Speakers","Active",8900,4.6,178],[2023,"Lighting","LED Bulbs","Active",4300,4.8,86],[2024,"Gaming","Video Games","Active",16000,4.5,320],[2023,"Furniture","Sofa","Active",5500,4.7,110],[2024,"Health","Vitamins","Active",7100,4.4,142],[2023,"Office","Desk Chair","Active",6300,4.6,126],[2024,"Books","Educational Textbooks","Active",9200,4.8,184],[2023,"Tools","Screwdriver Set","Active",3700,4.5,74],[2024,"Home & Garden","Patio Furniture","Active",4900,4.7,98],[2023,"Automotive","Car Seat Covers","Active",2600,4.4,52],[2024,"Electronics","Smart Home System","Active",10500,4.6,210],[2023,"Health","Blood Pressure Monitor","Active",3800,4.8,76],[2024,"Beauty","Makeup Kit","Active",5900,4.5,118],[2023,"Music","Turntable","Active",2100,4.7,42],[2024,"Toys","Board Games","Active",3300,4.4,66],[2023,"Clothing","Winter Coat","Active",4700,4.6,94],[2024,"Food","Gourmet Chocolates","Active",7400,4.8,148],[2023,"Home Decor","Curtains","Active",2900,4.5,58],[2024,"Pet Supplies","Cat Litter","Active",6100,4.7,122],[2023,"Outdoor","Hiking Boots","Active",3500,4.4,70],[2024,"Kitchen","Slow Cooker","Active",8200,4.6,164],[2023,"Toys","Dolls","Active",4400,4.8,88],[2024,"Books","Poetry Collection","Active",5300,4.5,106],[2023,"Health","Massage Chair","Active",6600,4.7,132],[2024,"Home & Garden","Fire Pit","Active",7700,4.4,154],[2023,"Automotive","Car Wash Kit","Active",4000,4.6,80],[2024,"Office Supplies","Highlighters","Active",5200,4.8,104],[2023,"Tools","Hammer","Active",3200,4.5,64],[2024,"Beauty","Hair Dryer","Active",6800,4.7,136],[2023,"Kitchen","Coffee Maker","Active",4600,4.4,92],[2024,"Toys","Remote Control Cars","Active",7900,4.6,158],[2023,"Home Decor","Picture Frames","Active",3300,4.8,66],[2024,"Electronics","Router","Active",8500,4.5,170],[2023,"Clothing","Suit","Active",5700,4.7,114]]; sheet.setArray(0, 0, data); sheet.getRange(0, 0, 1, 7).backColor("Accent 7 80"); sheet.setText(0, 9, "The usage with non-adjacent columns and multiple aggregations"); sheet.setFormula(1, 9,"=FORMULATEXT(J3)"); sheet.setFormula(2, 9,"=PIVOTBY(A1:B62,D1:D62,CHOOSECOLS(E1:G62,1,3),HSTACK(PERCENTOF,MAX),3,2)"); let ranges = [new GC.Spread.Sheets.Range(2, 9, 49, 8)]; sheet.conditionalFormats.addFormulaRule('$J3="Year"', new GC.Spread.Sheets.Style('Accent 2 40'), ranges); sheet.conditionalFormats.addFormulaRule('$K3=""', new GC.Spread.Sheets.Style('Accent 2 60',null,null,null,"Bold"), ranges); sheet.getRange(2, 9, 49, 2).font("Bold"); sheet.getRange(2, 9, 49, 2).backColor("Accent 2 80"); spread.resumeCalcService(); spread.resumePaint(); } </script> <style scoped> #app { height: 100%; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } #switchAutoMergeMode { margin: 10px 0px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } </style>
<!DOCTYPE html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>SpreadJS VUE</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script> <script src="./systemjs.config.js"></script> <script src="./compiler.js" type="module"></script> <script> var System = SystemJS; System.import("./src/app.js"); System.import('$DEMOROOT$/en/lib/vue3/license.js'); </script> </head> <body> <div id="app"></div> </body> </html>
(function (global) { SystemJS.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, packageConfigPaths: [ './node_modules/*/package.json', "./node_modules/@mescius/*/package.json", "./node_modules/@babel/*/package.json", "./node_modules/@vue/*/package.json" ], map: { 'vue': "npm:vue/dist/vue.esm-browser.js", 'tiny-emitter': 'npm:tiny-emitter/index.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', "systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js", '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-resources-en': 'npm:@mescius/spread-sheets-resources-en/index.js', '@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js' }, meta: { '*.css': { loader: 'systemjs-plugin-css' }, '*.vue': { loader: "../plugin-vue/index.js" } } }); })(this);