]> source.dussan.org Git - poi.git/commitdiff
bug 58348: add hyperlink copying and merging to CellCopyPolicy
authorJaven O'Neal <onealj@apache.org>
Mon, 2 Nov 2015 09:59:32 +0000 (09:59 +0000)
committerJaven O'Neal <onealj@apache.org>
Mon, 2 Nov 2015 09:59:32 +0000 (09:59 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1711926 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/usermodel/CellCopyPolicy.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java

index 4b901b06b4931610212aac72b39fecd2a074de7c..80043210a6b9e363ddc1c9e44371921ee9b5dab7 100644 (file)
@@ -21,23 +21,37 @@ import org.apache.poi.util.Beta;
 
 @Beta
 public class CellCopyPolicy implements Cloneable {
+    // cell-level policies
     public static final boolean DEFAULT_COPY_CELL_VALUE_POLICY = true;
     public static final boolean DEFAULT_COPY_CELL_STYLE_POLICY = true;
     public static final boolean DEFAULT_COPY_CELL_FORMULA_POLICY = true;
-    public static final boolean DEFAULT_COPY_MERGED_REGIONS_POLICY = true;
+    public static final boolean DEFAULT_COPY_HYPERLINK_POLICY = true;
+    public static final boolean DEFAULT_MERGE_HYPERLINK_POLICY = false;
+    
+    // row-level policies
     public static final boolean DEFAULT_COPY_ROW_HEIGHT_POLICY = true;
     public static final boolean DEFAULT_CONDENSE_ROWS_POLICY = false;
     
+    // sheet-level policies
+    public static final boolean DEFAULT_COPY_MERGED_REGIONS_POLICY = true;
+    
+    // cell-level policies
     private boolean copyCellValue = DEFAULT_COPY_CELL_VALUE_POLICY;
     private boolean copyCellStyle = DEFAULT_COPY_CELL_STYLE_POLICY;
     private boolean copyCellFormula = DEFAULT_COPY_CELL_FORMULA_POLICY;
-    private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
+    private boolean copyHyperlink = DEFAULT_COPY_HYPERLINK_POLICY;
+    private boolean mergeHyperlink = DEFAULT_MERGE_HYPERLINK_POLICY;
+    
+    // row-level policies
     private boolean copyRowHeight = DEFAULT_COPY_ROW_HEIGHT_POLICY;
     private boolean condenseRows = DEFAULT_CONDENSE_ROWS_POLICY;
     
+    // sheet-level policies
+    private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
+    
     /** 
      * Default CellCopyPolicy, uses default policy
-     * For custom CellCopyPolicy, use {@link #Builder} class
+     * For custom CellCopyPolicy, use {@link Builder} class
      */
     public CellCopyPolicy() { }
     
@@ -48,25 +62,37 @@ public class CellCopyPolicy implements Cloneable {
         copyCellValue = builder.copyCellValue;
         copyCellStyle = builder.copyCellStyle;
         copyCellFormula = builder.copyCellFormula;
-        copyMergedRegions = builder.copyMergedRegions;
+        copyHyperlink = builder.copyHyperlink;
+        mergeHyperlink = builder.mergeHyperlink;
+        
         copyRowHeight = builder.copyRowHeight;
         condenseRows = builder.condenseRows;
+        
+        copyMergedRegions = builder.copyMergedRegions;
     }
     
     public static class Builder {
+        // cell-level policies
         private boolean copyCellValue = DEFAULT_COPY_CELL_VALUE_POLICY;
         private boolean copyCellStyle = DEFAULT_COPY_CELL_STYLE_POLICY;
         private boolean copyCellFormula = DEFAULT_COPY_CELL_FORMULA_POLICY;
-        private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
+        private boolean copyHyperlink = DEFAULT_COPY_HYPERLINK_POLICY;
+        private boolean mergeHyperlink = DEFAULT_MERGE_HYPERLINK_POLICY;
+        
+        // row-level policies
         private boolean copyRowHeight = DEFAULT_COPY_ROW_HEIGHT_POLICY;
         private boolean condenseRows = DEFAULT_CONDENSE_ROWS_POLICY;
         
+        // sheet-level policies
+        private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
+        
         /**
          * Builder class for CellCopyPolicy
          */
         public Builder() {
         }
         
+        // cell-level policies
         public Builder cellValue(boolean copyCellValue) {
             this.copyCellValue = copyCellValue;
             return this;
@@ -79,10 +105,16 @@ public class CellCopyPolicy implements Cloneable {
             this.copyCellFormula = copyCellFormula;
             return this;
         }
-        public Builder mergedRegions(boolean copyMergedRegions) {
-            this.copyMergedRegions = copyMergedRegions;
+        public Builder copyHyperlink(boolean copyHyperlink) {
+            this.copyHyperlink = copyHyperlink;
             return this;
         }
+        public Builder mergeHyperlink(boolean mergeHyperlink) {
+            this.mergeHyperlink = mergeHyperlink;
+            return this;
+        }
+        
+        // row-level policies
         public Builder rowHeight(boolean copyRowHeight) {
             this.copyRowHeight = copyRowHeight;
             return this;
@@ -91,6 +123,12 @@ public class CellCopyPolicy implements Cloneable {
             this.condenseRows = condenseRows;
             return this;
         }
+        
+        // sheet-level policies
+        public Builder mergedRegions(boolean copyMergedRegions) {
+            this.copyMergedRegions = copyMergedRegions;
+            return this;
+        }
         public CellCopyPolicy build() {
             return new CellCopyPolicy(this);
         }
@@ -101,9 +139,11 @@ public class CellCopyPolicy implements Cloneable {
                 .cellValue(copyCellValue)
                 .cellStyle(copyCellStyle)
                 .cellFormula(copyCellFormula)
-                .mergedRegions(copyMergedRegions)
+                .copyHyperlink(copyHyperlink)
+                .mergeHyperlink(mergeHyperlink)
                 .rowHeight(copyRowHeight)
-                .condenseRows(condenseRows);
+                .condenseRows(condenseRows)
+                .mergedRegions(copyMergedRegions);
         return builder;
     }
     
@@ -111,7 +151,10 @@ public class CellCopyPolicy implements Cloneable {
     public CellCopyPolicy clone() {
         return createBuilder().build();
     }
-    
+
+/*
+ * Cell-level policies 
+ */
     /**
      * @return the copyCellValue
      */
@@ -153,21 +196,38 @@ public class CellCopyPolicy implements Cloneable {
     public void setCopyCellFormula(boolean copyCellFormula) {
         this.copyCellFormula = copyCellFormula;
     }
+    
+    /**
+     * @return the copyHyperlink
+     */
+    public boolean isCopyHyperlink() {
+        return copyHyperlink;
+    }
 
     /**
-     * @return the copyMergedRegions
+     * @param copyHyperlink the copyHyperlink to set
      */
-    public boolean isCopyMergedRegions() {
-        return copyMergedRegions;
+    public void setCopyHyperlink(boolean copyHyperlink) {
+        this.copyHyperlink = copyHyperlink;
+    }
+    
+    /**
+     * @return the mergeHyperlink
+     */
+    public boolean isMergeHyperlink() {
+        return mergeHyperlink;
     }
 
     /**
-     * @param copyMergedRegions the copyMergedRegions to set
+     * @param mergeHyperlink the mergeHyperlink to set
      */
-    public void setCopyMergedRegions(boolean copyMergedRegions) {
-        this.copyMergedRegions = copyMergedRegions;
+    public void setMergeHyperlink(boolean mergeHyperlink) {
+        this.mergeHyperlink = mergeHyperlink;
     }
 
+/*
+ * Row-level policies 
+ */
     /**
      * @return the copyRowHeight
      */
@@ -199,5 +259,23 @@ public class CellCopyPolicy implements Cloneable {
     public void setCondenseRows(boolean condenseRows) {
         this.condenseRows = condenseRows;
     }
+    
+    
+/*
+ * Sheet-level policies 
+ */
+    /**
+     * @return the copyMergedRegions
+     */
+    public boolean isCopyMergedRegions() {
+        return copyMergedRegions;
+    }
+
+    /**
+     * @param copyMergedRegions the copyMergedRegions to set
+     */
+    public void setCopyMergedRegions(boolean copyMergedRegions) {
+        this.copyMergedRegions = copyMergedRegions;
+    }
 
 }
index 9ee050b5814acaa9aea77874063dd79ab1888f54..1de2982dcdd8d7e37d6237e2ebaa0cf6ddeecc7c 100644 (file)
@@ -180,6 +180,25 @@ public final class XSSFCell implements Cell {
                 setCellStyle(null);
             }
         }
+        
+        if (policy.isMergeHyperlink()) {
+            // if srcCell doesn't have a hyperlink and destCell has a hyperlink, don't clear destCell's hyperlink
+            final Hyperlink srcHyperlink = srcCell.getHyperlink();
+            if (srcHyperlink != null) {
+                setHyperlink(srcHyperlink.clone());
+            }
+        }
+        else if (policy.isCopyHyperlink()) {
+            // overwrite the hyperlink at dest cell with srcCell's hyperlink
+            // if srcCell doesn't have a hyperlink, clear the hyperlink (if one exists) at destCell
+            final Hyperlink srcHyperlink = srcCell.getHyperlink();
+            if (srcHyperlink == null) {
+                setHyperlink(null);
+            }
+            else {
+                setHyperlink(srcHyperlink.clone());
+            }
+        }
     }
 
     /**
index 14510c83a73ae1555df38970d74ff6a0dca979c9..09dab7269148cdf0486c44ab024e52ac5a9abbbf 100644 (file)
@@ -21,9 +21,11 @@ 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 java.io.IOException;
+import java.util.List;
 
 import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.ss.SpreadsheetVersion;
@@ -31,7 +33,11 @@ import org.apache.poi.ss.usermodel.BaseTestXCell;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.CellCopyPolicy;
 import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CreationHelper;
 import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Hyperlink;
+import org.apache.poi.ss.usermodel.IndexedColors;
 import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
@@ -521,7 +527,6 @@ public final class TestXSSFCell extends BaseTestXCell {
         final CellCopyPolicy policy = new CellCopyPolicy.Builder().cellFormula(false).build();
         destCell.copyCellFrom(srcCell, policy);
         assertEquals(Cell.CELL_TYPE_NUMERIC, destCell.getCellType());
-        System.out.println("ERROR: fix formula evaluation");
     }
     
     @Test
@@ -540,6 +545,95 @@ public final class TestXSSFCell extends BaseTestXCell {
         assertEquals(true, destCell.getBooleanCellValue());
     }
     
+    @Test
+    public final void testCopyCellFrom_CellCopyPolicy_copyHyperlink() throws IOException {
+        setUp_testCopyCellFrom_CellCopyPolicy();
+        final Workbook wb = srcCell.getSheet().getWorkbook();
+        final CreationHelper createHelper = wb.getCreationHelper();
+
+        srcCell.setCellValue("URL LINK");
+        Hyperlink link = createHelper.createHyperlink(Hyperlink.LINK_URL);
+        link.setAddress("http://poi.apache.org/");
+        srcCell.setHyperlink(link);
+
+        // Set link cell style (optional)
+        CellStyle hlinkStyle = wb.createCellStyle();
+        Font hlinkFont = wb.createFont();
+        hlinkFont.setUnderline(Font.U_SINGLE);
+        hlinkFont.setColor(IndexedColors.BLUE.getIndex());
+        hlinkStyle.setFont(hlinkFont);
+        srcCell.setCellStyle(hlinkStyle);
+
+        // Copy hyperlink
+        final CellCopyPolicy policy = new CellCopyPolicy.Builder().copyHyperlink(true).mergeHyperlink(false).build();
+        destCell.copyCellFrom(srcCell, policy);
+        assertNotNull(destCell.getHyperlink());
+
+        assertSame("unit test assumes srcCell and destCell are on the same sheet",
+                srcCell.getSheet(), destCell.getSheet());
+
+        final List<XSSFHyperlink> links = srcCell.getSheet().getHyperlinkList();
+        assertEquals("number of hyperlinks on sheet", 2, links.size());
+        assertEquals("source hyperlink",
+                new CellReference(srcCell).formatAsString(), links.get(0).getCellRef());
+        assertEquals("destination hyperlink",
+                new CellReference(destCell).formatAsString(), links.get(1).getCellRef());
+        
+        wb.close();
+    }
+    
+    @Test
+    public final void testCopyCellFrom_CellCopyPolicy_mergeHyperlink() throws IOException {
+        setUp_testCopyCellFrom_CellCopyPolicy();
+        final Workbook wb = srcCell.getSheet().getWorkbook();
+        final CreationHelper createHelper = wb.getCreationHelper();
+
+        srcCell.setCellValue("URL LINK");
+        Hyperlink link = createHelper.createHyperlink(Hyperlink.LINK_URL);
+        link.setAddress("http://poi.apache.org/");
+        destCell.setHyperlink(link);
+
+        // Set link cell style (optional)
+        CellStyle hlinkStyle = wb.createCellStyle();
+        Font hlinkFont = wb.createFont();
+        hlinkFont.setUnderline(Font.U_SINGLE);
+        hlinkFont.setColor(IndexedColors.BLUE.getIndex());
+        hlinkStyle.setFont(hlinkFont);
+        destCell.setCellStyle(hlinkStyle);
+        
+        // Pre-condition assumptions. This test is broken if either of these fail.
+        assertSame("unit test assumes srcCell and destCell are on the same sheet",
+                srcCell.getSheet(), destCell.getSheet());
+        assertNull(srcCell.getHyperlink());
+
+        // Merge hyperlink - since srcCell doesn't have a hyperlink, destCell's hyperlink is not overwritten (cleared).
+        final CellCopyPolicy policy = new CellCopyPolicy.Builder().mergeHyperlink(true).copyHyperlink(false).build();
+        destCell.copyCellFrom(srcCell, policy);
+        assertNull(srcCell.getHyperlink());
+        assertNotNull(destCell.getHyperlink());
+        assertSame(link, destCell.getHyperlink());
+
+        List<XSSFHyperlink> links;
+        links = srcCell.getSheet().getHyperlinkList();
+        assertEquals("number of hyperlinks on sheet", 1, links.size());
+        assertEquals("source hyperlink",
+                new CellReference(destCell).formatAsString(), links.get(0).getCellRef());
+        
+        // Merge destCell's hyperlink to srcCell. Since destCell does have a hyperlink, this should copy destCell's hyperlink to srcCell.
+        srcCell.copyCellFrom(destCell, policy);
+        assertNotNull(srcCell.getHyperlink());
+        assertNotNull(destCell.getHyperlink());
+        
+        links = srcCell.getSheet().getHyperlinkList();
+        assertEquals("number of hyperlinks on sheet", 2, links.size());
+        assertEquals("dest hyperlink",
+                new CellReference(destCell).formatAsString(), links.get(0).getCellRef());
+        assertEquals("source hyperlink",
+                new CellReference(srcCell).formatAsString(), links.get(1).getCellRef());
+        
+        wb.close();
+    }
+    
     private final void setUp_testCopyCellFrom_CellCopyPolicy() {
         @SuppressWarnings("resource")
         final XSSFWorkbook wb = new XSSFWorkbook();