|
|
|
@ -36,6 +36,7 @@ import com.fr.third.v2.org.apache.poi.ss.usermodel.Cell;
|
|
|
|
|
import com.fr.third.v2.org.apache.poi.ss.usermodel.CellStyle; |
|
|
|
|
import com.fr.third.v2.org.apache.poi.ss.usermodel.CellType; |
|
|
|
|
import com.fr.third.v2.org.apache.poi.ss.usermodel.FormulaError; |
|
|
|
|
import com.fr.third.v2.org.apache.poi.ss.usermodel.RichTextString; |
|
|
|
|
import com.fr.third.v2.org.apache.poi.ss.util.CellReference; |
|
|
|
|
import com.fr.third.v2.org.apache.poi.util.POILogFactory; |
|
|
|
|
import com.fr.third.v2.org.apache.poi.util.POILogger; |
|
|
|
@ -201,113 +202,116 @@ public class SheetDataWriter implements Closeable {
|
|
|
|
|
_numberLastFlushedRow = Math.max(rownum, _numberLastFlushedRow); |
|
|
|
|
_numberOfCellsOfLastFlushedRow = row.getLastCellNum(); |
|
|
|
|
_numberOfFlushedRows++; |
|
|
|
|
beginRow(rownum, row); |
|
|
|
|
int size = this._numberOfCellsOfLastFlushedRow > 0 ? this._numberOfCellsOfLastFlushedRow : 1; |
|
|
|
|
StringBuilder sb = new StringBuilder(size << 6); |
|
|
|
|
beginRow(rownum, row, sb); |
|
|
|
|
Iterator<Cell> cells = row.allCellsIterator(); |
|
|
|
|
int columnIndex = 0; |
|
|
|
|
while (cells.hasNext()) { |
|
|
|
|
writeCell(columnIndex++, cells.next()); |
|
|
|
|
writeCell(columnIndex++, cells.next(),sb); |
|
|
|
|
} |
|
|
|
|
endRow(); |
|
|
|
|
endRow(sb); |
|
|
|
|
this._out.write(sb.toString()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void beginRow(int rownum, SXSSFRow row) throws IOException { |
|
|
|
|
_out.write("<row"); |
|
|
|
|
writeAttribute("r", Integer.toString(rownum + 1)); |
|
|
|
|
void beginRow(int rownum, SXSSFRow row,StringBuilder sb) throws IOException { |
|
|
|
|
sb.append("<row"); |
|
|
|
|
writeAttribute("r", Integer.toString(rownum + 1), sb); |
|
|
|
|
if (row.hasCustomHeight()) { |
|
|
|
|
writeAttribute("customHeight", "true"); |
|
|
|
|
writeAttribute("ht", Float.toString(row.getHeightInPoints())); |
|
|
|
|
writeAttribute("customHeight", "true", sb); |
|
|
|
|
writeAttribute("ht", Float.toString(row.getHeightInPoints()), sb); |
|
|
|
|
} |
|
|
|
|
if (row.getZeroHeight()) { |
|
|
|
|
writeAttribute("hidden", "true"); |
|
|
|
|
writeAttribute("hidden", "true", sb); |
|
|
|
|
} |
|
|
|
|
if (row.isFormatted()) { |
|
|
|
|
writeAttribute("s", Integer.toString(row.getRowStyleIndex())); |
|
|
|
|
writeAttribute("customFormat", "1"); |
|
|
|
|
writeAttribute("s", Integer.toString(row.getRowStyleIndex()), sb); |
|
|
|
|
writeAttribute("customFormat", "1", sb); |
|
|
|
|
} |
|
|
|
|
if (row.getOutlineLevel() != 0) { |
|
|
|
|
writeAttribute("outlineLevel", Integer.toString(row.getOutlineLevel())); |
|
|
|
|
writeAttribute("outlineLevel", Integer.toString(row.getOutlineLevel()), sb); |
|
|
|
|
} |
|
|
|
|
if (row.getHidden() != null) { |
|
|
|
|
writeAttribute("hidden", row.getHidden() ? "1" : "0"); |
|
|
|
|
writeAttribute("hidden", row.getHidden() ? "1" : "0", sb); |
|
|
|
|
} |
|
|
|
|
if (row.getCollapsed() != null) { |
|
|
|
|
writeAttribute("collapsed", row.getCollapsed() ? "1" : "0"); |
|
|
|
|
writeAttribute("collapsed", row.getCollapsed() ? "1" : "0", sb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_out.write(">\n"); |
|
|
|
|
sb.append(">\n"); |
|
|
|
|
this._rownum = rownum; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void endRow() throws IOException { |
|
|
|
|
_out.write("</row>\n"); |
|
|
|
|
void endRow(StringBuilder sb) throws IOException { |
|
|
|
|
sb.append("</row>\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void writeCell(int columnIndex, Cell cell) throws IOException { |
|
|
|
|
public void writeCell(int columnIndex, Cell cell,StringBuilder sb) throws IOException { |
|
|
|
|
if (cell == null) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
String ref = new CellReference(_rownum, columnIndex).formatAsString(); |
|
|
|
|
_out.write("<c"); |
|
|
|
|
writeAttribute("r", ref); |
|
|
|
|
sb.append("<c"); |
|
|
|
|
writeAttribute("r", ref,sb); |
|
|
|
|
CellStyle cellStyle = cell.getCellStyle(); |
|
|
|
|
if (cellStyle.getIndex() != 0) { |
|
|
|
|
// need to convert the short to unsigned short as the indexes can be up to 64k
|
|
|
|
|
// ideally we would use int for this index, but that would need changes to some more
|
|
|
|
|
// APIs
|
|
|
|
|
writeAttribute("s", Integer.toString(cellStyle.getIndex() & 0xffff)); |
|
|
|
|
writeAttribute("s", Integer.toString(cellStyle.getIndex() & 0xffff),sb); |
|
|
|
|
} |
|
|
|
|
CellType cellType = cell.getCellType(); |
|
|
|
|
switch (cellType) { |
|
|
|
|
case BLANK: { |
|
|
|
|
_out.write('>'); |
|
|
|
|
sb.append('>'); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case FORMULA: { |
|
|
|
|
switch (cell.getCachedFormulaResultType()) { |
|
|
|
|
case NUMERIC: |
|
|
|
|
writeAttribute("t", "n"); |
|
|
|
|
writeAttribute("t", "n",sb); |
|
|
|
|
break; |
|
|
|
|
case STRING: |
|
|
|
|
writeAttribute("t", STCellType.STR.toString()); |
|
|
|
|
writeAttribute("t", STCellType.STR.toString(),sb); |
|
|
|
|
break; |
|
|
|
|
case BOOLEAN: |
|
|
|
|
writeAttribute("t", "b"); |
|
|
|
|
writeAttribute("t", "b",sb); |
|
|
|
|
break; |
|
|
|
|
case ERROR: |
|
|
|
|
writeAttribute("t", "e"); |
|
|
|
|
writeAttribute("t", "e",sb); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
_out.write("><f>"); |
|
|
|
|
outputQuotedString(cell.getCellFormula()); |
|
|
|
|
_out.write("</f>"); |
|
|
|
|
sb.append("><f>"); |
|
|
|
|
outputQuotedString(cell.getCellFormula(),sb); |
|
|
|
|
sb.append("</f>"); |
|
|
|
|
switch (cell.getCachedFormulaResultType()) { |
|
|
|
|
case NUMERIC: |
|
|
|
|
double nval = cell.getNumericCellValue(); |
|
|
|
|
if (!Double.isNaN(nval)) { |
|
|
|
|
_out.write("<v>"); |
|
|
|
|
_out.write(Double.toString(nval)); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append("<v>"); |
|
|
|
|
sb.append(Double.toString(nval)); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case STRING: |
|
|
|
|
String value = cell.getStringCellValue(); |
|
|
|
|
if (value != null && !value.isEmpty()) { |
|
|
|
|
_out.write("<v>"); |
|
|
|
|
_out.write(value); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append("<v>"); |
|
|
|
|
sb.append(value); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case BOOLEAN: |
|
|
|
|
_out.write("><v>"); |
|
|
|
|
_out.write(cell.getBooleanCellValue() ? "1" : "0"); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append("><v>"); |
|
|
|
|
sb.append(cell.getBooleanCellValue() ? "1" : "0"); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
case ERROR: { |
|
|
|
|
FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); |
|
|
|
|
|
|
|
|
|
_out.write("><v>"); |
|
|
|
|
_out.write(error.getString()); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append("><v>"); |
|
|
|
|
sb.append(error.getString()); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -315,81 +319,81 @@ public class SheetDataWriter implements Closeable {
|
|
|
|
|
} |
|
|
|
|
case STRING: { |
|
|
|
|
if (_sharedStringSource != null&& cell.isRichText()) { |
|
|
|
|
XSSFRichTextString rt = new XSSFRichTextString(cell.getStringCellValue()); |
|
|
|
|
RichTextString rt = cell.getRichStringCellValue(); |
|
|
|
|
int sRef = _sharedStringSource.addSharedStringItem(rt); |
|
|
|
|
|
|
|
|
|
writeAttribute("t", STCellType.S.toString()); |
|
|
|
|
_out.write("><v>"); |
|
|
|
|
_out.write(String.valueOf(sRef)); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
writeAttribute("t", STCellType.S.toString(),sb); |
|
|
|
|
sb.append("><v>"); |
|
|
|
|
sb.append(String.valueOf(sRef)); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
} else { |
|
|
|
|
writeAttribute("t", "inlineStr"); |
|
|
|
|
_out.write("><is><t"); |
|
|
|
|
writeAttribute("t", "inlineStr",sb); |
|
|
|
|
sb.append("><is><t"); |
|
|
|
|
if (hasLeadingTrailingSpaces(cell.getStringCellValue())) { |
|
|
|
|
writeAttribute("xml:space", "preserve"); |
|
|
|
|
writeAttribute("xml:space", "preserve",sb); |
|
|
|
|
} |
|
|
|
|
_out.write(">"); |
|
|
|
|
outputQuotedString(cell.getStringCellValue()); |
|
|
|
|
_out.write("</t></is>"); |
|
|
|
|
sb.append(">"); |
|
|
|
|
outputQuotedString(cell.getStringCellValue(),sb); |
|
|
|
|
sb.append("</t></is>"); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case NUMERIC_STRING: { |
|
|
|
|
_out.write(" t=\"n\"><v>"); |
|
|
|
|
_out.write(cell.getNumericStringCellValue()); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append(" t=\"n\"><v>"); |
|
|
|
|
sb.append(cell.getNumericStringCellValue()); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case NUMERIC_BIG_DECIMAL: { |
|
|
|
|
_out.write(" t=\"n\">"); |
|
|
|
|
_out.write("<v>"); |
|
|
|
|
_out.write(cell.getNumericBigDecimalCellValue().toString()); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append(" t=\"n\">"); |
|
|
|
|
sb.append("<v>"); |
|
|
|
|
sb.append(cell.getNumericBigDecimalCellValue().toString()); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case NUMERIC_BIG_INTEGER: { |
|
|
|
|
_out.write(" t=\"n\">"); |
|
|
|
|
_out.write("<v>"); |
|
|
|
|
_out.write(cell.getNumericBigIntegerCellValue().toString()); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
sb.append(" t=\"n\">"); |
|
|
|
|
sb.append("<v>"); |
|
|
|
|
sb.append(cell.getNumericBigIntegerCellValue().toString()); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case NUMERIC: { |
|
|
|
|
writeAttribute("t", "n"); |
|
|
|
|
_out.write("><v>"); |
|
|
|
|
_out.write(Double.toString(cell.getNumericCellValue())); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
writeAttribute("t", "n",sb); |
|
|
|
|
sb.append("><v>"); |
|
|
|
|
sb.append(Double.toString(cell.getNumericCellValue())); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case BOOLEAN: { |
|
|
|
|
writeAttribute("t", "b"); |
|
|
|
|
_out.write("><v>"); |
|
|
|
|
_out.write(cell.getBooleanCellValue() ? "1" : "0"); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
writeAttribute("t", "b",sb); |
|
|
|
|
sb.append("><v>"); |
|
|
|
|
sb.append(cell.getBooleanCellValue() ? "1" : "0"); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case ERROR: { |
|
|
|
|
FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); |
|
|
|
|
|
|
|
|
|
writeAttribute("t", "e"); |
|
|
|
|
_out.write("><v>"); |
|
|
|
|
_out.write(error.getString()); |
|
|
|
|
_out.write("</v>"); |
|
|
|
|
writeAttribute("t", "e",sb); |
|
|
|
|
sb.append("><v>"); |
|
|
|
|
sb.append(error.getString()); |
|
|
|
|
sb.append("</v>"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
default: { |
|
|
|
|
throw new IllegalStateException("Invalid cell type: " + cellType); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
_out.write("</c>"); |
|
|
|
|
sb.append("</c>"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void writeAttribute(String name, String value) throws IOException { |
|
|
|
|
_out.write(' '); |
|
|
|
|
_out.write(name); |
|
|
|
|
_out.write("=\""); |
|
|
|
|
_out.write(value); |
|
|
|
|
_out.write('\"'); |
|
|
|
|
private void writeAttribute(String name, String value,StringBuilder sb) throws IOException { |
|
|
|
|
sb.append(' '); |
|
|
|
|
sb.append(name); |
|
|
|
|
sb.append("=\""); |
|
|
|
|
sb.append(value); |
|
|
|
|
sb.append('\"'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -405,7 +409,7 @@ public class SheetDataWriter implements Closeable {
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected void outputQuotedString(String s) throws IOException { |
|
|
|
|
protected void outputQuotedString(String s,StringBuilder sb) throws IOException { |
|
|
|
|
if (s == null || s.length() == 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -413,29 +417,29 @@ public class SheetDataWriter implements Closeable {
|
|
|
|
|
for (String codepoint : new StringCodepointsIterable(s)) { |
|
|
|
|
switch (codepoint) { |
|
|
|
|
case "<": |
|
|
|
|
_out.write("<"); |
|
|
|
|
sb.append("<"); |
|
|
|
|
break; |
|
|
|
|
case ">": |
|
|
|
|
_out.write(">"); |
|
|
|
|
sb.append(">"); |
|
|
|
|
break; |
|
|
|
|
case "&": |
|
|
|
|
_out.write("&"); |
|
|
|
|
sb.append("&"); |
|
|
|
|
break; |
|
|
|
|
case "\"": |
|
|
|
|
_out.write("""); |
|
|
|
|
sb.append("""); |
|
|
|
|
break; |
|
|
|
|
// Special characters
|
|
|
|
|
case "\n": |
|
|
|
|
_out.write("
"); |
|
|
|
|
sb.append("
"); |
|
|
|
|
break; |
|
|
|
|
case "\r": |
|
|
|
|
_out.write("
"); |
|
|
|
|
sb.append("
"); |
|
|
|
|
break; |
|
|
|
|
case "\t": |
|
|
|
|
_out.write("	"); |
|
|
|
|
sb.append("	"); |
|
|
|
|
break; |
|
|
|
|
case "\u00A0": // NO-BREAK SPACE
|
|
|
|
|
_out.write(" "); |
|
|
|
|
sb.append(" "); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
if (codepoint.length() == 1) { |
|
|
|
@ -443,12 +447,12 @@ public class SheetDataWriter implements Closeable {
|
|
|
|
|
// YK: XmlBeans silently replaces all ISO control characters ( < 32) with question marks.
|
|
|
|
|
// the same rule applies to "not a character" symbols.
|
|
|
|
|
if (replaceWithQuestionMark(c)) { |
|
|
|
|
_out.write('?'); |
|
|
|
|
sb.append('?'); |
|
|
|
|
} else { |
|
|
|
|
_out.write(c); |
|
|
|
|
sb.append(c); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
_out.write(codepoint); |
|
|
|
|
sb.append(codepoint); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|