001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.servlet.view.document;
018:
019: import java.util.Locale;
020: import java.util.Map;
021:
022: import javax.servlet.ServletOutputStream;
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025:
026: import org.apache.poi.hssf.usermodel.HSSFCell;
027: import org.apache.poi.hssf.usermodel.HSSFRow;
028: import org.apache.poi.hssf.usermodel.HSSFSheet;
029: import org.apache.poi.hssf.usermodel.HSSFWorkbook;
030: import org.apache.poi.poifs.filesystem.POIFSFileSystem;
031:
032: import org.springframework.core.io.Resource;
033: import org.springframework.core.io.support.LocalizedResourceHelper;
034: import org.springframework.web.servlet.support.RequestContextUtils;
035: import org.springframework.web.servlet.view.AbstractView;
036:
037: /**
038: * Convenient superclass for Excel document views.
039: *
040: * <p>Properties:
041: * <ul>
042: * <li>url (optional): The url of an existing Excel document to pick as a starting point.
043: * It is done without localization part nor the ".xls" extension.
044: * </ul>
045: *
046: * <p>The file will be searched with locations in the following order:
047: * <ul>
048: * <li>[url]_[language]_[country].xls
049: * <li>[url]_[language].xls
050: * <li>[url].xls
051: * </ul>
052: *
053: * <p>For working with the workbook in the subclass, see
054: * <a href="http://jakarta.apache.org/poi/index.html">Jakarta's POI site</a>
055: *
056: * <p>As an example, you can try this snippet:
057: *
058: * <pre>
059: * protected void buildExcelDocument(
060: * Map model, HSSFWorkbook workbook,
061: * HttpServletRequest request, HttpServletResponse response) {
062: *
063: * // Go to the first sheet.
064: * // getSheetAt: only if workbook is created from an existing document
065: * // HSSFSheet sheet = workbook.getSheetAt(0);
066: * HSSFSheet sheet = workbook.createSheet("Spring");
067: * sheet.setDefaultColumnWidth(12);
068: *
069: * // Write a text at A1.
070: * HSSFCell cell = getCell(sheet, 0, 0);
071: * setText(cell, "Spring POI test");
072: *
073: * // Write the current date at A2.
074: * HSSFCellStyle dateStyle = workbook.createCellStyle();
075: * dateStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
076: * cell = getCell(sheet, 1, 0);
077: * cell.setCellValue(new Date());
078: * cell.setCellStyle(dateStyle);
079: *
080: * // Write a number at A3
081: * getCell(sheet, 2, 0).setCellValue(458);
082: *
083: * // Write a range of numbers.
084: * HSSFRow sheetRow = sheet.createRow(3);
085: * for (short i = 0; i < 10; i++) {
086: * sheetRow.createCell(i).setCellValue(i * 10);
087: * }
088: * }</pre>
089: *
090: * This class is similar to the AbstractPdfView class in usage style.
091: *
092: * @author Jean-Pierre Pawlak
093: * @author Juergen Hoeller
094: * @see AbstractPdfView
095: */
096: public abstract class AbstractExcelView extends AbstractView {
097:
098: /** The content type for an Excel response */
099: private static final String CONTENT_TYPE = "application/vnd.ms-excel";
100:
101: /** The extension to look for existing templates */
102: private static final String EXTENSION = ".xls";
103:
104: private String url;
105:
106: /**
107: * Default Constructor.
108: * Sets the content type of the view to "application/vnd.ms-excel".
109: */
110: public AbstractExcelView() {
111: setContentType(CONTENT_TYPE);
112: }
113:
114: /**
115: * Set the URL of the Excel workbook source, without localization part nor extension.
116: */
117: public void setUrl(String url) {
118: this .url = url;
119: }
120:
121: /**
122: * Renders the Excel view, given the specified model.
123: */
124: protected final void renderMergedOutputModel(Map model,
125: HttpServletRequest request, HttpServletResponse response)
126: throws Exception {
127:
128: HSSFWorkbook workbook;
129: if (this .url != null) {
130: workbook = getTemplateSource(this .url, request);
131: } else {
132: workbook = new HSSFWorkbook();
133: logger.debug("Created Excel Workbook from scratch");
134: }
135:
136: buildExcelDocument(model, workbook, request, response);
137:
138: // response.setContentLength(workbook.getBytes().length);
139: response.setContentType(getContentType());
140: ServletOutputStream out = response.getOutputStream();
141: workbook.write(out);
142: out.flush();
143: }
144:
145: /**
146: * Creates the workbook from an existing XLS document.
147: * @param url the URL of the Excel template without localization part nor extension
148: * @param request current HTTP request
149: * @return the HSSFWorkbook
150: * @throws Exception in case of failure
151: */
152: protected HSSFWorkbook getTemplateSource(String url,
153: HttpServletRequest request) throws Exception {
154: LocalizedResourceHelper helper = new LocalizedResourceHelper(
155: getApplicationContext());
156: Locale userLocale = RequestContextUtils.getLocale(request);
157: Resource inputFile = helper.findLocalizedResource(url,
158: EXTENSION, userLocale);
159:
160: // Create the Excel document from the source.
161: if (logger.isDebugEnabled()) {
162: logger.debug("Loading Excel workbook from " + inputFile);
163: }
164: POIFSFileSystem fs = new POIFSFileSystem(inputFile
165: .getInputStream());
166: HSSFWorkbook workBook = new HSSFWorkbook(fs);
167: return workBook;
168: }
169:
170: /**
171: * Subclasses must implement this method to create an Excel HSSFWorkbook document,
172: * given the model.
173: * @param model the model Map
174: * @param workbook the Excel workbook to complete
175: * @param request in case we need locale etc. Shouldn't look at attributes.
176: * @param response in case we need to set cookies. Shouldn't write to it.
177: */
178: protected abstract void buildExcelDocument(Map model,
179: HSSFWorkbook workbook, HttpServletRequest request,
180: HttpServletResponse response) throws Exception;
181:
182: /**
183: * Convenient method to obtain the cell in the given sheet, row and column.
184: * <p>Creates the row and the cell if they still doesn't already exist.
185: * Thus, the column can be passed as an int, the method making the needed downcasts.
186: * @param sheet a sheet object. The first sheet is usually obtained by workbook.getSheetAt(0)
187: * @param row thr row number
188: * @param col the column number
189: * @return the HSSFCell
190: */
191: protected HSSFCell getCell(HSSFSheet sheet, int row, int col) {
192: HSSFRow sheetRow = sheet.getRow(row);
193: if (sheetRow == null) {
194: sheetRow = sheet.createRow(row);
195: }
196: HSSFCell cell = sheetRow.getCell((short) col);
197: if (cell == null) {
198: cell = sheetRow.createCell((short) col);
199: }
200: return cell;
201: }
202:
203: /**
204: * Convenient method to set a String as text content in a cell.
205: * @param cell the cell in which the text must be put
206: * @param text the text to put in the cell
207: */
208: protected void setText(HSSFCell cell, String text) {
209: cell.setCellType(HSSFCell.CELL_TYPE_STRING);
210: cell.setCellValue(text);
211: }
212:
213: }
|