2008-02-07 04:24:49 -05:00
|
|
|
/* ====================================================================
|
|
|
|
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.
|
|
|
|
==================================================================== */
|
|
|
|
|
2008-01-25 11:25:14 -05:00
|
|
|
package org.apache.poi.xssf.usermodel.helpers;
|
|
|
|
|
2008-03-13 07:50:50 -04:00
|
|
|
import java.util.Arrays;
|
2008-10-21 13:56:34 -04:00
|
|
|
import java.util.Iterator;
|
|
|
|
import java.text.AttributedString;
|
|
|
|
import java.text.NumberFormat;
|
|
|
|
import java.text.DecimalFormat;
|
|
|
|
import java.awt.font.TextLayout;
|
|
|
|
import java.awt.font.FontRenderContext;
|
|
|
|
import java.awt.font.TextAttribute;
|
|
|
|
import java.awt.geom.AffineTransform;
|
2008-01-25 11:25:14 -05:00
|
|
|
|
2008-04-10 03:35:47 -04:00
|
|
|
import org.apache.poi.ss.usermodel.CellStyle;
|
2008-10-21 13:56:34 -04:00
|
|
|
import org.apache.poi.ss.util.CellRangeAddress;
|
2008-03-13 07:50:50 -04:00
|
|
|
import org.apache.poi.xssf.util.CTColComparator;
|
|
|
|
import org.apache.poi.xssf.util.NumericRanges;
|
2008-10-21 13:56:34 -04:00
|
|
|
import org.apache.poi.xssf.usermodel.*;
|
2008-01-25 11:25:14 -05:00
|
|
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
|
|
|
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
|
|
|
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
|
|
|
|
2008-09-15 16:54:49 -04:00
|
|
|
/**
|
|
|
|
* Helper class for dealing with the Column settings on
|
|
|
|
* a CTWorksheet (the data part of a sheet).
|
|
|
|
* Note - within POI, we use 0 based column indexes, but
|
|
|
|
* the column definitions in the XML are 1 based!
|
|
|
|
*/
|
2008-01-25 11:25:14 -05:00
|
|
|
public class ColumnHelper {
|
2008-03-13 07:50:50 -04:00
|
|
|
|
2008-02-07 04:24:49 -05:00
|
|
|
private CTWorksheet worksheet;
|
2008-02-29 09:18:06 -05:00
|
|
|
private CTCols newCols;
|
2008-01-25 11:25:14 -05:00
|
|
|
|
2008-02-07 04:24:49 -05:00
|
|
|
public ColumnHelper(CTWorksheet worksheet) {
|
|
|
|
super();
|
|
|
|
this.worksheet = worksheet;
|
|
|
|
cleanColumns();
|
2008-01-25 11:25:14 -05:00
|
|
|
}
|
|
|
|
|
2008-02-07 04:24:49 -05:00
|
|
|
public void cleanColumns() {
|
2008-02-29 09:18:06 -05:00
|
|
|
this.newCols = CTCols.Factory.newInstance();
|
2008-02-07 04:24:49 -05:00
|
|
|
CTCols[] colsArray = worksheet.getColsArray();
|
|
|
|
int i = 0;
|
2008-03-13 07:50:50 -04:00
|
|
|
for (i = 0; i < colsArray.length; i++) {
|
2008-02-07 04:24:49 -05:00
|
|
|
CTCols cols = colsArray[i];
|
|
|
|
CTCol[] colArray = cols.getColArray();
|
2008-03-13 07:50:50 -04:00
|
|
|
for (int y = 0; y < colArray.length; y++) {
|
|
|
|
CTCol col = colArray[y];
|
|
|
|
newCols = addCleanColIntoCols(newCols, col);
|
2008-02-07 04:24:49 -05:00
|
|
|
}
|
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
for (int y = i - 1; y >= 0; y--) {
|
2008-02-07 04:24:49 -05:00
|
|
|
worksheet.removeCols(y);
|
|
|
|
}
|
|
|
|
worksheet.addNewCols();
|
|
|
|
worksheet.setColsArray(0, newCols);
|
2008-01-25 11:25:14 -05:00
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
|
2009-10-04 06:08:47 -04:00
|
|
|
public static void sortColumns(CTCols newCols) {
|
2008-03-13 07:50:50 -04:00
|
|
|
CTCol[] colArray = newCols.getColArray();
|
|
|
|
Arrays.sort(colArray, new CTColComparator());
|
|
|
|
newCols.setColArray(colArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
public CTCol cloneCol(CTCols cols, CTCol col) {
|
|
|
|
CTCol newCol = cols.addNewCol();
|
|
|
|
newCol.setMin(col.getMin());
|
|
|
|
newCol.setMax(col.getMax());
|
|
|
|
setColumnAttributes(col, newCol);
|
|
|
|
return newCol;
|
|
|
|
}
|
|
|
|
|
2008-09-15 16:54:49 -04:00
|
|
|
/**
|
|
|
|
* Returns the Column at the given 0 based index
|
|
|
|
*/
|
2008-04-10 03:35:47 -04:00
|
|
|
public CTCol getColumn(long index, boolean splitColumns) {
|
2008-09-15 16:54:49 -04:00
|
|
|
return getColumn1Based(index+1, splitColumns);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Returns the Column at the given 1 based index.
|
|
|
|
* POI default is 0 based, but the file stores
|
|
|
|
* as 1 based.
|
|
|
|
*/
|
|
|
|
public CTCol getColumn1Based(long index1, boolean splitColumns) {
|
2008-04-10 03:35:47 -04:00
|
|
|
CTCols colsArray = worksheet.getColsArray(0);
|
|
|
|
for (int i = 0; i < colsArray.sizeOfColArray(); i++) {
|
|
|
|
CTCol colArray = colsArray.getColArray(i);
|
2008-09-15 16:54:49 -04:00
|
|
|
if (colArray.getMin() <= index1 && colArray.getMax() >= index1) {
|
2008-04-10 03:35:47 -04:00
|
|
|
if (splitColumns) {
|
2008-09-15 16:54:49 -04:00
|
|
|
if (colArray.getMin() < index1) {
|
|
|
|
insertCol(colsArray, colArray.getMin(), (index1 - 1), new CTCol[]{colArray});
|
2008-04-10 03:35:47 -04:00
|
|
|
}
|
2008-09-15 16:54:49 -04:00
|
|
|
if (colArray.getMax() > index1) {
|
|
|
|
insertCol(colsArray, (index1 + 1), colArray.getMax(), new CTCol[]{colArray});
|
2008-04-10 03:35:47 -04:00
|
|
|
}
|
2008-09-15 16:54:49 -04:00
|
|
|
colArray.setMin(index1);
|
|
|
|
colArray.setMax(index1);
|
2008-04-10 03:35:47 -04:00
|
|
|
}
|
|
|
|
return colArray;
|
2008-02-07 04:24:49 -05:00
|
|
|
}
|
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public CTCols addCleanColIntoCols(CTCols cols, CTCol col) {
|
|
|
|
boolean colOverlaps = false;
|
|
|
|
for (int i = 0; i < cols.sizeOfColArray(); i++) {
|
|
|
|
CTCol ithCol = cols.getColArray(i);
|
|
|
|
long[] range1 = { ithCol.getMin(), ithCol.getMax() };
|
|
|
|
long[] range2 = { col.getMin(), col.getMax() };
|
|
|
|
long[] overlappingRange = NumericRanges.getOverlappingRange(range1,
|
|
|
|
range2);
|
|
|
|
int overlappingType = NumericRanges.getOverlappingType(range1,
|
|
|
|
range2);
|
|
|
|
// different behavior required for each of the 4 different
|
|
|
|
// overlapping types
|
|
|
|
if (overlappingType == NumericRanges.OVERLAPS_1_MINOR) {
|
|
|
|
ithCol.setMax(overlappingRange[0] - 1);
|
|
|
|
CTCol rangeCol = insertCol(cols, overlappingRange[0],
|
|
|
|
overlappingRange[1], new CTCol[] { ithCol, col });
|
|
|
|
i++;
|
|
|
|
CTCol newCol = insertCol(cols, (overlappingRange[1] + 1), col
|
|
|
|
.getMax(), new CTCol[] { col });
|
|
|
|
i++;
|
|
|
|
} else if (overlappingType == NumericRanges.OVERLAPS_2_MINOR) {
|
|
|
|
ithCol.setMin(overlappingRange[1] + 1);
|
|
|
|
CTCol rangeCol = insertCol(cols, overlappingRange[0],
|
|
|
|
overlappingRange[1], new CTCol[] { ithCol, col });
|
|
|
|
i++;
|
|
|
|
CTCol newCol = insertCol(cols, col.getMin(),
|
|
|
|
(overlappingRange[0] - 1), new CTCol[] { col });
|
|
|
|
i++;
|
|
|
|
} else if (overlappingType == NumericRanges.OVERLAPS_2_WRAPS) {
|
|
|
|
setColumnAttributes(col, ithCol);
|
|
|
|
if (col.getMin() != ithCol.getMin()) {
|
|
|
|
CTCol newColBefore = insertCol(cols, col.getMin(), (ithCol
|
|
|
|
.getMin() - 1), new CTCol[] { col });
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (col.getMax() != ithCol.getMax()) {
|
|
|
|
CTCol newColAfter = insertCol(cols, (ithCol.getMax() + 1),
|
|
|
|
col.getMax(), new CTCol[] { col });
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} else if (overlappingType == NumericRanges.OVERLAPS_1_WRAPS) {
|
|
|
|
if (col.getMin() != ithCol.getMin()) {
|
|
|
|
CTCol newColBefore = insertCol(cols, ithCol.getMin(), (col
|
|
|
|
.getMin() - 1), new CTCol[] { ithCol });
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (col.getMax() != ithCol.getMax()) {
|
|
|
|
CTCol newColAfter = insertCol(cols, (col.getMax() + 1),
|
|
|
|
ithCol.getMax(), new CTCol[] { ithCol });
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
ithCol.setMin(overlappingRange[0]);
|
|
|
|
ithCol.setMax(overlappingRange[1]);
|
|
|
|
setColumnAttributes(col, ithCol);
|
|
|
|
}
|
|
|
|
if (overlappingType != NumericRanges.NO_OVERLAPS) {
|
|
|
|
colOverlaps = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!colOverlaps) {
|
|
|
|
CTCol newCol = cloneCol(cols, col);
|
|
|
|
}
|
|
|
|
sortColumns(cols);
|
|
|
|
return cols;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Insert a new CTCol at position 0 into cols, setting min=min, max=max and
|
|
|
|
* copying all the colsWithAttributes array cols attributes into newCol
|
|
|
|
*/
|
2008-09-11 11:11:57 -04:00
|
|
|
private CTCol insertCol(CTCols cols, long min, long max,
|
|
|
|
CTCol[] colsWithAttributes) {
|
|
|
|
if(!columnExists(cols,min,max)){
|
|
|
|
CTCol newCol = cols.insertNewCol(0);
|
|
|
|
newCol.setMin(min);
|
|
|
|
newCol.setMax(max);
|
|
|
|
for (CTCol col : colsWithAttributes) {
|
|
|
|
setColumnAttributes(col, newCol);
|
|
|
|
}
|
|
|
|
return newCol;
|
2008-03-13 07:50:50 -04:00
|
|
|
}
|
2008-09-11 11:11:57 -04:00
|
|
|
return null;
|
2008-01-25 11:25:14 -05:00
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
|
2008-09-15 16:54:49 -04:00
|
|
|
/**
|
|
|
|
* Does the column at the given 0 based index exist
|
|
|
|
* in the supplied list of column definitions?
|
|
|
|
*/
|
2008-02-07 04:24:49 -05:00
|
|
|
public boolean columnExists(CTCols cols, long index) {
|
2008-09-15 16:54:49 -04:00
|
|
|
return columnExists1Based(cols, index+1);
|
|
|
|
}
|
|
|
|
private boolean columnExists1Based(CTCols cols, long index1) {
|
2008-03-13 07:50:50 -04:00
|
|
|
for (int i = 0; i < cols.sizeOfColArray(); i++) {
|
2008-09-15 16:54:49 -04:00
|
|
|
if (cols.getColArray(i).getMin() == index1) {
|
2008-02-07 04:24:49 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2008-01-25 11:25:14 -05:00
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
|
|
|
|
public void setColumnAttributes(CTCol fromCol, CTCol toCol) {
|
2009-02-25 14:12:53 -05:00
|
|
|
if(fromCol.isSetBestFit()) toCol.setBestFit(fromCol.getBestFit());
|
|
|
|
if(fromCol.isSetCustomWidth()) toCol.setCustomWidth(fromCol.getCustomWidth());
|
|
|
|
if(fromCol.isSetHidden()) toCol.setHidden(fromCol.getHidden());
|
|
|
|
if(fromCol.isSetStyle()) toCol.setStyle(fromCol.getStyle());
|
|
|
|
if(fromCol.isSetWidth()) toCol.setWidth(fromCol.getWidth());
|
|
|
|
if(fromCol.isSetCollapsed()) toCol.setCollapsed(fromCol.getCollapsed());
|
|
|
|
if(fromCol.isSetPhonetic()) toCol.setPhonetic(fromCol.getPhonetic());
|
|
|
|
if(fromCol.isSetOutlineLevel()) toCol.setOutlineLevel(fromCol.getOutlineLevel());
|
2009-05-17 14:32:55 -04:00
|
|
|
toCol.setCollapsed(fromCol.isSetCollapsed());
|
2008-01-25 11:25:14 -05:00
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
|
2008-02-29 09:18:06 -05:00
|
|
|
public void setColBestFit(long index, boolean bestFit) {
|
2008-09-15 16:54:49 -04:00
|
|
|
CTCol col = getOrCreateColumn1Based(index+1, false);
|
2008-03-13 07:50:50 -04:00
|
|
|
col.setBestFit(bestFit);
|
2008-02-29 09:18:06 -05:00
|
|
|
}
|
2008-10-21 13:56:34 -04:00
|
|
|
public void setCustomWidth(long index, boolean bestFit) {
|
2009-10-04 06:08:47 -04:00
|
|
|
CTCol col = getOrCreateColumn1Based(index+1, true);
|
2008-10-21 13:56:34 -04:00
|
|
|
col.setCustomWidth(bestFit);
|
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
|
2008-02-29 09:18:06 -05:00
|
|
|
public void setColWidth(long index, double width) {
|
2009-10-04 06:08:47 -04:00
|
|
|
CTCol col = getOrCreateColumn1Based(index+1, true);
|
2008-03-13 07:50:50 -04:00
|
|
|
col.setWidth(width);
|
2008-02-29 09:18:06 -05:00
|
|
|
}
|
2008-03-13 07:50:50 -04:00
|
|
|
|
2008-02-29 09:18:06 -05:00
|
|
|
public void setColHidden(long index, boolean hidden) {
|
2009-10-04 06:08:47 -04:00
|
|
|
CTCol col = getOrCreateColumn1Based(index+1, true);
|
2008-03-13 07:50:50 -04:00
|
|
|
col.setHidden(hidden);
|
|
|
|
}
|
|
|
|
|
2008-09-15 16:54:49 -04:00
|
|
|
/**
|
|
|
|
* Return the CTCol at the given (0 based) column index,
|
|
|
|
* creating it if required.
|
|
|
|
*/
|
|
|
|
protected CTCol getOrCreateColumn1Based(long index1, boolean splitColumns) {
|
|
|
|
CTCol col = getColumn1Based(index1, splitColumns);
|
2008-03-13 07:50:50 -04:00
|
|
|
if (col == null) {
|
|
|
|
col = worksheet.getColsArray(0).addNewCol();
|
2008-09-15 16:54:49 -04:00
|
|
|
col.setMin(index1);
|
|
|
|
col.setMax(index1);
|
2008-03-13 07:50:50 -04:00
|
|
|
}
|
|
|
|
return col;
|
2008-02-29 09:18:06 -05:00
|
|
|
}
|
|
|
|
|
2008-04-10 03:35:47 -04:00
|
|
|
public void setColDefaultStyle(long index, CellStyle style) {
|
|
|
|
setColDefaultStyle(index, style.getIndex());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setColDefaultStyle(long index, int styleId) {
|
2008-09-15 16:54:49 -04:00
|
|
|
CTCol col = getOrCreateColumn1Based(index+1, true);
|
2008-04-10 03:35:47 -04:00
|
|
|
col.setStyle(styleId);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns -1 if no column is found for the given index
|
|
|
|
public int getColDefaultStyle(long index) {
|
|
|
|
if (getColumn(index, false) != null) {
|
|
|
|
return (int) getColumn(index, false).getStyle();
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2008-09-15 16:54:49 -04:00
|
|
|
|
|
|
|
private boolean columnExists(CTCols cols, long min, long max) {
|
|
|
|
for (int i = 0; i < cols.sizeOfColArray(); i++) {
|
|
|
|
if (cols.getColArray(i).getMin() == min && cols.getColArray(i).getMax() == max) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getIndexOfColumn(CTCols cols, CTCol col) {
|
|
|
|
for (int i = 0; i < cols.sizeOfColArray(); i++) {
|
|
|
|
if (cols.getColArray(i).getMin() == col.getMin() && cols.getColArray(i).getMax() == col.getMax()) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2008-10-21 13:56:34 -04:00
|
|
|
|
|
|
|
public static double getColumnWidth(XSSFSheet sheet, int column, boolean useMergedCells){
|
|
|
|
AttributedString str;
|
|
|
|
TextLayout layout;
|
|
|
|
/**
|
|
|
|
* Excel measures columns in units of 1/256th of a character width
|
|
|
|
* but the docs say nothing about what particular character is used.
|
|
|
|
* '0' looks to be a good choice.
|
|
|
|
*/
|
|
|
|
char defaultChar = '0';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is the multiple that the font height is scaled by when determining the
|
|
|
|
* boundary of rotated text.
|
|
|
|
*/
|
|
|
|
double fontHeightMultiple = 2.0;
|
|
|
|
|
|
|
|
FontRenderContext frc = new FontRenderContext(null, true, true);
|
|
|
|
|
|
|
|
XSSFWorkbook wb = sheet.getWorkbook();
|
|
|
|
XSSFFont defaultFont = wb.getFontAt((short) 0);
|
|
|
|
|
|
|
|
str = new AttributedString("" + defaultChar);
|
|
|
|
copyAttributes(defaultFont, str, 0, 1);
|
|
|
|
layout = new TextLayout(str.getIterator(), frc);
|
|
|
|
int defaultCharWidth = (int)layout.getAdvance();
|
|
|
|
|
|
|
|
double width = -1;
|
|
|
|
rows:
|
|
|
|
for (Iterator it = sheet.rowIterator(); it.hasNext();) {
|
|
|
|
XSSFRow row = (XSSFRow) it.next();
|
|
|
|
XSSFCell cell = row.getCell(column);
|
|
|
|
|
|
|
|
if (cell == null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int colspan = 1;
|
|
|
|
for (int i = 0 ; i < sheet.getNumMergedRegions(); i++) {
|
|
|
|
CellRangeAddress region = sheet.getMergedRegion(i);
|
|
|
|
if (containsCell(region, row.getRowNum(), column)) {
|
|
|
|
if (!useMergedCells) {
|
|
|
|
// If we're not using merged cells, skip this one and move on to the next.
|
|
|
|
continue rows;
|
|
|
|
}
|
|
|
|
cell = row.getCell(region.getFirstColumn());
|
|
|
|
colspan = 1 + region.getLastColumn() - region.getFirstColumn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XSSFCellStyle style = cell.getCellStyle();
|
2009-02-19 12:29:55 -05:00
|
|
|
int cellType = cell.getCellType();
|
|
|
|
if(cellType == XSSFCell.CELL_TYPE_FORMULA) cellType = cell.getCachedFormulaResultType();
|
2008-10-21 13:56:34 -04:00
|
|
|
XSSFFont font = wb.getFontAt(style.getFontIndex());
|
|
|
|
|
2009-02-19 12:29:55 -05:00
|
|
|
if (cellType == XSSFCell.CELL_TYPE_STRING) {
|
2008-10-21 13:56:34 -04:00
|
|
|
XSSFRichTextString rt = cell.getRichStringCellValue();
|
|
|
|
String[] lines = rt.getString().split("\\n");
|
|
|
|
for (int i = 0; i < lines.length; i++) {
|
|
|
|
String txt = lines[i] + defaultChar;
|
|
|
|
str = new AttributedString(txt);
|
|
|
|
copyAttributes(font, str, 0, txt.length());
|
|
|
|
|
|
|
|
if (rt.numFormattingRuns() > 0) {
|
|
|
|
int pos = 0;
|
|
|
|
for (int j = 0; j < rt.numFormattingRuns(); j++) {
|
|
|
|
XSSFFont fnt = rt.getFontOfFormattingRun(j);
|
|
|
|
if (fnt != null) {
|
|
|
|
int len = rt.getLengthOfFormattingRun(j);
|
2009-12-04 06:24:02 -05:00
|
|
|
if(len > 0) { //ignore degenerate zero-length runs
|
|
|
|
copyAttributes(fnt, str, pos, pos + len);
|
|
|
|
pos += len;
|
|
|
|
}
|
2008-10-21 13:56:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
layout = new TextLayout(str.getIterator(), frc);
|
|
|
|
if(style.getRotation() != 0){
|
|
|
|
/*
|
|
|
|
* Transform the text using a scale so that it's height is increased by a multiple of the leading,
|
|
|
|
* and then rotate the text before computing the bounds. The scale results in some whitespace around
|
|
|
|
* the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but
|
|
|
|
* is added by the standard Excel autosize.
|
|
|
|
*/
|
|
|
|
AffineTransform trans = new AffineTransform();
|
|
|
|
trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0));
|
|
|
|
trans.concatenate(
|
|
|
|
AffineTransform.getScaleInstance(1, fontHeightMultiple)
|
|
|
|
);
|
|
|
|
width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
|
|
|
} else {
|
|
|
|
width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
String sval = null;
|
2009-02-19 12:29:55 -05:00
|
|
|
if (cellType == XSSFCell.CELL_TYPE_NUMERIC) {
|
|
|
|
String dfmt = style.getDataFormatString();
|
|
|
|
String format = dfmt == null ? null : dfmt.replaceAll("\"", "");
|
2008-10-21 13:56:34 -04:00
|
|
|
double value = cell.getNumericCellValue();
|
|
|
|
try {
|
|
|
|
NumberFormat fmt;
|
|
|
|
if ("General".equals(format))
|
|
|
|
sval = "" + value;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fmt = new DecimalFormat(format);
|
|
|
|
sval = fmt.format(value);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
sval = "" + value;
|
|
|
|
}
|
2009-02-19 12:29:55 -05:00
|
|
|
} else if (cellType == XSSFCell.CELL_TYPE_BOOLEAN) {
|
2008-10-21 13:56:34 -04:00
|
|
|
sval = String.valueOf(cell.getBooleanCellValue());
|
|
|
|
}
|
|
|
|
if(sval != null) {
|
|
|
|
String txt = sval + defaultChar;
|
|
|
|
str = new AttributedString(txt);
|
|
|
|
copyAttributes(font, str, 0, txt.length());
|
|
|
|
|
|
|
|
layout = new TextLayout(str.getIterator(), frc);
|
|
|
|
if(style.getRotation() != 0){
|
|
|
|
/*
|
|
|
|
* Transform the text using a scale so that it's height is increased by a multiple of the leading,
|
|
|
|
* and then rotate the text before computing the bounds. The scale results in some whitespace around
|
|
|
|
* the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but
|
|
|
|
* is added by the standard Excel autosize.
|
|
|
|
*/
|
|
|
|
AffineTransform trans = new AffineTransform();
|
|
|
|
trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0));
|
|
|
|
trans.concatenate(
|
|
|
|
AffineTransform.getScaleInstance(1, fontHeightMultiple)
|
|
|
|
);
|
|
|
|
width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
|
|
|
} else {
|
|
|
|
width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copy text attributes from the supplied HSSFFont to Java2D AttributedString
|
|
|
|
*/
|
|
|
|
private static void copyAttributes(XSSFFont font, AttributedString str, int startIdx, int endIdx) {
|
|
|
|
str.addAttribute(TextAttribute.FAMILY, font.getFontName(), startIdx, endIdx);
|
|
|
|
str.addAttribute(TextAttribute.SIZE, new Float(font.getFontHeightInPoints()));
|
|
|
|
if (font.getBoldweight() == XSSFFont.BOLDWEIGHT_BOLD) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx);
|
|
|
|
if (font.getItalic() ) str.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, startIdx, endIdx);
|
|
|
|
if (font.getUnderline() == XSSFFont.U_SINGLE ) str.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, startIdx, endIdx);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) {
|
|
|
|
if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx
|
|
|
|
&& cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-01-25 11:25:14 -05:00
|
|
|
}
|