<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-touch.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-animate.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/pdfmake.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.1.1/ui-grid.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.1.1/ui-grid.css" type="text/css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" type="text/css">
  <script src="script.js"></script>
</head>

<body ng-controller="MainCtrl">
  <h1>ui-grid</h1>
  <br />
  <br />
  <div class="grid" ui-grid="gridOptions"  ui-grid-exporter>
  </div>
</body>

</html>
var app = angular.module('plunker', ['ngAnimate', 'ngTouch', 'ui.grid', 'ui.grid.selection', 'ui.grid.exporter']);

app.controller('MainCtrl', ['$scope', 'uiGridConstants', function($scope, uiGridConstants) {

  $scope.gridOptions = {
    headerTemplate: 'header-template.html',
    enableColumnResizing: true,

    enableGridMenu: true,
    enableSelectAll: true,
    exporterPdfDefaultStyle: {
      fontSize: 9
    },
    exporterPdfTableStyle: {
      margin: [30, 30, 30, 30]
    },
    exporterPdfTableHeaderStyle: {
      fontSize: 10,
      bold: true,
      italics: true,
      color: 'red'
    },
    exporterPdfHeader: {
      text: "My Header",
      style: 'headerStyle'
    },
    exporterPdfFooter: function(currentPage, pageCount) {
      return {
        text: currentPage.toString() + ' of ' + pageCount.toString(),
        style: 'footerStyle'
      };
    },
    exporterPdfCustomFormatter: function(docDefinition) {
      docDefinition.styles.headerStyle = {
        fontSize: 22,
        bold: true
      };
      docDefinition.styles.footerStyle = {
        fontSize: 10,
        bold: true
      };
      return docDefinition;
    },
    exporterPdfOrientation: 'portrait',
    exporterPdfPageSize: 'LETTER',
    exporterPdfMaxGridWidth: 500,

    columnDefs: [{
      field: 'col1',

      displayName: 'Column 1',
      width: 175
    }, {
      field: 'col2',
      category: 'Month A',
      displayName: 'Column 2',
      width: 175
    }, {
      field: 'col3',
      category: 'Month A',
      displayName: 'Column 3',
      width: 175
    }],

    data: [{
      col1: "Hello",
      col2: "World",
      col3: "tester"
    }, {
      col1: "Hello 2",
      col2: "World",
      col3: "tester"
    }, {
      col1: "Hello 3",
      col2: "World",
      col3: "tester"
    }, {
      col1: "Hello 4",
      col2: "World",
      col3: "tester"
    }, {
      col1: "Hello 5",
      col2: "World",
      col3: "tester"
    }],
    enableRowSelection: true,
    onRegisterApi: function(gridApi) {
      $scope.gridApi = gridApi;
    }
  };


}]);

app.filter('uniqueheader', function() {
  return function(input, property) {
    var uniqueList = []
    angular.forEach(input, function(obj, key) {
      if (uniqueList.length === 0 || obj.colDef[property] === undefined) {
        uniqueList.push(obj)
      } else {
        if (obj.colDef[property] !== undefined) {
          var result = $.grep(uniqueList, function(e) {
            return e.colDef[property] === obj.colDef[property]
          })
          if (result.length === 0) {
            uniqueList.push(obj)
          }
        }
      }
    })
    return uniqueList
  }
})
/* Styles go here */

.ui-grid-cell-contents {
    padding: 5px !important;
}

.ui-grid-category {
  text-align: center;border-right: 0px;box-shadow: -1px 1px #d4d4d4;
}

.ui-grid-categorytext{
    padding-bottom: 7%;
}

.ui-grid-container{
    display: table-cell;
}
<div role="rowgroup" class="ui-grid-header">
  <div class="ui-grid-top-panel">
    <div class="ui-grid-header-viewport">
      <div class="ui-grid-header-canvas">
        <div class="ui-grid-header-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()">
          <div role="row" class="ui-grid-header-cell-row">
            <div class="ui-grid-container" ng-repeat="cat in colContainer.renderedColumns | uniqueheader:'category'">

              <div ng-if="cat.colDef.category" class="ui-grid-header-cell ui-grid-clearfix ui-grid-category" ng-repeat="col in colContainer.renderedColumns | filter:{ uid: cat.uid }">
                <div style="padding-bottom: 10px">{{cat.colDef.category}}</div>
                <hr style="height:1px; background-color:lightgrey; margin-top: 0;margin-bottom: 0;">
                <div class="ui-grid-header-cell ui-grid-clearfix" ng-repeat="col in colContainer.renderedColumns | filter:{ colDef:{category: cat.colDef.category} }" ui-grid-header-cell col="col" render-index="$index">
                </div>
              </div>
              <!--!cat.visible && -->
              <div class="ui-grid-header-cell ui-grid-clearfix" ng-if="col.colDef.category === undefined" ng-repeat="col in colContainer.renderedColumns | filter:{ uid: cat.uid }" ui-grid-header-cell col="col" render-index="$index">
              </div>

            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>