Repository: wangguanquan/eec
Pull request #317 (2022-12-09 13:12:41)

Fix#294 Convert Row data to Map


Patch:
diff --git a/src/main/java/org/ttzero/excel/reader/Row.java b/src/main/java/org/ttzero/excel/reader/Row.java
index 630ef237..39dc17cb 100644
--- a/src/main/java/org/ttzero/excel/reader/Row.java
+++ b/src/main/java/org/ttzero/excel/reader/Row.java
@@ -28,7 +28,10 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.StringJoiner;
 
 import static org.ttzero.excel.reader.Cell.BLANK;
@@ -1356,6 +1359,57 @@ public abstract class Row {
         return joiner.toString();
     }
 
+    /**
+     * Convert row data to LinkedMap(sort by column index)
+     *
+     * @return the key is name or index(if not name here)
+     */
+    public Map<String, Object> toMap() {
+        if (isEmpty() || hr == null) return Collections.emptyMap();
+        // Maintain the column orders
+        Map<String, Object> data = new LinkedHashMap<>(hr.lc - hr.fc);
+        String[] names = hr.names;
+        String key;
+        for (int i = hr.fc; i < hr.lc; i++) {
+            Cell c = cells[i];
+            key = names[i];
+            // Ignore null key
+            if (key == null) continue;
+            switch (c.t) {
+                case SST:
+                    if (c.sv == null) {
+                        c.setSv(sst.get(c.nv));
+                    }
+                    // @Mark:=>There is no missing `break`, this is normal logic here
+                case INLINESTR:
+                    data.put(key, c.sv);
+                    break;
+                case BOOL:
+                    data.put(key, c.bv);
+                    break;
+                case NUMERIC:
+                    if (!styles.fastTestDateFmt(c.xf)) data.put(key, c.nv);
+                    else data.put(key, toTimestamp(c.nv));
+                    break;
+                case LONG:
+                    data.put(key, c.lv);
+                    break;
+                case DOUBLE:
+                    if (!styles.fastTestDateFmt(c.xf)) data.put(key, c.dv);
+                    else if (c.dv > 1.00001) data.put(key, toTimestamp(c.dv));
+                    else data.put(key, toTime(c.dv));
+                    break;
+                case BLANK:
+                case EMPTY_TAG:
+                    data.put(key, EMPTY);
+                    break;
+                default:
+                    data.put(key, null);
+            }
+        }
+        return data;
+    }
+
     /**
      * Add function shared ref
      * <blockquote><pre>
diff --git a/src/main/java/org/ttzero/excel/util/DateUtil.java b/src/main/java/org/ttzero/excel/util/DateUtil.java
index 52f14c36..a5c2159c 100644
--- a/src/main/java/org/ttzero/excel/util/DateUtil.java
+++ b/src/main/java/org/ttzero/excel/util/DateUtil.java
@@ -205,7 +205,7 @@ public class DateUtil {
      * @return java.util.Date
      */
     public static java.util.Date toDate(double d) {
-        if (d - DAYS_1900_TO_1970 < .00001) {
+        if (d < DAYS_1900_TO_1970) {
             throw new UncheckedTypeException("ConstantNumber " + d + " can't convert to java.util.Date");
         }
         int n = (int) d, m = (int) (((d - n) * MILLIS_OF_DAY + 0.5) / 1000); // Causes data over 0.5s to be carried over to 1s
@@ -240,7 +240,7 @@ public class DateUtil {
     }
 
     public static java.sql.Timestamp toTimestamp(double d) {
-        if (d - DAYS_1900_TO_1970 < .00001) {
+        if (d < DAYS_1900_TO_1970) {
             throw new UncheckedTypeException("ConstantNumber " + d + " can't convert to java.util.Date");
         }
         int n = (int) d, m = (int) (((d - n) * MILLIS_OF_DAY + 0.5) / 1000); // Causes data over 0.5s to be carried over to 1s
@@ -249,7 +249,7 @@ public class DateUtil {
 
 
     public static LocalDateTime toLocalDateTime(double d) {
-        if (d - DAYS_1900_TO_1970 < .00001) {
+        if (d < DAYS_1900_TO_1970) {
             throw new UncheckedTypeException("ConstantNumber " + d + " can't convert to java.util.Date");
         }
         int n = (int) d, m = (int) (((d - n) * MILLIS_OF_DAY + 0.5) / 1000); // Causes data over 0.5s to be carried over to 1s


Test patch:
diff --git a/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java b/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java
index 1d86590e..b0345a7c 100644
--- a/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java
+++ b/src/test/java/org/ttzero/excel/reader/ExcelReaderTest.java
@@ -41,6 +41,7 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
@@ -659,6 +660,19 @@ public class ExcelReaderTest {
         }
     }
 
+    @Test public void testRowToMap() throws IOException {
+        try (ExcelReader reader = ExcelReader.read(testResourceRoot().resolve("1.xlsx"))) {
+            List<Map<String, Object>> list = reader.sheet(0).dataRows().map(Row::toMap).collect(Collectors.toList());
+            assert list.size() == 94;
+            assert list.get(0).toString().equals("{渠道ID=4, 游戏=极品飞车, account=XuSu2gFg32, 注册时间=2018-11-21 00:00:00.0, 是否满30级=true, VIP=F}");
+            Map<String, Object> row9 = list.get(8); // Include header row
+            assert "LOL".equals(row9.get("游戏"));
+            assert "1WRQMx".equals(row9.get("account"));
+            assert (Boolean) row9.get("是否满30级");
+            assert list.get(93).toString().equals("{渠道ID=3, 游戏=WOW, account=Ae9CNO6eTu, 注册时间=2018-11-21 00:00:00.0, 是否满30级=true, VIP=B}");
+        }
+    }
+
     public static class O {
         @ExcelColumn("亚马逊FBA子单号/箱唛号")
         private String fbaNo;