Source Code Cross Referenced for ExcelPrinter.java in  » Report » pentaho-report » org » jfree » report » modules » output » table » xls » helper » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Report » pentaho report » org.jfree.report.modules.output.table.xls.helper 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * ===========================================
003:         * JFreeReport : a free Java reporting library
004:         * ===========================================
005:         *
006:         * Project Info:  http://reporting.pentaho.org/
007:         *
008:         * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
009:         *
010:         * This library is free software; you can redistribute it and/or modify it under the terms
011:         * of the GNU Lesser General Public License as published by the Free Software Foundation;
012:         * either version 2.1 of the License, or (at your option) any later version.
013:         *
014:         * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015:         * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016:         * See the GNU Lesser General Public License for more details.
017:         *
018:         * You should have received a copy of the GNU Lesser General Public License along with this
019:         * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020:         * Boston, MA 02111-1307, USA.
021:         *
022:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023:         * in the United States and other countries.]
024:         *
025:         * ------------
026:         * ExcelPrinter.java
027:         * ------------
028:         * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029:         */package org.jfree.report.modules.output.table.xls.helper;
030:
031:        import java.awt.Graphics2D;
032:        import java.awt.Image;
033:        import java.awt.Shape;
034:        import java.awt.image.BufferedImage;
035:        import java.io.BufferedInputStream;
036:        import java.io.IOException;
037:        import java.io.InputStream;
038:        import java.io.OutputStream;
039:        import java.net.URL;
040:        import java.util.Date;
041:        import java.util.HashMap;
042:
043:        import org.apache.poi.hssf.usermodel.HSSFCell;
044:        import org.apache.poi.hssf.usermodel.HSSFCellStyle;
045:        import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
046:        import org.apache.poi.hssf.usermodel.HSSFPatriarch;
047:        import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
048:        import org.apache.poi.hssf.usermodel.HSSFRichTextString;
049:        import org.apache.poi.hssf.usermodel.HSSFRow;
050:        import org.apache.poi.hssf.usermodel.HSSFSheet;
051:        import org.apache.poi.hssf.usermodel.HSSFWorkbook;
052:        import org.apache.poi.hssf.util.Region;
053:        import org.apache.poi.poifs.filesystem.POIFSFileSystem;
054:        import org.jfree.io.IOUtils;
055:        import org.jfree.report.Anchor;
056:        import org.jfree.report.ElementAlignment;
057:        import org.jfree.report.ImageContainer;
058:        import org.jfree.report.InvalidReportStateException;
059:        import org.jfree.report.LocalImageContainer;
060:        import org.jfree.report.URLImageContainer;
061:        import org.jfree.report.DefaultImageReference;
062:        import org.jfree.report.layout.model.LogicalPageBox;
063:        import org.jfree.report.layout.model.PhysicalPageBox;
064:        import org.jfree.report.layout.model.RenderBox;
065:        import org.jfree.report.layout.model.RenderNode;
066:        import org.jfree.report.layout.output.LogicalPageKey;
067:        import org.jfree.report.layout.output.OutputProcessorMetaData;
068:        import org.jfree.report.layout.output.RenderUtility;
069:        import org.jfree.report.layout.output.OutputProcessorFeature;
070:        import org.jfree.report.modules.output.table.base.SheetLayout;
071:        import org.jfree.report.modules.output.table.base.TableCellDefinition;
072:        import org.jfree.report.modules.output.table.base.TableContentProducer;
073:        import org.jfree.report.modules.output.table.base.TableRectangle;
074:        import org.jfree.report.modules.output.table.xls.ExcelTableModule;
075:        import org.jfree.report.resourceloader.ImageFactory;
076:        import org.jfree.report.style.ElementStyleKeys;
077:        import org.jfree.report.style.StyleSheet;
078:        import org.jfree.report.util.ImageUtils;
079:        import org.jfree.report.util.IntegerCache;
080:        import org.jfree.report.util.MemoryByteArrayOutputStream;
081:        import org.jfree.report.util.geom.StrictBounds;
082:        import org.jfree.report.util.geom.StrictGeomUtility;
083:        import org.jfree.ui.Drawable;
084:        import org.jfree.util.Configuration;
085:        import org.jfree.util.Log;
086:        import org.jfree.util.StringUtils;
087:        import org.jfree.util.WaitingImageObserver;
088:
089:        /**
090:         * Creation-Date: 09.05.2007, 14:52:05
091:         *
092:         * @author Thomas Morgner
093:         */
094:        public class ExcelPrinter {
095:            private InputStream templateInputStream;
096:            private OutputStream outputStream;
097:            private HSSFWorkbook workbook;
098:            private HashMap sheetNamesCount;
099:            private double scaleFactor;
100:            private Configuration config;
101:            private OutputProcessorMetaData metaData;
102:            private HSSFSheet sheet;
103:            private HSSFPatriarch patriarch;
104:            private HSSFCellStyleProducer cellStyleProducer;
105:
106:            public ExcelPrinter() {
107:                this .sheetNamesCount = new HashMap();
108:            }
109:
110:            public void init(final Configuration config,
111:                    final OutputProcessorMetaData metaData,
112:                    final OutputStream outputStream) {
113:                this .outputStream = outputStream;
114:                this .config = config;
115:                this .metaData = metaData;
116:                try {
117:                    final String scaleFactorText = config
118:                            .getConfigProperty("org.jfree.report.modules.output.table.xls.CellWidthScaleFactor");
119:                    if (scaleFactorText == null) {
120:                        scaleFactor = 50;
121:                    } else {
122:                        scaleFactor = Double.parseDouble(scaleFactorText);
123:                    }
124:                } catch (Exception e) {
125:                    this .scaleFactor = 50;
126:                }
127:            }
128:
129:            public InputStream getTemplateInputStream() {
130:                return templateInputStream;
131:            }
132:
133:            public void setTemplateInputStream(
134:                    final InputStream templateInputStream) {
135:                this .templateInputStream = templateInputStream;
136:            }
137:
138:            private String makeUnique(final String name) {
139:                final Integer count = (Integer) sheetNamesCount.get(name);
140:                if (count == null) {
141:                    sheetNamesCount.put(name, IntegerCache.getInteger(1));
142:                    return name;
143:                }
144:
145:                final int value = count.intValue() + 1;
146:                sheetNamesCount.put(name, IntegerCache.getInteger(value));
147:                return makeUnique(name + ' ' + value);
148:            }
149:
150:            private boolean isValidSheetName(final String sheetname) {
151:                if ((sheetname.indexOf('/') > -1)
152:                        || (sheetname.indexOf('\\') > -1)
153:                        || (sheetname.indexOf('?') > -1)
154:                        || (sheetname.indexOf('*') > -1)
155:                        || (sheetname.indexOf(']') > -1)
156:                        || (sheetname.indexOf('[') > -1)
157:                        || (sheetname.indexOf(':') > -1)) {
158:                    return false;
159:                }
160:
161:                return true;
162:            }
163:
164:            private HSSFCell getCellAt(final short x, final int y) {
165:                final HSSFRow row = getRowAt(y);
166:                final HSSFCell cell = row.getCell(x);
167:                if (cell != null) {
168:                    return cell;
169:                }
170:                return row.createCell(x);
171:            }
172:
173:            private HSSFRow getRowAt(final int y) {
174:                final HSSFRow row = sheet.getRow(y);
175:                if (row != null) {
176:                    return row;
177:                }
178:                return sheet.createRow(y);
179:            }
180:
181:            public void print(final LogicalPageKey logicalPageKey,
182:                    final LogicalPageBox logicalPage,
183:                    final TableContentProducer contentProducer,
184:                    final boolean incremental) {
185:                if (workbook == null) {
186:                    workbook = createWorkbook();
187:
188:                    final boolean hardLimit = "true"
189:                            .equals(config
190:                                    .getConfigProperty("org.jfree.report.modules.output.table.xls.HardStyleCountLimit"));
191:                    cellStyleProducer = new HSSFCellStyleProducer(workbook,
192:                            hardLimit);
193:                }
194:
195:                if (sheet == null) {
196:                    sheet = openSheet(contentProducer.getSheetName());
197:                    // Start a new page.
198:                    final PhysicalPageBox page = logicalPage.getPageGrid()
199:                            .getPage(0, 0);
200:                    configureSheet(page);
201:
202:                    // Set column widths ..
203:                    final SheetLayout sheetLayout = contentProducer
204:                            .getSheetLayout();
205:                    final int columnCount = contentProducer.getColumnCount();
206:                    for (short col = 0; col < columnCount; col++) {
207:                        final double cellWidth = StrictGeomUtility
208:                                .toExternalValue(sheetLayout.getCellWidth(col,
209:                                        col + 1));
210:                        final double poiCellWidth = (cellWidth * scaleFactor);
211:                        sheet.setColumnWidth(col, (short) poiCellWidth);
212:                    }
213:
214:                    // ... and row heights ..
215:                    final int rowCount = contentProducer.getRowCount();
216:                    for (int row = 0; row < rowCount; row += 1) {
217:                        final HSSFRow hssfRow = getRowAt(row);
218:                        final double lastRowHeight = StrictGeomUtility
219:                                .toExternalValue(sheetLayout.getRowHeight(row));
220:                        hssfRow.setHeightInPoints((float) (lastRowHeight));
221:                    }
222:                }
223:
224:                // and finally the content ..
225:                final SheetLayout sheetLayout = contentProducer
226:                        .getSheetLayout();
227:                final int colCount = sheetLayout.getColumnCount();
228:                final int startRow = contentProducer.getFinishedRows();
229:                final int finishRow = contentProducer.getFilledRows();
230:                //Log.debug ("Excel: Processing: " + startRow + " " + finishRow + " " + incremental);
231:
232:                for (int row = startRow; row < finishRow; row++) {
233:                    for (short col = 0; col < colCount; col++) {
234:                        final RenderBox content = contentProducer.getContent(
235:                                row, col);
236:                        final TableCellDefinition background = sheetLayout
237:                                .getBackgroundAt(row, col);
238:
239:                        if (content == null && background == null) {
240:                            if (row == 0 && col == 0) {
241:                                // create a single cell, so that we dont run into nullpointer inside POI..
242:                                getCellAt(col, row);
243:                            }
244:                            // An empty cell .. ignore
245:                            continue;
246:                        }
247:                        if (content == null) {
248:                            // A empty cell with a defined background ..
249:                            final HSSFCell cell = getCellAt(col, row);
250:                            final HSSFCellStyle style = cellStyleProducer
251:                                    .createCellStyle(null, background);
252:                            if (style != null) {
253:                                cell.setCellStyle(style);
254:                            }
255:                            continue;
256:                        }
257:
258:                        if (content.isCommited() == false) {
259:                            throw new InvalidReportStateException(
260:                                    "Uncommited content encountered");
261:                        }
262:
263:                        final long contentOffset = contentProducer
264:                                .getContentOffset(row, col);
265:                        final TableRectangle rectangle = sheetLayout
266:                                .getTableBounds(content.getX(), content.getY()
267:                                        + contentOffset, content.getWidth(),
268:                                        content.getHeight(), null);
269:                        if (rectangle.isOrigin(col, row) == false) {
270:                            // A spanned cell ..
271:                            continue;
272:                        }
273:
274:                        final TableCellDefinition realBackground;
275:                        if (background == null
276:                                || (rectangle.getColumnSpan() == 1 && rectangle
277:                                        .getRowSpan() == 1)) {
278:                            realBackground = background;
279:                        } else {
280:                            realBackground = sheetLayout.getBackgroundAt(
281:                                    rectangle.getX1(), rectangle.getY1(),
282:                                    rectangle.getColumnSpan(), rectangle
283:                                            .getRowSpan());
284:                        }
285:                        // export the cell and all content ..
286:
287:                        final HSSFCell cell = getCellAt(col, row);
288:                        final HSSFCellStyle style = cellStyleProducer
289:                                .createCellStyle(content, realBackground);
290:                        if (style != null) {
291:                            cell.setCellStyle(style);
292:                        }
293:
294:                        if (applyCellValue(metaData, content, cell,
295:                                sheetLayout, rectangle, contentOffset)) {
296:                            mergeCellRegion(rectangle, row, col, sheetLayout,
297:                                    content);
298:                        }
299:
300:                        content.setFinished(true);
301:                    }
302:
303:                }
304:
305:                if (incremental == false) {
306:                    // cleanup ..
307:                    patriarch = null;
308:                    sheet = null;
309:                }
310:            }
311:
312:            private void mergeCellRegion(final TableRectangle rectangle,
313:                    final int row, final short col,
314:                    final SheetLayout sheetLayout, final RenderBox content) {
315:                final int rowSpan = rectangle.getRowSpan();
316:                final int columnSpan = rectangle.getColumnSpan();
317:                if (rowSpan > 1 || columnSpan > 1) {
318:                    sheet
319:                            .addMergedRegion(new Region(row, col, (row
320:                                    + rowSpan - 1),
321:                                    (short) (col + columnSpan - 1)));
322:                    final int rectX = rectangle.getX1();
323:                    final int rectY = rectangle.getY1();
324:
325:                    for (int spannedRow = 0; spannedRow < rowSpan; spannedRow += 1) {
326:                        for (int spannedCol = 0; spannedCol < columnSpan; spannedCol += 1) {
327:                            final TableCellDefinition bg = sheetLayout
328:                                    .getBackgroundAt(rectY + spannedRow, rectX
329:                                            + spannedCol);
330:                            final HSSFCell regionCell = getCellAt(
331:                                    (short) (col + spannedCol), row
332:                                            + spannedRow);
333:                            final HSSFCellStyle spannedStyle = cellStyleProducer
334:                                    .createCellStyle(content, bg);
335:                            if (spannedStyle != null) {
336:                                regionCell.setCellStyle(spannedStyle);
337:                            }
338:                        }
339:                    }
340:                }
341:            }
342:
343:            /**
344:             * Applies the cell value and determines whether the cell should be merged. Merging will only take place if the cell
345:             * has a row or colspan greater than one. Images will never be merged, as image content is rendered into an anchored
346:             * frame on top of the cells.
347:             *
348:             * @param content
349:             * @param cell
350:             * @param sheetLayout
351:             * @param rectangle
352:             * @return true, if the cell may to be put into a merged region, false otherwise.
353:             */
354:            private boolean applyCellValue(
355:                    final OutputProcessorMetaData metaData,
356:                    final RenderBox content, final HSSFCell cell,
357:                    final SheetLayout sheetLayout,
358:                    final TableRectangle rectangle, final long contentOffset) {
359:                final ExcelTextExtractor etx = new ExcelTextExtractor(metaData);
360:                final Object value = etx.compute(content, cellStyleProducer
361:                        .getFontFactory());
362:
363:                if (value instanceof  Image) {
364:                    try {
365:                        final ImageContainer imageContainer = new DefaultImageReference(
366:                                (Image) value);
367:                        final RenderNode rawSource = etx.getRawSource();
368:                        final StrictBounds contentBounds = new StrictBounds(
369:                                content.getX(), content.getY() + contentOffset,
370:                                content.getWidth(), content.getHeight());
371:                        createImageCell(rawSource, imageContainer, sheetLayout,
372:                                rectangle, contentBounds);
373:                    } catch (IOException ioe) {
374:                        // Should not happen.
375:                        Log.warn("Failed to process AWT-Image in Excel-Export",
376:                                ioe);
377:                    }
378:                    return false;
379:                } else if (value instanceof  ImageContainer) {
380:                    final ImageContainer imageContainer = (ImageContainer) value;
381:                    final RenderNode rawSource = etx.getRawSource();
382:                    final StrictBounds contentBounds = new StrictBounds(content
383:                            .getX(), content.getY() + contentOffset, content
384:                            .getWidth(), content.getHeight());
385:                    createImageCell(rawSource, imageContainer, sheetLayout,
386:                            rectangle, contentBounds);
387:                    return false;
388:                } else if (value instanceof  Drawable) {
389:                    final Drawable drawable = (Drawable) value;
390:                    final RenderNode rawSource = etx.getRawSource();
391:                    final StrictBounds contentBounds = new StrictBounds(
392:                            rawSource.getX(), rawSource.getY() + contentOffset,
393:                            rawSource.getWidth(), rawSource.getHeight());
394:                    final ImageContainer imageFromDrawable = RenderUtility
395:                            .createImageFromDrawable(drawable, contentBounds,
396:                                    content, metaData);
397:                    createImageCell(rawSource, imageFromDrawable, sheetLayout,
398:                            rectangle, contentBounds);
399:                    return false;
400:                } else if (value instanceof  Shape) {
401:                    // We *could* do this as well ... but for now we dont.
402:                    return false;
403:                }
404:
405:                final String linkTarget = (String) content.getStyleSheet()
406:                        .getStyleProperty(ElementStyleKeys.HREF_TARGET);
407:                if (linkTarget != null) {
408:                    // this may be wrong if we have quotes inside. We should escape them ..
409:                    cell.setCellFormula("HYPERLINK(\"" + linkTarget + "\",\""
410:                            + etx.getText() + "\")");
411:                } else if (value instanceof  HSSFRichTextString) {
412:                    cell.setCellValue((HSSFRichTextString) value);
413:                } else if (value instanceof  Date) {
414:                    cell.setCellValue((Date) value);
415:                } else if (value instanceof  Number) {
416:                    final Number number = (Number) value;
417:                    cell.setCellValue(number.doubleValue());
418:                } else if (value instanceof  Boolean) {
419:                    cell.setCellValue(Boolean.TRUE.equals(value));
420:                } else if (value instanceof  Anchor) {
421:                    // Anchors are not printable and therefore ignored.
422:                } else // Something we can't handle.
423:                {
424:                    if (value == null) {
425:                        cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
426:                    } else {
427:                        cell.setCellValue(new HSSFRichTextString(String
428:                                .valueOf(value)));
429:                    }
430:                }
431:                return true;
432:            }
433:
434:            private void configureSheet(final PhysicalPageBox page) {
435:                // make sure a new patriarch is created if needed.
436:                patriarch = null;
437:
438:                final String paper = config
439:                        .getConfigProperty(ExcelTableModule.CONFIGURATION_PREFIX
440:                                + ".Paper");
441:                final String orientation = config
442:                        .getConfigProperty(ExcelTableModule.CONFIGURATION_PREFIX
443:                                + ".PaperOrientation");
444:
445:                final HSSFPrintSetup printSetup = sheet.getPrintSetup();
446:                ExcelPrintSetupFactory.performPageSetup(printSetup, page,
447:                        paper, orientation);
448:
449:                final boolean displayGridLines = "true"
450:                        .equals(config
451:                                .getConfigProperty(ExcelTableModule.CONFIGURATION_PREFIX
452:                                        + ".GridLinesDisplayed"));
453:                final boolean printGridLines = "true"
454:                        .equals(config
455:                                .getConfigProperty(ExcelTableModule.CONFIGURATION_PREFIX
456:                                        + ".GridLinesPrinted"));
457:                sheet.setDisplayGridlines(displayGridLines);
458:                sheet.setPrintGridlines(printGridLines);
459:            }
460:
461:            public void close() {
462:                if (workbook != null) {
463:                    try {
464:                        workbook.write(outputStream);
465:                        // cleanup..
466:                        patriarch = null;
467:                        sheet = null;
468:                        outputStream.flush();
469:                    } catch (IOException e) {
470:                        Log.warn("could not write xls data. Message:", e);
471:                    } finally {
472:                        workbook = null;
473:                    }
474:                }
475:
476:            }
477:
478:            private HSSFWorkbook createWorkbook() {
479:                // Not opened yet. Lets do this now.
480:                if (templateInputStream != null) {
481:                    // do some preprocessing ..
482:                    try {
483:                        final POIFSFileSystem fs = new POIFSFileSystem(
484:                                templateInputStream);
485:                        final HSSFWorkbook workbook = new HSSFWorkbook(fs);
486:
487:                        // OK, we have a workbook, but we can't stop here..
488:                        final int sheetCount = workbook.getNumberOfSheets();
489:                        for (int i = 0; i < sheetCount; i++) {
490:                            final String sheetName = workbook.getSheetName(i);
491:                            // make sure that that name is marked as used ..
492:                            makeUnique(sheetName);
493:                        }
494:
495:                        // todo: Read in the existing styles, maybe we can reuse some of them ..
496:                        return workbook;
497:                    } catch (IOException e) {
498:                        Log.warn("Unable to read predefined xls-data.", e);
499:                    }
500:                }
501:                return new HSSFWorkbook();
502:            }
503:
504:            private HSSFSheet openSheet(final String sheetName) {
505:                if (sheetName == null) {
506:                    return workbook.createSheet();
507:                } else {
508:                    final String uniqueSheetname = makeUnique(sheetName);
509:                    if (uniqueSheetname.length() == 0
510:                            || uniqueSheetname.length() > 31) {
511:                        Log
512:                                .warn("A sheet name must not be empty and greater than 31 characters");
513:                        return workbook.createSheet();
514:                    } else if (isValidSheetName(uniqueSheetname) == false) {
515:                        Log
516:                                .warn("A sheet name must not contain any of ':/\\*?[]'");
517:                        // OpenOffice is even more restrictive and only allows Letters,
518:                        // Digits, Spaces and the Underscore
519:                        return workbook.createSheet();
520:                    } else {
521:                        return workbook.createSheet(uniqueSheetname);
522:                    }
523:                }
524:            }
525:
526:            /**
527:             * Produces the content for image or drawable cells. Excel does not support image-content in cells. Images are
528:             * rendered to an embedded OLE canvas instead, which is then positioned over the cell that would contain the image.
529:             *
530:             * @param contentNode the render node that contains the image.
531:             * @param image the image object
532:             * @param currentLayout the current sheet layout containing all row and column breaks
533:             * @param rectangle the current cell in grid-coordinates
534:             * @param cellBounds the bounds of the cell.
535:             */
536:            private void createImageCell(final RenderNode contentNode,
537:                    final ImageContainer image,
538:                    final SheetLayout currentLayout, TableRectangle rectangle,
539:                    final StrictBounds cellBounds) {
540:                try {
541:                    if (rectangle == null) {
542:                        // there was an error while computing the grid-position for this
543:                        // element. Evil me...
544:                        Log
545:                                .debug("Invalid reference: I was not able to compute "
546:                                        + "the rectangle for the content.");
547:                        return;
548:                    }
549:
550:                    final StyleSheet layoutContext = contentNode
551:                            .getStyleSheet();
552:                    final boolean shouldScale = layoutContext
553:                            .getBooleanStyleProperty(ElementStyleKeys.SCALE);
554:
555:                    final int imageWidth = image.getImageWidth();
556:                    final int imageHeight = image.getImageHeight();
557:                    if (imageWidth < 1 || imageHeight < 1) {
558:                        return;
559:                    }
560:
561:                    final double scaleFactor;
562:                    final double devResolution = metaData
563:                            .getNumericFeatureValue(OutputProcessorFeature.DEVICE_RESOLUTION);
564:                    if (metaData
565:                            .isFeatureSupported(OutputProcessorFeature.IMAGE_RESOLUTION_MAPPING)) {
566:                        if (devResolution != 72.0 && devResolution > 0) {
567:                            // Need to scale the device to its native resolution before attempting to draw the image..
568:                            scaleFactor = (devResolution / 72.0);
569:
570:                        } else {
571:                            scaleFactor = 1;
572:                        }
573:                    } else {
574:                        scaleFactor = 1;
575:                    }
576:
577:                    final ElementAlignment horizontalAlignment = (ElementAlignment) layoutContext
578:                            .getStyleProperty(ElementStyleKeys.ALIGNMENT);
579:                    final ElementAlignment verticalAlignment = (ElementAlignment) layoutContext
580:                            .getStyleProperty(ElementStyleKeys.VALIGNMENT);
581:
582:                    final long internalImageWidth = StrictGeomUtility
583:                            .toInternalValue(scaleFactor * imageWidth);
584:                    final long internalImageHeight = StrictGeomUtility
585:                            .toInternalValue(scaleFactor * imageHeight);
586:
587:                    final long cellWidth = cellBounds.getWidth();
588:                    final long cellHeight = cellBounds.getHeight();
589:
590:                    final StrictBounds cb;
591:                    final int pictureId;
592:                    if (shouldScale) {
593:                        final double scaleX;
594:                        final double scaleY;
595:
596:                        final boolean keepAspectRatio = layoutContext
597:                                .getBooleanStyleProperty(ElementStyleKeys.KEEP_ASPECT_RATIO);
598:                        if (keepAspectRatio) {
599:                            final double imgScaleFactor = Math.min(cellWidth
600:                                    / (double) internalImageWidth, cellHeight
601:                                    / (double) internalImageHeight);
602:                            scaleX = imgScaleFactor;
603:                            scaleY = imgScaleFactor;
604:                        } else {
605:                            scaleX = cellWidth / (double) internalImageWidth;
606:                            scaleY = cellHeight / (double) internalImageHeight;
607:                        }
608:
609:                        final long clipWidth = (long) (scaleX * internalImageWidth);
610:                        final long clipHeight = (long) (scaleY * internalImageHeight);
611:
612:                        final long alignmentX = RenderUtility
613:                                .computeHorizontalAlignment(
614:                                        horizontalAlignment, cellWidth,
615:                                        clipWidth);
616:                        final long alignmentY = RenderUtility
617:                                .computeVerticalAlignment(verticalAlignment,
618:                                        cellHeight, clipHeight);
619:
620:                        cb = new StrictBounds(cellBounds.getX() + alignmentX,
621:                                cellBounds.getY() + alignmentY, Math.min(
622:                                        clipWidth, cellWidth), Math.min(
623:                                        clipHeight, cellHeight));
624:
625:                        // Recompute the cells that this image will cover (now that it has been resized)
626:                        rectangle = currentLayout.getTableBounds(cb, rectangle);
627:
628:                        pictureId = loadImage(workbook, image);
629:                        if (pictureId <= 0) {
630:                            return;
631:                        }
632:                    } else {
633:                        // unscaled ..
634:                        if (internalImageWidth <= cellWidth
635:                                && internalImageHeight <= cellHeight) {
636:                            // No clipping needed.
637:                            final long alignmentX = RenderUtility
638:                                    .computeHorizontalAlignment(
639:                                            horizontalAlignment, cellBounds
640:                                                    .getWidth(),
641:                                            internalImageWidth);
642:                            final long alignmentY = RenderUtility
643:                                    .computeVerticalAlignment(
644:                                            verticalAlignment, cellBounds
645:                                                    .getHeight(),
646:                                            internalImageHeight);
647:
648:                            cb = new StrictBounds(cellBounds.getX()
649:                                    + alignmentX, cellBounds.getY()
650:                                    + alignmentY, internalImageWidth,
651:                                    internalImageHeight);
652:
653:                            // Recompute the cells that this image will cover (now that it has been resized)
654:                            rectangle = currentLayout.getTableBounds(cb,
655:                                    rectangle);
656:
657:                            pictureId = loadImage(workbook, image);
658:                            if (pictureId <= 0) {
659:                                return;
660:                            }
661:                        } else {
662:                            // at least somewhere there is clipping needed.
663:                            final long clipWidth = Math.min(cellWidth,
664:                                    internalImageWidth);
665:                            final long clipHeight = Math.min(cellHeight,
666:                                    internalImageHeight);
667:                            final long alignmentX = RenderUtility
668:                                    .computeHorizontalAlignment(
669:                                            horizontalAlignment, cellBounds
670:                                                    .getWidth(), clipWidth);
671:                            final long alignmentY = RenderUtility
672:                                    .computeVerticalAlignment(
673:                                            verticalAlignment, cellBounds
674:                                                    .getHeight(), clipHeight);
675:                            cb = new StrictBounds(cellBounds.getX()
676:                                    + alignmentX, cellBounds.getY()
677:                                    + alignmentY, clipWidth, clipHeight);
678:
679:                            // Recompute the cells that this image will cover (now that it has been resized)
680:                            rectangle = currentLayout.getTableBounds(cb,
681:                                    rectangle);
682:
683:                            pictureId = loadImageWithClipping(workbook, image,
684:                                    clipWidth, clipHeight, scaleFactor);
685:                            if (pictureId <= 0) {
686:                                return;
687:                            }
688:                        }
689:                    }
690:
691:                    final int cell1x = rectangle.getX1();
692:                    final int cell1y = rectangle.getY1();
693:                    final int cell2x = Math.max(cell1x, rectangle.getX2() - 1);
694:                    final int cell2y = Math.max(cell1y, rectangle.getY2() - 1);
695:
696:                    final long cell1width = currentLayout.getCellWidth(cell1x);
697:                    final long cell1height = currentLayout.getRowHeight(cell1y);
698:                    final long cell2width = currentLayout.getCellWidth(cell2x);
699:                    final long cell2height = currentLayout.getRowHeight(cell2y);
700:
701:                    final long cell1xPos = currentLayout.getXPosition(cell1x);
702:                    final long cell1yPos = currentLayout.getYPosition(cell1y);
703:                    final long cell2xPos = currentLayout.getXPosition(cell2x);
704:                    final long cell2yPos = currentLayout.getYPosition(cell2y);
705:
706:                    final int dx1 = (int) (1023 * ((cb.getX() - cell1xPos) / (double) cell1width));
707:                    final int dy1 = (int) (255 * ((cb.getY() - cell1yPos) / (double) cell1height));
708:                    final int dx2 = (int) (1023 * ((cb.getX() + cb.getWidth() - cell2xPos) / (double) cell2width));
709:                    final int dy2 = (int) (255 * ((cb.getY() + cb.getHeight() - cell2yPos) / (double) cell2height));
710:
711:                    final HSSFClientAnchor anchor = new HSSFClientAnchor(dx1,
712:                            dy1, dx2, dy2, (short) cell1x, cell1y,
713:                            (short) cell2x, cell2y);
714:                    anchor.setAnchorType(2); // Move, but don't size
715:                    if (patriarch == null) {
716:                        patriarch = sheet.createDrawingPatriarch();
717:                    }
718:                    patriarch.createPicture(anchor, pictureId);
719:                } catch (IOException e) {
720:                    Log.warn("Failed to add image. Ignoring.");
721:                }
722:            }
723:
724:            private int getImageFormat(final URL sourceURL) {
725:                final String file = sourceURL.getFile();
726:                if (StringUtils.endsWithIgnoreCase(file, ".png")) {
727:                    return HSSFWorkbook.PICTURE_TYPE_PNG;
728:                }
729:                if (StringUtils.endsWithIgnoreCase(file, ".jpg")
730:                        || StringUtils.endsWithIgnoreCase(file, ".jpeg")) {
731:                    return HSSFWorkbook.PICTURE_TYPE_JPEG;
732:                }
733:                if (StringUtils.endsWithIgnoreCase(file, ".bmp")
734:                        || StringUtils.endsWithIgnoreCase(file, ".ico")) {
735:                    return HSSFWorkbook.PICTURE_TYPE_DIB;
736:                }
737:                return -1;
738:            }
739:
740:            private int loadImageWithClipping(final HSSFWorkbook workbook,
741:                    final ImageContainer reference, final long clipWidth,
742:                    final long clipHeight, final double deviceScaleFactor)
743:                    throws IOException {
744:
745:                Image image = null;
746:                // The image has an assigned URL ...
747:                if (reference instanceof  URLImageContainer) {
748:                    final URLImageContainer urlImage = (URLImageContainer) reference;
749:                    final URL url = urlImage.getSourceURL();
750:                    // if we have an source to load the image data from ..
751:                    if (url != null && urlImage.isLoadable()) {
752:                        if (reference instanceof  LocalImageContainer) {
753:                            final LocalImageContainer li = (LocalImageContainer) reference;
754:                            image = li.getImage();
755:                        }
756:                        if (image == null) {
757:                            image = ImageFactory.getInstance().createImage(url);
758:                        }
759:                    }
760:                }
761:
762:                if (reference instanceof  LocalImageContainer) {
763:                    // Check, whether the imagereference contains an AWT image.
764:                    // if so, then we can use that image instance for the recoding
765:                    final LocalImageContainer li = (LocalImageContainer) reference;
766:                    if (image == null) {
767:                        image = li.getImage();
768:                    }
769:                }
770:
771:                if (image != null) {
772:                    // now encode the image. We don't need to create digest data
773:                    // for the image contents, as the image is perfectly identifyable
774:                    // by its URL
775:                    return clipAndEncodeImage(workbook, image, clipWidth,
776:                            clipHeight, deviceScaleFactor);
777:                }
778:                return -1;
779:            }
780:
781:            private int clipAndEncodeImage(final HSSFWorkbook workbook,
782:                    final Image image, final long width, final long height,
783:                    final double deviceScaleFactor) {
784:                final int imageWidth = (int) StrictGeomUtility
785:                        .toExternalValue(width);
786:                final int imageHeight = (int) StrictGeomUtility
787:                        .toExternalValue(height);
788:                // first clip.
789:                final BufferedImage bi = ImageUtils.createTransparentImage(
790:                        imageWidth, imageHeight);
791:                final Graphics2D graphics = (Graphics2D) bi.getGraphics();
792:                graphics.scale(deviceScaleFactor, deviceScaleFactor);
793:
794:                if (image instanceof  BufferedImage) {
795:                    //      final int imgW = image.getWidth(null);
796:                    //      final int imgH = image.getHeight(null);
797:                    //      graphics.translate((imageWidth - imgW) >> 1, (imageHeight - imgH) >> 1);
798:                    if (graphics.drawImage(image, null, null) == false) {
799:                        Log
800:                                .debug("Failed to render the image. This should not happen for BufferedImages");
801:                    }
802:                } else {
803:                    final WaitingImageObserver obs = new WaitingImageObserver(
804:                            image);
805:                    obs.waitImageLoaded();
806:                    //      final int imgW = image.getWidth(obs);
807:                    //      final int imgH = image.getHeight(obs);
808:                    //      graphics.translate((imageWidth - imgW) >> 1, (imageHeight - imgH) >> 1);
809:
810:                    while (graphics.drawImage(image, null, obs) == false) {
811:                        obs.waitImageLoaded();
812:                        if (obs.isError()) {
813:                            Log
814:                                    .warn("Error while loading the image during the rendering.");
815:                            break;
816:                        }
817:                    }
818:                }
819:
820:                graphics.dispose();
821:                final byte[] data = RenderUtility.encodeImage(bi);
822:                return workbook.addPicture(data, HSSFWorkbook.PICTURE_TYPE_PNG);
823:
824:            }
825:
826:            private int loadImage(final HSSFWorkbook workbook,
827:                    final ImageContainer reference) throws IOException {
828:                Image image = null;
829:                // The image has an assigned URL ...
830:                if (reference instanceof  URLImageContainer) {
831:                    final URLImageContainer urlImage = (URLImageContainer) reference;
832:                    final URL url = urlImage.getSourceURL();
833:                    // if we have an source to load the image data from ..
834:                    if (url != null && urlImage.isLoadable()) {
835:                        // and the image is one of the supported image formats ...
836:                        // we we can embedd it directly ...
837:                        final int format = getImageFormat(urlImage
838:                                .getSourceURL());
839:                        if (format == -1) {
840:                            // This is a unsupported image format.
841:                            if (reference instanceof  LocalImageContainer) {
842:                                final LocalImageContainer li = (LocalImageContainer) reference;
843:                                image = li.getImage();
844:                            }
845:                            if (image == null) {
846:                                image = ImageFactory.getInstance().createImage(
847:                                        url);
848:                            }
849:                        } else {
850:                            final MemoryByteArrayOutputStream bout = new MemoryByteArrayOutputStream();
851:                            final InputStream urlIn = new BufferedInputStream(
852:                                    urlImage.getSourceURL().openStream());
853:                            try {
854:                                IOUtils.getInstance().copyStreams(urlIn, bout);
855:                            } finally {
856:                                bout.close();
857:                                urlIn.close();
858:                            }
859:
860:                            final byte[] data = bout.toByteArray();
861:                            // create the image
862:                            return workbook.addPicture(data, format);
863:                        }
864:                    }
865:                }
866:
867:                if (reference instanceof  LocalImageContainer) {
868:                    // Check, whether the imagereference contains an AWT image.
869:                    // if so, then we can use that image instance for the recoding
870:                    final LocalImageContainer li = (LocalImageContainer) reference;
871:                    if (image == null) {
872:                        image = li.getImage();
873:                    }
874:                }
875:
876:                if (image != null) {
877:                    // now encode the image. We don't need to create digest data
878:                    // for the image contents, as the image is perfectly identifyable
879:                    // by its URL
880:                    final byte[] data = RenderUtility.encodeImage(image);
881:                    return workbook.addPicture(data,
882:                            HSSFWorkbook.PICTURE_TYPE_PNG);
883:                }
884:                return -1;
885:            }
886:
887:        }
www___._j___a_v_a__2s_.__c__o__m___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.