ExportTableAjax.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. Lib::loadClass('Core_AclHelper');
  4. class Route_ExportTableAjax extends RouteBase {
  5. /**
  6. * @param $_GET['namespace'] = AclNamespace
  7. * @param $_GET['format'] = 'csv' | 'html'
  8. * @param $_GET['flds'] = csv - coma separated field names
  9. * @param $_GET['sortCol'] = FieldName
  10. * @param $_GET['sortDir'] = SortDir ('desc' | 'asc')
  11. * @param $_GET['f_{$fieldName}'] = filter
  12. * @param $_GET['sf_{$fieldName}'] = force filter
  13. */
  14. function defaultAction() {
  15. $args = $_GET;
  16. $namespace = V::get('namespace', '', $args, 'word');
  17. if (!$namespace) throw new HttpException("Bad Request - missing namespace", 400);
  18. $acl = Core_AclHelper::getAclByNamespace($namespace);
  19. $exportLimit = 10000;
  20. $params = array();
  21. $params['limit'] = $exportLimit;
  22. // $params['limitstart'] = 0;
  23. $params['order_by'] = V::get('sortCol', '', $args);
  24. $params['order_dir'] = V::get('sortDir', '', $args);
  25. $params['cols'] = array($acl->getPrimaryKeyField());
  26. $toExportFields = explode(',', V::get('flds', '', $_GET));
  27. if (empty($toExportFields)) throw new Exception("Nie wybrano żandych pól do exportu.");
  28. $allowedExportFieldList = Core_AclHelper::getExportFieldList($acl);
  29. foreach ($toExportFields as $fieldName) {
  30. if ($fieldName == $acl->getPrimaryKeyField()) continue;
  31. if (!in_array($fieldName, $allowedExportFieldList)) throw new Exception("Brak uprawnień do exportu pola '{$fieldName}'");
  32. $params['cols'][] = $fieldName;
  33. }
  34. foreach ($args as $k => $v) {
  35. if (strlen($k) > 3 && substr($k, 0, 2) == 'f_' && strlen($v) > 0) {// filter prefix
  36. $params[$k] = $v;
  37. }
  38. else if (strlen($k) > 4 && substr($k, 0, 3) == 'sf_' && strlen($v) > 0) {// special filter prefix
  39. $params[$k] = $v;
  40. }
  41. }
  42. try {
  43. $queryFeatures = $acl->buildQuery($params);
  44. $total = $queryFeatures->getTotal();
  45. $listItems = $queryFeatures->getItems();
  46. $primaryKeyField = $acl->getPrimaryKeyField();
  47. $items = []; foreach ($listItems as $item) $items[ $item[$primaryKeyField] ] = $item;
  48. } catch (Exception $e) {
  49. DBG::log($e);
  50. throw $e;
  51. }
  52. $format = V::get('format', 'html', $_GET);
  53. switch ($format) {
  54. case 'html': return $this->_exportToHTML($acl, $items, $toExportFields, $format);
  55. case 'xls': return $this->_exportToXLS($acl, $items, $toExportFields, $format);
  56. case 'xlsx': return $this->_exportToXLSX($acl, $items, $toExportFields, $format);
  57. case 'csv_cp1250': return $this->_exportToCSV($acl, $items, $toExportFields, $format);
  58. case 'csv': return $this->_exportToCSV($acl, $items, $toExportFields, $format);
  59. }
  60. die("Nieobsługiwany format danych.");
  61. }
  62. function _exportToHTML($acl, $items, $toExportFields, $format = 'html') {
  63. $labels = array();
  64. foreach ($toExportFields as $fieldName) {
  65. $labels[ $fieldName ] = $acl->getFieldLabel($fieldName);
  66. }
  67. UI::gora();
  68. echo UI::h('table', ['class'=>'table table-bordered table-hover'], [
  69. UI::h('thead', [], [
  70. UI::h('tr', [], array_map(function ($label) {
  71. return UI::h('th', [], $label);
  72. }, $labels))
  73. ]),
  74. UI::h('tbody', [], array_map(function ($item) use($labels) {
  75. return UI::h('tr', [], array_map(function ($fieldName) use ($item) {
  76. return UI::h('td', [], V::get($fieldName, '', $item));
  77. }, array_keys($labels)));
  78. }, $items)),
  79. ]);
  80. UI::dol();
  81. }
  82. function _exportToCSV($acl, $items, $toExportFields, $format = 'csv') {
  83. $csvFileName = "Tabela-" . $acl->getName() . "-" . date("Y-m-d_H_s");
  84. $csvSeparator = ';';
  85. $labels = array();
  86. foreach ($toExportFields as $fieldName) {
  87. $labels[ $fieldName ] = $acl->getFieldLabel($fieldName);
  88. }
  89. $csvHeader = implode($csvSeparator, array_map(function ($label) use ($item) {
  90. return '"' . addslashes($label) . '"';
  91. }, array_values($labels)));
  92. $csvRows = implode("\r\n", array_map(function ($item) use ($labels, $csvSeparator) {
  93. return implode($csvSeparator, array_map(function ($fieldName) use ($item) {
  94. return '"' . addslashes(V::get($fieldName, '', $item)) . '"';
  95. }, array_keys($labels)));
  96. }, $items));
  97. header('Content-Type: text/csv; charset=utf-8');
  98. header("Content-Disposition: attachment; filename={$csvFileName}.csv");
  99. switch ($format) {
  100. case 'csv': echo $csvHeader . "\n" . $csvRows; exit;
  101. case 'csv_cp1250': echo iconv('utf-8', 'Windows-1250//IGNORE', $csvHeader) . "\r\n" . iconv('utf-8', 'Windows-1250//IGNORE', $csvRows); exit;
  102. die("Nieobsługiwane kodowanie danych csv.");
  103. }
  104. }
  105. function _exportToXLS($acl, $items, $toExportFields, $format = 'xls') {
  106. // https://en.wikipedia.org/wiki/Microsoft_Excel#XML_Spreadsheet
  107. $csvFileName = "Tabela-" . $acl->getName() . "-" . date("Y-m-d_H_s");
  108. $labels = array();
  109. foreach ($toExportFields as $fieldName) {
  110. $labels[ $fieldName ] = $acl->getFieldLabel($fieldName);
  111. }
  112. $xw = new XMLWriter();
  113. $xw->openMemory();
  114. $xw->startDocument("1.0");
  115. $xw->startElement("Workbook");
  116. $xw->writeAttribute("xmlns", "urn:schemas-microsoft-com:office:spreadsheet");
  117. $xw->writeAttribute("xmlns:o", "urn:schemas-microsoft-com:office:office");
  118. $xw->writeAttribute("xmlns:x", "urn:schemas-microsoft-com:office:excel");
  119. $xw->writeAttribute("xmlns:ss", "urn:schemas-microsoft-com:office:spreadsheet");
  120. $xw->writeAttribute("xmlns:html", "http://www.w3.org/TR/REC-html40");
  121. {
  122. $xw->startElement("Worksheet");
  123. $xw->writeAttribute("ss:Name", "Sheet1");
  124. {
  125. $xw->startElement("Table");
  126. $xw->writeAttribute("ss:ExpandedColumnCount", "2");
  127. $xw->writeAttribute("ss:ExpandedRowCount", "2");
  128. $xw->writeAttribute("x:FullColumns", "1");
  129. $xw->writeAttribute("x:FullRows", "1");
  130. {
  131. $xw->startElement("Row");
  132. foreach ($labels as $fieldName => $label) {
  133. $xw->startElement('Cell');
  134. {
  135. $xw->startElement('Data');
  136. $xw->writeAttribute("ss:Type", "String");
  137. $xw->text(str_replace([ '<br>', '<br/>' ], "\n", $label));
  138. $xw->endElement();
  139. }
  140. $xw->endElement();
  141. }
  142. $xw->endElement();
  143. foreach ($items as $item) {
  144. $xw->startElement("Row");
  145. foreach ($labels as $fieldName => $label) {
  146. $xw->startElement('Cell');
  147. {
  148. $xw->startElement('Data');
  149. $xw->writeAttribute("ss:Type", "String");
  150. $xw->text($item[$fieldName]);
  151. $xw->endElement();
  152. }
  153. $xw->endElement();
  154. }
  155. $xw->endElement();
  156. }
  157. }
  158. $xw->endElement();
  159. }
  160. $xw->endElement();
  161. }
  162. $xw->endElement();
  163. $xw->endDocument();
  164. header("Content-Type: text/xml; charset=utf-8");
  165. header("Content-Disposition: attachment; filename={$csvFileName}.xls");
  166. echo $xw->outputMemory();
  167. }
  168. function _exportToXLSX($acl, $items, $toExportFields, $format = 'xlsx') {
  169. // https://github.com/mk-j/PHP_XLSXWriter
  170. Lib::loadClass('Vendor_XLSXWriter');
  171. $csvFileName = "Tabela-" . $acl->getName() . "-" . date("Y-m-d_H_s");
  172. $labels = array();
  173. foreach ($toExportFields as $fieldName) {
  174. $labels[ $fieldName ] = $acl->getFieldLabel($fieldName);
  175. }
  176. $xlsx = new Vendor_XLSXWriter();
  177. $xlsx->writeSheetHeader('Sheet1', array_combine(
  178. array_values($labels),
  179. array_map(function ($label) { return 'string'; }, $labels)
  180. ));
  181. foreach ($items as $item) {
  182. $row = array_map(function ($fieldName) use ($item) {
  183. return V::get($fieldName, '', $item);
  184. }, array_keys($labels));
  185. $xlsx->writeSheetRow('Sheet1', $row);
  186. }
  187. header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8");
  188. header("Content-Disposition: attachment; filename={$csvFileName}.xlsx");
  189. $xlsx->writeToStdOut();
  190. }
  191. }