array( 'name' => 'ID Sản phẩm Web', 'width' => '10', 'data_field_name' => 'id', ), "B" => array( 'name' => 'Mã kho (SKU)', 'width' => '10', 'data_field_name' => 'storeSKU', ),*/ //... ]; protected $field_column_mappings = [ //'name' => "A", //'price' => "B", ]; private $header_row_index = 2; // hold cach for some operations protected $cache = []; protected $format_item_middlewares = []; // list of middleware object to format item public function __construct($client_config_file_name='', $export_file_name='', $work_sheet_title = '') { if($client_config_file_name) { $this->setColumnConfigUseConfigFile($client_config_file_name); } $this->export_file_name = ($export_file_name) ?: "file_".CURRENT_TIME; $this->work_sheet_title = ($work_sheet_title) ?: "Danh sách"; } protected function setColumnConfigUseConfigFile($client_config_file_name) { //this from a config file for each client $client_config_file = "config/client/excel/".$client_config_file_name; if( ! file_exists(ROOT_DIR .'/'. $client_config_file)) { die("Please create config file: ".$client_config_file); } $client_fields_config = include ROOT_DIR .'/'. $client_config_file; // auto add excel column names based on fields' index $this->client_excel_col_config = $this->_make_columns(array_values($client_fields_config)); // create field-col map $this->createFieldColumnMappings(); } private function createFieldColumnMappings() { $field_column_mappings = []; foreach ($this->client_excel_col_config as $column_name => $_prop) { $field_column_mappings[$_prop['data_field_name']] = $column_name; } $this->field_column_mappings = $field_column_mappings; } public function setColumnConfigManually(array $col_config) { $this->client_excel_col_config = $this->_make_columns($col_config); // create field-col map $this->createFieldColumnMappings(); } protected function _make_columns($fields_config) { $new_array = []; $total_names = sizeof(static::$column_names); foreach ($fields_config as $index => $config) { if($index >= $total_names) break; $new_array[static::$column_names[$index]] = $config; } return $new_array; } public function start(array $options = [ "debug_mode" => '', // show-item-list "excelOption" => [], "sheetOption" => [], "sheetStartRowNumber" => 3, "sheetHeaderRowNumber" => 2, "getItemListOption" => [ "brand" => [], "category" => [], "page" => 1, "limit" => 100, ], "exportFileOption" => [], ]) { $debug_mode = $options['debug_mode'] ?? false; // debug mode if($debug_mode) { // show item list if($debug_mode == 'show-item-list') { $item_list = $this->getItemList($options['getItemListOption']); print_r($item_list); } // show formatted list if($debug_mode == 'show-formatted-list') { $item_list = $this->formatItemList( $this->getItemList($options['getItemListOption']) ); print_r($item_list); } return true; } // setup if(isset($options['sheetHeaderRowNumber']) && $options['sheetHeaderRowNumber']) { $this->header_row_index = $options['sheetHeaderRowNumber']; } $this->createExcelObject($options['excelOption'] ?? []); $this->createActiveSheet(0, $options['sheetOption'] ?? []); // num beforeWriteList $this->beforeWriteList(); // fetch all items and write till the end $has_fetch_all_items = false; $start_row = (isset($options["sheetStartRowNumber"])) ? $options["sheetStartRowNumber"] : 3; $item_list = $this->formatItemList( $this->getItemList($options['getItemListOption']) ); //debug_var($item_list); //exit; $has_fetch_all_items = true; $this->writeItemsToExcel($start_row, $item_list); /*$getItemListOption = $options['getItemListOption']; $pageIndex = 0; while (!$has_fetch_all_items) { // run from page 1->end $pageIndex += 1; $getItemListOption["page"] = $pageIndex; $item_list = $this->getItemList($getItemListOption); // flag if(!sizeof($item_list)) { $has_fetch_all_items = true; } // else, start write $last_row = $this->writeItemsToExcel($start_row, $item_list); // update $start_row $start_row = $last_row;// + 1 }*/ // export if($has_fetch_all_items) { $this->getExcelFile($options['exportFileOption']); } return true; } // abstract methods protected function beforeWriteList() { } abstract protected function getItemList(array $options); abstract protected function defaultFormatItemInfo(array $item_info, $index =0); protected function registerFormatItemInfoMiddleware($middleware_ojb) { $this->format_item_middlewares[] = $middleware_ojb; } protected function formatItemInfo(array $item_info, $index = 0) { // apply middleware if(sizeof($this->format_item_middlewares)) { foreach ($this->format_item_middlewares as $_middleware) { $item_info = call_user_func($_middleware, $item_info); } } else { $item_info = $this->defaultFormatItemInfo($item_info, $index); } return $item_info; } protected function createExcelObject(array $options) { // Create new Spreadsheet object $this->objExcel = new Spreadsheet(); // Set properties $this->objExcel->getProperties()->setCreator("Hurasoft"); $this->objExcel->getProperties()->setLastModifiedBy("Hurasoft"); $this->objExcel->getProperties()->setTitle("Excel Document"); $this->objExcel->getProperties()->setSubject("Excel Document"); $this->objExcel->getProperties()->setDescription("Tao file excel"); } protected function createActiveSheet($sheet_index = 0, array $options=[]) { // Create a first sheet, representing sales data $this->objExcel->setActiveSheetIndex($sheet_index); $this->currentActiveSheet = $this->objExcel->getActiveSheet(); $this->currentActiveSheet->setCellValueExplicit('A1', $this->work_sheet_title, DataType::TYPE_STRING); $this->currentActiveSheet->getStyle('A1')->getFont()->setSize(16); $this->currentActiveSheet->getStyle('A1')->getFont()->setBold(true); // Set header row $row_index = $this->header_row_index; foreach ($this->client_excel_col_config as $col_name => $_prop) { $col_width = (isset($_prop['width']) && intval($_prop['width']) > 0) ? intval($_prop['width']) : 15; $this->currentActiveSheet->getColumnDimension($col_name)->setWidth($col_width); $this->currentActiveSheet->setCellValueExplicit($col_name. $row_index, $_prop["name"], DataType::TYPE_STRING); $this->currentActiveSheet->getStyle($col_name . $row_index)->getFont()->setBold(true); } } protected function formatItemList(array $item_list) { $new_list = []; foreach ( $item_list as $index => $item_info ) { $new_list[$index] = $this->formatItemInfo($item_info, $index); } return $new_list; } protected function writeItemsToExcel($start_row = 1, array $item_list=[]) { $write_row = $start_row; foreach ( $item_list as $index => $item_info ) { // write each field to its corresponding columns foreach ($item_info as $_field => $_value) { if( !isset($this->field_column_mappings[$_field])) continue; if(is_array($_value)) $_value = serialize($_value); $write_column = $this->field_column_mappings[$_field]; $this->currentActiveSheet->setCellValueExplicit($write_column . $write_row, $_value, DataType::TYPE_STRING); $this->currentActiveSheet->getStyle($write_column . $write_row)->getAlignment()->setWrapText(true); } // next rows $write_row += 1; } // get the last row return $write_row; } protected function getExcelFile(array $options) { // write to a local file $local_file = $options['local_file'] ?? ''; if($local_file) { $this->_save_to_file($local_file); return true; } // default: export to browser to download $this->_export_to_browser(); return true; } protected function cleanUp(){ // clean up $this->objExcel->disconnectWorksheets(); unset($this->objExcel); } protected function _save_to_file($file_path){ // delete old file if exist if(file_exists($file_path)) { @unlink($file_path); } $writer = new Xlsx($this->objExcel); $writer->save($file_path); $this->cleanUp(); } protected function _export_to_browser(){ // Rename sheet header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="'.$this->export_file_name.'.xlsx"'); header('Cache-Control: max-age=0'); $writer = new Xlsx($this->objExcel); ob_end_clean(); $writer->save('php://output'); $this->cleanUp(); exit(); } }