org.apache.poi.xssf.streaming.SheetDataWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.poi
Show all versions of org.apache.servicemix.bundles.poi
This OSGi bundle wraps poi, poi-contrib, poi-ooxml, poi-ooxml-schemas and poi-scratchpad ${pkgVersion} jar files.
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.apache.poi.xssf.streaming;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FormulaError;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.TempFile;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
/**
* Initially copied from BigGridDemo "SpreadsheetWriter".
* Unlike the original code which wrote the entire document,
* this class only writes the "sheetData" document fragment
* so that it was renamed to "SheetDataWriter"
*/
public class SheetDataWriter {
private final File _fd;
private final Writer _out;
private int _rownum;
private int _numberOfFlushedRows;
private int _lowestIndexOfFlushedRows; // meaningful only of _numberOfFlushedRows>0
private int _numberOfCellsOfLastFlushedRow; // meaningful only of _numberOfFlushedRows>0
private int _numberLastFlushedRow = -1; // meaningful only of _numberOfFlushedRows>0
/**
* Table of strings shared across this workbook.
* If two cells contain the same string, then the cell value is the same index into SharedStringsTable
*/
private SharedStringsTable _sharedStringSource;
public SheetDataWriter() throws IOException {
_fd = createTempFile();
_out = createWriter(_fd);
}
public SheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException{
this();
this._sharedStringSource = sharedStringsTable;
}
/**
* Create a temp file to write sheet data.
* By default, temp files are created in the default temporary-file directory
* with a prefix "poi-sxssf-sheet" and suffix ".xml". Subclasses can override
* it and specify a different temp directory or filename or suffix, e.g. .gz
*
* @return temp file to write sheet data
*/
public File createTempFile() throws IOException {
return TempFile.createTempFile("poi-sxssf-sheet", ".xml");
}
/**
* Create a writer for the sheet data.
*
* @param fd the file to write to
*/
public Writer createWriter(File fd)throws IOException {
return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fd), "UTF-8"));
}
/**
* flush and close the temp data writer.
* This method must be invoked before calling {@link #getWorksheetXMLInputStream()}
*/
public void close() throws IOException{
_out.flush();
_out.close();
}
File getTempFile(){
return _fd;
}
/**
* @return a stream to read temp file with the sheet data
*/
public InputStream getWorksheetXMLInputStream() throws IOException {
File fd = getTempFile();
return new FileInputStream(fd);
}
public int getNumberOfFlushedRows() {
return _numberOfFlushedRows;
}
public int getNumberOfCellsOfLastFlushedRow() {
return _numberOfCellsOfLastFlushedRow;
}
public int getLowestIndexOfFlushedRows() {
return _lowestIndexOfFlushedRows;
}
public int getLastFlushedRow() {
return _numberLastFlushedRow;
}
@Override
protected void finalize() throws Throwable {
_fd.delete();
super.finalize();
}
/**
* Write a row to the file
*
* @param rownum 0-based row number
* @param row a row
*/
public void writeRow(int rownum, SXSSFRow row) throws IOException {
if (_numberOfFlushedRows == 0)
_lowestIndexOfFlushedRows = rownum;
_numberLastFlushedRow = Math.max(rownum, _numberLastFlushedRow);
_numberOfCellsOfLastFlushedRow = row.getLastCellNum();
_numberOfFlushedRows++;
beginRow(rownum, row);
Iterator cells = row.allCellsIterator();
int columnIndex = 0;
while (cells.hasNext()) {
writeCell(columnIndex++, cells.next());
}
endRow();
}
void beginRow(int rownum, SXSSFRow row) throws IOException {
_out.write("\n");
this._rownum = rownum;
}
void endRow() throws IOException {
_out.write(" \n");
}
public void writeCell(int columnIndex, Cell cell) throws IOException {
if (cell == null) {
return;
}
String ref = new CellReference(_rownum, columnIndex).formatAsString();
_out.write("");
break;
}
case Cell.CELL_TYPE_FORMULA: {
_out.write(">");
_out.write("");
outputQuotedString(cell.getCellFormula());
_out.write(" ");
switch (cell.getCachedFormulaResultType()) {
case Cell.CELL_TYPE_NUMERIC:
double nval = cell.getNumericCellValue();
if (!Double.isNaN(nval)) {
_out.write("" + nval + " ");
}
break;
}
break;
}
case Cell.CELL_TYPE_STRING: {
if (_sharedStringSource != null) {
XSSFRichTextString rt = new XSSFRichTextString(cell.getStringCellValue());
int sRef = _sharedStringSource.addEntry(rt.getCTRst());
_out.write(" t=\"" + STCellType.S.toString() + "\">");
_out.write("");
_out.write(String.valueOf(sRef));
_out.write(" ");
} else {
_out.write(" t=\"inlineStr\">");
_out.write("");
outputQuotedString(cell.getStringCellValue());
_out.write(" ");
}
break;
}
case Cell.CELL_TYPE_NUMERIC: {
_out.write(" t=\"n\">");
_out.write("" + cell.getNumericCellValue() + " ");
break;
}
case Cell.CELL_TYPE_BOOLEAN: {
_out.write(" t=\"b\">");
_out.write("" + (cell.getBooleanCellValue() ? "1" : "0") + " ");
break;
}
case Cell.CELL_TYPE_ERROR: {
FormulaError error = FormulaError.forInt(cell.getErrorCellValue());
_out.write(" t=\"e\">");
_out.write("" + error.getString() + " ");
break;
}
default: {
throw new RuntimeException("Huh?");
}
}
_out.write(" ");
}
/**
* @return whether the string has leading / trailing spaces that
* need to be preserved with the xml:space=\"preserve\" attribute
*/
boolean hasLeadingTrailingSpaces(String str) {
if (str != null && str.length() > 0) {
char firstChar = str.charAt(0);
char lastChar = str.charAt(str.length() - 1);
return Character.isWhitespace(firstChar) || Character.isWhitespace(lastChar) ;
}
return false;
}
//Taken from jdk1.3/src/javax/swing/text/html/HTMLWriter.java
protected void outputQuotedString(String s) throws IOException {
if (s == null || s.length() == 0) {
return;
}
char[] chars = s.toCharArray();
int last = 0;
int length = s.length();
for (int counter = 0; counter < length; counter++) {
char c = chars[counter];
switch (c) {
case '<':
if (counter > last) {
_out.write(chars, last, counter - last);
}
last = counter + 1;
_out.write("<");
break;
case '>':
if (counter > last) {
_out.write(chars, last, counter - last);
}
last = counter + 1;
_out.write(">");
break;
case '&':
if (counter > last) {
_out.write(chars, last, counter - last);
}
last = counter + 1;
_out.write("&");
break;
case '"':
if (counter > last) {
_out.write(chars, last, counter - last);
}
last = counter + 1;
_out.write(""");
break;
// Special characters
case '\n':
case '\r':
if (counter > last) {
_out.write(chars, last, counter - last);
}
_out.write("
");
last = counter + 1;
break;
case '\t':
if (counter > last) {
_out.write(chars, last, counter - last);
}
_out.write(" ");
last = counter + 1;
break;
case 0xa0:
if (counter > last) {
_out.write(chars, last, counter - last);
}
_out.write(" ");
last = counter + 1;
break;
default:
// YK: XmlBeans silently replaces all ISO control characters ( < 32) with question marks.
// the same rule applies to unicode surrogates and "not a character" symbols.
if( c < ' ' || Character.isLowSurrogate(c) || Character.isHighSurrogate(c) ||
('\uFFFE' <= c && c <= '\uFFFF')) {
if (counter > last) {
_out.write(chars, last, counter - last);
}
_out.write('?');
last = counter + 1;
}
else if (c > 127) {
if (counter > last) {
_out.write(chars, last, counter - last);
}
last = counter + 1;
// If the character is outside of ascii, write the
// numeric value.
_out.write("");
_out.write(String.valueOf((int) c));
_out.write(";");
}
break;
}
}
if (last < length) {
_out.write(chars, last, length - last);
}
}
/**
* Deletes the temporary file that backed this sheet on disk.
* @return true if the file was deleted, false if it wasn't.
*/
boolean dispose() throws IOException {
_out.close();
return _fd.delete();
}
}
|