GROUPBY function

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

The GROUPBY function allows you to create a data summary via a formula. It supports grouping along one 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. 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 that specifies whether the row_fields and values have headers and whether field headers should be returned in the results. [total_depth] N Determines whether the row headers should contain totals. [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. [filter_array] N A column-oriented 1D array of Booleans that indicate whether the corresponding row of data should be considered. [field_relationship] N Specifies the relationship fields when multiple columns are provided to row_fields. Note: The GROUPBY 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.
window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 1 }); initSpread(spread); }; function initSpread(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 basic usage with conditional formatting"); sheet.setFormula(1,9,"=FORMULATEXT(J3)"); sheet.setFormula(2,9,"=GROUPBY(A1:B62,E1:E62,SUM,3,2)"); let ranges = [new GC.Spread.Sheets.Range(2, 9, 46, 3)]; sheet.conditionalFormats.addFormulaRule('$J3="Year"', new GC.Spread.Sheets.Style('Accent 2 60'), ranges); sheet.conditionalFormats.addFormulaRule('$K3=""', new GC.Spread.Sheets.Style('Accent 2 80',null,null,null,"Bold"), ranges); sheet.setText(0, 15, "The non-adjacent columns and multiple aggregations with VSTACK"); sheet.setFormula(1,15,"=FORMULATEXT(P3)"); sheet.setFormula(2,15,'=GROUPBY(B1:B62,E1:G62,VSTACK(COUNT,LAMBDA(a,IF(COUNT(a)>2,"↑","↓")),PERCENTOF),,0)'); ranges = [new GC.Spread.Sheets.Range(2, 15, 93, 3)]; sheet.conditionalFormats.addFormulaRule('$Q3="COUNT"', new GC.Spread.Sheets.Style('Accent 4 80'), ranges); sheet.conditionalFormats.addFormulaRule('$Q3="CUSTOM"', new GC.Spread.Sheets.Style('Accent 6 80'), ranges); sheet.conditionalFormats.addFormulaRule('$Q3="PERCENTOF"', new GC.Spread.Sheets.Style('Accent 5 80'), ranges); spread.resumeCalcService(); spread.resumePaint(); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" style="width:100%;height:100%"></div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }