Sales V Sliced Cross Report

Sales v sliced cross reports can be useful for tracking the performance of individual salespeople or product lines, identifying trends in consumer behavior, and determining overall growth or decline in revenue.

Description
app.js
index.html
styles.css
Copy to CodeMine
Open the demo in new window can open the designer

How to open desgnr

You can use the ‘Group' and 'Summary’ cell types to generate the sales v sliced report in the following steps.

  • Define the sales table in the DataManager.
  • Set the style for the template.
  • Bind the data column to the template and use the ‘Group' and ‘Summary’ cell types, and use both ‘Horizontal’ and 'Vertical’ spill directions.
const spread = new GC.Spread.Sheets.Workbook('ss', { sheetCount: 1 });
spread.options.scrollByPixel = true;
spread.options.scrollbarMaxAlign = true;
const records = [
    ['East', 'John', 'Fruits', 'Banana', 180],
    ['East', 'Mike', 'Fruits', 'Banana', 200],
    ['East', 'Emma', 'Fruits', 'Banana', 210],
    ['East', 'Sophia', 'Fruits', 'Banana', 316],
    ['East', 'Jennifer', 'Fruits', 'Banana', 130],
    ['North', 'Kristen', 'Fruits', 'Banana', 410.0],
    ['North', 'Mia', 'Fruits', 'Banana', 290.0],
    ['North', 'Bella', 'Fruits', 'Banana', 342.0],
    ['North', 'Eva', 'Fruits', 'Banana', 214.0],
    ['East', 'John', 'Fruits', 'Strawberry', 230.0],
    ['East', 'Mike', 'Fruits', 'Strawberry', 641.0],
    ['East', 'Emma', 'Fruits', 'Strawberry', 234.0],
    ['East', 'Sophia', 'Fruits', 'Strawberry', 625.0],
    ['East', 'Jennifer', 'Fruits', 'Strawberry', 241.0],
    ['North', 'Kristen', 'Fruits', 'Strawberry', 195.0],
    ['North', 'Mia', 'Fruits', 'Strawberry', 569.0],
    ['North', 'Bella', 'Fruits', 'Strawberry', 698.0],
    ['North', 'Eva', 'Fruits', 'Strawberry', 214.0],
    ['East', 'John', 'Fruits', 'Watermelon', 147.0],
    ['East', 'Mike', 'Fruits', 'Watermelon', 489.0],
    ['East', 'Emma', 'Fruits', 'Watermelon', 347.0],
    ['East', 'Sophia', 'Fruits', 'Watermelon', 652.0],
    ['East', 'Jennifer', 'Fruits', 'Watermelon', 471.0],
    ['North', 'Kristen', 'Fruits', 'Watermelon', 287.0],
    ['North', 'Mia', 'Fruits', 'Watermelon', 349.0],
    ['North', 'Bella', 'Fruits', 'Watermelon', 163.0],
    ['North', 'Eva', 'Fruits', 'Watermelon', 841.0],
    ['East', 'John', 'Snack', 'Chips', 292.0],
    ['East', 'Mike', 'Snack', 'Chips', 514.0],
    ['East', 'Emma', 'Snack', 'Chips', 256.0],
    ['East', 'Sophia', 'Snack', 'Chips', 148.0],
    ['East', 'Jennifer', 'Snack', 'Chips', 486.0],
    ['North', 'Kristen', 'Snack', 'Chips', 285.0],
    ['North', 'Mia', 'Snack', 'Chips', 741.0],
    ['North', 'Bella', 'Snack', 'Chips', 249.0],
    ['North', 'Eva', 'Snack', 'Chips', 105.0],
    ['East', 'John', 'Snack', 'Cookie', 554.0],
    ['East', 'Mike', 'Snack', 'Cookie', 311.0],
    ['East', 'Emma', 'Snack', 'Cookie', 186.0],
    ['East', 'Sophia', 'Snack', 'Cookie', 654.0],
    ['East', 'Jennifer', 'Snack', 'Cookie', 247.0],
    ['North', 'Kristen', 'Snack', 'Cookie', 143.0],
    ['North', 'Mia', 'Snack', 'Cookie', 617.0],
    ['North', 'Bella', 'Snack', 'Cookie', 214.0],
    ['North', 'Eva', 'Snack', 'Cookie', 324.0],
];
const columns = ['Region', 'Salesman', 'ProductType', 'Product', 'Sales'];
const salesTable = spread.dataManager().addTable('Sales', {
    data: records.map((x) => {
        const record = {};
        columns.forEach((c, i) => record[c] = x[i]);
        return record;
    })
});

salesTable.fetch().then(() => {
    const reportSheet = spread.addSheetTab(0, 'report1', GC.Spread.Sheets.SheetType.reportSheet);
    const templateSheet = reportSheet.getTemplate();

    // set style for the template
    templateSheet.defaults.colWidth = 100;
    templateSheet.defaults.rowHeight = 30;
    templateSheet.setColumnWidth(0, 200);
    const headerStyle = new GC.Spread.Sheets.Style();
    headerStyle.backColor = '#90CAF9';
    headerStyle.foreColor = '#424242';
    headerStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center;
    headerStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center;
    headerStyle.font = '12px Maine';
    templateSheet.getRange('A1:D8').setStyle(headerStyle);
    [2, 4, 6].forEach(r => {
        const newStyle = templateSheet.getStyle(r, 0).clone();
        newStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.left;
        newStyle.textIndent = 1;
        templateSheet.setStyle(r, 0, newStyle);
    });
    [1, 2].forEach(c => {
        const newStyle = templateSheet.getStyle(1, c).clone();
        newStyle.backColor = '#B3E5FC';
        templateSheet.setStyle(1, c, newStyle);
    });
    const newStyle = templateSheet.getStyle(0, 1).clone();
    newStyle.backColor = '#B3E5FC';
    templateSheet.setStyle(0, 1, newStyle);
    const border = new GC.Spread.Sheets.LineBorder('#E0E0E0', 1);
    ['#C8E6C9', '#A5D6A7', '#81C784'].forEach((bg, r) => {
        r = (r * 2) + 3;
        const newStyle = templateSheet.getStyle(r, 0).clone();
        newStyle.backColor = bg;
        templateSheet.setStyle(r, 0, newStyle);

        ['#FFCC80', undefined, '#FFA726'].forEach((x, c) => {
            const newStyle1 = templateSheet.getStyle(r, c + 1).clone();
            newStyle1.backColor = x;
            if (!x) {
                newStyle1.borderBottom = border;
                newStyle1.borderTop = border;
                newStyle1.borderLeft = border;
                newStyle1.borderRight = border;
            }
            templateSheet.setStyle(r, c + 1, newStyle1);
        })
    });

    [[0, 0, 2, 1], [0, 1, 2, 1], [0, 3, 2, 1], [2, 0, 1, 4], [4, 0, 1, 4], [6, 0, 1, 4]].forEach(x => templateSheet.addSpan(...x));
    templateSheet.setValue(0, 0, 'Category');
    templateSheet.setValue(0, 2, 'Include');
    templateSheet.setValue(0, 3, 'Total');
    templateSheet.setValue(2, 0, 'Product Sales');
    templateSheet.setValue(4, 0, 'Product Type Sales');
    templateSheet.setValue(6, 0, 'Total Sales');
    templateSheet.setValue(7, 0, 'Total');

    // binding for the template
    templateSheet.setTemplateCell(0, 1, {
        type: 'Group',
        binding: 'Sales[Region]',
        spillDirection: 'Horizontal',
        showCollapseButton: true,
    });
    templateSheet.setTemplateCell(1, 2, {
        type: 'Group',
        binding: 'Sales[Salesman]',
        spillDirection: 'Horizontal',
        context: {
            horizontal: 'B1',
        },
    });
    ['Product', 'ProductType', ''].forEach((x, r) => {
        r = (r * 2) + 3;
        if (x) {
            templateSheet.setTemplateCell(r, 0, {
                type: 'Group',
                binding: `Sales[${x}]`,
            });
        }

        [1, 2, 3].forEach(c => {
            templateSheet.setTemplateCell(r, c, {
                type: 'Summary',
                aggregate: 'Sum',
                binding: 'Sales[Sales]',
                context: {
                    horizontal: c === 1
                        ? 'B1'
                        : c === 2 ? 'C2' : 'Default',
                },
            });
        });
    });
    [2, 4, 6].forEach(r => {
        templateSheet.setTemplateCell(r, 0, {
            type: 'Static',
            context: {
                horizontal: 'None',
            },
        });
    });

    reportSheet.refresh();
});
Open the demo in new window can open the designer You can use the ‘Group' and 'Summary’ cell types to generate the sales v sliced report in the following steps. Define the sales table in the DataManager. Set the style for the template. Bind the data column to the template and use the ‘Group' and ‘Summary’ cell types, and use both ‘Horizontal’ and 'Vertical’ spill directions.
window.onload = async () => { const loadingTip = addLoadingTip(); const { spread, designer } = createSpreadAndDesigner(); const res = await fetch('$DEMOROOT$/en/sample/features/report-sheet/showcase/cross-report/sales-v-sliced-cross-report/spread.json'); await spread.fromJSON(await res.json()); loadingTip.remove(); if (designer) { designer.refresh(); } } function createSpreadAndDesigner() { const demoHost = document.getElementById('demo-host'); if (window !== top) { return { spread: new GC.Spread.Sheets.Workbook(demoHost, { sheetCount: 1 }), } } else { const designer = new GC.Spread.Sheets.Designer.Designer(demoHost, undefined, undefined, { sheetCount: 1 }); return { designer, spread: designer.getWorkbook(), } } } function addLoadingTip() { const div = document.createElement('div'); div.style.position = 'absolute'; div.style.inset = '0'; div.style.display = 'flex'; div.style.alignItems = 'center'; div.style.justifyContent = 'center'; div.style.background = 'white'; div.style.zIndex = '100'; div.textContent = 'Loading data from server ...'; document.body.appendChild(div); return div; }
<!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"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css"> <link rel="stylesheet" type="text/css" href="styles.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-print/dist/gc.spread.sheets.print.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$/en/purejs/node_modules/@mescius/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script> const designerDependencyScripts = [ '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer-resources-en/dist/gc.spread.sheets.designer.resource.en.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js', '$DEMOROOT$/spread/source/js/designer/license.js', ] function appendScriptNode (src) { const script = document.createElement('script'); script.src = src; script.async = false; script.type = 'text/javascript'; document.head.appendChild(script); } if (top === window) { // not in iframe designerDependencyScripts.forEach(appendScriptNode); } </script> <script src="app.js" type="text/javascript"></script> </head> <body> <div class="sample-tutorial"> <div id="demo-host"></div> </div> </body> </html>
body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } #demo-host { width: 100%; height: 100%; overflow: hidden; float: left; }