
# Header Summary

The total and statistical values of each column are displayed at the start of the grid, with a footer located at the end of the grid. If you set gridView.headerSummaries.visible = true, you can see that a bar with the same function as the footer is displayed at the starting position.

#### Column Header Summary

The way to set the summary displayed at the top is by setting it in the column.headerSummary property. It is the same as the setting method summarized in the footer.

```js
const fields = [
  { fieldName: "OrderID", dataType: "text" },
  { fieldName: "CustomerID", dataType: "text" },
  { fieldName: "EmployeeID", dataType: "text" },
  { fieldName: "OrderDate", dataType: "datetime", datetimeFormat: "yyyy-MM-dd", amText: "AM", pmText: "PM" },
  { fieldName: "CompanyName", dataType: "text" },
  { fieldName: "Country", dataType: "text" },
  { fieldName: "Phone", dataType: "text" },
  { fieldName: "ProductName", dataType: "text" },
  { fieldName: "QuantityPerUnit", dataType: "text" },
  { fieldName: "Quantity", dataType: "number" },
  { fieldName: "UnitPrice", dataType: "number" }
];

const columns = [
  { name: "Country", fieldName: "Country", width: "100", header: { text: "Country" } },
  { 
    name: "CompanyName", 
    fieldName: "CompanyName", 
    width: "120", 
    header: { text: "Company Name", styleName: "orange-column" },
    headerSummary: { text: "Count: " }
  },
  { 
    name: "OrderID", 
    fieldName: "OrderID", 
    width: "80", 
    header: { text: "Order ID", styleName: "orange-column" },
    headerSummary: { expression: "count" }
  },
  { name: "CustomerID", fieldName: "CustomerID", width: "90", header: { text: "Customer ID" } },
  { 
    name: "QuantityPerUnit", 
    fieldName: "QuantityPerUnit", 
    width: "100", 
    header: { text: "Quantity / Unit", styleName: "orange-column" },
    headerSummary: { text: "Total: " }
  },
  { 
    name: "Quantity", 
    fieldName: "Quantity", 
    width: "100", 
    header: { text: "Quantity", styleName: "orange-column" },
    headerSummary: { expression: "sum", numberFormat: "#,##0" },
    footer: { expression: "sum", numberFormat: "#,##0" }
  },
  { name: "EmployeeID", fieldName: "EmployeeID", width: "90", header: { text: "Employee ID" } },
  { name: "OrderDate", fieldName: "OrderDate", width: "130", header: { text: "Order Date" } },
  { name: "Phone", fieldName: "Phone", width: "90", renderer: { type: "button" }, header: { text: "Phone" } },
  { name: "ProductName", fieldName: "ProductName", width: "200", header: { text: "Product Name" } },
  { 
    name: "UnitPrice", 
    fieldName: "UnitPrice", 
    width: "100", 
    header: { text: "Unit Price" },
    footer: { expression: "avg", numberFormat: "#,##0.00" }
  }
];

function btnShowHeaderSummary() {
  gridView.headerSummaries.visible = true;
}

function btnHideHeaderSummary() {
  gridView.headerSummaries.visible = false;
}

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: {
    height: 40
  },
  display: {
    rowHeight: 36,
    emptyMessage: "No data to display."
  },
  footer: {
    height: 40
  },
  stateBar: {
    width: 16
  },
  headerSummary: {
    height: 40
  },
  onInitialized: (grid) => {
    fetch('/data/en/editor_demoData.json')
      .then(response => response.json())
      .then(data => {
        dataProvider.setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
window.btnShowHeaderSummary = btnShowHeaderSummary;
window.btnHideHeaderSummary = btnHideHeaderSummary;
```

```js
function btnShowHeaderSummary() {
   gridView.headerSummaries.visible = true;
}

function btnHideHeaderSummary() {
   gridView.headerSummaries.visible = false;
}
```

```js
var columns = [{
     ...
}, {
   "name": "QuantityPerUnit",
   "fieldName": "QuantityPerUnit",
   "width": "100",
   "header": {
       "text": "Quantity / Unit"
   },
   "headerSummary": {
     "text": "Total: "
   }
}, {
   "name": "Quantity",
   "fieldName": "Quantity",
   "width": "100",
   "header": {
       "text": "Quantity"
   },
   "headerSummary": {
     "expression": "sum",
     "numberFormat": "#,##0"
   },
   "footer": {
       "expression": "sum",
       "numberFormat": "#,##0"
   }
}, {
     ...
}];
```

#### Dynamic calculation of Column Header Summary

If the developer wants to calculate and display the summary displayed at the top, set it to column.headerSummary.valueCallback.
The OrderID column displays the number of data rows/2, and the Quantity column displays the total of checked rows.
(Proceed by returning the value you want to display.)

```js
const fields = [
  { fieldName: "OrderID", dataType: "text" },
  { fieldName: "CustomerID", dataType: "text" },
  { fieldName: "EmployeeID", dataType: "text" },
  { fieldName: "OrderDate", dataType: "datetime", datetimeFormat: "yyyy-MM-dd", amText: "AM", pmText: "PM" },
  { fieldName: "CompanyName", dataType: "text" },
  { fieldName: "Country", dataType: "text" },
  { fieldName: "Phone", dataType: "text" },
  { fieldName: "ProductName", dataType: "text" },
  { fieldName: "QuantityPerUnit", dataType: "text" },
  { fieldName: "Quantity", dataType: "number" },
  { fieldName: "UnitPrice", dataType: "number" }
];

const columns = [
  { name: "Country", fieldName: "Country", width: "100", header: { text: "Country" } },
  { 
    name: "CompanyName", 
    fieldName: "CompanyName", 
    width: "120", 
    header: { text: "Company Name" },
    headerSummary: { text: "count / 2 = " }
  },
  { 
    name: "OrderID", 
    fieldName: "OrderID", 
    width: "80", 
    header: { text: "Order ID", styleName: "orange-column" },
    headerSummary: {
      valueCallback: function (grid, column, childIndex, summary, value) {
        return grid.getSummary("OrderID", "count") / 2;
      }
    }
  },
  { name: "CustomerID", fieldName: "CustomerID", width: "90", header: { text: "Customer ID" } },
  { 
    name: "QuantityPerUnit", 
    fieldName: "QuantityPerUnit", 
    width: "100", 
    header: { text: "Quantity / Unit" },
    headerSummary: { text: "Check Total: " }
  },
  { 
    name: "Quantity", 
    fieldName: "Quantity", 
    width: "100", 
    header: { text: "Quantity", styleName: "orange-column" },
    headerSummary: {
      numberFormat: "#,##0.#",
      valueCallback: function (grid, column, childIndex, summary, value) {
        var prod = grid.getDataSource();
        var checkedRows = grid.getCheckedRows();
        var sum = 0;
        checkedRows.forEach(function(e) {
          sum += prod.getValue(e, column.fieldName);
        });
        return sum;
      }
    },
    footer: { expression: "sum", numberFormat: "#,##0" }
  },
  { name: "EmployeeID", fieldName: "EmployeeID", width: "90", header: { text: "Employee ID" } },
  { name: "OrderDate", fieldName: "OrderDate", width: "130", header: { text: "Order Date" } },
  { name: "Phone", fieldName: "Phone", width: "90", renderer: { type: "button" }, header: { text: "Phone" } },
  { name: "ProductName", fieldName: "ProductName", width: "200", header: { text: "Product Name" } },
  { 
    name: "UnitPrice", 
    fieldName: "UnitPrice", 
    width: "100", 
    header: { text: "Unit Price" },
    footer: { expression: "avg", numberFormat: "#,##0.00" }
  }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: {
    height: 40
  },
  display: {
    rowHeight: 36,
    emptyMessage: "No data to display."
  },
  footer: {
    height: 40
  },
  stateBar: {
    width: 16
  },
  checkBar: {
    visible: true
  },
  headerSummary: {
    height: 40
  },
  headerSummaries: {
    visible: true
  },
  onInitialized: (grid) => {
    fetch('/data/en/editor_demoData.json')
      .then(response => response.json())
      .then(data => {
        dataProvider.setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

```js
var columns = [{
     ...
}, {
   "name": "OrderID",
   "fieldName": "OrderID",
   "width": "80",
   "header": {
       "text": "Order ID"
   },
   "headerSummary": {
     valueCallback: function (grid, column, childIndex, summary, value) {
       //return the value you want to display
       return grid.getSummary("OrderID", "count") / 2;
     }
   }
}, {
     ...
}, {
   "name": "Quantity",
   "fieldName": "Quantity",
   "width": "100",
   "header": {
       "text": "Quantity",
       "styleName": "orange-column"
   },
   "headerSummary": {
     "numberFormat": "#,##0.#",
     valueCallback: function (grid, column, childIndex, summary, value) {
       var prod = grid.getDataSource();
       var checkedRows = grid.getCheckedRows();
       var sum = 0;

       checkedRows.forEach(function(e) {
         sum += prod.getValue(e, column.fieldName);
       });

       return sum;
     }
   },
   "footer": {
       "expression": "sum",
       "numberFormat": "#,##0"
   }
}, {
     ...
}];
```

#### Header Summary Display multiple rows

The top summary can be displayed in multiple rows.

```js
const fields = [
  { fieldName: "OrderID", dataType: "text" },
  { fieldName: "CustomerID", dataType: "text" },
  { fieldName: "EmployeeID", dataType: "text" },
  { fieldName: "OrderDate", dataType: "datetime", datetimeFormat: "yyyy-MM-dd", amText: "AM", pmText: "PM" },
  { fieldName: "CompanyName", dataType: "text" },
  { fieldName: "Country", dataType: "text" },
  { fieldName: "Phone", dataType: "text" },
  { fieldName: "ProductName", dataType: "text" },
  { fieldName: "QuantityPerUnit", dataType: "text" },
  { fieldName: "Quantity", dataType: "number" },
  { fieldName: "UnitPrice", dataType: "number" }
];

const columns = [
  { 
    name: "Country", 
    fieldName: "Country", 
    width: "100", 
    header: { text: "Country" }
  },
  { 
    name: "CompanyName", 
    fieldName: "CompanyName", 
    width: "120", 
    header: { text: "Company Name" }
  },
  { 
    name: "QuantityPerUnit", 
    fieldName: "QuantityPerUnit", 
    width: "100", 
    header: { text: "Quantity / Unit", styleName: "orange-column" },
    summaries: [
      { text: "Total ==>  " },
      { text: "Average ==>  " }
    ]
  },
  { 
    name: "Quantity", 
    fieldName: "Quantity", 
    width: "100", 
    header: { text: "Quantity", styleName: "orange-column" },
    summaries: [
      { expression: "sum", numberFormat: "#,##0.00" },
      { expression: "avg", numberFormat: "#,##0.00" }
    ]
  },
  { name: "OrderID", fieldName: "OrderID", width: "80", header: { text: "Order ID" } },
  { name: "CustomerID", fieldName: "CustomerID", width: "90", header: { text: "Customer ID" } },
  { name: "EmployeeID", fieldName: "EmployeeID", width: "90", header: { text: "Employee ID" } },
  { name: "OrderDate", fieldName: "OrderDate", width: "130", header: { text: "Order Date" } },
  { name: "Phone", fieldName: "Phone", width: "90", renderer: { type: "button" }, header: { text: "Phone" } },
  { name: "ProductName", fieldName: "ProductName", width: "200", header: { text: "Product Name" } },
  { name: "UnitPrice", fieldName: "UnitPrice", width: "100", header: { text: "Unit Price" } }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: {
    height: 40
  },
  display: {
    rowHeight: 36,
    emptyMessage: "No data to display."
  },
  footer: {
    height: 40
  },
  stateBar: {
    width: 16
  },
  onInitialized: (grid) => {
    grid.setHeaderSummaries({
      visible: true,
      items: [
        { height: 40 },
        { height: 40 }
      ]
    });
    
    fetch('/data/en/editor_demoData.json')
      .then(response => response.json())
      .then(data => {
        dataProvider.setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

* options
  
```js
gridView.setHeaderSummaries({
   visible:true,
   items:[
     {
       //styleName: "blue-column", if individual CSS style application is required
       height: 40
     },
     {
       height: 40
     }
   ]
});
```

* columns
  
```js
var columns = [{
     ...
}, {
   "name": "QuantityPerUnit",
   "fieldName": "QuantityPerUnit",
   "width": "100",
   "header": {
       "text": "Quantity / Unit"
   },
   "summaries": [{
     "text": "Total ==> ",
   }, {
     "text": "Average ==> ",
   }]
}, {
   "name": "Quantity",
   "fieldName": "Quantity",
   "width": "100",
   "header": {
       "text": "Quantity"
   },
   "summaries": [{
     "expression": "sum",
     "numberFormat": "#,##0.00"
   }, {
     "expression": "avg",
     "numberFormat": "#,##0.00"
   }]
}, {
     ...
}];
```

#### Individual row colSpan of multiple Header Summary rows

A Header Summary consisting of multiple rows can be colSpanned for each row.
In this case, layout must be used, and the text of the colSpanned cell is set in the first column (Country column).

```js
const fields = [
  { fieldName: "OrderID", dataType: "text" },
  { fieldName: "CustomerID", dataType: "text" },
  { fieldName: "EmployeeID", dataType: "text" },
  { fieldName: "OrderDate", dataType: "datetime", datetimeFormat: "yyyy-MM-dd", amText: "AM", pmText: "PM" },
  { fieldName: "CompanyName", dataType: "text" },
  { fieldName: "Country", dataType: "text" },
  { fieldName: "Phone", dataType: "text" },
  { fieldName: "ProductName", dataType: "text" },
  { fieldName: "QuantityPerUnit", dataType: "text" },
  { fieldName: "Quantity", dataType: "number" },
  { fieldName: "UnitPrice", dataType: "number" }
];

const columns = [
  { 
    name: "Country", 
    fieldName: "Country", 
    width: "100", 
    header: { text: "Country" },
    summaries: [
      { text: "Total ==>  " },
      { text: "Average ==>  " }
    ],
    summaryUserSpans: [{ colspan: 3 }, { colspan: 3 }]
  },
  { 
    name: "CompanyName", 
    fieldName: "CompanyName", 
    width: "120", 
    header: { text: "Company Name" }
  },
  { 
    name: "QuantityPerUnit", 
    fieldName: "QuantityPerUnit", 
    width: "100", 
    header: { text: "Quantity / Unit", styleName: "orange-column" }
  },
  { 
    name: "Quantity", 
    fieldName: "Quantity", 
    width: "100", 
    header: { text: "Quantity", styleName: "orange-column" },
    summaries: [
      { expression: "sum", numberFormat: "#,##0.00" },
      { expression: "avg", numberFormat: "#,##0.00" }
    ]
  },
  { name: "OrderID", fieldName: "OrderID", width: "80", header: { text: "Order ID" } },
  { name: "CustomerID", fieldName: "CustomerID", width: "90", header: { text: "Customer ID" } },
  { name: "EmployeeID", fieldName: "EmployeeID", width: "90", header: { text: "Employee ID" } },
  { name: "OrderDate", fieldName: "OrderDate", width: "130", header: { text: "Order Date" } },
  { name: "Phone", fieldName: "Phone", width: "90", renderer: { type: "button" }, header: { text: "Phone" } },
  { name: "ProductName", fieldName: "ProductName", width: "200", header: { text: "Product Name" } }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: {
    height: 40
  },
  display: {
    rowHeight: 36,
    emptyMessage: "No data to display."
  },
  footer: {
    height: 40
  },
  stateBar: {
    width: 16
  },
  onInitialized: (grid) => {
    gridView.setHeaderSummaries({
      visible: true,
      items: [
        { height: 40 },
        { height: 40 }
      ]
    });

    const layout = [
      {
        column: "Country",
        summaryUserSpans: [{ colspan: 3 }, { colspan: 3 }]
      },
      "CompanyName",
      "QuantityPerUnit", 
      "Quantity",
      "OrderID",
      "CustomerID",
      "EmployeeID",
      "OrderDate",
      "Phone",
      "ProductName"
    ];
    
    gridView.setColumnLayout(layout);
    
    fetch('/data/en/editor_demoData.json')
      .then(response => response.json())
      .then(data => {
        dataProvider.setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

```js
gridView.setHeaderSummaries({
   visible:true,
   items:[
     {
       //styleName: "blue-column", if individual CSS style application is required
       height: 40
     },
     {
       height: 40
     }
   ]
});
```

* columns
  
```js
var columns = [{
   "name": "Country",
   "fieldName": "Country",
   "width": "100",
   "header": {
     "text": "Country"
   }
   "summaries": [{
     "text": "Total ==> ",
   }, {
     "text": "Average ==> ",
   }]
}, {
   ...
}, {
   "name": "Quantity",
   "fieldName": "Quantity",
   "width": "100",
   "header": {
       "text": "Quantity"
   },
   "summaries": [{
     "expression": "sum",
     "numberFormat": "#,##0.00"
   }, {
     "expression": "avg",
     "numberFormat": "#,##0.00"
   }]
}, {
     ...
}];
```

* layout

Method 1.
```js
gridView.layoutByColumn("Country").summaryUserSpans = [{ colspan: 3 }, { colspan: 3}];
```

Method 2.
```js
var layout1 = [
   {
     column: "Country",
     summaryUserSpans: [{ colspan: 3 }, { colspan: 3}]
   },
   "CompanyName",
   "QuantityPerUnit",
   "Quantity",
   "OrderID",
   "CustomerID",
   "EmployeeID",
   "OrderDate",
   "Phone",
   "ProductName"
];

gridView.setColumnLayout(layout1);
```

#### rowSpan, colSpan of multiple Header Summary rows

Header Summary consisting of multiple rows can be rowSpan and colSpan.
In this case, you must use a layout, and the text of the spanned cell is set in the first column (Country column).

```js
const fields = [
  { fieldName: "OrderID", dataType: "text" },
  { fieldName: "CustomerID", dataType: "text" },
  { fieldName: "EmployeeID", dataType: "text" },
  { fieldName: "OrderDate", dataType: "datetime", datetimeFormat: "yyyy-MM-dd", amText: "AM", pmText: "PM" },
  { fieldName: "CompanyName", dataType: "text" },
  { fieldName: "Country", dataType: "text" },
  { fieldName: "Phone", dataType: "text" },
  { fieldName: "ProductName", dataType: "text" },
  { fieldName: "QuantityPerUnit", dataType: "text" },
  { fieldName: "Quantity", dataType: "number" },
  { fieldName: "UnitPrice", dataType: "number" }
];

const columns = [
  { 
    name: "Country", 
    fieldName: "Country", 
    width: "100", 
    header: { text: "Country" },
    summaries: [
      { text: "Total/Average ==>" }
    ]
  },
  { 
    name: "CompanyName", 
    fieldName: "CompanyName", 
    width: "120", 
    header: { text: "Company Name" }
  },
  { 
    name: "QuantityPerUnit", 
    fieldName: "QuantityPerUnit", 
    width: "100", 
    header: { text: "Quantity / Unit", styleName: "orange-column" }
  },
  { 
    name: "Quantity", 
    fieldName: "Quantity", 
    width: "100", 
    header: { text: "Quantity", styleName: "orange-column" },
    summaries: [
      { expression: "sum", numberFormat: "#,##0.00" },
      { expression: "avg", numberFormat: "#,##0.00" }
    ]
  },
  { name: "OrderID", fieldName: "OrderID", width: "80", header: { text: "Order ID" } },
  { name: "CustomerID", fieldName: "CustomerID", width: "90", header: { text: "Customer ID" } },
  { name: "EmployeeID", fieldName: "EmployeeID", width: "90", header: { text: "Employee ID" } },
  { name: "OrderDate", fieldName: "OrderDate", width: "130", header: { text: "Order Date" } },
  { name: "Phone", fieldName: "Phone", width: "90", renderer: { type: "button" }, header: { text: "Phone" } },
  { name: "ProductName", fieldName: "ProductName", width: "200", header: { text: "Product Name" } },
  { name: "UnitPrice", fieldName: "UnitPrice", width: "100", header: { text: "Unit Price" } }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: {
    height: 40
  },
  display: {
    rowHeight: 36,
    emptyMessage: "No data to display."
  },
  footer: {
    height: 40
  },
  stateBar: {
    width: 16
  },
  onInitialized: (grid) => {
    grid.setHeaderSummaries({
      visible: true,
      items: [
        { height: 40 },
        { height: 40 }
      ]
    });

    const layout = [
      {
        column: "Country",
        summaryUserSpans: [{ rowspan: 2, colspan: 3 }]
      },
      "CompanyName",
      "QuantityPerUnit", 
      "Quantity",
      "OrderID",
      "CustomerID",
      "EmployeeID",
      "OrderDate",
      "Phone",
      "ProductName"
    ];
    
    gridView.setColumnLayout(layout);
    
    fetch('/data/en/editor_demoData.json')
      .then(response => response.json())
      .then(data => {
        dataProvider.setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

```js
gridView.setHeaderSummaries({
   visible:true,
   items:[
     {
       //styleName: "blue-column", if individual CSS style application is required
       height: 40
     },
     {
       height: 40
     }
   ]
});
```

* columns
  
```js
var columns = [{
   "name": "Country",
   "fieldName": "Country",
   "width": "100",
   "header": {
     "text": "Country"
   },
   "summaries": [{
     "text": "sum/average ==>"
   }]
}, {
   ...
}, {
   "name": "Quantity",
   "fieldName": "Quantity",
   "width": "100",
   "header": {
       "text": "Quantity"
   },
   "summaries": [{
     "expression": "sum",
     "numberFormat": "#,##0.00"
   }, {
     "expression": "avg",
     "numberFormat": "#,##0.00"
   }]
}, {
     ...
}];
```

* layout

Method 1.
```js
gridView.layoutByColumn("Country").summaryUserSpans = [{ rowspan: 2, colspan: 3 }];
```

Method 2.
```js
var layout1 = [
   {
     column: "Country",
     summaryUserSpans: [{ rowspan: 2, colspan: 3 }]
   },
   "CompanyName",
   "QuantityPerUnit",
   "Quantity",
   "OrderID",
   "CustomerID",
   "EmployeeID",
   "OrderDate",
   "Phone",
   "ProductName"
];

gridView.setColumnLayout(layout1);
```