ui-grid.exporter.js 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  1. /*!
  2. * ui-grid - v4.4.6 - 2018-04-06
  3. * Copyright (c) 2018 ; License: MIT
  4. */
  5. /* global ExcelBuilder */
  6. /* global console */
  7. (function () {
  8. 'use strict';
  9. /**
  10. * @ngdoc overview
  11. * @name ui.grid.exporter
  12. * @description
  13. *
  14. * # ui.grid.exporter
  15. *
  16. * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
  17. *
  18. * This module provides the ability to export data from the grid.
  19. *
  20. * Data can be exported in a range of formats, and all data, visible
  21. * data, or selected rows can be exported, with all columns or visible
  22. * columns.
  23. *
  24. * No UI is provided, the caller should provide their own UI/buttons
  25. * as appropriate, or enable the gridMenu
  26. *
  27. * <br/>
  28. * <br/>
  29. *
  30. * <div doc-module-components="ui.grid.exporter"></div>
  31. */
  32. var module = angular.module('ui.grid.exporter', ['ui.grid']);
  33. /**
  34. * @ngdoc object
  35. * @name ui.grid.exporter.constant:uiGridExporterConstants
  36. *
  37. * @description constants available in exporter module
  38. */
  39. /**
  40. * @ngdoc property
  41. * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
  42. * @name ALL
  43. * @description export all data, including data not visible. Can
  44. * be set for either rowTypes or colTypes
  45. */
  46. /**
  47. * @ngdoc property
  48. * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
  49. * @name VISIBLE
  50. * @description export only visible data, including data not visible. Can
  51. * be set for either rowTypes or colTypes
  52. */
  53. /**
  54. * @ngdoc property
  55. * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
  56. * @name SELECTED
  57. * @description export all data, including data not visible. Can
  58. * be set only for rowTypes, selection of only some columns is
  59. * not supported
  60. */
  61. module.constant('uiGridExporterConstants', {
  62. featureName: 'exporter',
  63. ALL: 'all',
  64. VISIBLE: 'visible',
  65. SELECTED: 'selected',
  66. CSV_CONTENT: 'CSV_CONTENT',
  67. BUTTON_LABEL: 'BUTTON_LABEL',
  68. FILE_NAME: 'FILE_NAME'
  69. });
  70. /**
  71. * @ngdoc service
  72. * @name ui.grid.exporter.service:uiGridExporterService
  73. *
  74. * @description Services for exporter feature
  75. */
  76. module.service('uiGridExporterService', ['$filter', '$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',
  77. function ($filter, $q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {
  78. var service = {
  79. delay: 100,
  80. initializeGrid: function (grid) {
  81. //add feature namespace and any properties to grid for needed state
  82. grid.exporter = {};
  83. this.defaultGridOptions(grid.options);
  84. /**
  85. * @ngdoc object
  86. * @name ui.grid.exporter.api:PublicApi
  87. *
  88. * @description Public Api for exporter feature
  89. */
  90. var publicApi = {
  91. events: {
  92. exporter: {
  93. }
  94. },
  95. methods: {
  96. exporter: {
  97. /**
  98. * @ngdoc function
  99. * @name csvExport
  100. * @methodOf ui.grid.exporter.api:PublicApi
  101. * @description Exports rows from the grid in csv format,
  102. * the data exported is selected based on the provided options
  103. * @param {string} rowTypes which rows to export, valid values are
  104. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  105. * uiGridExporterConstants.SELECTED
  106. * @param {string} colTypes which columns to export, valid values are
  107. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
  108. */
  109. csvExport: function (rowTypes, colTypes) {
  110. service.csvExport(grid, rowTypes, colTypes);
  111. },
  112. /**
  113. * @ngdoc function
  114. * @name pdfExport
  115. * @methodOf ui.grid.exporter.api:PublicApi
  116. * @description Exports rows from the grid in pdf format,
  117. * the data exported is selected based on the provided options
  118. * Note that this function has a dependency on pdfMake, all
  119. * going well this has been installed for you.
  120. * The resulting pdf opens in a new browser window.
  121. * @param {string} rowTypes which rows to export, valid values are
  122. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  123. * uiGridExporterConstants.SELECTED
  124. * @param {string} colTypes which columns to export, valid values are
  125. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
  126. */
  127. pdfExport: function (rowTypes, colTypes) {
  128. service.pdfExport(grid, rowTypes, colTypes);
  129. },
  130. /**
  131. * @ngdoc function
  132. * @name excelExport
  133. * @methodOf ui.grid.exporter.api:PublicApi
  134. * @description Exports rows from the grid in excel format,
  135. * the data exported is selected based on the provided options
  136. * @param {string} rowTypes which rows to export, valid values are
  137. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  138. * uiGridExporterConstants.SELECTED
  139. * @param {string} colTypes which columns to export, valid values are
  140. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
  141. */
  142. excelExport: function (rowTypes, colTypes) {
  143. service.excelExport(grid, rowTypes, colTypes);
  144. }
  145. }
  146. }
  147. };
  148. grid.api.registerEventsFromObject(publicApi.events);
  149. grid.api.registerMethodsFromObject(publicApi.methods);
  150. if (grid.api.core.addToGridMenu){
  151. service.addToMenu( grid );
  152. } else {
  153. // order of registration is not guaranteed, register in a little while
  154. $interval( function() {
  155. if (grid.api.core.addToGridMenu){
  156. service.addToMenu( grid );
  157. }
  158. }, this.delay, 1);
  159. }
  160. },
  161. defaultGridOptions: function (gridOptions) {
  162. //default option to true unless it was explicitly set to false
  163. /**
  164. * @ngdoc object
  165. * @name ui.grid.exporter.api:GridOptions
  166. *
  167. * @description GridOptions for exporter feature, these are available to be
  168. * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
  169. */
  170. /**
  171. * @ngdoc object
  172. * @name ui.grid.exporter.api:ColumnDef
  173. * @description ColumnDef settings for exporter
  174. */
  175. /**
  176. * @ngdoc object
  177. * @name exporterSuppressMenu
  178. * @propertyOf ui.grid.exporter.api:GridOptions
  179. * @description Don't show the export menu button, implying the user
  180. * will roll their own UI for calling the exporter
  181. * <br/>Defaults to false
  182. */
  183. gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;
  184. /**
  185. * @ngdoc object
  186. * @name exporterMenuLabel
  187. * @propertyOf ui.grid.exporter.api:GridOptions
  188. * @description The text to show on the exporter menu button
  189. * link
  190. * <br/>Defaults to 'Export'
  191. */
  192. gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';
  193. /**
  194. * @ngdoc object
  195. * @name exporterSuppressColumns
  196. * @propertyOf ui.grid.exporter.api:GridOptions
  197. * @description Columns that should not be exported. The selectionRowHeader is already automatically
  198. * suppressed, but if you had a button column or some other "system" column that shouldn't be shown in the
  199. * output then add it in this list. You should provide an array of column names.
  200. * <br/>Defaults to: []
  201. * <pre>
  202. * gridOptions.exporterSuppressColumns = [ 'buttons' ];
  203. * </pre>
  204. */
  205. gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];
  206. /**
  207. * @ngdoc object
  208. * @name exporterCsvColumnSeparator
  209. * @propertyOf ui.grid.exporter.api:GridOptions
  210. * @description The character to use as column separator
  211. * link
  212. * <br/>Defaults to ','
  213. */
  214. gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';
  215. /**
  216. * @ngdoc object
  217. * @name exporterCsvFilename
  218. * @propertyOf ui.grid.exporter.api:GridOptions
  219. * @description The default filename to use when saving the downloaded csv.
  220. * This will only work in some browsers.
  221. * <br/>Defaults to 'download.csv'
  222. */
  223. gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';
  224. /**
  225. * @ngdoc object
  226. * @name exporterPdfFilename
  227. * @propertyOf ui.grid.exporter.api:GridOptions
  228. * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)
  229. * <br/>Defaults to 'download.pdf'
  230. */
  231. gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';
  232. /**
  233. * @ngdoc object
  234. * @name exporterOlderExcelCompatibility
  235. * @propertyOf ui.grid.exporter.api:GridOptions
  236. * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes
  237. * through as  in the first column header. Setting this option to false will suppress this, at the
  238. * expense of proper utf-16 handling in applications that do recognise the BOM
  239. * <br/>Defaults to false
  240. */
  241. gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;
  242. /**
  243. * @ngdoc object
  244. * @name exporterIsExcelCompatible
  245. * @propertyOf ui.grid.exporter.api:GridOptions
  246. * @description Separator header, used to set a custom column separator in a csv file, only works on MS Excel.
  247. * Used it on other programs will make csv content display unproperly. Setting this option to false won't add this header.
  248. * <br/>Defaults to false
  249. */
  250. gridOptions.exporterIsExcelCompatible = gridOptions.exporterIsExcelCompatible === true;
  251. /**
  252. * @ngdoc object
  253. * @name exporterMenuItemOrder
  254. * @propertyOf ui.grid.exporter.api:GridOptions
  255. * @description An option to determine the starting point for the menu items created by the exporter
  256. * <br/>Defaults to 200
  257. */
  258. gridOptions.exporterMenuItemOrder = gridOptions.exporterMenuItemOrder ? gridOptions.exporterMenuItemOrder : 200;
  259. /**
  260. * @ngdoc object
  261. * @name exporterPdfDefaultStyle
  262. * @propertyOf ui.grid.exporter.api:GridOptions
  263. * @description The default style in pdfMake format
  264. * <br/>Defaults to:
  265. * <pre>
  266. * {
  267. * fontSize: 11
  268. * }
  269. * </pre>
  270. */
  271. gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };
  272. /**
  273. * @ngdoc object
  274. * @name exporterPdfTableStyle
  275. * @propertyOf ui.grid.exporter.api:GridOptions
  276. * @description The table style in pdfMake format
  277. * <br/>Defaults to:
  278. * <pre>
  279. * {
  280. * margin: [0, 5, 0, 15]
  281. * }
  282. * </pre>
  283. */
  284. gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };
  285. /**
  286. * @ngdoc object
  287. * @name exporterPdfTableHeaderStyle
  288. * @propertyOf ui.grid.exporter.api:GridOptions
  289. * @description The tableHeader style in pdfMake format
  290. * <br/>Defaults to:
  291. * <pre>
  292. * {
  293. * bold: true,
  294. * fontSize: 12,
  295. * color: 'black'
  296. * }
  297. * </pre>
  298. */
  299. gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };
  300. /**
  301. * @ngdoc object
  302. * @name exporterPdfHeader
  303. * @propertyOf ui.grid.exporter.api:GridOptions
  304. * @description The header section for pdf exports. Can be
  305. * simple text:
  306. * <pre>
  307. * gridOptions.exporterPdfHeader = 'My Header';
  308. * </pre>
  309. * Can be a more complex object in pdfMake format:
  310. * <pre>
  311. * gridOptions.exporterPdfHeader = {
  312. * columns: [
  313. * 'Left part',
  314. * { text: 'Right part', alignment: 'right' }
  315. * ]
  316. * };
  317. * </pre>
  318. * Or can be a function, allowing page numbers and the like
  319. * <pre>
  320. * gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
  321. * </pre>
  322. */
  323. gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;
  324. /**
  325. * @ngdoc object
  326. * @name exporterPdfFooter
  327. * @propertyOf ui.grid.exporter.api:GridOptions
  328. * @description The header section for pdf exports. Can be
  329. * simple text:
  330. * <pre>
  331. * gridOptions.exporterPdfFooter = 'My Footer';
  332. * </pre>
  333. * Can be a more complex object in pdfMake format:
  334. * <pre>
  335. * gridOptions.exporterPdfFooter = {
  336. * columns: [
  337. * 'Left part',
  338. * { text: 'Right part', alignment: 'right' }
  339. * ]
  340. * };
  341. * </pre>
  342. * Or can be a function, allowing page numbers and the like
  343. * <pre>
  344. * gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
  345. * </pre>
  346. */
  347. gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;
  348. /**
  349. * @ngdoc object
  350. * @name exporterPdfOrientation
  351. * @propertyOf ui.grid.exporter.api:GridOptions
  352. * @description The orientation, should be a valid pdfMake value,
  353. * 'landscape' or 'portrait'
  354. * <br/>Defaults to landscape
  355. */
  356. gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';
  357. /**
  358. * @ngdoc object
  359. * @name exporterPdfPageSize
  360. * @propertyOf ui.grid.exporter.api:GridOptions
  361. * @description The orientation, should be a valid pdfMake
  362. * paper size, usually 'A4' or 'LETTER'
  363. * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}
  364. * <br/>Defaults to A4
  365. */
  366. gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';
  367. /**
  368. * @ngdoc object
  369. * @name exporterPdfMaxGridWidth
  370. * @propertyOf ui.grid.exporter.api:GridOptions
  371. * @description The maxium grid width - the current grid width
  372. * will be scaled to match this, with any fixed width columns
  373. * being adjusted accordingly.
  374. * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER
  375. */
  376. gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;
  377. /**
  378. * @ngdoc object
  379. * @name exporterPdfTableLayout
  380. * @propertyOf ui.grid.exporter.api:GridOptions
  381. * @description A tableLayout in pdfMake format,
  382. * controls gridlines and the like. We use the default
  383. * layout usually.
  384. * <br/>Defaults to null, which means no layout
  385. */
  386. /**
  387. * @ngdoc object
  388. * @name exporterMenuAllData
  389. * @porpertyOf ui.grid.exporter.api:GridOptions
  390. * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
  391. */
  392. gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;
  393. /**
  394. * @ngdoc object
  395. * @name exporterMenuVisibleData
  396. * @porpertyOf ui.grid.exporter.api:GridOptions
  397. * @description Add export visible data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
  398. */
  399. gridOptions.exporterMenuVisibleData = gridOptions.exporterMenuVisibleData !== undefined ? gridOptions.exporterMenuVisibleData : true;
  400. /**
  401. * @ngdoc object
  402. * @name exporterMenuSelectedData
  403. * @porpertyOf ui.grid.exporter.api:GridOptions
  404. * @description Add export selected data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
  405. */
  406. gridOptions.exporterMenuSelectedData = gridOptions.exporterMenuSelectedData !== undefined ? gridOptions.exporterMenuSelectedData : true;
  407. /**
  408. * @ngdoc object
  409. * @name exporterMenuCsv
  410. * @propertyOf ui.grid.exporter.api:GridOptions
  411. * @description Add csv export menu items to the ui-grid grid menu, if it's present. Defaults to true.
  412. */
  413. gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;
  414. /**
  415. * @ngdoc object
  416. * @name exporterMenuPdf
  417. * @propertyOf ui.grid.exporter.api:GridOptions
  418. * @description Add pdf export menu items to the ui-grid grid menu, if it's present. Defaults to true.
  419. */
  420. gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;
  421. /**
  422. * @ngdoc object
  423. * @name exporterMenuExcel
  424. * @propertyOf ui.grid.exporter.api:GridOptions
  425. * @description Add excel export menu items to the ui-grid grid menu, if it's present. Defaults to true.
  426. */
  427. gridOptions.exporterMenuExcel = gridOptions.exporterMenuExcel !== undefined ? gridOptions.exporterMenuExcel : true;
  428. /**
  429. * @ngdoc object
  430. * @name exporterPdfCustomFormatter
  431. * @propertyOf ui.grid.exporter.api:GridOptions
  432. * @description A custom callback routine that changes the pdf document, adding any
  433. * custom styling or content that is supported by pdfMake. Takes in the complete docDefinition, and
  434. * must return an updated docDefinition ready for pdfMake.
  435. * @example
  436. * In this example we add a style to the style array, so that we can use it in our
  437. * footer definition.
  438. * <pre>
  439. * gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {
  440. * docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };
  441. * return docDefinition;
  442. * }
  443. *
  444. * gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }
  445. * </pre>
  446. */
  447. gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };
  448. /**
  449. * @ngdoc object
  450. * @name exporterHeaderFilterUseName
  451. * @propertyOf ui.grid.exporter.api:GridOptions
  452. * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.
  453. * If set to true, then will pass `name` instead.
  454. *
  455. *
  456. * @example
  457. * <pre>
  458. * gridOptions.exporterHeaderFilterUseName = true;
  459. * </pre>
  460. */
  461. gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;
  462. /**
  463. * @ngdoc object
  464. * @name exporterHeaderFilter
  465. * @propertyOf ui.grid.exporter.api:GridOptions
  466. * @description A function to apply to the header displayNames before exporting. Useful for internationalisation,
  467. * for example if you were using angular-translate you'd set this to `$translate.instant`. Note that this
  468. * call must be synchronous, it cannot be a call that returns a promise.
  469. *
  470. * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.
  471. *
  472. * @example
  473. * <pre>
  474. * gridOptions.exporterHeaderFilter = function( displayName ){ return 'col: ' + name; };
  475. * </pre>
  476. * OR
  477. * <pre>
  478. * gridOptions.exporterHeaderFilter = $translate.instant;
  479. * </pre>
  480. */
  481. /**
  482. * @ngdoc function
  483. * @name exporterFieldCallback
  484. * @propertyOf ui.grid.exporter.api:GridOptions
  485. * @description A function to call for each field before exporting it. Allows
  486. * massaging of raw data into a display format, for example if you have applied
  487. * filters to convert codes into decodes, or you require
  488. * a specific date format in the exported content.
  489. *
  490. * The method is called once for each field exported, and provides the grid, the
  491. * gridCol and the GridRow for you to use as context in massaging the data.
  492. *
  493. * @param {Grid} grid provides the grid in case you have need of it
  494. * @param {GridRow} row the row from which the data comes
  495. * @param {GridColumn} col the column from which the data comes
  496. * @param {object} value the value for your massaging
  497. * @returns {object} you must return the massaged value ready for exporting
  498. *
  499. * @example
  500. * <pre>
  501. * gridOptions.exporterFieldCallback = function ( grid, row, col, value ){
  502. * if ( col.name === 'status' ){
  503. * value = decodeStatus( value );
  504. * }
  505. * return value;
  506. * }
  507. * </pre>
  508. */
  509. gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : defaultExporterFieldCallback;
  510. /**
  511. * @ngdoc function
  512. * @name exporterFieldFormatCallback
  513. * @propertyOf ui.grid.exporter.api:GridOptions
  514. * @description A function to call for each field before exporting it. Allows
  515. * general object to be return to modify the format of a cell in the case of
  516. * excel exports
  517. *
  518. * The method is called once for each field exported, and provides the grid, the
  519. * gridCol and the GridRow for you to use as context in massaging the data.
  520. *
  521. * @param {Grid} grid provides the grid in case you have need of it
  522. * @param {GridRow} row the row from which the data comes
  523. * @param {GridColumn} col the column from which the data comes
  524. * @param {object} value the value for your massaging
  525. * @returns {object} you must return the massaged value ready for exporting
  526. *
  527. * @example
  528. * <pre>
  529. * gridOptions.exporterFieldCallback = function ( grid, row, col, value ){
  530. * if ( col.name === 'status' ){
  531. * value = decodeStatus( value );
  532. * }
  533. * return value;
  534. * }
  535. * </pre>
  536. */
  537. gridOptions.exporterFieldFormatCallback = gridOptions.exporterFieldFormatCallback ? gridOptions.exporterFieldFormatCallback : function( grid, row, col, value ) { return null; };
  538. /**
  539. * @ngdoc object
  540. * @name exporterFieldApplyFilters
  541. * @propertyOf ui.grid.exporter.api:GridOptions
  542. * @description Defaults to false, which leads to filters being evaluated on export *
  543. *
  544. * @example
  545. * <pre>
  546. * gridOptions.exporterFieldApplyFilters = true;
  547. * </pre>
  548. */
  549. gridOptions.exporterFieldApplyFilters = gridOptions.exporterFieldApplyFilters === true;
  550. /**
  551. * @ngdoc function
  552. * @name exporterAllDataFn
  553. * @propertyOf ui.grid.exporter.api:GridOptions
  554. * @description This promise is needed when exporting all rows,
  555. * and the data need to be provided by server side. Default is null.
  556. * @returns {Promise} a promise to load all data from server
  557. *
  558. * @example
  559. * <pre>
  560. * gridOptions.exporterAllDataFn = function () {
  561. * return $http.get('/data/100.json')
  562. * }
  563. * </pre>
  564. */
  565. gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;
  566. /**
  567. * @ngdoc function
  568. * @name exporterAllDataPromise
  569. * @propertyOf ui.grid.exporter.api:GridOptions
  570. * @description DEPRECATED - exporterAllDataFn used to be
  571. * called this, but it wasn't a promise, it was a function that returned
  572. * a promise. Deprecated, but supported for backward compatibility, use
  573. * exporterAllDataFn instead.
  574. * @returns {Promise} a promise to load all data from server
  575. *
  576. * @example
  577. * <pre>
  578. * gridOptions.exporterAllDataFn = function () {
  579. * return $http.get('/data/100.json')
  580. * }
  581. * </pre>
  582. */
  583. if ( gridOptions.exporterAllDataFn === null && gridOptions.exporterAllDataPromise ) {
  584. gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;
  585. }
  586. },
  587. /**
  588. * @ngdoc function
  589. * @name addToMenu
  590. * @methodOf ui.grid.exporter.service:uiGridExporterService
  591. * @description Adds export items to the grid menu,
  592. * allowing the user to select export options
  593. * @param {Grid} grid the grid from which data should be exported
  594. */
  595. addToMenu: function ( grid ) {
  596. grid.api.core.addToGridMenu( grid, [
  597. {
  598. title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),
  599. action: function ($event) {
  600. grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
  601. },
  602. shown: function() {
  603. return grid.options.exporterMenuCsv && grid.options.exporterMenuAllData;
  604. },
  605. order: grid.options.exporterMenuItemOrder
  606. },
  607. {
  608. title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),
  609. action: function ($event) {
  610. grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
  611. },
  612. shown: function() {
  613. return grid.options.exporterMenuCsv && grid.options.exporterMenuVisibleData;
  614. },
  615. order: grid.options.exporterMenuItemOrder + 1
  616. },
  617. {
  618. title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),
  619. action: function ($event) {
  620. grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
  621. },
  622. shown: function() {
  623. return grid.options.exporterMenuCsv && grid.options.exporterMenuSelectedData &&
  624. ( grid.api.selection && grid.api.selection.getSelectedRows().length > 0 );
  625. },
  626. order: grid.options.exporterMenuItemOrder + 2
  627. },
  628. {
  629. title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),
  630. action: function ($event) {
  631. grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
  632. },
  633. shown: function() {
  634. return grid.options.exporterMenuPdf && grid.options.exporterMenuAllData;
  635. },
  636. order: grid.options.exporterMenuItemOrder + 3
  637. },
  638. {
  639. title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),
  640. action: function ($event) {
  641. grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
  642. },
  643. shown: function() {
  644. return grid.options.exporterMenuPdf && grid.options.exporterMenuVisibleData;
  645. },
  646. order: grid.options.exporterMenuItemOrder + 4
  647. },
  648. {
  649. title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),
  650. action: function ($event) {
  651. grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
  652. },
  653. shown: function() {
  654. return grid.options.exporterMenuPdf && grid.options.exporterMenuSelectedData &&
  655. ( grid.api.selection && grid.api.selection.getSelectedRows().length > 0 );
  656. },
  657. order: grid.options.exporterMenuItemOrder + 5
  658. },
  659. {
  660. title: i18nService.getSafeText('gridMenu.exporterAllAsExcel'),
  661. action: function ($event) {
  662. grid.api.exporter.excelExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
  663. },
  664. shown: function() {
  665. return grid.options.exporterMenuExcel && grid.options.exporterMenuAllData;
  666. },
  667. order: grid.options.exporterMenuItemOrder + 6
  668. },
  669. {
  670. title: i18nService.getSafeText('gridMenu.exporterVisibleAsExcel'),
  671. action: function ($event) {
  672. grid.api.exporter.excelExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
  673. },
  674. shown: function() {
  675. return grid.options.exporterMenuExcel && grid.options.exporterMenuVisibleData;
  676. },
  677. order: grid.options.exporterMenuItemOrder + 7
  678. },
  679. {
  680. title: i18nService.getSafeText('gridMenu.exporterSelectedAsExcel'),
  681. action: function ($event) {
  682. grid.api.exporter.excelExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
  683. },
  684. shown: function() {
  685. return grid.options.exporterMenuExcel && grid.options.exporterMenuSelectedData &&
  686. ( grid.api.selection && grid.api.selection.getSelectedRows().length > 0 );
  687. },
  688. order: grid.options.exporterMenuItemOrder + 8
  689. }
  690. ]);
  691. },
  692. /**
  693. * @ngdoc function
  694. * @name csvExport
  695. * @methodOf ui.grid.exporter.service:uiGridExporterService
  696. * @description Exports rows from the grid in csv format,
  697. * the data exported is selected based on the provided options
  698. * @param {Grid} grid the grid from which data should be exported
  699. * @param {string} rowTypes which rows to export, valid values are
  700. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  701. * uiGridExporterConstants.SELECTED
  702. * @param {string} colTypes which columns to export, valid values are
  703. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  704. * uiGridExporterConstants.SELECTED
  705. */
  706. csvExport: function (grid, rowTypes, colTypes) {
  707. var self = this;
  708. this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
  709. var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
  710. var exportData = self.getData(grid, rowTypes, colTypes);
  711. var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);
  712. self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterCsvColumnSeparator, grid.options.exporterOlderExcelCompatibility, grid.options.exporterIsExcelCompatible);
  713. });
  714. },
  715. /**
  716. * @ngdoc function
  717. * @name loadAllDataIfNeeded
  718. * @methodOf ui.grid.exporter.service:uiGridExporterService
  719. * @description When using server side pagination, use exporterAllDataFn to
  720. * load all data before continuing processing.
  721. * When using client side pagination, return a resolved promise so processing
  722. * continues immediately
  723. * @param {Grid} grid the grid from which data should be exported
  724. * @param {string} rowTypes which rows to export, valid values are
  725. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  726. * uiGridExporterConstants.SELECTED
  727. * @param {string} colTypes which columns to export, valid values are
  728. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  729. * uiGridExporterConstants.SELECTED
  730. */
  731. loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {
  732. if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {
  733. return grid.options.exporterAllDataFn()
  734. .then(function(allData) {
  735. grid.modifyRows(allData);
  736. });
  737. } else {
  738. var deferred = $q.defer();
  739. deferred.resolve();
  740. return deferred.promise;
  741. }
  742. },
  743. /**
  744. * @ngdoc property
  745. * @propertyOf ui.grid.exporter.api:ColumnDef
  746. * @name exporterSuppressExport
  747. * @description Suppresses export for this column. Used by selection and expandable.
  748. */
  749. /**
  750. * @ngdoc function
  751. * @name getColumnHeaders
  752. * @methodOf ui.grid.exporter.service:uiGridExporterService
  753. * @description Gets the column headers from the grid to use
  754. * as a title row for the exported file, all headers have
  755. * headerCellFilters applied as appropriate.
  756. *
  757. * Column headers are an array of objects, each object has
  758. * name, displayName, width and align attributes. Only name is
  759. * used for csv, all attributes are used for pdf.
  760. *
  761. * @param {Grid} grid the grid from which data should be exported
  762. * @param {string} colTypes which columns to export, valid values are
  763. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  764. * uiGridExporterConstants.SELECTED
  765. */
  766. getColumnHeaders: function (grid, colTypes) {
  767. var headers = [];
  768. var columns;
  769. if ( colTypes === uiGridExporterConstants.ALL ){
  770. columns = grid.columns;
  771. } else {
  772. var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
  773. var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
  774. var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
  775. columns = leftColumns.concat(bodyColumns,rightColumns);
  776. }
  777. columns.forEach( function( gridCol ) {
  778. // $$hashKey check since when grouping and sorting pragmatically this ends up in export. Filtering it out
  779. if ( gridCol.colDef.exporterSuppressExport !== true && gridCol.field !== '$$hashKey' &&
  780. grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
  781. var headerEntry = {
  782. name: gridCol.field,
  783. displayName: getDisplayName(grid, gridCol),
  784. width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,
  785. align: gridCol.colDef.align ? gridCol.colDef.align : (gridCol.colDef.type === 'number' ? 'right' : 'left')
  786. };
  787. headers.push(headerEntry);
  788. }
  789. });
  790. return headers;
  791. },
  792. /**
  793. * @ngdoc property
  794. * @propertyOf ui.grid.exporter.api:ColumnDef
  795. * @name exporterPdfAlign
  796. * @description the alignment you'd like for this specific column when
  797. * exported into a pdf. Can be 'left', 'right', 'center' or any other
  798. * valid pdfMake alignment option.
  799. */
  800. /**
  801. * @ngdoc object
  802. * @name ui.grid.exporter.api:GridRow
  803. * @description GridRow settings for exporter
  804. */
  805. /**
  806. * @ngdoc object
  807. * @name exporterEnableExporting
  808. * @propertyOf ui.grid.exporter.api:GridRow
  809. * @description If set to false, then don't export this row, notwithstanding visible or
  810. * other settings
  811. * <br/>Defaults to true
  812. */
  813. /**
  814. * @ngdoc function
  815. * @name getRowsFromNode
  816. * @methodOf ui.grid.exporter.service:uiGridExporterService
  817. * @description Gets rows from a node. If the node is grouped it will
  818. * recurse down into the children to get to the raw data element
  819. * which is a row without children (a leaf).
  820. * @param {Node} aNode the tree node on the grid
  821. * @returns {Array} an array of leaf nodes
  822. */
  823. getRowsFromNode: function(aNode) {
  824. var rows = [];
  825. for (var i = 0; i<aNode.children.length; i++) {
  826. if (aNode.children[i].children && aNode.children[i].children.length === 0) {
  827. rows.push(aNode.children[i]);
  828. } else {
  829. var nodeRows = this.getRowsFromNode(aNode.children[i]);
  830. rows = rows.concat(nodeRows);
  831. }
  832. }
  833. return rows;
  834. },
  835. /**
  836. * @ngdoc function
  837. * @name getDataSorted
  838. * @methodOf ui.grid.exporter.service:uiGridExporterService
  839. * @description Gets rows from a node. If the node is grouped it will
  840. * recurse down into the children to get to the raw data element
  841. * which is a row without children (a leaf). If the grid is not
  842. * grouped this will return just the raw rows
  843. * @param {Grid} grid the grid from which data should be exported
  844. * @param {string} rowTypes which rows to export, valid values are
  845. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  846. * uiGridExporterConstants.SELECTED
  847. * @param {string} colTypes which columns to export, valid values are
  848. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  849. * uiGridExporterConstants.SELECTED
  850. * @param {boolean} applyCellFilters whether or not to get the display value or the raw value of the data
  851. * @returns {Array} an array of leaf nodes
  852. */
  853. getDataSorted: function (grid, rowTypes, colTypes, applyCellFilters) {
  854. if (!grid.treeBase || grid.treeBase.numberLevels === 0) {
  855. return grid.rows;
  856. }
  857. var rows = [];
  858. for (var i = 0; i< grid.treeBase.tree.length; i++) {
  859. var nodeRows = this.getRowsFromNode(grid.treeBase.tree[i]);
  860. for (var j = 0; j<nodeRows.length; j++) {
  861. rows.push(nodeRows[j].row);
  862. }
  863. }
  864. return rows;
  865. },
  866. /**
  867. * @ngdoc function
  868. * @name getData
  869. * @methodOf ui.grid.exporter.service:uiGridExporterService
  870. * @description Gets data from the grid based on the provided options,
  871. * all cells have cellFilters applied as appropriate. Any rows marked
  872. * `exporterEnableExporting: false` will not be exported
  873. * @param {Grid} grid the grid from which data should be exported
  874. * @param {string} rowTypes which rows to export, valid values are
  875. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  876. * uiGridExporterConstants.SELECTED
  877. * @param {string} colTypes which columns to export, valid values are
  878. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  879. * uiGridExporterConstants.SELECTED
  880. * @param {boolean} applyCellFilters whether or not to get the display value or the raw value of the data
  881. */
  882. getData: function (grid, rowTypes, colTypes, applyCellFilters) {
  883. var data = [];
  884. var rows;
  885. var columns;
  886. switch ( rowTypes ) {
  887. case uiGridExporterConstants.ALL:
  888. rows = this.getDataSorted(grid, rowTypes, colTypes, applyCellFilters);
  889. break;
  890. case uiGridExporterConstants.VISIBLE:
  891. rows = grid.getVisibleRows();
  892. break;
  893. case uiGridExporterConstants.SELECTED:
  894. if ( grid.api.selection ){
  895. rows = grid.api.selection.getSelectedGridRows();
  896. } else {
  897. gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');
  898. }
  899. break;
  900. }
  901. if ( colTypes === uiGridExporterConstants.ALL ){
  902. columns = grid.columns;
  903. } else {
  904. var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
  905. var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
  906. var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ){ return column.visible; } ) : [];
  907. columns = leftColumns.concat(bodyColumns,rightColumns);
  908. }
  909. rows.forEach( function( row, index ) {
  910. if (row.exporterEnableExporting !== false) {
  911. var extractedRow = [];
  912. columns.forEach( function( gridCol, index ) {
  913. // $$hashKey check since when grouping and sorting programmatically this ends up in export. Filtering it out
  914. if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&
  915. gridCol.colDef.exporterSuppressExport !== true && gridCol.field !== '$$hashKey' &&
  916. grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ){
  917. var cellValue = applyCellFilters ? grid.getCellDisplayValue( row, gridCol ) : grid.getCellValue( row, gridCol );
  918. var extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, cellValue ) };
  919. var extension = grid.options.exporterFieldFormatCallback( grid, row, gridCol, cellValue );
  920. if (extension) {
  921. Object.assign(extractedField, extension);
  922. }
  923. if ( gridCol.colDef.exporterPdfAlign ) {
  924. extractedField.alignment = gridCol.colDef.exporterPdfAlign;
  925. }
  926. extractedRow.push(extractedField);
  927. }
  928. });
  929. data.push(extractedRow);
  930. }
  931. });
  932. return data;
  933. },
  934. /**
  935. * @ngdoc function
  936. * @name formatAsCsv
  937. * @methodOf ui.grid.exporter.service:uiGridExporterService
  938. * @description Formats the column headers and data as a CSV,
  939. * and sends that data to the user
  940. * @param {array} exportColumnHeaders an array of column headers,
  941. * where each header is an object with name, width and maybe alignment
  942. * @param {array} exportData an array of rows, where each row is
  943. * an array of column data
  944. * @param {string} separator a string that represents the separator to be used in the csv file
  945. * @returns {string} csv the formatted csv as a string
  946. */
  947. formatAsCsv: function (exportColumnHeaders, exportData, separator) {
  948. var self = this;
  949. var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});
  950. var csv = bareHeaders.length > 0 ? (self.formatRowAsCsv(this, separator)(bareHeaders) + '\n') : '';
  951. csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\n');
  952. return csv;
  953. },
  954. /**
  955. * @ngdoc function
  956. * @name formatRowAsCsv
  957. * @methodOf ui.grid.exporter.service:uiGridExporterService
  958. * @description Renders a single field as a csv field, including
  959. * quotes around the value
  960. * @param {exporterService} exporter pass in exporter
  961. * @param {array} row the row to be turned into a csv string
  962. * @returns {string} a csv-ified version of the row
  963. */
  964. formatRowAsCsv: function (exporter, separator) {
  965. return function (row) {
  966. return row.map(exporter.formatFieldAsCsv).join(separator);
  967. };
  968. },
  969. /**
  970. * @ngdoc function
  971. * @name formatFieldAsCsv
  972. * @methodOf ui.grid.exporter.service:uiGridExporterService
  973. * @description Renders a single field as a csv field, including
  974. * quotes around the value
  975. * @param {field} field the field to be turned into a csv string,
  976. * may be of any type
  977. * @returns {string} a csv-ified version of the field
  978. */
  979. formatFieldAsCsv: function (field) {
  980. if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
  981. return '';
  982. }
  983. if (typeof(field.value) === 'number') {
  984. return field.value;
  985. }
  986. if (typeof(field.value) === 'boolean') {
  987. return (field.value ? 'TRUE' : 'FALSE') ;
  988. }
  989. if (typeof(field.value) === 'string') {
  990. return '"' + field.value.replace(/"/g,'""') + '"';
  991. }
  992. return JSON.stringify(field.value);
  993. },
  994. /**
  995. * @ngdoc function
  996. * @name isIE
  997. * @methodOf ui.grid.exporter.service:uiGridExporterService
  998. * @description Checks whether current browser is IE and returns it's version if it is
  999. */
  1000. isIE: function () {
  1001. var match = navigator.userAgent.search(/(?:Edge|MSIE|Trident\/.*; rv:)/);
  1002. var isIE = false;
  1003. if (match !== -1) {
  1004. isIE = true;
  1005. }
  1006. return isIE;
  1007. },
  1008. /**
  1009. * @ngdoc function
  1010. * @name downloadFile
  1011. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1012. * @description Triggers download of a csv file. Logic provided
  1013. * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391
  1014. * @param {string} fileName the filename we'd like our file to be
  1015. * given
  1016. * @param {string} csvContent the csv content that we'd like to
  1017. * download as a file
  1018. * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\uFEFF)
  1019. * @param {boolean} exporterIsExcelCompatible whether or not we add separator header ('sep=X')
  1020. */
  1021. downloadFile: function (fileName, csvContent, columnSeparator, exporterOlderExcelCompatibility, exporterIsExcelCompatible) {
  1022. var D = document;
  1023. var a = D.createElement('a');
  1024. var strMimeType = 'application/octet-stream;charset=utf-8';
  1025. var rawFile;
  1026. var ieVersion = this.isIE();
  1027. if (exporterIsExcelCompatible) {
  1028. csvContent = 'sep=' + columnSeparator + '\r\n' + csvContent;
  1029. }
  1030. // IE10+
  1031. if (navigator.msSaveBlob) {
  1032. return navigator.msSaveOrOpenBlob(
  1033. new Blob(
  1034. [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
  1035. { type: strMimeType } ),
  1036. fileName
  1037. );
  1038. }
  1039. if (ieVersion) {
  1040. var frame = D.createElement('iframe');
  1041. document.body.appendChild(frame);
  1042. frame.contentWindow.document.open('text/html', 'replace');
  1043. frame.contentWindow.document.write(csvContent);
  1044. frame.contentWindow.document.close();
  1045. frame.contentWindow.focus();
  1046. frame.contentWindow.document.execCommand('SaveAs', true, fileName);
  1047. document.body.removeChild(frame);
  1048. return true;
  1049. }
  1050. //html5 A[download]
  1051. if ('download' in a) {
  1052. var blob = new Blob(
  1053. [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
  1054. { type: strMimeType }
  1055. );
  1056. rawFile = URL.createObjectURL(blob);
  1057. a.setAttribute('download', fileName);
  1058. } else {
  1059. rawFile = 'data:' + strMimeType + ',' + encodeURIComponent(csvContent);
  1060. a.setAttribute('target', '_blank');
  1061. }
  1062. a.href = rawFile;
  1063. a.setAttribute('style', 'display:none;');
  1064. D.body.appendChild(a);
  1065. setTimeout(function() {
  1066. if (a.click) {
  1067. a.click();
  1068. // Workaround for Safari 5
  1069. } else if (document.createEvent) {
  1070. var eventObj = document.createEvent('MouseEvents');
  1071. eventObj.initEvent('click', true, true);
  1072. a.dispatchEvent(eventObj);
  1073. }
  1074. D.body.removeChild(a);
  1075. }, this.delay);
  1076. },
  1077. /**
  1078. * @ngdoc function
  1079. * @name pdfExport
  1080. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1081. * @description Exports rows from the grid in pdf format,
  1082. * the data exported is selected based on the provided options.
  1083. * Note that this function has a dependency on pdfMake, which must
  1084. * be installed. The resulting pdf opens in a new
  1085. * browser window.
  1086. * @param {Grid} grid the grid from which data should be exported
  1087. * @param {string} rowTypes which rows to export, valid values are
  1088. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  1089. * uiGridExporterConstants.SELECTED
  1090. * @param {string} colTypes which columns to export, valid values are
  1091. * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
  1092. * uiGridExporterConstants.SELECTED
  1093. */
  1094. pdfExport: function (grid, rowTypes, colTypes) {
  1095. var self = this;
  1096. this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {
  1097. var exportColumnHeaders = self.getColumnHeaders(grid, colTypes);
  1098. var exportData = self.getData(grid, rowTypes, colTypes);
  1099. var docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);
  1100. if (self.isIE() || navigator.appVersion.indexOf("Edge") !== -1) {
  1101. self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);
  1102. } else {
  1103. pdfMake.createPdf(docDefinition).open();
  1104. }
  1105. });
  1106. },
  1107. /**
  1108. * @ngdoc function
  1109. * @name downloadPdf
  1110. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1111. * @description Generates and retrieves the pdf as a blob, then downloads
  1112. * it as a file. Only used in IE, in all other browsers we use the native
  1113. * pdfMake.open function to just open the PDF
  1114. * @param {string} fileName the filename to give to the pdf, can be set
  1115. * through exporterPdfFilename
  1116. * @param {object} docDefinition a pdf docDefinition that we can generate
  1117. * and get a blob from
  1118. */
  1119. downloadPDF: function (fileName, docDefinition) {
  1120. var D = document;
  1121. var a = D.createElement('a');
  1122. var strMimeType = 'application/octet-stream;charset=utf-8';
  1123. var rawFile;
  1124. var ieVersion;
  1125. ieVersion = this.isIE(); // This is now a boolean value
  1126. var doc = pdfMake.createPdf(docDefinition);
  1127. var blob;
  1128. doc.getBuffer( function (buffer) {
  1129. blob = new Blob([buffer]);
  1130. // IE10+
  1131. if (navigator.msSaveBlob) {
  1132. return navigator.msSaveBlob(
  1133. blob, fileName
  1134. );
  1135. }
  1136. // Previously: && ieVersion < 10
  1137. // ieVersion now returns a boolean for the
  1138. // sake of sanity. We just check `msSaveBlob` first.
  1139. if (ieVersion) {
  1140. var frame = D.createElement('iframe');
  1141. document.body.appendChild(frame);
  1142. frame.contentWindow.document.open("text/html", "replace");
  1143. frame.contentWindow.document.write(blob);
  1144. frame.contentWindow.document.close();
  1145. frame.contentWindow.focus();
  1146. frame.contentWindow.document.execCommand('SaveAs', true, fileName);
  1147. document.body.removeChild(frame);
  1148. return true;
  1149. }
  1150. });
  1151. },
  1152. /**
  1153. * @ngdoc function
  1154. * @name renderAsPdf
  1155. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1156. * @description Renders the data into a pdf, and opens that pdf.
  1157. *
  1158. * @param {Grid} grid the grid from which data should be exported
  1159. * @param {array} exportColumnHeaders an array of column headers,
  1160. * where each header is an object with name, width and maybe alignment
  1161. * @param {array} exportData an array of rows, where each row is
  1162. * an array of column data
  1163. * @returns {object} a pdfMake format document definition, ready
  1164. * for generation
  1165. */
  1166. prepareAsPdf: function(grid, exportColumnHeaders, exportData) {
  1167. var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );
  1168. var headerColumns = exportColumnHeaders.map( function( header ) {
  1169. return { text: header.displayName, style: 'tableHeader' };
  1170. });
  1171. var stringData = exportData.map(this.formatRowAsPdf(this));
  1172. var allData = [headerColumns].concat(stringData);
  1173. var docDefinition = {
  1174. pageOrientation: grid.options.exporterPdfOrientation,
  1175. pageSize: grid.options.exporterPdfPageSize,
  1176. content: [{
  1177. style: 'tableStyle',
  1178. table: {
  1179. headerRows: 1,
  1180. widths: headerWidths,
  1181. body: allData
  1182. }
  1183. }],
  1184. styles: {
  1185. tableStyle: grid.options.exporterPdfTableStyle,
  1186. tableHeader: grid.options.exporterPdfTableHeaderStyle
  1187. },
  1188. defaultStyle: grid.options.exporterPdfDefaultStyle
  1189. };
  1190. if ( grid.options.exporterPdfLayout ){
  1191. docDefinition.layout = grid.options.exporterPdfLayout;
  1192. }
  1193. if ( grid.options.exporterPdfHeader ){
  1194. docDefinition.header = grid.options.exporterPdfHeader;
  1195. }
  1196. if ( grid.options.exporterPdfFooter ){
  1197. docDefinition.footer = grid.options.exporterPdfFooter;
  1198. }
  1199. if ( grid.options.exporterPdfCustomFormatter ){
  1200. docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );
  1201. }
  1202. return docDefinition;
  1203. },
  1204. /**
  1205. * @ngdoc function
  1206. * @name calculatePdfHeaderWidths
  1207. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1208. * @description Determines the column widths base on the
  1209. * widths we got from the grid. If the column is drawn
  1210. * then we have a drawnWidth. If the column is not visible
  1211. * then we have '*', 'x%' or a width. When columns are
  1212. * not visible they don't contribute to the overall gridWidth,
  1213. * so we need to adjust to allow for extra columns
  1214. *
  1215. * Our basic heuristic is to take the current gridWidth, plus
  1216. * numeric columns and call this the base gridwidth.
  1217. *
  1218. * To that we add 100 for any '*' column, and x% of the base gridWidth
  1219. * for any column that is a %
  1220. *
  1221. * @param {Grid} grid the grid from which data should be exported
  1222. * @param {array} exportHeaders array of header information
  1223. * @returns {object} an array of header widths
  1224. */
  1225. calculatePdfHeaderWidths: function ( grid, exportHeaders ) {
  1226. var baseGridWidth = 0;
  1227. exportHeaders.forEach( function(value){
  1228. if (typeof(value.width) === 'number'){
  1229. baseGridWidth += value.width;
  1230. }
  1231. });
  1232. var extraColumns = 0;
  1233. exportHeaders.forEach( function(value){
  1234. if (value.width === '*'){
  1235. extraColumns += 100;
  1236. }
  1237. if (typeof(value.width) === 'string' && value.width.match(/(\d)*%/)) {
  1238. var percent = parseInt(value.width.match(/(\d)*%/)[0]);
  1239. value.width = baseGridWidth * percent / 100;
  1240. extraColumns += value.width;
  1241. }
  1242. });
  1243. var gridWidth = baseGridWidth + extraColumns;
  1244. return exportHeaders.map(function( header ) {
  1245. return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;
  1246. });
  1247. },
  1248. /**
  1249. * @ngdoc function
  1250. * @name formatRowAsPdf
  1251. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1252. * @description Renders a row in a format consumable by PDF,
  1253. * mainly meaning casting everything to a string
  1254. * @param {exporterService} exporter pass in exporter
  1255. * @param {array} row the row to be turned into a csv string
  1256. * @returns {string} a csv-ified version of the row
  1257. */
  1258. formatRowAsPdf: function ( exporter ) {
  1259. return function( row ) {
  1260. return row.map(exporter.formatFieldAsPdfString);
  1261. };
  1262. },
  1263. /**
  1264. * @ngdoc function
  1265. * @name formatFieldAsCsv
  1266. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1267. * @description Renders a single field as a pdf-able field, which
  1268. * is different from a csv field only in that strings don't have quotes
  1269. * around them
  1270. * @param {field} field the field to be turned into a pdf string,
  1271. * may be of any type
  1272. * @returns {string} a string-ified version of the field
  1273. */
  1274. formatFieldAsPdfString: function (field) {
  1275. var returnVal;
  1276. if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
  1277. returnVal = '';
  1278. } else if (typeof(field.value) === 'number') {
  1279. returnVal = field.value.toString();
  1280. } else if (typeof(field.value) === 'boolean') {
  1281. returnVal = (field.value ? 'TRUE' : 'FALSE') ;
  1282. } else if (typeof(field.value) === 'string') {
  1283. returnVal = field.value.replace(/"/g,'""');
  1284. } else if (field.value instanceof Date) {
  1285. returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
  1286. } else if (typeof(field.value) === 'object') {
  1287. returnVal = field.value;
  1288. } else {
  1289. returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
  1290. }
  1291. if (field.alignment && typeof(field.alignment) === 'string' ){
  1292. returnVal = { text: returnVal, alignment: field.alignment };
  1293. }
  1294. return returnVal;
  1295. },
  1296. /**
  1297. * @ngdoc function
  1298. * @name formatAsExcel
  1299. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1300. * @description Formats the column headers and data as a excel,
  1301. * and sends that data to the user
  1302. * @param {array} exportColumnHeaders an array of column headers,
  1303. * where each header is an object with name, width and maybe alignment
  1304. * @param {array} exportData an array of rows, where each row is
  1305. * an array of column data
  1306. * @param {string} separator a string that represents the separator to be used in the csv file
  1307. * @returns {string} csv the formatted excel as a string
  1308. */
  1309. formatAsExcel: function (exportColumnHeaders, exportData, workbook, sheet, docDefinition) {
  1310. var self = this;
  1311. var bareHeaders = exportColumnHeaders.map(function(header){return { value: header.displayName };});
  1312. var sheetData = [];
  1313. var headerData = [];
  1314. for (var i = 0; i < bareHeaders.length; i++) {
  1315. // TODO - probably need callback to determine header value and header styling
  1316. var exportStyle = 'header';
  1317. switch (exportColumnHeaders[i].align) {
  1318. case 'center':
  1319. exportStyle = 'headerCenter';
  1320. break;
  1321. case 'right':
  1322. exportStyle = 'headerRight';
  1323. break;
  1324. }
  1325. var metadata = (docDefinition.styles && docDefinition.styles[exportStyle]) ? {style: docDefinition.styles[exportStyle].id} : null;
  1326. headerData.push({value: bareHeaders[i].value, metadata: metadata});
  1327. }
  1328. sheetData.push(headerData);
  1329. var result = exportData.map(this.formatRowAsExcel(this, workbook, sheet));
  1330. for (var j = 0; j<result.length; j++) {
  1331. sheetData.push(result[j]);
  1332. }
  1333. return sheetData;
  1334. },
  1335. /**
  1336. * @ngdoc function
  1337. * @name formatRowAsExcel
  1338. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1339. * @description Renders a single field as a csv field, including
  1340. * quotes around the value
  1341. * @param {exporterService} exporter pass in exporter
  1342. * @param {array} row the row to be turned into a excel string
  1343. * @returns {array} array of cell objects (i.e. {value: x, metadata: y})
  1344. */
  1345. formatRowAsExcel: function (exporter, workbook, sheet) {
  1346. return function (row) {
  1347. var values = [];
  1348. for (var i = 0; i<row.length; i++) {
  1349. var value = exporter.formatFieldAsExcel(row[i], workbook, sheet);
  1350. values.push({value: value, metadata: row[i].metadata});
  1351. }
  1352. return values;
  1353. };
  1354. },
  1355. /**
  1356. * @ngdoc function
  1357. * @name formatFieldAsExcel
  1358. * @methodOf ui.grid.exporter.service:uiGridExporterService
  1359. * @description Renders a single field as a csv field, including
  1360. * quotes around the value
  1361. * @param {field} field the field to be turned into a csv string,
  1362. * may be of any type
  1363. * @returns {string} a excel-ified version of the field
  1364. */
  1365. formatFieldAsExcel: function (field, workbook, sheet, formatters) {
  1366. if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
  1367. return '';
  1368. }
  1369. if (typeof(field.value) === 'number') {
  1370. return field.value;
  1371. }
  1372. if (typeof(field.value) === 'boolean') {
  1373. return (field.value ? 'TRUE' : 'FALSE') ;
  1374. }
  1375. if (typeof(field.value) === 'string') {
  1376. return field.value.replace(/"/g,'""');
  1377. }
  1378. return JSON.stringify(field.value);
  1379. },
  1380. prepareAsExcel: function(grid, workbook, sheet) {
  1381. var docDefinition = {
  1382. styles: {
  1383. }
  1384. };
  1385. if ( grid.options.exporterExcelCustomFormatters ){
  1386. docDefinition = grid.options.exporterExcelCustomFormatters( grid, workbook, docDefinition );
  1387. }
  1388. if ( grid.options.exporterExcelHeader ) {
  1389. if (angular.isFunction( grid.options.exporterExcelHeader )) {
  1390. grid.options.exporterExcelHeader(grid, workbook, sheet, docDefinition);
  1391. } else {
  1392. var headerText = grid.options.exporterExcelHeader.text;
  1393. var style = grid.options.exporterExcelHeader.style;
  1394. sheet.data.push([{value: headerText, metadata: {style: docDefinition.styles[style].id}}]);
  1395. }
  1396. }
  1397. return docDefinition;
  1398. },
  1399. excelExport: function (grid, rowTypes, colTypes) {
  1400. var self = this;
  1401. this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
  1402. var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
  1403. var workbook = new ExcelBuilder.Workbook();
  1404. var aName = grid.options.exporterExcelSheetName ? grid.options.exporterExcelSheetName : 'Sheet1';
  1405. var sheet = new ExcelBuilder.Worksheet({name: aName});
  1406. workbook.addWorksheet(sheet);
  1407. var docDefinition = self.prepareAsExcel(grid, workbook, sheet);
  1408. // The standard column width in Microsoft Excel 2000 is 8.43 characters based on fixed-width Courier font
  1409. // Width of 10 in excel is 75 pixels
  1410. var colWidths = [];
  1411. var startDataIndex = grid.treeBase ? grid.treeBase.numberLevels : (grid.enableRowSelection !== false ? 1 : 0);
  1412. for (var i = startDataIndex; i < grid.columns.length; i++) {
  1413. colWidths.push({width: (grid.columns[i].drawnWidth / 75) * 10});
  1414. }
  1415. sheet.setColumns(colWidths);
  1416. var exportData = self.getData(grid, rowTypes, colTypes, grid.options.exporterFieldApplyFilters);
  1417. // set column widhths. See function called from prepareAsExcel method
  1418. //sheet.setColumns(docDefinition.columnWidths);
  1419. //for (var i=0; i< grid.treeBase.tree.length; i++) {
  1420. // console.log(grid.treeBase.tree[i]);
  1421. //}
  1422. var excelContent = self.formatAsExcel(exportColumnHeaders, exportData, workbook, sheet, docDefinition);
  1423. sheet.setData(sheet.data.concat(excelContent));
  1424. ExcelBuilder.Builder.createFile(workbook, {type:"blob"}).then(function(result) {
  1425. self.downloadFile (grid.options.exporterExcelFilename, result, grid.options.exporterCsvColumnSeparator, grid.options.exporterOlderExcelCompatibility);
  1426. });
  1427. });
  1428. }
  1429. };
  1430. function getDisplayName(grid, gridCol) {
  1431. if (grid.options.exporterHeaderFilter) {
  1432. return grid.options.exporterHeaderFilterUseName ?
  1433. grid.options.exporterHeaderFilter(gridCol.name) :
  1434. grid.options.exporterHeaderFilter(gridCol.displayName);
  1435. }
  1436. return gridCol.headerCellFilter ?
  1437. $filter(gridCol.headerCellFilter)(gridCol.displayName) :
  1438. gridCol.displayName;
  1439. }
  1440. function defaultExporterFieldCallback(grid, row, col, value) {
  1441. return col.cellFilter ? $filter(col.cellFilter)(value) : value;
  1442. }
  1443. return service;
  1444. }
  1445. ]);
  1446. /**
  1447. * @ngdoc directive
  1448. * @name ui.grid.exporter.directive:uiGridExporter
  1449. * @element div
  1450. * @restrict A
  1451. *
  1452. * @description Adds exporter features to grid
  1453. *
  1454. * @example
  1455. <example module="app">
  1456. <file name="app.js">
  1457. var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);
  1458. app.controller('MainCtrl', ['$scope', function ($scope) {
  1459. $scope.data = [
  1460. { name: 'Bob', title: 'CEO' },
  1461. { name: 'Frank', title: 'Lowly Developer' }
  1462. ];
  1463. $scope.gridOptions = {
  1464. enableGridMenu: true,
  1465. exporterMenuCsv: false,
  1466. columnDefs: [
  1467. {name: 'name', enableCellEdit: true},
  1468. {name: 'title', enableCellEdit: true}
  1469. ],
  1470. data: $scope.data
  1471. };
  1472. }]);
  1473. </file>
  1474. <file name="index.html">
  1475. <div ng-controller="MainCtrl">
  1476. <div ui-grid="gridOptions" ui-grid-exporter></div>
  1477. </div>
  1478. </file>
  1479. </example>
  1480. */
  1481. module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',
  1482. function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {
  1483. return {
  1484. replace: true,
  1485. priority: 0,
  1486. require: '^uiGrid',
  1487. scope: false,
  1488. link: function ($scope, $elm, $attrs, uiGridCtrl) {
  1489. uiGridExporterService.initializeGrid(uiGridCtrl.grid);
  1490. uiGridCtrl.grid.exporter.$scope = $scope;
  1491. }
  1492. };
  1493. }
  1494. ]);
  1495. })();