PhpSpreadsheet 설치 및 사용법 정리
이 게시글은 아래의 사양에서 테스트 및 작성되었습니다.
Server OS : Ubuntu 20.04.3 LTS on WSL2
WebServer : Apache 2.4
Backend : PHP 8
목차
웹 서비스를 개발하다가 엑셀을 다뤄야 할 일이 생겨서 찾아보던 중에 PHPExcel이라는 것을 알게 되었다. 그런데 이미 오래 전에 지원이 종료되었다.
공식 Github 문서. DEAD라고 표시한 프로젝트는 처음이다.
공식 문서에서도 PhpSpreadsheet로 변경할 것을 강력하게 권고하고 있다. 그러나 업무에서 사용하는 PHP의 버전이 낮다면 어쩔수 없이 PHPExcel을 사용해야 할 것이다. PhpSpreadsheet는 PHP 7.3 이상의 버전을 지원하기 때문이다.
공식 문서의 사용 조건
공식 문서 링크 : https://phpspreadsheet.readthedocs.io/en/latest/
필자는 마침 PHP 8이 배포된지 시간도 지났고 속도 개선과 여러가지 기능이 추가되었다고 해서 사용을 하는 중이었다. 그래서 사용을 하려고 하는데 공식 문서에는 생략된 내용이 꽤 많았고 여러 해외 사이트를 찾아다니면서 정보를 수집해야 했다.
아직 한국에서는 PHP 5버전을 사용하는 곳이 많아서 그런지 PHPExcel이 많이 사용되어서 그런지는 모르지만 한국어로 된 페이지는 대부분 설치 방법이나 간단한 설명만 있었다.
추후에도 사용을 할 예정이라서 나중을 위해 사용법을 정리하기로 했다.
0. 사전준비
위에도 적혀있지만 PHP의 버전이 최소한 7.3이어야 한다. 참고로 2021년 12월 24일을 기준으로 7.3버전 조차 공식 지원이 종료되었다.
PHP 공식 지원이 종료된 버전 목록. 5.6도 지원이 종료된지 3년이 가깝다.혹시 이전버전을 사용한다면 버전을 올리고 진행을 해야 한다.
또한 PhpSpreadsheet를 설치하기 위해서 PHP의 패키지 관리 소프트웨어인 composer가 설치되어 있어야 한다. 설치 방법은 공식 홈페이지에 쉽게 설명되어 있으니 참조하면 된다.
리눅스를 사용한다면 패키지 관리자를 통해 php 설치를 했을 텐데 몇 가지 추가로 설치를 해 주어야 한다.
sudo apt install php-xml php-gd php-mbstring php-zip
위 확장 모듈이 없다면 PhpSpreadsheet 설치가 진행이 되지 않는다. 필자도 설치가 되지 않아서 찾아보니 위의 모듈을 필요로 하는데 공식 문서에는 내용이 없었다. 반드시 위의 모듈이 설치되어 있는지 확인을 한 후에 진행을 한다.
1. 설치
composer와 확장 모듈이 설치되었다면 원하는 폴더로 이동한 후에 설치 명령어를 입력한다.
composer require phpoffice/phpspreadsheet
문제가 없다면 composer가 알아서 필요한 추가 패키지와 함께 설치를 완료한다.
2. 기본 사용법
<?php
/* 서버에 파일 저장하기 */
require 'vendor/autoload.php';
// 문서 생성용
use PhpOffice\PhpSpreadsheet\Spreadsheet;
// 문서 저장 및 불러오기용
use PhpOffice\PhpSpreadsheet\IOFactory;
// 엑셀 문서 생성
$spreadsheet = new Spreadsheet();
// 현재 활성화된 Sheet 가져오기
$sheet = $spreadsheet->getActiveSheet();
// Sheet의 특정 셀에 값 입력
$sheet->setCellValue('A1', 'Hello World !');
// 저장을 위한 파일작성자 생성
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
// 서버에 파일 저장
$writer->save('hello world.xlsx');
위 코드는 가장 기초적인 사용법으로 특정 셀에 값을 입력하고 PHP 파일이 있는 위치에 엑셀을 저장하는 코드다.
실행을 해 보면 php 파일의 위치에 'hello world.xslx' 파일이 생성된다. 그리고 엑셀을 실행하면 A1 셀에 값이 입력이 되어 있다.
엑셀이 저장되는 폴더의 소유자가 웹서버가 아닌 경우에는 권한이 없다는 에러를 출력한다.
권한이 없어서 저장에 실패이런 에러가 발생한다면 폴더 소유를 웹서버로 변경 후에 다시 시도하면 정상적으로 저장이 된다.
위 내용을 토대로 반복문을 사용해서 여러 셀에 값을 입력을 할 수 있다.
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 행번호 초기화
$column = 'A';
$headers = ['번호', '작성일', '이름'];
foreach ($headers as $header) {
$sheet->setCellValue($column++ . '1', $header);
}
// 행번호 초기화
$column = 'A';
// 열번호 초기화
$rowNum = 2;
// 테스트 값
$values = [
['num' => 1, 'time' => '2021-10-01', 'name' => 'tester1'],
['num' => 2, 'time' => '2021-11-11', 'name' => 'tester2'],
['num' => 3, 'time' => '2021-12-21', 'name' => 'tester3']
];
foreach ($values as $value) {
$sheet->setCellValue($column++ . $rowNum, $value['num']);
$sheet->setCellValue($column++ . $rowNum, $value['time']);
$sheet->setCellValue($column . $rowNum++, $value['name']);
$column = 'A';
}
// 저장을 위한 파일작성자 생성
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
// 서버에 파일 저장
$writer->save('testers.xlsx');
위 처럼 반복문을 사용하면 많은 데이터를 더 편리하게 값을 입력 할 수 있다.
아니면 배열로 한번에 입력을 하는 방법도 있다.
<?php
// ... 시트 생성 ...
// 테스트 배열
$values = [
['번호', '작성일', '이름'],
[1, '2021-10-10', 'tester1'],
[2, '2021-11-21', 'tester2'],
[3, '2021-12-16', 'tester3'],
];
// 배열을 C3부터 입력
$sheet->fromArray($values, NULL, 'C3');
// ... 엑셀 저장 ...
fromArray() 함수를 사용하여 배열 값을 한번에 입력할 수 있다. fromArray(입력할 배열, NULL 데이터 대체값, 시작지점) 형태로 사용을 한다.
해당 함수를 확인해 보니 foreach문을 사용하고 있다. 결국, 직접 반복문을 사용하거나 제공되는 함수를 사용하거나 하는 차이인 것 같다.
3. 이미지 추가
이미지 추가는 서버에 저장된 파일을 넣는 방법과 외부 URL에서 불러오는 방법이 있다. 두 방법 모두 한 번에 하나의 이미지를 추가할 수 있다.
우선 서버에서 이미지를 불러와 추가하는 방법이다.
<?php
/* 로컬에서 이미지 추가 */
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 이미지 처리용 객체 생성
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
// 엑셀에 저장될 이미지 이름 설정
$drawing->setName('Test Image');
// 이미지 설명
$drawing->setDescription('Test Image Description');
// 이미지 경로
$drawing->setPath('./tiger.jpg');
// 이미지 자동 크기조절 비활성화
$drawing->setResizeProportional(false);
// 이미지 가로 세로 길이 설정(pixel 단위)
$drawing->setWidthAndHeight(64, 64);
// 이미지가 추가될 위치 지정
$drawing->setCoordinates('B2');
// 이미지를 sheet에 추가
$drawing->setWorksheet($sheet);
// 엑셀 문서 저장
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save('image-test.xlsx');
이미지 추가 예시엑셀 시트에 이미지를 넣는 기본적인 방법이다. PhpSpreadsheet에서 이미지를 추가할 기본 설정이 이미지 크기를 줄이지 않고 그대로 삽입한다. 그래서 크기 조절을 위해 가로, 세로 길이를 입력하면 자동으로 비율에 맞춰서 삽입을 한다.
그러니 이미지의 크기를 조절할 때 비율을 무시하고 직접 조정하고 싶다면 setResizeProportional(false)로 리사이징을 비활성화 해야 한다.
다음으로 URL에서 이미지를 호출하여 엑셀에 추가하는 방법이다. 이 방법을 사용하기 위해서는 php의 gd 확장 모듈을 사용한다.
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 테스트 이미지를 지원해주는 사이트를 사용
$imageUrl = 'http://placeimg.com/640/480/animals';
// 이미지의 확장자 확인
if (strpos($imageUrl, ".png")) {
$imageType = 'png';
$gdImage = imagecreatefrompng($imageUrl);
} else if (strpos($imageUrl, ".gif")) {
$imageType = 'gif';
$gdImage = imagecreatefromgif($imageUrl);
} else {
$imageType = 'jpeg';
$gdImage = imagecreatefromjpeg($imageUrl);
}
// php-gd 모듈을 사용하여 확장자별로 url에서 이미지 생성
if ($imageType === 'png') {
$gdImage = imagecreatefrompng($imageUrl);
} else if ($imageType === 'gif') {;
$gdImage = imagecreatefromgif($imageUrl);
} else {
$gdImage = imagecreatefromjpeg($imageUrl);
}
$drawing = new PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
$drawing->setName('Test Image');
$drawing->setDescription('Test Image Description');
$drawing->setResizeProportional(false);
$drawing->setImageResource($gdImage);
// 확장자별로 이미지 렌더링 및 mime 추가
if ($imageType === 'png') {
$drawing->setRenderingFunction(
\PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_PNG
);
$drawing->setMimeType(\PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_PNG);
} else if ($imageType === 'gif') {;
$drawing->setRenderingFunction(
\PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_GIF
);
$drawing->setMimeType(\PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_GIF);
} else {
$drawing->setRenderingFunction(
\PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_JPEG
);
$drawing->setMimeType(\PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_JPEG);
}
$drawing->setWidthAndHeight(128, 128);
$drawing->setCoordinates('B2');
$drawing->setWorksheet($sheet);
// 엑셀 문서 저장
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save('image-test-url.xlsx');
URL에서 불러온 이미지 추가gd 모듈을 사용하여 이미지를 불러온 후 sheet에 추가하는 예시 코드다.
이미지 확장자가 여러가지 있지만 PhpSpreadsheet에서 지원하는 확장자는 png, gif, jpeg 세 가지다. MimeType을 설정하는 기본 값이 jpeg로 되어 있다. 그래서 png와 gif인지를 먼저 구분한 후 이외의 것들은 모두 jpeg로 판단하고 처리를 한다.
이미지를 처리하는 코드는 한 번에 하나를 처리하고 세세한 설정에 들어가면 코드가 길어지므로 별개의 함수로 만들어 사용하는 것을 추천한다.
4. 셀 스타일 변경
PhpSpreadsheet에서 셀 스타일을 변경하려면 조금 번거롭다.
<?php
//... 시트 생성 ...
// 테스트 값
$values = [
['색상', '정렬', '테두리-위',],
['테두리-아래', '배경색'],
];
//테스트 값 입력
$sheet->fromArray($values, NULL, 'B2');
// 글 색상 변경
$sheet->getStyle('B2')->getFont()
->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);
// 정렬
$sheet->getStyle('C2')->getAlignment()
->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT);
// 셀 위 테두리
$sheet->getStyle('D2')->getBorders()
->getTop()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE);
// 셀 아래 테두리
$sheet->getStyle('B3')->getBorders()
->getBottom()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK);
// 셀 테두리 색상
$sheet->getStyle('C3')->getBorders()
->getBottom()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN)
->setColor(new \PhpOffice\PhpSpreadsheet\Style\Color('FF2800C9'));
// 배경색
$sheet->getStyle('D3')->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('FFFF0000');
// ... 시트 저장 ...
셀 스타일링 예시
기본적으로 사용되는 서식의 변경 방법이다. 서식 변경을 원하는 셀의 스타일을 불러온 후 색상, 테두리 등 원하는 설정을 변경하는 방식이다. 테두리의 경우 색을 지정하지 않으면 검은색으로 지정이 된다.
색상을 지정할 때 PhpSpreadsheet는 ARGB 형식을 사용하는데 일반적인 RGB에 불투명도를 추가한 형식이다. 총 8자리로 표현하는데 앞의 두 자리가 불투명도(00~FF)를 나타낸다. 세세하게 색을 변경할 것이 아니라면 FF를 사용하면 된다.
만약 한번에 여러 셀을 변경하고 싶다면 'B1:F1'과 같은 형식으로 사용하면 된다.
<?php
//... 생략
// B1에서 F1까지 범위의 글 색상 변경
$sheet->getStyle('B1:F1')->getFont()
->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);