Sales Summary Report

Sales summary 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 summary report in the following steps.

  • Define the Order, OrderDetail(contains calculated column), Employee tables in the DataManager.
  • Set the style for the template.
  • Bind the data column to the template and use the 'Group'(formula group) and 'Summary' cell types, and use both 'Horizontal' and 'Vertical' spill directions.
  • Set the sortOptions and filter for the template cell.
  • Add the formula for the summary cell.
window.onload = async () => {
    const spread = new GC.Spread.Sheets.Workbook('demo-host', { sheetCount: 1 });
    await addTables(spread);
    addSalesSummaryReport(spread);
}

async function addTables(spread) {
    const baseUrl = window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api';
    const tables = ['Order', 'OrderDetail', 'Employee'].map(x => spread.dataManager().addTable(x, { remote: { read: { url: `${baseUrl}/${x}` } } }));
    await Promise.all(tables.map(x => x.fetch()));
    tables[1].columns['Sales'] = {
        value: '=[@UnitPrice]*[@Quantity]*(1-[@Discount])',
        caption: 'Sales',
    };
}
function addSalesSummaryReport(spread) {
    const reportSheet = spread.addSheetTab(0, 'Sales Summary Report', GC.Spread.Sheets.SheetType.reportSheet);
    const templateSheet = reportSheet.getTemplate();

    templateSheet.options.gridline.showHorizontalGridline = false;
    templateSheet.options.gridline.showVerticalGridline = false;
    templateSheet.defaults.colWidth = 160;
    templateSheet.defaults.rowHeight = 30;
    const headerStyle = new GC.Spread.Sheets.Style();
    headerStyle.backColor = '#BBDEFB';
    headerStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center;
    headerStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center;
    headerStyle.foreColor = '#424242';
    headerStyle.font = '12px "Open Sans"';
    const dataStyle = new GC.Spread.Sheets.Style();
    dataStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center;
    dataStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center;
    dataStyle.foreColor = '#424242';
    dataStyle.font = '12px "Open Sans"';
    const border = new GC.Spread.Sheets.LineBorder('#e0e0e0', 1);
    dataStyle.borderBottom = border;
    templateSheet.setValue(0, 0, 'Employee');
    templateSheet.setValue(0, 2, 'Trend');
    templateSheet.getRange(0, 0, 1, 3).setStyle(headerStyle);
    templateSheet.getRange(1, 0, 1, 3).setStyle(dataStyle);
    templateSheet.setFormatter(1, 1, '0.00');
    templateSheet.setFormula(1, 2, '=LINESPARKLINE(B2,0)');
    const summaryStyle = dataStyle.clone();
    summaryStyle.backColor = '#FFECB3';
    templateSheet.getRange(2, 0, 1, 3).setStyle(summaryStyle);
    templateSheet.setValue(2, 0, 'Total');
    templateSheet.setFormatter(2, 1, '0.00');
    templateSheet.setFormula(2, 1, 'SUM(B2)');
    templateSheet.setFormula(2, 2, '=LINESPARKLINE(B3,0)');

    templateSheet.setTemplateCell(0, 1, {
        type: 'Group',
        formula: '=Year([@OrderDate])',
        binding: 'Order[OrderDate]',
        spillDirection: 'Horizontal',
    });
    templateSheet.setTemplateCell(1, 0, {
        type: 'Group',
        binding: 'Employee[FirstName]',
        filter: {
            condition: {
                column: 'Id',
                operator: 'Equal',
                dataColumn: {
                    tableName: 'Order',
                    columnName: 'EmployeeId',
                }
            },
        },
        sortOptions: [{ asc: 'FirstName' }]
    });
    templateSheet.setTemplateCell(1, 1, {
        type: 'Summary',
        aggregate: 'Sum',
        binding: 'OrderDetail[Sales]',
        filter: {
            condition: {
                column: 'OrderId',
                operator: 'Equal',
                dataColumn: {
                    tableName: 'Order',
                    columnName: 'Id',
                }
            },
        },
    });

    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 summary report in the following steps. Define the Order, OrderDetail(contains calculated column), Employee tables in the DataManager. Set the style for the template. Bind the data column to the template and use the 'Group'(formula group) and 'Summary' cell types, and use both 'Horizontal' and 'Vertical' spill directions. Set the sortOptions and filter for the template cell. Add the formula for the summary cell.
window.onload = async () => { const loadingTip = addLoadingTip(); const { spread, designer } = createSpreadAndDesigner(); const res = await fetch('$DEMOROOT$/en/sample/features/report-sheet/showcase/cross-report/sales-summary-report/spread.json'); await spread.fromJSON(correctTableUrl(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; } function correctTableUrl(json) { const baseUrl = '$DEMOROOT$'; const localUrl = 'http://localhost:8070/spreadjs/demos'; const replaceUrl = (obj) => { if (obj && obj.url && obj.url.startsWith(localUrl)) { obj.url = obj.url.replace(localUrl, baseUrl); } } if (json.dataManager && json.dataManager.tables) { json.dataManager.tables.forEach((table) => { if (table.dataSourceOption && table.dataSourceOption.remote) { Object.values(table.dataSourceOption.remote).forEach(replaceUrl); } }); } return json; }
<!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; }