6년 전 필자는 PHP를 사용하여 데이터를 Microsoft® Excel® 스프레드시트로 내보내는 방법을 다룬 "Read and write Excel data with PHP"라는 기사를 작성했다. 알다시피 이 기사는 다음 기사를 고대할 정도로 인기가 많이 있었다. 첫 번째 기사에서는 Excel의 강력한 기능을 개괄하는 데 그쳤다. 그러나 이번 기사에서는 Excel의 내보내기 기능의 유용성을 보여주는 예제를 통해 더 고급 기능 중 하나인 피벗 테이블을 사용하는 방법을 설명할 것이다.
고급 Excel 내보내기 기능을 PHP와 함께 사용하여 피벗 테이블 작성
피벗 테이블은 행 표제 및 열 표제로 사용되는 필드와 각 셀의 데이터로 표현되는 것을 사용자가 동적으로 선택할 수 있는 테이블이다. 피벗 테이블에는 필드를 즉시 재배열할 수 있는 기능이 있어서 사용자는 복잡한 질문에 응답할 수 있을 뿐만 아니라 데이터에서 중요한 패턴을 찾을 수도 있다.
그림 1에는 기본적인 Excel 스프레드시트가 표시되어 있다. 첫 번째 행에는 필드 이름(Account, Genre, Images, Average Ran, Total Size)이 포함되어 있고 그 다음 행에는 데이터가 포함되어 있다. 이 경우에는 이미지 스토리지 사이트(예: Flickr)의 내보내기 기능을 살펴볼 것이다. 각 행에는 이미지 유형, 업로드된 이미지 수, 이미지의 평균 순위 및 결합된 모든 이미지의 총 크기(바이트)와 같은 정보가 포함되어 있다.
그림 1. 기본 Excel 테이블
Excel로 피벗 테이블을 작성하려면 피벗 테이블로 사용할 데이터 열을 선택한 후, Data 메뉴에서 PivotTable Report 메뉴 항목을 선택한다. 그러면 보고서에서 사용할 데이터를 지정하는 프롬프트가 마법사에 표시된다. 마법사가 완료되면 Excel 파일에 시트가 새로 추가된다.
그림 2에는 창 위에 PivotTable 도구 모음이 겹쳐 있는 빈 피벗 테이블이 표시되어 있다. 이 스프레드시트에는 각 필드 항목을 끌어 놓아서 보고서를 생성할 수 있는 영역이 있다.
그림 2. 피벗 테이블 작성
그림 3에는 PivotTable 도구 모음이 자세히 표시되어 있다. 맨 위에는 PivotTable 메뉴와 테이블의 깊이를 제어할 수 있는 몇 가지 도구 모음 단추가 있다. 도구 모음의 맨 아래에는 사용 가능한 필드(Account, Genre, Images, Average Ran, Total Size)가 있다.
그림 3. 피벗 도구 모음
피벗 테이블을 조정하려면 필드를 선택한 후, 이 필드를 해당 페이지의 적절한 영역에 놓는다. 그림 4에는 보고서 왼쪽에 유형과 계정 및 데이터 영역의 총 크기를 차례로 놓은 결과가 표시되어 있다.
그림 4. 데이터로 채워진 피벗 테이블
현재 이 보고서에는 유형과 계정으로 차례로 그룹화된 레코드가 표시되어 있다. 크기는 각 계정마다 표시한 후, 각 유형별로 합하여 총계를 표시한다. 필드를 끌어서 놓는 순서를 변경하면 표시되는 데이터의 순서를 간단하게 조정할 수 있다. 이러한 기능은 데이터를 탐색하는 데 필요한 매우 강력한 메커니즘이며 용량이 크거나 복잡한 데이터 세트가 있는 경우에는 사용할만한 가치가 있다.
Excel 스프레드시트를 XML 형식으로 저장하면 모든 데이터와 피벗 테이블 매개변수가 XML 파일에 저장된다. 목록 1에는 이 파일에 대한 예가 일부 표시되어 있다.
목록 1. Excel 내보내기 예제
<?xml version="1.0"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"> <Author>Jack Herrington</Author> <LastAuthor>Jack Herrington</LastAuthor> <Created>2011-03-26T21:15:20Z</Created> <LastSaved>2011-03-26T21:45:33Z</LastSaved> <Company>Myself</Company> <Version>12.0</Version> </DocumentProperties> ... </Workbook> |
예제 PHP 애플리케이션은 원시 데이터가 있는 워크시트와 PivotTable이 있는 워크시트가 하나씩 있는 Excel XML 파일을 작성한다. Excel로 파일을 작성했을 때와
마찬가지로 피벗 테이블 탭에서 모든 동적 기능을 사용할 수 있다.
시작하려면 먼저 데이터를 스프레드시트에 삽입해야 한다.
더 수월하게 하려면 목록 2와 같이 데이터를 XML 파일로 저장한다.
목록 2. data.xml
<users>
<user account="Megan" genre="Portraits" images="20"
avgrank="4.0" size="72000" />
<user account="Hannah" genre="Landscapes" images="31"
avgrank="3.5" size="83000" />
<user account="Vicky" genre="Floral" images="25"
avgrank="4.2" size="42000" />
<user account="Ian" genre="Portraits" images="40"
avgrank="3.7" size="92000" />
<user account="Michael" genre="Landscapes" images="23"
avgrank="3.8" size="72000" />
<user account="Daniel" genre="Landscapes" images="29"
avgrank="4.4" size="85000" />
</users>
|
XML의 루트는 각 사용자 태그가 있는 users 태그이다. 각 user 태그에는 account, genre, images, avgrank 및 size 속성이 포함되어 있다. 이러한 속성은
각 계정의 관련 데이터를 유지한다.
간단한 data.php 파일에는 데이터를 읽는 데 필요한 load_data 함수가 포함되어 있다. 이 함수는 XML을 읽어서 해시 테이블의 배열로 데이터를
다시 리턴한다. 목록 3에는 이 함수의 코드가 표시되어 있다.
목록 3. data.php
<?php
function load_data() {
$xmlDoc = new DOMDocument();
$xmlDoc->load("data.xml");
$data = array();
foreach ($xmlDoc->documentElement->childNodes AS $item)
{
if ( $item->nodeType == XML_ELEMENT_NODE ) {
$data []= array( "account" => $item->getAttribute("account"),
"genre" => $item->getAttribute("genre"),
"images" => $item->getAttribute("images"),
"avgrank" => $item->getAttribute("avgrank"),
"size" => $item->getAttribute("size") );
}
}
return $data;
}
?>
|
이 코드에서는 먼저 해당 파일에서 XML을 로드하는 데 사용할 DOMDocument 오브젝트를 작성한다. 그 다음에는 foreach 루프를 사용하여 각 사용자 노드 전체를
반복하고 해당 속성을 데이터 배열에 저장한다. 그런 다음 호출자에게 이 데이터 배열을 리턴한다.
데이터 리더 이외에도 파일의 전체 컨텐츠를 표시하기 위해 print_file 함수를 사용한다.
목록 4에는 이 함수가 표시되어 있다.
목록 4. helpers.php
<?php
function print_file( $file ) {
print file_get_contents( $file );
}
?>
|
print_file 함수를 사용하는 이유는 간단하다. Excel XML 파일은 매우 복잡하다. 따라서 이 파일을 작성하는 가장 쉬운 방법은 먼저 XML로부터
파일을 내보낸 다음, 이 파일의 일부를 내보내기 파일의 시드 코드로 사용하는 것이다. 이 경우에는 파일의 맨 위에 있는 부분(첫 번째 통합 문서가 정의되어 있는 위치까지)을
복사하여 body_header.txt에 삽입한다. 이 파일의 맨 아래 부분(마지막 통합 문서가 끝나는 지점 이후)은 body_footer.txt에 저장한다.
비슷한 파일인 data_header.txt와 data_footer.txt를 사용하여 스프레드시트의 Data 탭에 있는 테이블을 괄호로 묶는다.
데이터 리더와 파일 프린터가 준비되면 Excel 스프레드시트 작성을 시작할 수 있다. 목록 5에는 첫 번째 Excel 내보내기 코드가 표시되어 있다.
목록 5. helpers.php
<?php
require_once 'data.php';
require_once 'helpers.php';
require_once 'exporters.php';
$data = load_data();
print_file( 'body_header.txt' );
print_file( 'data_header.txt' );
?>
<Table ss:ExpandedColumnCount="5"
ss:ExpandedRowCount="<?php echo( count($data) + 1 ) ?>" x:FullColumns="1"
x:FullRows="1">
<Row>
<Cell ss:StyleID="s21"><Data ss:Type="String">Account</Data></Cell>
<Cell ss:StyleID="s21"><Data ss:Type="String">Genre</Data></Cell>
<Cell ss:StyleID="s21"><Data ss:Type="String">Images</Data></Cell>
<Cell ss:StyleID="s21"><Data ss:Type="String">Average Ranking</Data></Cell>
<Cell ss:StyleID="s21"><Data ss:Type="String">Total Size</Data></Cell>
</Row>
<?php foreach( $data as $row ) { ?>
<Row>
<Cell><Data ss:Type="String"><?php echo( $row['account'] ) ?></Data></Cell>
<Cell><Data ss:Type="String"><?php echo( $row['genre'] ) ?></Data></Cell>
<Cell><Data ss:Type="Number"><?php echo( $row['images'] ) ?></Data></Cell>
<Cell><Data ss:Type="Number"><?php echo( $row['avgrank'] ) ?></Data></Cell>
<Cell><Data ss:Type="Number"><?php echo( $row['size'] ) ?></Data></Cell>
</Row>
<?php } ?>
</Table>
<?php
print_file( 'data_footer.txt' );
print_file( 'body_footer.txt' );
?>
|
이 코드에서는 먼저 데이터를 읽고 본문과 데이터 헤더를 인쇄한다. 그 다음에는 XML 코드로 데이터 헤더가 첫 번째 행에 있는 테이블을 정의한다. 그리고
foreach 루프를 사용하여 각 데이터 항목을 반복하고 데이터가 있는 행을 새로 작성한다.
프로그램이 실행되면 그 결과물이 Excel에서 열리는 파일에 저장된다. 결과는 그림 5에 있는 결과와 비슷하다.
그림 5. PHP를 사용하여 내보낸 기본 테이블
그림 5에는 원래의 파일과 마찬가지로 적절하게 형식화된 데이터가 표시되어 있다. 첫 번째 행에는 필드의 표제가 표시되고 각각의 후속 행에는 데이터가 있다.
독자가 사용하는 필드와 데이터는 여기에서 사용한 것과 다를 것이기 때문에 Excel을 내보내는 데 사용할 코드는 이 코드와 정확히 같지는 않을 것이다. 그러나 먼저 Excel 파일을 작성하고 헤더와 푸터 섹션을 잘라낸 후, 자신의 데이터를 시트에 삽입하는 시트 작성 프로세스는 동일하다.
피벗 테이블 스프레드시트는 약간 더 복잡하지만, 개념은 거의 동일하다. 스크립트에서는 먼저 데이터를 읽은 후, 본문 헤더를 인쇄한다. 그런 다음, 데이터 페이지와 피벗 테이블 및 푸터 페이지를 차례로 인쇄한다. 목록 6에는 이 프로세스를 처리하는 코드가 표시되어 있다.
목록 6. build2.php
<?php require_once 'data.php'; require_once 'helpers.php'; require_once 'exporters.php'; header( 'Content-type: application/excel' ); header( 'Content-Disposition: attachment; filename="pivot.xml"' ); $data = load_data(); print_file( 'body_header.txt' ); export_data( $data ); export_pivot( $data ); print_file( 'body_footer.txt' ); ?> |
중요한 점은 시작 부분에서 header 함수를 호출하여 브라우저에게 이 파일을 어떻게 처리해야 하는지를 알려준다는 사실이다. Content-type 헤더를 사용하여
이 스크립트가 Excel 스프레드시트를 내보낸다는 점을 브라우저에게 알린다. 또한, Content-disposition 헤더를 사용하여 이 스프레드시트가 파일로 저장되며
이름은 pivot.xml이라는 사실을 브라우저에게 알린다.
많은 작업이 export 함수로 수행되며 이 함수는 목록 7에 있는 exporters.php에 정의되어 있다.
목록 7. exporters.php
<?php
require_once 'helpers.php';
function export_data( $data ) {
print_file( 'data_header.txt' );
?>
<Table ss:ExpandedColumnCount="5"
ss:ExpandedRowCount="<?php echo( count($data) + 1 ) ?>" x:FullColumns="1"
x:FullRows="1">
...
</Table>
<?php
print_file( 'data_footer.txt' );
}
function export_pivot( $data ) {
?>
<Worksheet ss:Name="Pivot 1">
<?php
export_pivot_table( $data );
export_pivot_worksheet_options( $data );
export_pivot_pivottable( $data );
?>
</Worksheet>
<?php
export_pivotcache( $data );
}
function export_pivot_table( $data ) {
?>
<Table ss:ExpandedColumnCount="2"
ss:ExpandedRowCount="<?php echo( count($data) + 5 ) ?>" x:FullColumns="1"
x:FullRows="1">
<Column ss:Width="96.0"/>
<Column ss:AutoFitWidth="0" ss:Width="49.0"/>
<Row ss:Index="3">
<Cell ss:StyleID="s22">
<Data ss:Type="String">Sum of Total Size</Data>
</Cell>
<Cell ss:StyleID="s24"/>
</Row>
<Row>
<Cell ss:StyleID="s34">
<Data ss:Type="String">Account</Data>
</Cell>
<Cell ss:StyleID="s24">
<Data ss:Type="String">Total</Data>
</Cell>
</Row>
<?php
$total = 0;
foreach( $data as $row ) {
$total += intval( $row['size'] );
?>
<Row>
<Cell ss:StyleID="s22">
<Data ss:Type="String"><?php echo( $row['account'] ) ?></Data>
</Cell>
<Cell ss:StyleID="s26">
<Data ss:Type="Number"><?php echo( $row['size'] ) ?></Data>
</Cell>
</Row>
<?php } ?>
<Row>
<Cell ss:StyleID="s31">
<Data ss:Type="String">Grand Total</Data>
</Cell>
<Cell ss:StyleID="s33">
<Data ss:Type="Number"><?php echo( $total ) ?></Data>
</Cell>
</Row>
</Table>
<?php
}
function export_pivot_pivottable( $data ) {
?>
<PivotTable xmlns="urn:schemas-microsoft-com:office:excel">
...
</PivotTable>
<?php
}
function export_pivot_worksheet_options( $data ) {
?>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
...
</WorksheetOptions>
<?php
}
function export_pivotcache( $data ) {
?>
<PivotCache xmlns="urn:schemas-microsoft-com:office:excel">
...
<?php foreach( $data as $row ) { ?>
<row Col1="<?php echo( $row['account'] ) ?>" Col2="<?php echo( $row['genre'] ) ?>"
Col3="<?php echo( $row['images'] ) ?>" Col4="<?php echo( $row['avgrank'] ) ?>"
Col5="<?php echo( $row['size'] ) ?>" xmlns="#RowsetSchema"/>
<?php } ?>
</data>
</PivotCache>
<?php
}
?>
|
이러한 함수의 컨텐츠 중 대부분은 공간을 절약하기 위해 제거되었다. 완전한 작업 코드는 excelpivotxml.zip 다운로드 파일에 있다(다운로드 참조). 첫 번째 함수인
export_data는 첫 번째 스크립트에서 데이터를 내보내는 데 사용되었다. 피벗 테이블 탭을 작성하기 위해 export_pivot 함수를 사용하여
먼저 워크시트를 작성한 다음, 데이터 테이블, 워크시트 옵션 및 PivotTable XML을 추가한다. PivotCache는 워크시트가 완료된 후에 마지막으로 작성한다.
솔직히 말해서 피벗 테이블을 정의하는 데는 이렇게 많은 XML 코드를 사용할 필요가 없다. 분명히 이 코드는 간단한 데이터 테이블을 처리하는 코드보다 더 양이 많다. 그러나 피벗 테이블을 Excel로 작성하여 XML로 저장한 후, 이 XML 코드를 자신의 코드에 필요한 템플리트로 사용할 수 있다는 점은 좋은 점이다.
이 PHP 스크립트를 실행하고 그 결과를 파일에 저장한 후, Excel에서 이 파일을 열어서 그림 6과 같은 결과를 확인한다.
그림 6. 내보낸 피벗 테이블
그림 6의 피벗 테이블에는 각 계정과 계정별 총계(크기)가 있고 마지막에는 전체 계정 총계가 표시되어 있다. Excel 피벗 테이블이 정확히 작성되었기 때문에 PivotTable 도구 모음이 창 위에 표시된다. 이제는 이 도구 모음을 사용하여 필드를 추가하고 테이블을 조정할 수 있다.
XML 형식의 Excel을 사용하는 것이 약간 복잡하기는 하지만, 저장된 XML 파일을 내보낼 스프레드시트를 작성하는 데 필요한 템플리트로 사용할 수 있다. 이러한 접근 방식을 이용하면 사용자가 자신이 확인하고 싶은 스프레드시트를 작성하게 할 수 있는 수단과 XML 파일을 생성하는 프로세스를 대폭 단순화할 수 있으며 그런 다음에는 스프레드시트를 내보내어 여기에 실시간 데이터를 즉시 채울 수 있다. 이러한 방법은 계속해서 서버에서 PHP와 XML을 사용하면서 고객에게 새로운 가치를 제공할 수 있는 우수한 방법이다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Source code for article | excelpivotxml.zip | HTTP |
교육
- Read and write Excel data with PHP: Using XML support(Jack D. Herrington, developerWorks, 2010년 8월 업데이트됨, 원본은 2005년 10월에 발행됨):
Microsoft Excel 2003에서 내보낸 XML에서 데이터를 읽을 수 있는, PHP의 XML 지원 기능에 관한 원래의 Excel PHP 기사를 읽어보자.
- Microsoft Office XML formats(Wikipedia): 비슷한 XML 형식(특히 Open Office의 XML 형식)을 비교한 내용이 있는 Excel 파일 형식 관련 논의를 정독하자.
- PHP: 하이퍼텍스트 프리프로세서 웹 사이트: 사용 가능한 최상의 PHP 참고자료를 살펴보자.
- W3C 웹 사이트: 다양한 표준을 확인할 수 있는 이 우수한 사이트를 탐색하자. 특히 XML 표준은 이 기사와도 관련이 있다.
- Excel에서 지원되는 파일 형식: Microsoft 사이트에서 자세한 정보를 확인하자.
- Microsoft Office XML formats(Wikipedia): 모든 Microsoft Office 애플리케이션은 XML을 지원한다. Excel이 독자와 관련이 없으면 독자에게 더 중요한 다른 형식을
확인해 보자.
- 필자의 더 많은 기사(Jack Herrington저, developerWorks, 2005년 3월 - 현재): Ajax, JSON, PHP, XML 및 다른 기술에 대한 기사를 읽어보자.
- developerWorks의 XML 영역: XML 분야의 기술을 향상시키는 데 도움이 되는 참고자료를 얻을 수 있다.
- developerWorks 오픈 소스 영역: 오픈 소스 기술을 활용하여 개발 작업을 수행하고 이러한 기술을 IBM 제품과 함께 사용하는 데 도움이 되는 사용법 정보, 도구 및 프로젝트 업데이트와
IBM에서 가장 인기있는 기사 및 튜토리얼을 확인할 수 있다.
- My developerWorks: developerWorks와 관련된 경험을 개인화할 수 있다.
- IBM XML 인증: XML 및 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾아볼 수 있다.
- XML 기술 자료: developerWorks XML 영역에서 다양한 기술 관련 기사와 팁, 튜토리얼, 표준 및 IBM Redbook을 볼 수 있다. 또한 더 많은 XML 팁을 읽어본다.
- developerWorks 기술 행사 및 웹 캐스트: 이러한 세션에 참가하여 최신 기술에 대한 정보를 얻을 수 있다.
- Twitter의 developerWorks 페이지: 오늘 가입하여 developerWorks 트윗을 팔로우하자.
- developerWorks
podcasts: 소프트웨어 개발자의 흥미로운 인터뷰와 토론을 확인할 수 있다.
- developerWorks on-demand demos: 입문자를 위한 제품 설치 및 설정 과정에서 숙련된 개발자를 위한 고급 기능의 활용에 이르기까지 다양한 데모를 제공한다.
제품 및 기술 얻기
- IBM 제품 평가판: IBM SQA Sandbox의 온라인 시험판을 다운로드하거나 살펴보고
DB2®, Lotus®, Rational®, Tivoli® 및 WebSphere® 애플리케이션 개발 도구 및 미들웨어 제품을 사용해 볼 수 있다.
토론
- XML 영역 토론 포럼: 여러 XML 관련 토론에 참여해 볼 수 있다.
- developerWorks 커뮤니티: 개발자가 운영하고 있는 블로그,
포럼, 그룹 및 위키를 살펴보면서 다른 developerWorks 사용자와 의견을 나눌 수 있다.
Jack D. Herrington은 20년 경력의 소프트웨어 엔지니어이다. Code Generation in Action, Podcasting Hacks, PHP Hacks(출간 예정)의 저자이기도 하다. 30개 이상의 기술자료도 집필했다. (jack_d_herrington@codegeneration.net)