Chillax in dev

[php] 엑셀 다운로드 Process 정리하기 본문

PHP & MySQL

[php] 엑셀 다운로드 Process 정리하기

Seong Story 2023. 5. 19. 08:45
728x90

[php] 엑셀 다운로드 Process 정리하기

- php model에서 엑셀 다운로드 하는 부분을 정리했습니다. 코드이그나이터 3.0을 기준으로 개발했습니다.

라인별 코멘트를 기준으로 전체적인 흐름을 참고해 주세요. 

 

1. 일단 엑셀로 다운 받을 데이터를 조회했다는 가정으로 작성했습니다. 

이렇게 $itemList 에 엑셀로 다운로드할 필드를 Array를 준비합니다. 

//예시
$qry = $this->db2->query("select * from `ws_units` where `unit_srl`='".$row->unit_srl."' ");
	if($qry->num_rows() == 1){
		$product = $qry->row();
		array_push($itemList, $product);			
	}

 

2. 엑셀 다운로드를 위한 준비 + 양식 + 데이터등을 생성해 줍니다. 

 

$pattenList는 엑셀 row에 맞도록 데이터를 저장한 Array 입니다.  예를 들어 'no' 순번 필드에 는 $itemList->no 값을 매칭하여 가공해 주는 방식입니다. 

 

최종적으로 엑셀을 다운로드합니다. 

// Excel 라이브러리 가져오기
$this->load->library("excels");

// PHP Excel PlugIn 활성화
$objPHPExcel = new PHPExcel();

// 시트번호 셋팅
$objPHPExcel->setActiveSheetIndex(0);

    $xl_head = array();
    foreach($pattenList as $row){
        if(isset($defaultKeyList[$row['field']])){
            $value = str_replace("<br>", "\n",$defaultKeyList[$row['field']]->volume);
            $value = str_replace("</br>", "\n",$value);
            $value = str_replace("<br/>", "\n",$value);
            array_push($xl_head, $value);

        }
    }

    // 총길이 순서 체크
    if(isset($itemList)){
        $max_row = count($itemList);
    }

    // 헤더 
    $last_char = $this->lib->column_char(count($xl_head) - 1);

    // BG COLOR : ffffe699 (헤더 색상 만들어주기)
    $objPHPExcel->getActiveSheet()->getStyle( "A1:".$last_char."1" )->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setARGB("FFFFE699");

    // 줄바꿈 허용추가
    $objPHPExcel->getActiveSheet()->getStyle( "A1:".$last_char."1" )->getAlignment()->setWrapText(true);

    //셀 텍스트 굵게
    $objPHPExcel->getActiveSheet()->getStyle ( "A1:".$last_char."1" )->getFont()->setBold(true);

    //셀 텍스트 사이즈 지정
    $objPHPExcel->getDefaultStyle()->getFont()->setName('Malgun gothic')->setSize(11);

    // border 만들어주기
    $defaultStyle = array(
        "borders" => [
            'allborders' => [
                "style" => PHPExcel_Style_Border::BORDER_THIN,	// 얇은 선으로 생성,
                'color' => array('rgb'=>'000000')	// 색상은 블랙으로
            ]
        ],
        "font" => [
            'size' => 9,
            'color' => array('rgb'=>'000000')
        ]
    );

    //다중 셀 border 스타일 적용
    $objPHPExcel->getActiveSheet()->getStyle("A1:".$last_char.($max_row+1))->applyFromArray($defaultStyle);

    //가운데 정렬 (가로)
    $objPHPExcel->getActiveSheet()->getStyle("A1:".$last_char.($max_row+1))->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER); 

    //가운데정렬 (세로)
    $objPHPExcel->getActiveSheet()->getStyle("A1:".$last_char.($max_row+1))->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER); 

    // 첫줄 사이즈 설정 
    $objPHPExcel->getActiveSheet()->getRowDimension('1')->setRowHeight(36);

    // 열별 높이 설정
    $objPHPExcel->getActiveSheet()->getRowDimension("A2:".$last_char.($max_row+1))->setRowHeight(19);

    // 사이즈 설정 적용
    $i = 1;
    foreach($pattenList as $row){
        if(isset($defaultKeyList[$row['field']])){
            $objPHPExcel->getActiveSheet()->getColumnDimension($this->lib->column_char($i - 1))->setWidth($defaultKeyList[$row['field']]->width);

            // 특정 필드는 배경 색상 적용
            if(in_array($row['field'], array("delivery-type","delivery-company","tracking-number"))){
                $objPHPExcel->getActiveSheet()->getStyle($this->lib->column_char($i - 1)."2:".$this->lib->column_char($i - 1).($max_row+1))->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
                $objPHPExcel->getActiveSheet()->getStyle($this->lib->column_char($i - 1)."2:".$this->lib->column_char($i - 1).($max_row+1))->getFill()->getStartColor()->setRGB('FFF7DD');
            }

            if(in_array($row['field'], array("open-order-code","channel-item-code","bundle-number", "individual-entry-code","seller-custom-code-1","seller-custom-code-2","resident-number","open-item-code","open-product-code","custom-product-code","open-option-code","custom-option-code","tracking-number"))){
                $objPHPExcel->getActiveSheet()->getStyle($this->lib->column_char($i - 1)."2:".$this->lib->column_char($i - 1).($max_row+1))->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_TEXT);
            }
            $i++;
        }
    }

    // 입력처리할 데이터 생성 
    $returnData = array();
    $returnData[0] = $xl_head;

    $no = 1;

    foreach($itemList as $row){
        $returnArray = array();
        foreach($pattenList as $field){
            $return = '';
            switch($field['field']){
                // 1 순번
                case "no":
                    $return = $no;
                break;
                 /*
                 . . . 중략 ... 
                 이런식으로 필드를 순회하며 데이터를 패턴에 맞게 가공해서 엑셀 필드에 맞춰줍니다.
                 */

            }
            $returnArray[$field['order'] - 1] = (string)$return;
        }
        $no++;
        array_push($returnData, $returnArray);
    }
    // Excel 데이터 입력
    $objPHPExcel->getActiveSheet()->fromArray($returnData,NULL,'A1');

    // 숫자 형식 필드를 전부 출력되도록 수정해준다.
    for($i=2;$i<=($max_row + 1);$i++){
        foreach($pattenList as $field){
            if(in_array($field['field'], array("master-code"))){

                $res = str_replace("'","",$objPHPExcel->getActiveSheet()->getCell($this->lib->column_char($field['order'] - 1).$i)->getValue());
                if(strlen($res) > 15){
                    $objPHPExcel->getActiveSheet()->setCellValueExplicit($this->lib->column_char($field['order'] - 1).$i, PHPExcel_Style_NumberFormat::toFormattedString($res, '@'), PHPExcel_Cell_DataType::TYPE_STRING);												
                }else{
                    $objPHPExcel->getActiveSheet()->setCellValueExplicit($this->lib->column_char($field['order'] - 1).$i, PHPExcel_Style_NumberFormat::toFormattedString($res, '0'), PHPExcel_Cell_DataType::TYPE_STRING);												
                }
            }

            // 숫자 변환 + 컴마 찍기
            if(in_array($field['field'], array("price-default","price-supply","stock-unit","stock-save","buy-min","buy-person-max","buy-order-max"))){
                $objPHPExcel->getActiveSheet()->setCellValueExplicit($this->lib->column_char($field['order'] - 1).$i,$objPHPExcel->getActiveSheet()->getCell($this->lib->column_char($field['order'] - 1).$i)->getValue(),PHPExcel_Cell_DataType::TYPE_NUMERIC);
                $objPHPExcel->getActiveSheet()->getStyle($this->lib->column_char($field['order'] - 1).$i)->getNumberFormat()->setFormatCode("#,##0");
            }
        }
    }

    $this->db2->close();	

    // 파일을 생성하여 만들기
    $objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);


    header("Pragma: public");
    header("Expires: 0");
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.date("YmdHms").'_Product_list.xlsx"');
    header("Content-Transfer-Encoding: binary");
    header('Cache-Control: max-age=0');


	//엑셀 다운로드
    $objWriter->save('php://output');

 

3.주의 사항

print_r() , echo와  같은 출력을 반드시 제거해야 합니다. 로직상에 하나라도 들어가면 열심히 만든 엑셀에 문제가 생겨 정상 다운로드 됐더라도 다음과 같은 에러를 반환합니다.

확장자명이 잘못되어 ... 에러 예시

 

처음 구현 하는 엑셀이라 다소 조잡합니다.

추후에 더욱 간결한 코드를 작성하도록 노력해봐야겠습니다!

감사합니다 

728x90
LIST
Comments