Repository: wangguanquan/eec
Pull request #223 (2021-12-04 08:19:18)

Fix#221


Patch:
diff --git a/src/main/java/org/ttzero/excel/annotation/RowNum.java b/src/main/java/org/ttzero/excel/annotation/RowNum.java
new file mode 100644
index 00000000..cdd4f9d0
--- /dev/null
+++ b/src/main/java/org/ttzero/excel/annotation/RowNum.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017-2021, guanquan.wang@yandex.com All Rights Reserved.
+ *
+ * Licensed 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.
+ */
+
+package org.ttzero.excel.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Inject line number.
+ *
+ * @author guanquan.wang at 2021-12-03 13:40
+ */
+@Target({ ElementType.FIELD, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface RowNum {
+//    /**
+//     * Specify the beginning number, one-base default.
+//     *
+//     * @return the beginning number
+//     */
+//    int begins() default 1;
+}
diff --git a/src/main/java/org/ttzero/excel/processor/ConversionProcessor.java b/src/main/java/org/ttzero/excel/processor/ConversionProcessor.java
index cb2d8cc9..11df6069 100644
--- a/src/main/java/org/ttzero/excel/processor/ConversionProcessor.java
+++ b/src/main/java/org/ttzero/excel/processor/ConversionProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, guanquan.wang@yandex.com All Rights Reserved.
+ * Copyright (c) 2017-2021, guanquan.wang@yandex.com All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ package org.ttzero.excel.processor;
  * Typically used to convert state values or enumerated values
  * to meaningful values
  *
- * @author guanquan.wang on 2017/10/13.
+ * @author guanquan.wang on 2021-11-30 19:10
  */
 @FunctionalInterface
 public interface ConversionProcessor {
diff --git a/src/main/java/org/ttzero/excel/reader/HeaderRow.java b/src/main/java/org/ttzero/excel/reader/HeaderRow.java
index 236b51f8..2a2bc173 100644
--- a/src/main/java/org/ttzero/excel/reader/HeaderRow.java
+++ b/src/main/java/org/ttzero/excel/reader/HeaderRow.java
@@ -18,6 +18,7 @@ package org.ttzero.excel.reader;
 
 import org.ttzero.excel.annotation.ExcelColumn;
 import org.ttzero.excel.annotation.IgnoreImport;
+import org.ttzero.excel.annotation.RowNum;
 import org.ttzero.excel.manager.Const;
 import org.ttzero.excel.util.ReflectUtil;
 import org.ttzero.excel.util.StringUtil;
@@ -46,7 +47,7 @@ import static org.ttzero.excel.entity.IWorksheetWriter.isLocalDate;
 import static org.ttzero.excel.entity.IWorksheetWriter.isLocalDateTime;
 import static org.ttzero.excel.entity.IWorksheetWriter.isLocalTime;
 import static org.ttzero.excel.util.ReflectUtil.listDeclaredFields;
-import static org.ttzero.excel.util.ReflectUtil.listWriteMethods;
+import static org.ttzero.excel.util.ReflectUtil.listDeclaredMethods;
 import static org.ttzero.excel.util.ReflectUtil.mapping;
 import static org.ttzero.excel.util.StringUtil.isNotEmpty;
 
@@ -106,7 +107,8 @@ class HeaderRow extends Row {
 
         Method[] writeMethods = null;
         try {
-            writeMethods = listWriteMethods(clazz, method -> method.getAnnotation(ExcelColumn.class) != null);
+            writeMethods = listDeclaredMethods(clazz, method -> method.getAnnotation(ExcelColumn.class) != null
+                    || method.getAnnotation(RowNum.class) != null);
         } catch (IntrospectionException e) {
             LOGGER.warn("Get [" + clazz + "] read declared failed.", e);
         }
@@ -115,7 +117,7 @@ class HeaderRow extends Row {
 
         int writeLength = methodMapping(clazz, writeMethods, tmp);
         methods = new Method[declaredFields.length + writeLength];
-
+        Class<?>[] fieldClazz = new Class[methods.length];
 
         int[] index = new int[declaredFields.length];
         int count = 0;
@@ -145,6 +147,15 @@ class HeaderRow extends Row {
                     }
                     continue;
                 }
+
+                // Row Num
+                RowNum rowNum = method.getAnnotation(RowNum.class);
+                if (rowNum != null) {
+                    fieldClazz[i] = RowNum.class;
+                    index[i] = i;
+                    count++;
+                    continue;
+                }
             }
 
             // skip not import fields
@@ -153,6 +164,16 @@ class HeaderRow extends Row {
                 declaredFields[i] = null;
                 continue;
             }
+
+            // Row Num
+            RowNum rowNum = f.getAnnotation(RowNum.class);
+            if (rowNum != null) {
+                index[i] = i;
+                count++;
+                fieldClazz[i] = RowNum.class;
+                continue;
+            }
+
             // field has display name
             ExcelColumn ec = f.getAnnotation(ExcelColumn.class);
             if (ec != null && isNotEmpty(ec.value())) {
@@ -196,7 +217,11 @@ class HeaderRow extends Row {
                 fields[j] = declaredFields[i];
                 columns[j] = index[i];
                 methods[j] = methods[i];
-                fieldClazz[j] = methods[i] != null ? methods[i].getParameterTypes()[0] : declaredFields[i].getType();
+                if (fieldClazz[i] != null) {
+                    this.fieldClazz[j] = fieldClazz[i];
+                } else {
+                    this.fieldClazz[j] = methods[i] != null ? methods[i].getParameterTypes()[0] : declaredFields[i].getType();
+                }
                 j++;
             }
         }
@@ -440,6 +465,9 @@ class HeaderRow extends Row {
             Short v;
             fields[i].set(t, (v = row.getShort(c)) != null ? v : 0);
         }
+        else if (fieldClazz[i] == RowNum.class) {
+            fields[i].set(t, row.getRowNum());
+        }
     }
 
     private void methodPut(int i, Row row, Object t) throws IllegalAccessException, InvocationTargetException {
@@ -524,5 +552,8 @@ class HeaderRow extends Row {
             Short v;
             methods[i].invoke(t, (v = row.getShort(c)) != null ? v : 0);
         }
+        else if (fieldClazz[i] == RowNum.class) {
+            methods[i].invoke(t, row.getRowNum());
+        }
     }
 }
diff --git a/src/main/java/org/ttzero/excel/reader/Row.java b/src/main/java/org/ttzero/excel/reader/Row.java
index ffdd8f94..5b8246c3 100644
--- a/src/main/java/org/ttzero/excel/reader/Row.java
+++ b/src/main/java/org/ttzero/excel/reader/Row.java
@@ -86,11 +86,22 @@ public abstract class Row {
      * The number of row. (one base)
      *
      * @return int value
+     * @deprecated replace with {@link #getRowNum()}
      */
+    @Deprecated
     public int getRowNumber() {
         return index;
     }
 
+    /**
+     * The number of row. (one base)
+     *
+     * @return int value
+     */
+    public int getRowNum() {
+        return index;
+    }
+
     /**
      * Returns the index of the first column (zero base)
      *
@@ -206,7 +217,7 @@ public abstract class Row {
                 }
             // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                v = isNotEmpty(c.sv);
+                v = c.sv != null && isNotEmpty(c.sv.trim());
                 break;
             case BLANK:
             case EMPTY_TAG:
@@ -378,9 +389,9 @@ public abstract class Row {
             // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
                 if (c.sv.indexOf('E') >= 0 || c.sv.indexOf('e') >= 0) {
-                    s = (short) Double.parseDouble(c.sv);
+                    s = (short) Double.parseDouble(c.sv.trim());
                 } else {
-                    s = Long.valueOf(c.sv).shortValue();
+                    s = Long.valueOf(c.sv.trim()).shortValue();
                 }
                 break;
             case BOOL:
@@ -442,9 +453,9 @@ public abstract class Row {
             // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
                 if (c.sv.indexOf('E') >= 0 || c.sv.indexOf('e') >= 0) {
-                    n = (int) Double.parseDouble(c.sv);
+                    n = (int) Double.parseDouble(c.sv.trim());
                 } else {
-                    n = Long.valueOf(c.sv).intValue();
+                    n = Long.valueOf(c.sv.trim()).intValue();
                 }
                 break;
             case BOOL:
@@ -507,9 +518,9 @@ public abstract class Row {
             // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
                 if (c.sv.indexOf('E') >= 0 || c.sv.indexOf('e') >= 0) {
-                    l = (long) Double.parseDouble(c.sv);
+                    l = (long) Double.parseDouble(c.sv.trim());
                 } else {
-                    l = Long.parseLong(c.sv);
+                    l = Long.parseLong(c.sv.trim());
                 }
                 break;
             case BOOL:
@@ -653,7 +664,7 @@ public abstract class Row {
                 }
             // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                d = Double.parseDouble(c.sv);
+                d = Double.parseDouble(c.sv.trim());
                 break;
             case BLANK:
             case EMPTY_TAG:
@@ -710,7 +721,7 @@ public abstract class Row {
                 }
                 // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                bd = new BigDecimal(c.sv);
+                bd = new BigDecimal(c.sv.trim());
                 break;
             case UNALLOCATED:
             case BLANK:
@@ -765,7 +776,7 @@ public abstract class Row {
                 }
                 // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                date = toDate(c.sv);
+                date = toDate(c.sv.trim());
                 break;
             case UNALLOCATED:
             case BLANK:
@@ -820,7 +831,7 @@ public abstract class Row {
                 }
                 // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                ts = toTimestamp(c.sv);
+                ts = toTimestamp(c.sv.trim());
                 break;
             case UNALLOCATED:
             case BLANK:
@@ -867,7 +878,7 @@ public abstract class Row {
                     c.setSv(sst.get(c.nv));
                 }
                 // @Mark:=>There is no missing `break`, this is normal logic here
-            case INLINESTR: t = toTime(c.sv); break;
+            case INLINESTR: t = toTime(c.sv.trim()); break;
             case UNALLOCATED:
             case BLANK:
             case EMPTY_TAG:
@@ -922,7 +933,7 @@ public abstract class Row {
                 }
                 // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                ldt = toTimestamp(c.sv).toLocalDateTime();
+                ldt = toTimestamp(c.sv.trim()).toLocalDateTime();
                 break;
             case UNALLOCATED:
             case BLANK:
@@ -977,7 +988,7 @@ public abstract class Row {
                 }
                 // @Mark:=>There is no missing `break`, this is normal logic here
             case INLINESTR:
-                ld = toTimestamp(c.sv).toLocalDateTime().toLocalDate();
+                ld = toTimestamp(c.sv.trim()).toLocalDateTime().toLocalDate();
                 break;
             case UNALLOCATED:
             case BLANK:
@@ -1034,9 +1045,9 @@ public abstract class Row {
             case INLINESTR:
                 // 00:00:00
                 if (c.sv.length() == 8 && c.sv.charAt(2) == ':' && c.sv.charAt(5) == ':') {
-                    lt = toLocalTime(c.sv);
+                    lt = toLocalTime(c.sv.trim());
                 } else {
-                    lt = toTimestamp(c.sv).toLocalDateTime().toLocalTime();
+                    lt = toTimestamp(c.sv.trim()).toLocalDateTime().toLocalTime();
                 }
                 break;
             case UNALLOCATED:
diff --git a/src/main/java/org/ttzero/excel/reader/XMLRow.java b/src/main/java/org/ttzero/excel/reader/XMLRow.java
index 092f273e..54293315 100644
--- a/src/main/java/org/ttzero/excel/reader/XMLRow.java
+++ b/src/main/java/org/ttzero/excel/reader/XMLRow.java
@@ -49,11 +49,23 @@ class XMLRow extends Row {
      * The number of row. (one base)
      *
      * @return int value
+     * @deprecated replace with {@link #getRowNum()}
      */
     @Override
+    @Deprecated
     public int getRowNumber() {
+        return this.getRowNum();
+    }
+
+    /**
+     * The number of row. (one base)
+     *
+     * @return int value
+     */
+    @Override
+    public int getRowNum() {
         if (index == -1)
-            searchRowNumber();
+            searchRowNum();
         // The first row index is one
         return index;
     }
@@ -97,7 +109,7 @@ class XMLRow extends Row {
         return this;
     }
 
-    private void searchRowNumber() {
+    private void searchRowNum() {
         int _f = from + 4, a; // skip '<row'
         for (; cb[_f] != '>' && _f < to; _f++) {
             if (cb[_f] <= ' ' && cb[_f + 1] == 'r' && cb[_f + 2] == '=') {
@@ -485,7 +497,7 @@ class XMLCalcRow extends XMLRow {
 
         // Parse formula if exists and can parse
         if (hasCalcFunc) {
-            calcFun.accept(getRowNumber(), cells, !unknownLength ? lc - fc : -1);
+            calcFun.accept(getRowNum(), cells, !unknownLength ? lc - fc : -1);
         }
 
         Cell cell;
@@ -536,7 +548,7 @@ class XMLCalcRow extends XMLRow {
         // Function string is shared
         else if (cell.si > -1) {
             // Get from ref
-            cell.fv = getCalc(cell.si, (getRowNumber() << 14) | cell.i);
+            cell.fv = getCalc(cell.si, (getRowNum() << 14) | cell.i);
         }
     }
 
@@ -643,6 +655,6 @@ class XMLMergeRow extends XMLRow {
         super.parseCellValue(cell);
 
         // Setting/copy value if merged
-        func.accept(getRowNumber(), cell);
+        func.accept(getRowNum(), cell);
     }
 }


Test patch:
diff --git a/src/test/java/org/ttzero/excel/reader/ExcelReaderSharedTest.java b/src/test/java/org/ttzero/excel/reader/ExcelReaderSharedTest.java
index 41fefdbe..df109499 100644
--- a/src/test/java/org/ttzero/excel/reader/ExcelReaderSharedTest.java
+++ b/src/test/java/org/ttzero/excel/reader/ExcelReaderSharedTest.java
@@ -31,7 +31,7 @@ public class ExcelReaderSharedTest {
 
     @Test public void testSharedRead() throws IOException {
         try (ExcelReader reader = ExcelReader.read(testResourceRoot().resolve("eec shared 100.xlsx"))) {
-            reader.sheets().flatMap(Sheet::rows).forEach(row -> println(row.getRowNumber() + "| " + row.toString()));
+            reader.sheets().flatMap(Sheet::rows).forEach(row -> println(row.getRowNum() + "| " + row.toString()));
         }
     }
 
diff --git a/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java b/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java
index df843046..b5917592 100644
--- a/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java
+++ b/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java
@@ -21,6 +21,7 @@ import org.junit.Test;
 import org.ttzero.excel.Print;
 import org.ttzero.excel.annotation.ExcelColumn;
 import org.ttzero.excel.annotation.IgnoreExport;
+import org.ttzero.excel.annotation.RowNum;
 import org.ttzero.excel.entity.ListObjectSheetTest;
 import org.ttzero.excel.entity.WorkbookTest;
 import org.ttzero.excel.util.DateUtil;
@@ -97,7 +98,7 @@ public class ExcelReaderTest {
             Sheet sheet = reader.sheet(0);
             for (Iterator<Row> it = sheet.iterator(); it.hasNext();) {
                 Row row = it.next();
-                println(row.getRowNumber()
+                println(row.getRowNum()
                     + " | " + row.getFirstColumnIndex()
                     + " | " + row.getLastColumnIndex()
                     + " => " + row);
@@ -128,9 +129,9 @@ public class ExcelReaderTest {
 
             for (Iterator<Row> it = sheet.iterator(); it.hasNext(); ) {
                 Row row = it.next();
-                if (row.getRowNumber() == 0) continue;
+                if (row.getRowNum() == 0) continue;
 
-                print(row.getRowNumber());
+                print(row.getRowNum());
                 for (int start = 0, end = row.getLastColumnIndex(); start < end; start++) {
                     print(header.getString(start));
                     print(" : ");
@@ -242,7 +243,7 @@ public class ExcelReaderTest {
                     for (int i = row.fc; i < row.lc; i++) {
                         if (row.hasFormula(i)) {
                             print(int2Col(i + 1));
-                            print(row.getRowNumber());
+                            print(row.getRowNum());
                             print("=");
                             print(row.getFormula(i));
                             println();
@@ -440,7 +441,7 @@ public class ExcelReaderTest {
             reader.sheets()
                 .peek(sheet -> println("--------" + sheet.getName() + "--------" + sheet.getDimension()))
                 .flatMap(Sheet::rows)
-                .forEach(row -> println(row.getRowNumber() + "|: " + row.toString()));
+                .forEach(row -> println(row.getRowNum() + "|: " + row.toString()));
 
         }
     }
@@ -453,7 +454,7 @@ public class ExcelReaderTest {
             reader.sheets().flatMap(Sheet::rows).forEach(row -> {
                 for (int i = row.fc; i < row.lc; i++) {
                     if (row.hasFormula(i)) {
-                        print(new Dimension(row.getRowNumber(), (short) (i + 1), 0, (short) 0));
+                        print(new Dimension(row.getRowNum(), (short) (i + 1), 0, (short) 0));
                         print(": ");
                         print(row.getFormula(i));
                         println('|');
@@ -466,9 +467,9 @@ public class ExcelReaderTest {
     @Test public void testToObject2() throws IOException {
         try (ExcelReader reader = ExcelReader.read(testResourceRoot().resolve("test-fixed-row.xlsx"))) {
             reader.sheet(0).rows().forEach(row -> {
-                if (row.getRowNumber() == 1) {
+                if (row.getRowNum() == 1) {
                     assert "我是固定表头".equals(row.getString(0));
-                } else if (row.getRowNumber() == 2) {
+                } else if (row.getRowNum() == 2) {
                     assert "我是内容".equals(row.getString(0));
                 }
             });
@@ -515,13 +516,13 @@ public class ExcelReaderTest {
 
     @Test public void test175() throws IOException {
         try (ExcelReader reader = ExcelReader.read(testResourceRoot().resolve("#175.xlsx"))) {
-            reader.sheet(0).rows().filter(row -> row.getRowNumber() > 7 && !row.isEmpty()).forEach(row -> println(row.getDouble(4)));
+            reader.sheet(0).rows().filter(row -> row.getRowNum() > 7 && !row.isEmpty()).forEach(row -> println(row.getDouble(4)));
             reader.sheet(0).reset();
             println("-------------DECIMAL-------------");
-            reader.sheet(0).rows().filter(row -> row.getRowNumber() > 7 && !row.isEmpty()).forEach(row -> println(row.getDecimal(4)));
+            reader.sheet(0).rows().filter(row -> row.getRowNum() > 7 && !row.isEmpty()).forEach(row -> println(row.getDecimal(4)));
             reader.sheet(0).reset();
             reader.sheet(0).rows()
-                    .filter(row -> row.getRowNumber() > 6 && !row.isEmpty())
+                    .filter(row -> row.getRowNum() > 6 && !row.isEmpty())
                     .map(row -> row.to(O.class))
                     .filter(Objects::nonNull)
                     .forEach(Print::println);
@@ -577,6 +578,8 @@ public class ExcelReaderTest {
     }
 
     public static class Entry {
+        @RowNum
+        private int num;
         @ExcelColumn("渠道ID")
         private Integer channelId;
         @ExcelColumn(value = "游戏", share = true)
@@ -629,7 +632,7 @@ public class ExcelReaderTest {
 
         @Override
         public String toString() {
-            return channelId + " | "
+            return num + " | " + channelId + " | "
                 + pro + " | "
                 + account + " | "
                 + (registered != null ? DateUtil.toDateString(registered) : null) + " | "
@@ -707,6 +710,7 @@ public class ExcelReaderTest {
         private int id;
         private String address;
         private char c;
+        private int rowNum;
 
         private boolean vip;
 
@@ -748,9 +752,14 @@ public class ExcelReaderTest {
             this.vip = c == 'A';
         }
 
+        @RowNum
+        public void setRowNum(int rowNum) {
+            this.rowNum = rowNum;
+        }
+
         @Override
         public String toString() {
-            return channelId + " | "
+            return rowNum + " | " + channelId + " | "
                 + pro + " | "
                 + account + " | "
                 + (registered != null ? DateUtil.toDateString(registered) : null) + " | "