mirror of https://github.com/apache/poi.git
adjust tests, javadoc, ...
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1811865 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d9a818dc22
commit
2dc64ebbcc
|
@ -130,7 +130,7 @@ public interface BorderFormatting {
|
|||
/**
|
||||
* Set bottom border.
|
||||
*
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderBottom(BorderStyle border);
|
||||
|
||||
|
@ -145,7 +145,7 @@ public interface BorderFormatting {
|
|||
/**
|
||||
* Set diagonal border.
|
||||
*
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderDiagonal(BorderStyle border);
|
||||
|
||||
|
@ -160,7 +160,7 @@ public interface BorderFormatting {
|
|||
/**
|
||||
* Set left border.
|
||||
*
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderLeft(BorderStyle border);
|
||||
|
||||
|
@ -175,7 +175,7 @@ public interface BorderFormatting {
|
|||
/**
|
||||
* Set right border.
|
||||
*
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderRight(BorderStyle border);
|
||||
|
||||
|
@ -190,7 +190,7 @@ public interface BorderFormatting {
|
|||
/**
|
||||
* Set top border.
|
||||
*
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderTop(BorderStyle border);
|
||||
|
||||
|
@ -198,7 +198,7 @@ public interface BorderFormatting {
|
|||
* Set range internal horizontal borders.
|
||||
*
|
||||
* @since 3.17 beta 1
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderHorizontal(BorderStyle border);
|
||||
|
||||
|
@ -206,7 +206,7 @@ public interface BorderFormatting {
|
|||
* Set range internal vertical borders.
|
||||
*
|
||||
* @since 3.17 beta 1
|
||||
* @param border
|
||||
* @param border The style of border to set.
|
||||
*/
|
||||
void setBorderVertical(BorderStyle border);
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ public class StylesTable extends POIXMLDocumentPart {
|
|||
}
|
||||
|
||||
private short getNumberFormatId(String fmt) {
|
||||
// Find the key, and return that
|
||||
// Find the key, and return that
|
||||
for (Entry<Short,String> numFmt : numberFormats.entrySet()) {
|
||||
if(numFmt.getValue().equals(fmt)) {
|
||||
return numFmt.getKey();
|
||||
|
|
|
@ -34,7 +34,7 @@ public class XSSFColor extends ExtendedColor {
|
|||
|
||||
/**
|
||||
* Create an instance of XSSFColor from the supplied XML bean, with default color indexes
|
||||
* @param color
|
||||
* @param color The {@link CTColor} to use as color-value.
|
||||
* @deprecated 3.17 beta 1 - pass the workbook styles indexed color map, if any
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -45,8 +45,8 @@ public class XSSFColor extends ExtendedColor {
|
|||
|
||||
/**
|
||||
* Create an instance of XSSFColor from the supplied XML bean, with the given color indexes
|
||||
* @param color
|
||||
* @param map
|
||||
* @param color The {@link CTColor} to use as color-value.
|
||||
* @param map The IndexedColorMap to use instead of the default one
|
||||
*/
|
||||
public XSSFColor(CTColor color, IndexedColorMap map) {
|
||||
this.ctColor = color;
|
||||
|
@ -72,8 +72,8 @@ public class XSSFColor extends ExtendedColor {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param rgb bytes
|
||||
* @param colorMap
|
||||
* @param rgb The RGB-byte-values for the Color
|
||||
* @param colorMap The IndexedColorMap to use instead of the default one
|
||||
*/
|
||||
public XSSFColor(byte[] rgb, IndexedColorMap colorMap) {
|
||||
this(CTColor.Factory.newInstance(), colorMap);
|
||||
|
@ -82,7 +82,7 @@ public class XSSFColor extends ExtendedColor {
|
|||
|
||||
/**
|
||||
* @param indexedColor color index (Enum named for default colors)
|
||||
* @param colorMap
|
||||
* @param colorMap The IndexedColorMap to use instead of the default one
|
||||
*/
|
||||
public XSSFColor(IndexedColors indexedColor, IndexedColorMap colorMap) {
|
||||
this(CTColor.Factory.newInstance(), colorMap);
|
||||
|
@ -131,20 +131,14 @@ public class XSSFColor extends ExtendedColor {
|
|||
* @return true if the ctColor has a alpha
|
||||
*/
|
||||
public boolean hasAlpha() {
|
||||
if (! ctColor.isSetRgb()) {
|
||||
return false;
|
||||
}
|
||||
return ctColor.getRgb().length == 4;
|
||||
return ctColor.isSetRgb() && ctColor.getRgb().length == 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the ctColor has a tint
|
||||
*/
|
||||
public boolean hasTint() {
|
||||
if (!ctColor.isSetTint()) {
|
||||
return false;
|
||||
}
|
||||
return ctColor.getTint() != 0;
|
||||
return ctColor.isSetTint() && ctColor.getTint() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,37 +371,25 @@ public class XSSFColor extends ExtendedColor {
|
|||
// Helper methods for {@link #equals(Object)}
|
||||
private boolean sameIndexed(XSSFColor other) {
|
||||
if (isIndexed() == other.isIndexed()) {
|
||||
if (isIndexed()) {
|
||||
return getIndexed() == other.getIndexed();
|
||||
}
|
||||
return true;
|
||||
return !isIndexed() || getIndexed() == other.getIndexed();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private boolean sameARGB(XSSFColor other) {
|
||||
if (isRGB() == other.isRGB()) {
|
||||
if (isRGB()) {
|
||||
return Arrays.equals(getARGB(), other.getARGB());
|
||||
}
|
||||
return true;
|
||||
return !isRGB() || Arrays.equals(getARGB(), other.getARGB());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private boolean sameTheme(XSSFColor other) {
|
||||
if (isThemed() == other.isThemed()) {
|
||||
if (isThemed()) {
|
||||
return getTheme() == other.getTheme();
|
||||
}
|
||||
return true;
|
||||
return !isThemed() || getTheme() == other.getTheme();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private boolean sameTint(XSSFColor other) {
|
||||
if (hasTint() == other.hasTint()) {
|
||||
if (hasTint()) {
|
||||
return getTint() == other.getTint();
|
||||
}
|
||||
return true;
|
||||
return !hasTint() || getTint() == other.getTint();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ public class XSSFFont implements Font {
|
|||
* get character-set to use.
|
||||
*
|
||||
* @return int - character-set (0-255)
|
||||
* @see org.apache.poi.ss.usermodel.FontCharset
|
||||
* @see FontCharset
|
||||
*/
|
||||
public int getCharSet() {
|
||||
CTIntProperty charset = _ctFont.sizeOfCharsetArray() == 0 ? null : _ctFont.getCharsetArray(0);
|
||||
|
@ -297,7 +297,7 @@ public class XSSFFont implements Font {
|
|||
public void setBold(boolean bold) {
|
||||
if(bold){
|
||||
CTBooleanProperty ctBold = _ctFont.sizeOfBArray() == 0 ? _ctFont.addNewB() : _ctFont.getBArray(0);
|
||||
ctBold.setVal(bold);
|
||||
ctBold.setVal(true);
|
||||
} else {
|
||||
_ctFont.setBArray(null);
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ public class XSSFFont implements Font {
|
|||
public void setItalic(boolean italic) {
|
||||
if(italic){
|
||||
CTBooleanProperty bool = _ctFont.sizeOfIArray() == 0 ? _ctFont.addNewI() : _ctFont.getIArray(0);
|
||||
bool.setVal(italic);
|
||||
bool.setVal(true);
|
||||
} else {
|
||||
_ctFont.setIArray(null);
|
||||
}
|
||||
|
@ -462,10 +462,11 @@ public class XSSFFont implements Font {
|
|||
* @param strikeout - value for strikeout or not
|
||||
*/
|
||||
public void setStrikeout(boolean strikeout) {
|
||||
if(!strikeout) _ctFont.setStrikeArray(null);
|
||||
else {
|
||||
if(strikeout) {
|
||||
CTBooleanProperty strike = _ctFont.sizeOfStrikeArray() == 0 ? _ctFont.addNewStrike() : _ctFont.getStrikeArray(0);
|
||||
strike.setVal(strikeout);
|
||||
strike.setVal(true);
|
||||
} else {
|
||||
_ctFont.setStrikeArray(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,14 +14,11 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -40,6 +36,7 @@ import org.junit.Test;
|
|||
* Class to test that HXF correctly detects OOXML
|
||||
* documents
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class TestDetectAsOOXML {
|
||||
@Test
|
||||
public void testOpensProperly() throws IOException, InvalidFormatException {
|
||||
|
@ -59,10 +56,9 @@ public class TestDetectAsOOXML {
|
|||
is = FileMagic.prepareToCheckMagic(is);
|
||||
FileMagic act = FileMagic.valueOf(is);
|
||||
|
||||
if (act == FileMagic.OOXML) {
|
||||
assertTrue(DocumentFactoryHelper.hasOOXMLHeader(is));
|
||||
}
|
||||
|
||||
assertEquals("OOXML files should be detected, others not",
|
||||
act == FileMagic.OOXML, DocumentFactoryHelper.hasOOXMLHeader(is));
|
||||
|
||||
assertEquals("file magic failed for "+fm[0], fm[1], act);
|
||||
is.close();
|
||||
}
|
||||
|
@ -70,7 +66,6 @@ public class TestDetectAsOOXML {
|
|||
|
||||
@Test
|
||||
public void testFileCorruption() throws Exception {
|
||||
|
||||
// create test InputStream
|
||||
byte[] testData = { 1, 2, 3 };
|
||||
ByteArrayInputStream testInput = new ByteArrayInputStream(testData);
|
||||
|
|
|
@ -124,6 +124,7 @@ public final class TestStylesTable {
|
|||
assertEquals(165, st.getStyleAt(3).getDataFormat());
|
||||
|
||||
assertEquals("yyyy/mm/dd", st.getStyleAt(3).getDataFormatString());
|
||||
assertEquals("[]", st.getExplicitTableStyleNames().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -186,8 +187,7 @@ public final class TestStylesTable {
|
|||
|
||||
@Test
|
||||
public void exceedNumberFormatLimit() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
try {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
StylesTable styles = wb.getStylesSource();
|
||||
for (int i = 0; i < styles.getMaxNumberOfDataFormats(); i++) {
|
||||
wb.getStylesSource().putNumberFormat("\"test" + i + " \"0");
|
||||
|
@ -195,15 +195,10 @@ public final class TestStylesTable {
|
|||
try {
|
||||
wb.getStylesSource().putNumberFormat("\"anotherformat \"0");
|
||||
} catch (final IllegalStateException e) {
|
||||
if (e.getMessage().startsWith("The maximum number of Data Formats was exceeded.")) {
|
||||
//expected
|
||||
}
|
||||
else {
|
||||
if (!e.getMessage().startsWith("The maximum number of Data Formats was exceeded.")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,145 +211,127 @@ public final class TestStylesTable {
|
|||
|
||||
@Test
|
||||
public void removeNumberFormat() throws IOException {
|
||||
XSSFWorkbook wb1 = new XSSFWorkbook();
|
||||
try {
|
||||
try (XSSFWorkbook wb1 = new XSSFWorkbook()) {
|
||||
final String fmt = customDataFormat;
|
||||
final short fmtIdx = (short) wb1.getStylesSource().putNumberFormat(fmt);
|
||||
|
||||
|
||||
Cell cell = wb1.createSheet("test").createRow(0).createCell(0);
|
||||
cell.setCellValue(5.25);
|
||||
CellStyle style = wb1.createCellStyle();
|
||||
style.setDataFormat(fmtIdx);
|
||||
cell.setCellStyle(style);
|
||||
|
||||
|
||||
assertEquals(fmt, cell.getCellStyle().getDataFormatString());
|
||||
assertEquals(fmt, wb1.getStylesSource().getNumberFormatAt(fmtIdx));
|
||||
|
||||
|
||||
// remove the number format from the workbook
|
||||
wb1.getStylesSource().removeNumberFormat(fmt);
|
||||
|
||||
assertTrue("The format is removed on first call",
|
||||
wb1.getStylesSource().removeNumberFormat(fmt));
|
||||
try {
|
||||
wb1.getStylesSource().removeNumberFormat(fmt);
|
||||
fail("Should fail here");
|
||||
} catch (IllegalStateException e) {
|
||||
// expected here
|
||||
}
|
||||
|
||||
// number format in CellStyles should be restored to default number format
|
||||
final short defaultFmtIdx = 0;
|
||||
final String defaultFmt = BuiltinFormats.getBuiltinFormat(0);
|
||||
assertEquals(defaultFmtIdx, style.getDataFormat());
|
||||
assertEquals(defaultFmt, style.getDataFormatString());
|
||||
|
||||
|
||||
// The custom number format should be entirely removed from the workbook
|
||||
Map<Short,String> numberFormats = wb1.getStylesSource().getNumberFormats();
|
||||
Map<Short, String> numberFormats = wb1.getStylesSource().getNumberFormats();
|
||||
assertNotContainsKey(numberFormats, fmtIdx);
|
||||
assertNotContainsValue(numberFormats, fmt);
|
||||
|
||||
|
||||
// The default style shouldn't be added back to the styles source because it's built-in
|
||||
assertEquals(0, wb1.getStylesSource().getNumDataFormats());
|
||||
|
||||
cell = null; style = null; numberFormats = null;
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutCloseAndReadBack(wb1);
|
||||
|
||||
cell = wb2.getSheet("test").getRow(0).getCell(0);
|
||||
style = cell.getCellStyle();
|
||||
|
||||
// number format in CellStyles should be restored to default number format
|
||||
assertEquals(defaultFmtIdx, style.getDataFormat());
|
||||
assertEquals(defaultFmt, style.getDataFormatString());
|
||||
|
||||
// The custom number format should be entirely removed from the workbook
|
||||
numberFormats = wb2.getStylesSource().getNumberFormats();
|
||||
assertNotContainsKey(numberFormats, fmtIdx);
|
||||
assertNotContainsValue(numberFormats, fmt);
|
||||
|
||||
// The default style shouldn't be added back to the styles source because it's built-in
|
||||
assertEquals(0, wb2.getStylesSource().getNumDataFormats());
|
||||
|
||||
wb2.close();
|
||||
|
||||
} finally {
|
||||
wb1.close();
|
||||
|
||||
try (XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutCloseAndReadBack(wb1)) {
|
||||
|
||||
cell = wb2.getSheet("test").getRow(0).getCell(0);
|
||||
style = cell.getCellStyle();
|
||||
|
||||
// number format in CellStyles should be restored to default number format
|
||||
assertEquals(defaultFmtIdx, style.getDataFormat());
|
||||
assertEquals(defaultFmt, style.getDataFormatString());
|
||||
|
||||
// The custom number format should be entirely removed from the workbook
|
||||
numberFormats = wb2.getStylesSource().getNumberFormats();
|
||||
assertNotContainsKey(numberFormats, fmtIdx);
|
||||
assertNotContainsValue(numberFormats, fmt);
|
||||
|
||||
// The default style shouldn't be added back to the styles source because it's built-in
|
||||
assertEquals(0, wb2.getStylesSource().getNumDataFormats());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxNumberOfDataFormats() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
|
||||
try {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
StylesTable styles = wb.getStylesSource();
|
||||
|
||||
|
||||
// Check default limit
|
||||
int n = styles.getMaxNumberOfDataFormats();
|
||||
// https://support.office.com/en-us/article/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3
|
||||
assertTrue(200 <= n);
|
||||
assertTrue(n <= 250);
|
||||
|
||||
|
||||
// Check upper limit
|
||||
n = Integer.MAX_VALUE;
|
||||
styles.setMaxNumberOfDataFormats(n);
|
||||
assertEquals(n, styles.getMaxNumberOfDataFormats());
|
||||
|
||||
|
||||
// Check negative (illegal) limits
|
||||
try {
|
||||
styles.setMaxNumberOfDataFormats(-1);
|
||||
fail("Expected to get an IllegalArgumentException(\"Maximum Number of Data Formats must be greater than or equal to 0\")");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
if (e.getMessage().startsWith("Maximum Number of Data Formats must be greater than or equal to 0")) {
|
||||
// expected
|
||||
} else {
|
||||
if (!e.getMessage().startsWith("Maximum Number of Data Formats must be greater than or equal to 0")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDataFormatsBeyondUpperLimit() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
|
||||
try {
|
||||
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
StylesTable styles = wb.getStylesSource();
|
||||
styles.setMaxNumberOfDataFormats(0);
|
||||
|
||||
|
||||
// Try adding a format beyond the upper limit
|
||||
try {
|
||||
styles.putNumberFormat("\"test \"0");
|
||||
fail("Expected to raise IllegalStateException");
|
||||
} catch (final IllegalStateException e) {
|
||||
if (e.getMessage().startsWith("The maximum number of Data Formats was exceeded.")) {
|
||||
// expected
|
||||
} else {
|
||||
if (!e.getMessage().startsWith("The maximum number of Data Formats was exceeded.")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decreaseUpperLimitBelowCurrentNumDataFormats() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
|
||||
try {
|
||||
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
StylesTable styles = wb.getStylesSource();
|
||||
styles.putNumberFormat(customDataFormat);
|
||||
|
||||
|
||||
// Try decreasing the upper limit below the current number of formats
|
||||
try {
|
||||
styles.setMaxNumberOfDataFormats(0);
|
||||
fail("Expected to raise IllegalStateException");
|
||||
} catch (final IllegalStateException e) {
|
||||
if (e.getMessage().startsWith("Cannot set the maximum number of data formats less than the current quantity.")) {
|
||||
// expected
|
||||
} else {
|
||||
if (!e.getMessage().startsWith("Cannot set the maximum number of data formats less than the current quantity.")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -363,6 +340,21 @@ public final class TestStylesTable {
|
|||
assertNotNull(workbook.getStylesSource());
|
||||
|
||||
StylesTable st = workbook.getStylesSource();
|
||||
assertNotNull(st);
|
||||
|
||||
assertNotNull(XSSFTestDataSamples.writeOutAndReadBack(workbook));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceStyle() {
|
||||
XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("style-alternate-content.xlsx");
|
||||
assertNotNull(workbook.getStylesSource());
|
||||
|
||||
StylesTable st = workbook.getStylesSource();
|
||||
assertNotNull(st);
|
||||
|
||||
st.replaceCellStyleXfAt(0, st.getCellStyleXfAt(1));
|
||||
st.replaceCellStyleXfAt(1, st.getCellStyleXfAt(1));
|
||||
|
||||
assertNotNull(XSSFTestDataSamples.writeOutAndReadBack(workbook));
|
||||
}
|
||||
|
|
|
@ -2524,20 +2524,20 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
|
||||
|
||||
CalculationChain chain = ((XSSFWorkbook) wb).getCalculationChain();
|
||||
for (CTCalcCell calc : chain.getCTCalcChain().getCList()) {
|
||||
// A2 to A6 should be gone
|
||||
assertFalse(calc.getR().equals("A2"));
|
||||
assertFalse(calc.getR().equals("A3"));
|
||||
assertFalse(calc.getR().equals("A4"));
|
||||
assertFalse(calc.getR().equals("A5"));
|
||||
assertFalse(calc.getR().equals("A6"));
|
||||
}
|
||||
checkCellsAreGone(chain);
|
||||
|
||||
Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
Sheet sheetBack = wbBack.getSheet("Func");
|
||||
assertNotNull(sheetBack);
|
||||
|
||||
chain = ((XSSFWorkbook) wbBack).getCalculationChain();
|
||||
checkCellsAreGone(chain);
|
||||
|
||||
wbBack.close();
|
||||
wb.close();
|
||||
}
|
||||
|
||||
private void checkCellsAreGone(CalculationChain chain) {
|
||||
for (CTCalcCell calc : chain.getCTCalcChain().getCList()) {
|
||||
// A2 to A6 should be gone
|
||||
assertFalse(calc.getR().equals("A2"));
|
||||
|
@ -2546,9 +2546,6 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
assertFalse(calc.getR().equals("A5"));
|
||||
assertFalse(calc.getR().equals("A6"));
|
||||
}
|
||||
|
||||
wbBack.close();
|
||||
wb.close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2571,22 +2568,6 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
|
|||
wb.close();
|
||||
}
|
||||
|
||||
private void assertFormula(Workbook wb, Cell intF, String expectedFormula, String expectedResultOrNull) {
|
||||
assertEquals(CellType.FORMULA, intF.getCellType());
|
||||
if (null == expectedResultOrNull) {
|
||||
assertEquals(CellType.ERROR, intF.getCachedFormulaResultType());
|
||||
expectedResultOrNull = "#VALUE!";
|
||||
} else {
|
||||
assertEquals(CellType.NUMERIC, intF.getCachedFormulaResultType());
|
||||
}
|
||||
|
||||
assertEquals(expectedFormula, intF.getCellFormula());
|
||||
|
||||
// Check we can evaluate it correctly
|
||||
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
||||
assertEquals(expectedResultOrNull, eval.evaluate(intF).formatAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test48962() throws IOException {
|
||||
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("48962.xlsx");
|
||||
|
|
|
@ -17,14 +17,6 @@
|
|||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -58,6 +50,8 @@ import org.junit.Test;
|
|||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public final class TestXSSFCell extends BaseTestXCell {
|
||||
|
||||
public TestXSSFCell() {
|
||||
|
@ -149,17 +143,16 @@ public final class TestXSSFCell extends BaseTestXCell {
|
|||
|
||||
@Test
|
||||
public void testFormulaString() throws IOException {
|
||||
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook();
|
||||
try {
|
||||
try (XSSFWorkbook wb = (XSSFWorkbook) _testDataProvider.createWorkbook()) {
|
||||
XSSFCell cell = wb.createSheet().createRow(0).createCell(0);
|
||||
CTCell ctCell = cell.getCTCell(); //low-level bean holding cell's xml
|
||||
|
||||
|
||||
cell.setCellFormula("A2");
|
||||
assertEquals(CellType.FORMULA, cell.getCellType());
|
||||
assertEquals("A2", cell.getCellFormula());
|
||||
//the value is not set and cell's type='N' which means blank
|
||||
assertEquals(STCellType.N, ctCell.getT());
|
||||
|
||||
|
||||
//set cached formula value
|
||||
cell.setCellValue("t='str'");
|
||||
//we are still of 'formula' type
|
||||
|
@ -168,57 +161,44 @@ public final class TestXSSFCell extends BaseTestXCell {
|
|||
//cached formula value is set and cell's type='STR'
|
||||
assertEquals(STCellType.STR, ctCell.getT());
|
||||
assertEquals("t='str'", cell.getStringCellValue());
|
||||
|
||||
|
||||
//now remove the formula, the cached formula result remains
|
||||
cell.setCellFormula(null);
|
||||
assertEquals(CellType.STRING, cell.getCellType());
|
||||
assertEquals(STCellType.STR, ctCell.getT());
|
||||
//the line below failed prior to fix of Bug #47889
|
||||
assertEquals("t='str'", cell.getStringCellValue());
|
||||
|
||||
|
||||
//revert to a blank cell
|
||||
cell.setCellValue((String)null);
|
||||
cell.setCellValue((String) null);
|
||||
assertEquals(CellType.BLANK, cell.getCellType());
|
||||
assertEquals(STCellType.N, ctCell.getT());
|
||||
assertEquals("", cell.getStringCellValue());
|
||||
|
||||
// check behavior with setCellFormulaValidation
|
||||
final String invalidFormula = "A", validFormula = "A2";
|
||||
FormulaParseException fpe = null;
|
||||
|
||||
// check that default is true
|
||||
assertTrue(wb.getCellFormulaValidation());
|
||||
|
||||
// check that valid formula does not throw exception
|
||||
try {
|
||||
cell.setCellFormula(validFormula);
|
||||
} catch(FormulaParseException e) {
|
||||
fpe = e;
|
||||
}
|
||||
assertNull(fpe);
|
||||
cell.setCellFormula(validFormula);
|
||||
|
||||
// check that invalid formula does throw exception
|
||||
try {
|
||||
cell.setCellFormula(invalidFormula);
|
||||
} catch(FormulaParseException e) {
|
||||
fpe = e;
|
||||
fail("Should catch exception here");
|
||||
} catch (FormulaParseException e) {
|
||||
// expected here
|
||||
}
|
||||
assertNotNull(fpe);
|
||||
fpe = null;
|
||||
|
||||
// set cell formula validation to false
|
||||
wb.setCellFormulaValidation(false);
|
||||
assertFalse(wb.getCellFormulaValidation());
|
||||
|
||||
// check that neither valid nor invalid formula throw an exception
|
||||
try {
|
||||
cell.setCellFormula(validFormula);
|
||||
cell.setCellFormula(invalidFormula);
|
||||
} catch(FormulaParseException e) {
|
||||
fpe = e;
|
||||
}
|
||||
assertNull(fpe);
|
||||
} finally {
|
||||
wb.close();
|
||||
cell.setCellFormula(validFormula);
|
||||
cell.setCellFormula(invalidFormula);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,37 +389,34 @@ public final class TestXSSFCell extends BaseTestXCell {
|
|||
|
||||
@Test
|
||||
public void test56170Reproduce() throws IOException {
|
||||
final Workbook wb = new XSSFWorkbook();
|
||||
try {
|
||||
try (Workbook wb = new XSSFWorkbook()) {
|
||||
final Sheet sheet = wb.createSheet();
|
||||
Row row = sheet.createRow(0);
|
||||
|
||||
|
||||
// by creating Cells out of order we trigger the handling in onDocumentWrite()
|
||||
Cell cell1 = row.createCell(1);
|
||||
Cell cell2 = row.createCell(0);
|
||||
|
||||
|
||||
validateRow(row);
|
||||
|
||||
|
||||
validateRow(row);
|
||||
|
||||
|
||||
// once again with removing one cell
|
||||
row.removeCell(cell1);
|
||||
|
||||
|
||||
validateRow(row);
|
||||
|
||||
|
||||
// once again with removing one cell
|
||||
row.removeCell(cell1);
|
||||
|
||||
|
||||
// now check again
|
||||
validateRow(row);
|
||||
|
||||
|
||||
// once again with removing one cell
|
||||
row.removeCell(cell2);
|
||||
|
||||
|
||||
// now check again
|
||||
validateRow(row);
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,40 +431,31 @@ public final class TestXSSFCell extends BaseTestXCell {
|
|||
|
||||
@Test
|
||||
public void testBug56644ReturnNull() throws IOException {
|
||||
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
|
||||
try {
|
||||
try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx")) {
|
||||
wb.setMissingCellPolicy(MissingCellPolicy.RETURN_BLANK_AS_NULL);
|
||||
Sheet sheet = wb.getSheet("samplelist");
|
||||
Row row = sheet.getRow(20);
|
||||
row.createCell(2);
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBug56644ReturnBlank() throws IOException {
|
||||
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
|
||||
try {
|
||||
try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx")) {
|
||||
wb.setMissingCellPolicy(MissingCellPolicy.RETURN_NULL_AND_BLANK);
|
||||
Sheet sheet = wb.getSheet("samplelist");
|
||||
Row row = sheet.getRow(20);
|
||||
row.createCell(2);
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBug56644CreateBlank() throws IOException {
|
||||
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
|
||||
try {
|
||||
try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx")) {
|
||||
wb.setMissingCellPolicy(MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
Sheet sheet = wb.getSheet("samplelist");
|
||||
Row row = sheet.getRow(20);
|
||||
row.createCell(2);
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,8 +93,8 @@ public class TestXSSFCellStyle {
|
|||
cellXf.setBorderId(1);
|
||||
cellXf.setFillId(1);
|
||||
cellXf.setFontId(1);
|
||||
stylesTable.putCellStyleXf(cellStyleXf);
|
||||
stylesTable.putCellXf(cellXf);
|
||||
assertEquals(2, stylesTable.putCellStyleXf(cellStyleXf));
|
||||
assertEquals(2, stylesTable.putCellXf(cellXf));
|
||||
cellStyle = new XSSFCellStyle(1, 1, stylesTable, null);
|
||||
|
||||
assertNotNull(stylesTable.getFillAt(1).getCTFill().getPatternFill());
|
||||
|
@ -537,7 +537,8 @@ public class TestXSSFCellStyle {
|
|||
assertEquals(IndexedColors.AUTOMATIC.getIndex(), cellStyle.getFillBackgroundColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testDefaultStyles() throws IOException {
|
||||
|
||||
XSSFWorkbook wb1 = new XSSFWorkbook();
|
||||
|
@ -569,7 +570,8 @@ public class TestXSSFCellStyle {
|
|||
wb2.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testGetFillForegroundColor() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
StylesTable styles = wb.getStylesSource();
|
||||
|
@ -610,6 +612,7 @@ public class TestXSSFCellStyle {
|
|||
wb.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testGetFillPattern() {
|
||||
|
||||
|
@ -674,7 +677,8 @@ public class TestXSSFCellStyle {
|
|||
assertEquals((short)13, cellStyle.getIndention());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testGetSetAlignment() {
|
||||
assertNull(cellStyle.getCellAlignment().getCTCellAlignment().getHorizontal());
|
||||
assertEquals(HorizontalAlignment.GENERAL, cellStyle.getAlignmentEnum());
|
||||
|
@ -695,7 +699,8 @@ public class TestXSSFCellStyle {
|
|||
assertEquals(STHorizontalAlignment.CENTER, cellStyle.getCellAlignment().getCTCellAlignment().getHorizontal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testGetSetVerticalAlignment() {
|
||||
assertEquals(VerticalAlignment.BOTTOM, cellStyle.getVerticalAlignmentEnum());
|
||||
assertEquals(VerticalAlignment.BOTTOM.getCode(), cellStyle.getVerticalAlignment());
|
||||
|
@ -958,6 +963,7 @@ public class TestXSSFCellStyle {
|
|||
assertEquals(HorizontalAlignment.RIGHT, styleBack.getAlignmentEnum());
|
||||
assertEquals(VerticalAlignment.TOP, styleBack.getVerticalAlignmentEnum());
|
||||
assertEquals(FillPatternType.SOLID_FOREGROUND, styleBack.getFillPatternEnum());
|
||||
//noinspection deprecation
|
||||
assertEquals(FillPatternType.SOLID_FOREGROUND.getCode(), styleBack.getFillPattern());
|
||||
|
||||
wbBack.close();
|
||||
|
|
|
@ -85,7 +85,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnsignedShortHex;
|
|||
|
||||
|
||||
public final class TestXSSFSheet extends BaseTestXSheet {
|
||||
|
||||
public TestXSSFSheet() {
|
||||
super(XSSFITestDataProvider.instance);
|
||||
}
|
||||
|
@ -319,7 +318,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
cellStyleXf.setFillId(0);
|
||||
cellStyleXf.setBorderId(0);
|
||||
cellStyleXf.setNumFmtId(0);
|
||||
stylesTable.putCellStyleXf(cellStyleXf);
|
||||
assertEquals(2, stylesTable.putCellStyleXf(cellStyleXf));
|
||||
CTXf cellXf = CTXf.Factory.newInstance();
|
||||
cellXf.setXfId(1);
|
||||
stylesTable.putCellXf(cellXf);
|
||||
|
@ -367,7 +366,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
|
||||
sheet.ungroupColumn(8, 10);
|
||||
colArray = cols.getColArray();
|
||||
//assertEquals(3, colArray[1].getOutlineLevel());
|
||||
assertEquals(3, colArray[1].getOutlineLevel());
|
||||
|
||||
sheet.ungroupColumn(4, 6);
|
||||
sheet.ungroupColumn(2, 2);
|
||||
|
@ -564,6 +563,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
* @param fromColumnIndex 0-indexed
|
||||
* @param toColumnIndex 0-indexed
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static void checkColumnGroup(
|
||||
CTCol col,
|
||||
int fromColumnIndex, int toColumnIndex,
|
||||
|
@ -615,6 +615,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
* @param fromColumnIndex 0-indexed
|
||||
* @param toColumnIndex 0-indexed
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static void checkColumnGroupIsExpanded(
|
||||
CTCol col,
|
||||
int fromColumnIndex, int toColumnIndex
|
||||
|
@ -992,6 +993,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
wb1.close();
|
||||
sheet = wb2.getSheetAt(0);
|
||||
wsh = sheet.getCTWorksheet();
|
||||
assertNotNull(wsh);
|
||||
xrow = sheetData.getRowArray();
|
||||
assertEquals(3, xrow.length);
|
||||
|
||||
|
@ -1888,52 +1890,43 @@ public final class TestXSSFSheet extends BaseTestXSheet {
|
|||
|
||||
@Test
|
||||
public void setTabColor() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
try {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sh = wb.createSheet();
|
||||
assertTrue(sh.getCTWorksheet().getSheetPr() == null || !sh.getCTWorksheet().getSheetPr().isSetTabColor());
|
||||
sh.setTabColor(new XSSFColor(IndexedColors.RED, null));
|
||||
assertTrue(sh.getCTWorksheet().getSheetPr().isSetTabColor());
|
||||
assertEquals(IndexedColors.RED.index,
|
||||
sh.getCTWorksheet().getSheetPr().getTabColor().getIndexed());
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTabColor() throws IOException {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
try {
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook()) {
|
||||
XSSFSheet sh = wb.createSheet();
|
||||
assertTrue(sh.getCTWorksheet().getSheetPr() == null || !sh.getCTWorksheet().getSheetPr().isSetTabColor());
|
||||
assertNull(sh.getTabColor());
|
||||
sh.setTabColor(new XSSFColor(IndexedColors.RED, null));
|
||||
XSSFColor expected = new XSSFColor(IndexedColors.RED, null);
|
||||
assertEquals(expected, sh.getTabColor());
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Test using an existing workbook saved by Excel
|
||||
@Test
|
||||
public void tabColor() throws IOException {
|
||||
XSSFWorkbook wb = openSampleWorkbook("SheetTabColors.xlsx");
|
||||
try {
|
||||
try (XSSFWorkbook wb = openSampleWorkbook("SheetTabColors.xlsx")) {
|
||||
// non-colored sheets do not have a color
|
||||
assertNull(wb.getSheet("default").getTabColor());
|
||||
|
||||
|
||||
// test indexed-colored sheet
|
||||
XSSFColor expected = new XSSFColor(IndexedColors.RED, null);
|
||||
assertEquals(expected, wb.getSheet("indexedRed").getTabColor());
|
||||
|
||||
|
||||
// test regular-colored (non-indexed, ARGB) sheet
|
||||
expected = new XSSFColor();
|
||||
expected.setARGBHex("FF7F2700");
|
||||
assertEquals(expected, wb.getSheet("customOrange").getTabColor());
|
||||
} finally {
|
||||
wb.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1872,7 +1872,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||
// Link our new workbook
|
||||
Workbook externalWb1 = new HSSFWorkbook();
|
||||
externalWb1.createSheet("Sheet1");
|
||||
wb1.linkExternalWorkbook("$http://gagravarr.org/FormulaRefs2.xls", externalWb1);
|
||||
assertEquals(4, wb1.linkExternalWorkbook("$http://gagravarr.org/FormulaRefs2.xls", externalWb1));
|
||||
|
||||
// Change 4
|
||||
row.getCell(1).setCellFormula("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2");
|
||||
|
@ -1881,7 +1881,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||
// Link our new workbook
|
||||
Workbook externalWb2 = new HSSFWorkbook();
|
||||
externalWb2.createSheet("Sheet1");
|
||||
wb1.linkExternalWorkbook("$http://example.com/FormulaRefs.xls", externalWb2);
|
||||
assertEquals(5, wb1.linkExternalWorkbook("$http://example.com/FormulaRefs.xls", externalWb2));
|
||||
|
||||
// Add 5
|
||||
row = s.createRow(5);
|
||||
|
@ -2782,22 +2782,6 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||
wb.close();
|
||||
}
|
||||
|
||||
private void assertFormula(Workbook wb, Cell intF, String expectedFormula, String expectedResultOrNull) {
|
||||
assertEquals(CellType.FORMULA, intF.getCellType());
|
||||
if (null == expectedResultOrNull) {
|
||||
assertEquals(CellType.ERROR, intF.getCachedFormulaResultType());
|
||||
expectedResultOrNull = "#VALUE!";
|
||||
} else {
|
||||
assertEquals(CellType.NUMERIC, intF.getCachedFormulaResultType());
|
||||
}
|
||||
|
||||
assertEquals(expectedFormula, intF.getCellFormula());
|
||||
|
||||
// Check we can evaluate it correctly
|
||||
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
||||
assertEquals(expectedResultOrNull, eval.evaluate(intF).formatAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bug42016() throws Exception {
|
||||
Workbook wb = openSample("42016.xls");
|
||||
|
|
|
@ -224,8 +224,7 @@ public final class TestHSSFFormulaEvaluator extends BaseTestFormulaEvaluator {
|
|||
// Check it evaluates correctly
|
||||
eval.evaluateFormulaCell(cell);
|
||||
assertEquals(24.60*1.8, cell.getNumericCellValue(), 0);
|
||||
|
||||
|
||||
|
||||
// Try to add a formula for a new external workbook, won't be allowed to start
|
||||
try {
|
||||
cell = wb1.getSheetAt(0).getRow(1).createCell(42);
|
||||
|
@ -238,7 +237,7 @@ public final class TestHSSFFormulaEvaluator extends BaseTestFormulaEvaluator {
|
|||
// Link our new workbook
|
||||
HSSFWorkbook wb3 = new HSSFWorkbook();
|
||||
wb3.createSheet().createRow(0).createCell(0).setCellValue("In another workbook");
|
||||
wb1.linkExternalWorkbook("alt.xls", wb3);
|
||||
assertEquals(2, wb1.linkExternalWorkbook("alt.xls", wb3));
|
||||
|
||||
// Now add a formula that refers to our new workbook
|
||||
cell.setCellFormula("[alt.xls]Sheet0!$A$1");
|
||||
|
|
|
@ -1896,4 +1896,20 @@ public abstract class BaseTestBugzillaIssues {
|
|||
|
||||
wb.close();
|
||||
}
|
||||
|
||||
protected void assertFormula(Workbook wb, Cell intF, String expectedFormula, String expectedResultOrNull) {
|
||||
assertEquals(CellType.FORMULA, intF.getCellType());
|
||||
if (null == expectedResultOrNull) {
|
||||
assertEquals(CellType.ERROR, intF.getCachedFormulaResultType());
|
||||
expectedResultOrNull = "#VALUE!";
|
||||
} else {
|
||||
assertEquals(CellType.NUMERIC, intF.getCachedFormulaResultType());
|
||||
}
|
||||
|
||||
assertEquals(expectedFormula, intF.getCellFormula());
|
||||
|
||||
// Check we can evaluate it correctly
|
||||
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
||||
assertEquals(expectedResultOrNull, eval.evaluate(intF).formatAsString());
|
||||
}
|
||||
}
|
|
@ -133,6 +133,7 @@ public abstract class BaseTestFont {
|
|||
Workbook wb3 = _testDataProvider.writeOutAndReadBack(wb2);
|
||||
wb2.close();
|
||||
s1 = wb3.getSheetAt(0);
|
||||
assertNotNull(s1);
|
||||
|
||||
assertEquals(num0 + 2, wb3.getNumberOfFonts());
|
||||
assertNotNull(wb3.getFontAt(font1Idx));
|
||||
|
@ -145,8 +146,6 @@ public abstract class BaseTestFont {
|
|||
|
||||
/**
|
||||
* Test that fonts get added properly
|
||||
*
|
||||
* @see org.apache.poi.hssf.usermodel.TestBugs#test45338()
|
||||
*/
|
||||
@Test
|
||||
public final void test45338() throws IOException {
|
||||
|
|
Loading…
Reference in New Issue