poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cen...@apache.org
Subject svn commit: r1850008 - in /poi/trunk: src/integrationtest/org/apache/poi/stress/ src/java/org/apache/poi/ss/formula/ src/java/org/apache/poi/ss/formula/ptg/ src/testcases/org/apache/poi/hssf/usermodel/ src/testcases/org/apache/poi/ss/formula/ test-data...
Date Sun, 30 Dec 2018 22:44:40 GMT
Author: centic
Date: Sun Dec 30 22:44:40 2018
New Revision: 1850008

URL: http://svn.apache.org/viewvc?rev=1850008&view=rev
Log:
Bug 60460: Handle null workbook or sheet names and emit #REF as Excel does
instead of throwing NullPointerException

Added:
    poi/trunk/test-data/spreadsheet/60460.xls
Modified:
    poi/trunk/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java
    poi/trunk/src/java/org/apache/poi/ss/formula/SheetNameFormatter.java
    poi/trunk/src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java
    poi/trunk/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
    poi/trunk/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java

Modified: poi/trunk/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java?rev=1850008&r1=1850007&r2=1850008&view=diff
==============================================================================
--- poi/trunk/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java (original)
+++ poi/trunk/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java Sun Dec 30
22:44:40 2018
@@ -22,10 +22,10 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.extractor.EmbeddedData;
 import org.apache.poi.ss.extractor.EmbeddedExtractor;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Name;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
@@ -91,6 +91,13 @@ public abstract class SpreadsheetHandler
 			    }
 			}
 		}
+
+		for (Name name : wb.getAllNames()) {
+			// this sometimes caused exceptions
+            if(!name.isFunctionName()) {
+                name.getRefersToFormula();
+            }
+		}
 	}
 
 	private void extractEmbedded(Workbook wb) throws IOException {

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/SheetNameFormatter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/SheetNameFormatter.java?rev=1850008&r1=1850007&r2=1850008&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/SheetNameFormatter.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/SheetNameFormatter.java Sun Dec 30 22:44:40
2018
@@ -17,11 +17,13 @@
 
 package org.apache.poi.ss.formula;
 
+import java.io.IOException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.util.Removal;
 
 /**
  * Formats sheet names for use in formula expressions.
@@ -47,106 +49,134 @@ public final class SheetNameFormatter {
 	 * sheet name will be converted to double single quotes ('').  
 	 */
 	public static String format(String rawSheetName) {
-        StringBuilder sb = new StringBuilder(rawSheetName.length() + 2);
+        StringBuilder sb = new StringBuilder((rawSheetName == null ? 0 : rawSheetName.length())
+ 2);
 		appendFormat(sb, rawSheetName);
 		return sb.toString();
 	}
-	
-	/**
-	 * Convenience method for ({@link #format(String)}) when a StringBuffer is already available.
-	 *
-     * @param out - sheet name will be appended here possibly with delimiting quotes
-     * @param rawSheetName - sheet name
-     * @deprecated use <code>appendFormat(StringBuilder out, String rawSheetName)</code>
instead
-	 */
-	@Deprecated
-	public static void appendFormat(StringBuffer out, String rawSheetName) {
-		boolean needsQuotes = needsDelimiting(rawSheetName);
-		if(needsQuotes) {
-			out.append(DELIMITER);
-			appendAndEscape(out, rawSheetName);
-			out.append(DELIMITER);
-		} else {
-			out.append(rawSheetName);
-		}
-	}
 
     /**
-     * @deprecated use <code>appendFormat(StringBuilder out, String workbookName, String
rawSheetName)</code> instead
+     * @deprecated Only kept for binary compatibility, will be replaced by the version with
Appendable as parameter
      */
     @Deprecated
-	public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName)
{
-		boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
-		if(needsQuotes) {
-			out.append(DELIMITER);
-			out.append('[');
-			appendAndEscape(out, workbookName.replace('[', '(').replace(']', ')'));
-			out.append(']');
-			appendAndEscape(out, rawSheetName);
-			out.append(DELIMITER);
-		} else {
-			out.append('[');
-			out.append(workbookName);
-			out.append(']');
-			out.append(rawSheetName);
+    @Removal(version="5.0.0")
+    public static void appendFormat(StringBuffer out, String rawSheetName) {
+        appendFormat((Appendable)out, rawSheetName);
+    }
+
+    /**
+     * @deprecated Only kept for binary compatibility, will be replaced by the version with
Appendable as parameter
+     */
+    @Deprecated
+    @Removal(version="5.0.0")
+    public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName)
{
+        appendFormat((Appendable)out, workbookName, rawSheetName);
+    }
+
+    /**
+     * Only kept for binary compatibility, will be replaced by the version with Appendable
as parameter
+     */
+    @Removal(version="5.0.0")
+    public static void appendFormat(StringBuilder out, String rawSheetName) {
+        appendFormat((Appendable)out, rawSheetName);
+    }
+
+    /**
+     * Only kept for binary compatibility, will be replaced by the version with Appendable
as parameter
+     */
+    @Removal(version="5.0.0")
+    public static void appendFormat(StringBuilder out, String workbookName, String rawSheetName)
{
+        appendFormat((Appendable)out, workbookName, rawSheetName);
+    }
+
+    /**
+     * Convenience method for ({@link #format(String)}) when a StringBuffer is already available.
+     *
+     * @param out - sheet name will be appended here possibly with delimiting quotes
+     * @param rawSheetName - sheet name
+     */
+	public static void appendFormat(Appendable out, String rawSheetName) {
+		try {
+			boolean needsQuotes = needsDelimiting(rawSheetName);
+			if(needsQuotes) {
+				out.append(DELIMITER);
+				appendAndEscape(out, rawSheetName);
+				out.append(DELIMITER);
+			} else {
+				appendAndEscape(out, rawSheetName);
+			}
+		} catch (Exception e) {
+			throw new RuntimeException(e);
 		}
 	}
 
 	/**
-	 * Convenience method for ({@link #format(String)}) when a StringBuilder is already available.
+	 * Convenience method for ({@link #format(String)}) when a StringBuffer is already available.
 	 *
 	 * @param out - sheet name will be appended here possibly with delimiting quotes
-     * @param rawSheetName - sheet name
+	 * @param workbookName - workbook name
+	 * @param rawSheetName - sheet name
 	 */
-	public static void appendFormat(StringBuilder out, String rawSheetName) {
-		boolean needsQuotes = needsDelimiting(rawSheetName);
-		if(needsQuotes) {
-			out.append(DELIMITER);
-			appendAndEscape(out, rawSheetName);
-			out.append(DELIMITER);
-		} else {
-			out.append(rawSheetName);
+	public static void appendFormat(Appendable out, String workbookName, String rawSheetName)
{
+		try {
+			boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
+			if(needsQuotes) {
+				out.append(DELIMITER);
+				out.append('[');
+				appendAndEscape(out, workbookName.replace('[', '(').replace(']', ')'));
+				out.append(']');
+				appendAndEscape(out, rawSheetName);
+				out.append(DELIMITER);
+			} else {
+				out.append('[');
+				appendOrREF(out, workbookName);
+				out.append(']');
+				appendOrREF(out, rawSheetName);
+			}
+		} catch (Exception e) {
+			throw new RuntimeException(e);
 		}
 	}
-	public static void appendFormat(StringBuilder out, String workbookName, String rawSheetName)
{
-		boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
-		if(needsQuotes) {
-			out.append(DELIMITER);
-			out.append('[');
-			appendAndEscape(out, workbookName.replace('[', '(').replace(']', ')'));
-			out.append(']');
-			appendAndEscape(out, rawSheetName);
-			out.append(DELIMITER);
+
+	private static void appendOrREF(Appendable out, String name) throws IOException {
+		if(name == null) {
+			out.append("#REF");
 		} else {
-			out.append('[');
-			out.append(workbookName);
-			out.append(']');
-			out.append(rawSheetName);
+			out.append(name);
 		}
 	}
 
-    static void appendAndEscape(Appendable sb, String rawSheetName) {
-        int len = rawSheetName.length();
-        for(int i=0; i<len; i++) {
-            char ch = rawSheetName.charAt(i);
-            try {
-                if(ch == DELIMITER) {
-                    // single quotes (') are encoded as ('')
-                    sb.append(DELIMITER);
-                }
-                sb.append(ch);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
+	static void appendAndEscape(Appendable sb, String rawSheetName) {
+		try {
+			if (rawSheetName == null) {
+				sb.append("#REF");
+				return;
+			}
+
+			int len = rawSheetName.length();
+			for (int i = 0; i < len; i++) {
+				char ch = rawSheetName.charAt(i);
+				if (ch == DELIMITER) {
+					// single quotes (') are encoded as ('')
+					sb.append(DELIMITER);
+				}
+				sb.append(ch);
+			}
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
     }
 
 	/**
 	 * Tell if the given raw sheet name needs screening/delimiting.
 	 * @param rawSheetName the sheet name.
-	 * @return true if the given raw sheet name needs screening/delimiting, false otherwise.
+	 * @return true if the given raw sheet name needs screening/delimiting, false otherwise
or
+	 * 			if the sheet name is null.
 	 */
 	static boolean needsDelimiting(String rawSheetName) {
+		if(rawSheetName == null) {
+			return false;
+		}
+
 		int len = rawSheetName.length();
 		if(len < 1) {
 			throw new RuntimeException("Zero length string is an invalid sheet name");
@@ -185,6 +215,7 @@ public final class SheetNameFormatter {
 		}
 		return false;
 	}
+
 	/**
 	 * @return <code>true</code> if the presence of the specified character in a
sheet name would 
 	 * require the sheet name to be delimited in formulas.  This includes every non-alphanumeric


Modified: poi/trunk/src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java?rev=1850008&r1=1850007&r2=1850008&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java
(original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java
Sun Dec 30 22:44:40 2018
@@ -66,8 +66,8 @@ public class SheetRangeAndWorkbookIndexF
     }
 
     private static boolean anySheetNameNeedsEscaping(String firstSheetName, String lastSheetName)
{
-        boolean anySheetNameNeedsDelimiting = firstSheetName != null && SheetNameFormatter.needsDelimiting(firstSheetName);
-        anySheetNameNeedsDelimiting |= lastSheetName != null && SheetNameFormatter.needsDelimiting(lastSheetName);
+        boolean anySheetNameNeedsDelimiting = SheetNameFormatter.needsDelimiting(firstSheetName);
+        anySheetNameNeedsDelimiting |= SheetNameFormatter.needsDelimiting(lastSheetName);
         return anySheetNameNeedsDelimiting;
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java?rev=1850008&r1=1850007&r2=1850008&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java Sun Dec
30 22:44:40 2018
@@ -37,7 +37,7 @@ final class ExternSheetNameResolver {
             String wbName = externalSheet.getWorkbookName();
             String sheetName = externalSheet.getSheetName();
             if (wbName != null) {
-                sb = new StringBuilder(wbName.length() + sheetName.length() + cellRefText.length()
+ 4);
+                sb = new StringBuilder(wbName.length() + (sheetName == null ? 0 : sheetName.length())
+ cellRefText.length() + 4);
                 SheetNameFormatter.appendFormat(sb, wbName, sheetName);
             } else {
                 sb = new StringBuilder(sheetName.length() + cellRefText.length() + 4);

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java?rev=1850008&r1=1850007&r2=1850008&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java Sun Dec 30 22:44:40
2018
@@ -3135,4 +3135,21 @@ public final class TestBugs extends Base
             assertEquals("\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF", font.getFontName());
         }
     }
+
+    @Test
+    public void test60460() throws IOException {
+        final Workbook wb = HSSFTestDataSamples.openSampleWorkbook("60460.xls");
+
+        assertEquals(2, wb.getAllNames().size());
+
+        Name rangedName = wb.getAllNames().get(0);
+        assertFalse(rangedName.isFunctionName());
+        assertEquals("'[\\\\HEPPC3/gt$/Teaching/Syn/physyn.xls]#REF'!$AK$70:$AL$70", rangedName.getRefersToFormula());
+
+        rangedName = wb.getAllNames().get(1);
+        assertFalse(rangedName.isFunctionName());
+        assertEquals("Questionnaire!$A$1:$L$65", rangedName.getRefersToFormula());
+
+        wb.close();
+    }
 }

Modified: poi/trunk/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java?rev=1850008&r1=1850007&r2=1850008&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/TestSheetNameFormatter.java Sun Dec
30 22:44:40 2018
@@ -17,22 +17,23 @@
 
 package org.apache.poi.ss.formula;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 /**
  * Tests for {@link SheetNameFormatter}
  * 
  * @author Josh Micich
  */
-public final class TestSheetNameFormatter extends TestCase {
-
-	private static void confirmFormat(String rawSheetName, String expectedSheetNameEncoding)
{
-		assertEquals(expectedSheetNameEncoding, SheetNameFormatter.format(rawSheetName));
-	}
-
+public final class TestSheetNameFormatter {
 	/**
 	 * Tests main public method 'format' 
 	 */
+	@Test
 	public void testFormat() {
 		
 		confirmFormat("abc", "abc");
@@ -43,14 +44,108 @@ public final class TestSheetNameFormatte
 
 		confirmFormat("O'Brian", "'O''Brian'"); // single quote gets doubled
 		
-		
 		confirmFormat("3rdTimeLucky", "'3rdTimeLucky'"); // digit in first pos
 		confirmFormat("_", "_"); // plain underscore OK
 		confirmFormat("my_3rd_sheet", "my_3rd_sheet"); // underscores and digits OK
 		confirmFormat("A12220", "'A12220'"); 
-		confirmFormat("TAXRETURN19980415", "TAXRETURN19980415"); 
+		confirmFormat("TAXRETURN19980415", "TAXRETURN19980415");
+
+		confirmFormat(null, "#REF");
 	}
-	
+
+	private static void confirmFormat(String rawSheetName, String expectedSheetNameEncoding)
{
+		// test all variants
+
+		assertEquals(expectedSheetNameEncoding, SheetNameFormatter.format(rawSheetName));
+
+		StringBuilder sb = new StringBuilder();
+		SheetNameFormatter.appendFormat(sb, rawSheetName);
+		assertEquals(expectedSheetNameEncoding, sb.toString());
+
+		sb = new StringBuilder();
+		SheetNameFormatter.appendFormat((Appendable)sb, rawSheetName);
+		assertEquals(expectedSheetNameEncoding, sb.toString());
+
+		StringBuffer sbf = new StringBuffer();
+		//noinspection deprecation
+		SheetNameFormatter.appendFormat(sbf, rawSheetName);
+		assertEquals(expectedSheetNameEncoding, sbf.toString());
+	}
+
+	@Test
+	public void testFormatWithWorkbookName() {
+
+		confirmFormat("abc", "abc", "[abc]abc");
+		confirmFormat("abc", "123", "'[abc]123'");
+
+		confirmFormat("abc", "my sheet", "'[abc]my sheet'"); // space
+		confirmFormat("abc", "A:MEM", "'[abc]A:MEM'"); // colon
+
+		confirmFormat("abc", "O'Brian", "'[abc]O''Brian'"); // single quote gets doubled
+
+		confirmFormat("abc", "3rdTimeLucky", "'[abc]3rdTimeLucky'"); // digit in first pos
+		confirmFormat("abc", "_", "[abc]_"); // plain underscore OK
+		confirmFormat("abc", "my_3rd_sheet", "[abc]my_3rd_sheet"); // underscores and digits OK
+		confirmFormat("abc", "A12220", "'[abc]A12220'");
+		confirmFormat("abc", "TAXRETURN19980415", "[abc]TAXRETURN19980415");
+
+		confirmFormat("abc", null, "[abc]#REF");
+		confirmFormat(null, "abc", "[#REF]abc");
+		confirmFormat(null, null, "[#REF]#REF");
+	}
+
+	private static void confirmFormat(String workbookName, String rawSheetName, String expectedSheetNameEncoding)
{
+		// test all variants
+
+		StringBuilder sb = new StringBuilder();
+		SheetNameFormatter.appendFormat(sb, workbookName, rawSheetName);
+		assertEquals(expectedSheetNameEncoding, sb.toString());
+
+		sb = new StringBuilder();
+		SheetNameFormatter.appendFormat((Appendable)sb, workbookName, rawSheetName);
+		assertEquals(expectedSheetNameEncoding, sb.toString());
+
+		StringBuffer sbf = new StringBuffer();
+		//noinspection deprecation
+		SheetNameFormatter.appendFormat(sbf, workbookName, rawSheetName);
+		assertEquals(expectedSheetNameEncoding, sbf.toString());
+	}
+
+	@Test
+	public void testFormatException() {
+		Appendable mock = new Appendable() {
+			@Override
+			public Appendable append(CharSequence csq) throws IOException {
+				throw new IOException("Test exception");
+			}
+
+			@Override
+			public Appendable append(CharSequence csq, int start, int end) throws IOException {
+				throw new IOException("Test exception");
+			}
+
+			@Override
+			public Appendable append(char c) throws IOException {
+				throw new IOException("Test exception");
+			}
+		};
+
+		try {
+			SheetNameFormatter.appendFormat(mock, null, null);
+			fail("Should catch exception here");
+		} catch (RuntimeException e) {
+			// expected here
+		}
+
+		try {
+			SheetNameFormatter.appendFormat(mock, null);
+			fail("Should catch exception here");
+		} catch (RuntimeException e) {
+			// expected here
+		}
+	}
+
+	@Test
 	public void testBooleanLiterals() {
 		confirmFormat("TRUE", "'TRUE'");
 		confirmFormat("FALSE", "'FALSE'");
@@ -69,6 +164,7 @@ public final class TestSheetNameFormatte
 	 * Tests functionality to determine whether a sheet name containing only letters and digits
 	 * would look (to Excel) like a cell name.
 	 */
+	@Test
 	public void testLooksLikePlainCellReference() {
 		
 		confirmCellNameMatch("A1", true);
@@ -91,6 +187,7 @@ public final class TestSheetNameFormatte
 	 * Tests exact boundaries for names that look very close to cell names (i.e. contain 1 or
more
 	 * letters followed by one or more digits).
 	 */
+	@Test
 	public void testCellRange() {
 		confirmCellRange("A1", 1, true);
 		confirmCellRange("a111", 1, true);

Added: poi/trunk/test-data/spreadsheet/60460.xls
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/60460.xls?rev=1850008&view=auto
==============================================================================
Binary files poi/trunk/test-data/spreadsheet/60460.xls (added) and poi/trunk/test-data/spreadsheet/60460.xls
Sun Dec 30 22:44:40 2018 differ



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message