From 1c9d06979b98cd11a2a805161fd30c375694846e Mon Sep 17 00:00:00 2001 From: huanhu01 Date: Thu, 3 Dec 2020 20:24:26 +0800 Subject: [PATCH 1/7] fix out of index --- .../src/main/java/cn/hutool/core/collection/ListUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index 98bf9645d..37d208f98 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -261,6 +261,9 @@ public class ListUtil { final int[] startEnd = PageUtil.transToStartEnd(pageNo, pageSize); if (startEnd[1] > resultSize) { startEnd[1] = resultSize; + if (startEnd[0] > startEnd[1]) { + return new ArrayList<>(0); + } } return list.subList(startEnd[0], startEnd[1]); From 52d341e650fda6e1b765b1d49cf4db91444bc998 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Dec 2020 11:09:45 +0800 Subject: [PATCH 2/7] add check --- CHANGELOG.md | 3 ++- .../src/main/java/cn/hutool/core/collection/ListUtil.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3816909cb..2f6504912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,12 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.3 (2020-12-02) +# 5.5.3 (2020-12-04) ### 新特性 * 【core 】 IdcardUtil增加行政区划83(issue#1277@Github) * 【core 】 multipart中int改为long,解决大文件上传越界问题(issue#I27WZ3@Gitee) +* 【core 】 ListUtil.page增加检查(pr#224@Gitee) ### Bug修复 * 【cache 】 修复Cache中get重复misCount计数问题(issue#1281@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index 37d208f98..b3bffe1c9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -245,7 +245,7 @@ public class ListUtil { int resultSize = list.size(); // 每页条目数大于总数直接返回所有 if (resultSize <= pageSize) { - if (pageNo < (PageUtil.getFirstPageNo()+1)) { + if (pageNo < (PageUtil.getFirstPageNo() + 1)) { return Collections.unmodifiableList(list); } else { // 越界直接返回空 @@ -253,7 +253,7 @@ public class ListUtil { } } // 相乘可能会导致越界 临时用long - if (((long) (pageNo-PageUtil.getFirstPageNo()) * pageSize) > resultSize) { + if (((long) (pageNo - PageUtil.getFirstPageNo()) * pageSize) > resultSize) { // 越界直接返回空 return new ArrayList<>(0); } @@ -262,7 +262,7 @@ public class ListUtil { if (startEnd[1] > resultSize) { startEnd[1] = resultSize; if (startEnd[0] > startEnd[1]) { - return new ArrayList<>(0); + return empty(); } } From afe5844b2508792863d69e6a3635bad655e8e6b6 Mon Sep 17 00:00:00 2001 From: LazzMan <17089793114@163.com> Date: Fri, 4 Dec 2020 16:41:48 +0800 Subject: [PATCH 3/7] NumberUtil add new method --- .../java/cn/hutool/core/util/NumberUtil.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index 96f17de45..f7de88e65 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -2493,6 +2493,58 @@ public class NumberUtil { return true; } + /** + * 检查value是否在[min,max]范围内 + * + * @param min 最小值 + * @param max 最大值 + * @param value 被检查值 + * @return 检查结果,范围内将返回true,否则返回false + * @since 5.5.4 + */ + public static boolean isBetween(int min, int max, int value) { + return value >= min && value <= max; + } + + /** + * 检查value是否在[min,max]范围内 + * + * @param min 最小值 + * @param max 最大值 + * @param value 被检查值 + * @return 检查结果,范围内将返回true,否则返回false + * @since 5.5.4 + */ + public static boolean isBetween(long min, long max, long value) { + return value >= min && value <= max; + } + + /** + * 检查value是否在[min,max]范围内 + * + * @param min 最小值 + * @param max 最大值 + * @param value 被检查值 + * @return 检查结果,范围内将返回true,否则返回false + * @since 5.5.4 + */ + public static boolean isBetween(float min, float max, float value) { + return value >= min && value <= max; + } + + /** + * 检查value是否在[min,max]范围内 + * + * @param min 最小值 + * @param max 最大值 + * @param value 被检查值 + * @return 检查结果,范围内将返回true,否则返回false + * @since 5.5.4 + */ + public static boolean isBetween(double min, double max, double value) { + return value >= min && value <= max; + } + // ------------------------------------------------------------------------------------------- Private method start private static int mathSubnode(int selectNum, int minNum) { if (selectNum == minNum) { From 626f4e51d0561970ec4e95bb2ddbe60f623de1b9 Mon Sep 17 00:00:00 2001 From: LazzMan <17089793114@163.com> Date: Fri, 4 Dec 2020 16:56:25 +0800 Subject: [PATCH 4/7] NumberUtil add unit-test --- .../src/test/java/cn/hutool/core/util/NumberUtilTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index cbd632a0f..5db2db167 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -303,4 +303,12 @@ public class NumberUtilTest { Assert.assertEquals("0", NumberUtil.toStr(NumberUtil.sub(new BigDecimal("9600.0000000000"), new BigDecimal("9600.000000")))); Assert.assertEquals("0", NumberUtil.toStr(new BigDecimal("9600.00000").subtract(new BigDecimal("9600.000000000")))); } + + @Test + public void isBetweenTest() { + Assert.assertTrue(NumberUtil.isBetween(0, 1, 0)); + Assert.assertTrue(NumberUtil.isBetween(0l, 1l, 1l)); + Assert.assertTrue(NumberUtil.isBetween(0.1f, 0.2f, 0.19f)); + Assert.assertTrue(NumberUtil.isBetween(0.1, 0.2, 0.19)); + } } From 9ad2848bbd718bbce25ea671bb9b9713bf7ac928 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 5 Dec 2020 16:05:36 +0800 Subject: [PATCH 5/7] fix code --- CHANGELOG.md | 2 +- .../java/cn/hutool/core/util/NumberUtil.java | 58 +------------------ .../cn/hutool/core/lang/ValidatorTest.java | 8 +++ .../cn/hutool/core/util/NumberUtilTest.java | 8 --- 4 files changed, 12 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f6504912..976b6982c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.3 (2020-12-04) +# 5.5.3 (2020-12-05) ### 新特性 * 【core 】 IdcardUtil增加行政区划83(issue#1277@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index f7de88e65..a300dc01e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -1516,7 +1516,7 @@ public class NumberUtil { */ public static int processMultiple(int selectNum, int minNum) { int result; - result = mathSubnode(selectNum, minNum) / mathNode(selectNum - minNum); + result = mathSubNode(selectNum, minNum) / mathNode(selectNum - minNum); return result; } @@ -2493,64 +2493,12 @@ public class NumberUtil { return true; } - /** - * 检查value是否在[min,max]范围内 - * - * @param min 最小值 - * @param max 最大值 - * @param value 被检查值 - * @return 检查结果,范围内将返回true,否则返回false - * @since 5.5.4 - */ - public static boolean isBetween(int min, int max, int value) { - return value >= min && value <= max; - } - - /** - * 检查value是否在[min,max]范围内 - * - * @param min 最小值 - * @param max 最大值 - * @param value 被检查值 - * @return 检查结果,范围内将返回true,否则返回false - * @since 5.5.4 - */ - public static boolean isBetween(long min, long max, long value) { - return value >= min && value <= max; - } - - /** - * 检查value是否在[min,max]范围内 - * - * @param min 最小值 - * @param max 最大值 - * @param value 被检查值 - * @return 检查结果,范围内将返回true,否则返回false - * @since 5.5.4 - */ - public static boolean isBetween(float min, float max, float value) { - return value >= min && value <= max; - } - - /** - * 检查value是否在[min,max]范围内 - * - * @param min 最小值 - * @param max 最大值 - * @param value 被检查值 - * @return 检查结果,范围内将返回true,否则返回false - * @since 5.5.4 - */ - public static boolean isBetween(double min, double max, double value) { - return value >= min && value <= max; - } - // ------------------------------------------------------------------------------------------- Private method start - private static int mathSubnode(int selectNum, int minNum) { + private static int mathSubNode(int selectNum, int minNum) { if (selectNum == minNum) { return 1; } else { - return selectNum * mathSubnode(selectNum - 1, minNum); + return selectNum * mathSubNode(selectNum - 1, minNum); } } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java index 3e240709d..101c53db8 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/ValidatorTest.java @@ -187,4 +187,12 @@ public class ValidatorTest { zipCode = Validator.isZipCode("102629"); Assert.assertTrue(zipCode); } + + @Test + public void isBetweenTest() { + Assert.assertTrue(Validator.isBetween(0, 0, 1)); + Assert.assertTrue(Validator.isBetween(1L, 0L, 1L)); + Assert.assertTrue(Validator.isBetween(0.19f, 0.1f, 0.2f)); + Assert.assertTrue(Validator.isBetween(0.19, 0.1, 0.2)); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 5db2db167..cbd632a0f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -303,12 +303,4 @@ public class NumberUtilTest { Assert.assertEquals("0", NumberUtil.toStr(NumberUtil.sub(new BigDecimal("9600.0000000000"), new BigDecimal("9600.000000")))); Assert.assertEquals("0", NumberUtil.toStr(new BigDecimal("9600.00000").subtract(new BigDecimal("9600.000000000")))); } - - @Test - public void isBetweenTest() { - Assert.assertTrue(NumberUtil.isBetween(0, 1, 0)); - Assert.assertTrue(NumberUtil.isBetween(0l, 1l, 1l)); - Assert.assertTrue(NumberUtil.isBetween(0.1f, 0.2f, 0.19f)); - Assert.assertTrue(NumberUtil.isBetween(0.1, 0.2, 0.19)); - } } From 7103adc02e4951ca8360b6d34b499018528ec6c2 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 5 Dec 2020 16:37:49 +0800 Subject: [PATCH 6/7] change packge and add date format support --- .../poi/excel/sax/Excel07SaxReader.java | 16 ++++++++-------- .../cn/hutool/poi/excel/sax/ExcelSaxUtil.java | 19 +++++++++++++++++++ .../excel/{test => }/BigExcelWriteTest.java | 0 .../poi/excel/{test => }/CellUtilTest.java | 0 .../poi/excel/{test => }/ExcelReadTest.java | 0 .../excel/{test => }/ExcelSaxReadTest.java | 2 +- .../poi/excel/{test => }/ExcelUtilTest.java | 0 .../poi/excel/{test => }/ExcelWriteTest.java | 0 .../poi/excel/{test => }/OrderExcel.java | 0 .../hutool/poi/excel/{test => }/TestBean.java | 0 .../poi/word/{test => }/WordWriterTest.java | 0 11 files changed, 28 insertions(+), 9 deletions(-) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/BigExcelWriteTest.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/CellUtilTest.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/ExcelReadTest.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/ExcelSaxReadTest.java (93%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/ExcelUtilTest.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/ExcelWriteTest.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/OrderExcel.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/excel/{test => }/TestBean.java (100%) rename hutool-poi/src/test/java/cn/hutool/poi/word/{test => }/WordWriterTest.java (100%) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java index beb254621..2fb116468 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java @@ -4,6 +4,7 @@ import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.cell.FormulaCellValue; import cn.hutool.poi.excel.sax.handler.RowHandler; @@ -410,21 +411,20 @@ public class Excel07SaxReader extends DefaultHandler implements ExcelSaxReader m月d日 + // 31 -> yyyy年m月d日 + return true; + } return org.apache.poi.ss.usermodel.DateUtil.isADateFormat(formatIndex, formatString); } diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/BigExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/BigExcelWriteTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/CellUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/CellUtilTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java similarity index 93% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index c1319182a..ffce24266 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -65,7 +65,7 @@ public class ExcelSaxReadTest { @Test @Ignore public void readBySaxTest2() { - ExcelUtil.readBySax("e:/B23_20180404164901240.xlsx", 2, (sheetIndex, rowIndex, rowList) -> Console.log(rowList)); + ExcelUtil.readBySax("d:/test/default.xlsx", -1, (sheetIndex, rowIndex, rowList) -> Console.log(rowList)); } private RowHandler createRowHandler() { diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelUtilTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelWriteTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/OrderExcel.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/OrderExcel.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/TestBean.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/excel/test/TestBean.java rename to hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java diff --git a/hutool-poi/src/test/java/cn/hutool/poi/word/test/WordWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java similarity index 100% rename from hutool-poi/src/test/java/cn/hutool/poi/word/test/WordWriterTest.java rename to hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java From 897dea0b30ca7ae77e0f08537cbb0789bc07d7be Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 5 Dec 2020 17:13:05 +0800 Subject: [PATCH 7/7] fix date read for sax bug --- CHANGELOG.md | 1 + .../poi/excel/sax/Excel03SaxReader.java | 2 +- .../cn/hutool/poi/excel/sax/ExcelSaxUtil.java | 76 ++++++++++-------- .../hutool/poi/excel/BigExcelWriteTest.java | 11 +-- .../cn/hutool/poi/excel/CellUtilTest.java | 2 +- .../cn/hutool/poi/excel/ExcelReadTest.java | 4 +- .../cn/hutool/poi/excel/ExcelSaxReadTest.java | 29 +++++-- .../cn/hutool/poi/excel/ExcelUtilTest.java | 3 +- .../cn/hutool/poi/excel/ExcelWriteTest.java | 16 ++-- .../java/cn/hutool/poi/excel/OrderExcel.java | 2 +- .../java/cn/hutool/poi/excel/TestBean.java | 2 +- .../cn/hutool/poi/word/WordWriterTest.java | 2 +- .../src/test/resources/data_for_sax_test.xls | Bin 31232 -> 31744 bytes .../src/test/resources/data_for_sax_test.xlsx | Bin 10000 -> 10176 bytes 14 files changed, 83 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 976b6982c..fdd19a094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Bug修复 * 【cache 】 修复Cache中get重复misCount计数问题(issue#1281@Github) +* 【poi 】 修复sax读取自定义格式单元格无法识别日期类型的问题(issue#1283@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index 67d31b67f..dbd97dd04 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -268,7 +268,7 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader createSaxReader(boolean isXlsx, RowHandler rowHandler) { + return isXlsx + ? new Excel07SaxReader(rowHandler) + : new Excel03SaxReader(rowHandler); + } + /** * 根据数据类型获取数据 * @@ -175,12 +190,13 @@ public class ExcelSaxUtil { /** * 判断数字Record中是否为日期格式 - * @param cell 单元格记录 + * + * @param cell 单元格记录 * @param formatListener {@link FormatTrackingHSSFListener} * @return 是否为日期格式 * @since 5.4.8 */ - public static boolean isDateFormat(CellValueRecordInterface cell, FormatTrackingHSSFListener formatListener){ + public static boolean isDateFormat(CellValueRecordInterface cell, FormatTrackingHSSFListener formatListener) { final int formatIndex = formatListener.getFormatIndex(cell); final String formatString = formatListener.getFormatString(cell); return isDateFormat(formatIndex, formatString); @@ -189,15 +205,15 @@ public class ExcelSaxUtil { /** * 判断日期格式 * - * @param formatIndex 格式索引,一般用于内建格式 + * @param formatIndex 格式索引,一般用于内建格式 * @param formatString 格式字符串 * @return 是否为日期格式 * @since 5.5.3 */ - public static boolean isDateFormat(int formatIndex, String formatString){ + public static boolean isDateFormat(int formatIndex, String formatString) { // https://blog.csdn.net/u014342130/article/details/50619503 // issue#1283@Github - if(formatIndex == 28 || formatIndex == 31){ + if (formatIndex == 28 || formatIndex == 31) { // 28 -> m月d日 // 31 -> yyyy年m月d日 return true; @@ -227,43 +243,22 @@ public class ExcelSaxUtil { return DateUtil.date(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value, false)); } - /** - * 创建 {@link ExcelSaxReader} - * - * @param isXlsx 是否为xlsx格式(07格式) - * @param rowHandler 行处理器 - * @return {@link ExcelSaxReader} - * @since 5.4.4 - */ - public static ExcelSaxReader createSaxReader(boolean isXlsx, RowHandler rowHandler) { - return isXlsx - ? new Excel07SaxReader(rowHandler) - : new Excel03SaxReader(rowHandler); - } - /** * 在Excel03 sax读取中获取日期或数字类型的结果值 - * @param cell 记录单元格 - * @param value 值 + * + * @param cell 记录单元格 + * @param value 值 * @param formatListener {@link FormatTrackingHSSFListener} * @return 值,可能为Date或Double或Long * @since 5.5.0 */ - public static Object getNumberOrDateValue(CellValueRecordInterface cell, double value, FormatTrackingHSSFListener formatListener){ + public static Object getNumberOrDateValue(CellValueRecordInterface cell, double value, FormatTrackingHSSFListener formatListener) { Object result; - if(ExcelSaxUtil.isDateFormat(cell, formatListener)){ + if (isDateFormat(cell, formatListener)) { // 可能为日期格式 - result = ExcelSaxUtil.getDateValue(value); - } else { - final long longPart = (long) value; - // 对于无小数部分的数字类型,转为Long,否则保留原数字 - if (((double) longPart) == value) { - result = longPart; - } else { - result = value; - } + return getDateValue(value); } - return result; + return getNumberValue(value, formatListener.getFormatString(cell)); } /** @@ -278,9 +273,20 @@ public class ExcelSaxUtil { if (StrUtil.isBlank(value)) { return null; } - double numValue = Double.parseDouble(value); + return getNumberValue(Double.parseDouble(value), numFmtString); + } + + /** + * 获取数字类型值,除非格式中明确数字保留小数,否则无小数情况下按照long返回 + * + * @param numValue 值 + * @param numFmtString 格式 + * @return 数字,可以是Double、Long + * @since 5.5.3 + */ + private static Number getNumberValue(double numValue, String numFmtString) { // 普通数字 - if (null != numFmtString && numFmtString.indexOf(StrUtil.C_DOT) < 0) { + if (null != numFmtString && false == StrUtil.contains(numFmtString, CharUtil.DOT)) { final long longPart = (long) numValue; //noinspection RedundantIfStatement if (longPart == numValue) { diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java index 6cf85898d..1b5cf41ed 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/BigExcelWriteTest.java @@ -1,13 +1,10 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.poi.excel.BigExcelWriter; -import cn.hutool.poi.excel.ExcelUtil; -import cn.hutool.poi.excel.ExcelWriter; import cn.hutool.poi.excel.style.StyleUtil; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.FillPatternType; @@ -163,21 +160,21 @@ public class BigExcelWriteTest { @Test @Ignore public void writeBeanTest() { - TestBean bean1 = new TestBean(); + cn.hutool.poi.excel.TestBean bean1 = new cn.hutool.poi.excel.TestBean(); bean1.setName("张三"); bean1.setAge(22); bean1.setPass(true); bean1.setScore(66.30); bean1.setExamDate(DateUtil.date()); - TestBean bean2 = new TestBean(); + cn.hutool.poi.excel.TestBean bean2 = new cn.hutool.poi.excel.TestBean(); bean2.setName("李四"); bean2.setAge(28); bean2.setPass(false); bean2.setScore(38.50); bean2.setExamDate(DateUtil.date()); - List rows = CollUtil.newArrayList(bean1, bean2); + List rows = CollUtil.newArrayList(bean1, bean2); // 通过工具类创建writer String file = "e:/bigWriteBeanTest.xlsx"; FileUtil.del(file); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java index 63a4cac69..11f11f896 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/CellUtilTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.junit.Ignore; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java index 1ed8526e1..ea6ba57a3 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelReadTest.java @@ -1,11 +1,9 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.poi.excel.ExcelReader; -import cn.hutool.poi.excel.ExcelUtil; import lombok.Data; import org.junit.Assert; import org.junit.Ignore; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java index ffce24266..3407be109 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelSaxReadTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; @@ -6,7 +6,6 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Console; import cn.hutool.core.util.StrUtil; -import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.cell.FormulaCellValue; import cn.hutool.poi.excel.sax.Excel03SaxReader; import cn.hutool.poi.excel.sax.handler.RowHandler; @@ -138,15 +137,33 @@ public class ExcelSaxReadTest { } @Test - public void dateReadTest() { + public void dateReadXlsTest() { List rows = new ArrayList<>(); - ExcelUtil.readBySax("data_for_sax_test.xls", 0, (i, i1, list) -> - rows.add(StrUtil.toString(list.get(0)))); + ExcelUtil.readBySax("data_for_sax_test.xls", 0, + (i, i1, list) ->{ + rows.add(StrUtil.toString(list.get(0))); + } + ); Assert.assertEquals("2020-10-09 00:00:00", rows.get(1)); // 非日期格式不做转换 Assert.assertEquals("112233", rows.get(2)); - Assert.assertEquals("1000", rows.get(3)); + Assert.assertEquals("1000.0", rows.get(3)); + Assert.assertEquals("2012-12-21 00:00:00", rows.get(4)); + } + + @Test + public void dateReadXlsxTest() { + List rows = new ArrayList<>(); + ExcelUtil.readBySax("data_for_sax_test.xlsx", 0, + (i, i1, list) -> rows.add(StrUtil.toString(list.get(0))) + ); + + Assert.assertEquals("2020-10-09 00:00:00", rows.get(1)); + // 非日期格式不做转换 + Assert.assertEquals("112233", rows.get(2)); + Assert.assertEquals("1000.0", rows.get(3)); + Assert.assertEquals("2012-12-21 00:00:00", rows.get(4)); } @Test diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java index 8d723f9bf..0a0a7d1ca 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelUtilTest.java @@ -1,6 +1,5 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; -import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.cell.CellLocation; import org.junit.Assert; import org.junit.Test; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java index 17bc26ba7..4d16c964d 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; @@ -6,8 +6,6 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.poi.excel.ExcelUtil; -import cn.hutool.poi.excel.ExcelWriter; import cn.hutool.poi.excel.style.StyleUtil; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.FillPatternType; @@ -340,21 +338,21 @@ public class ExcelWriteTest { @Test @Ignore public void writeBeanTest() { - TestBean bean1 = new TestBean(); + cn.hutool.poi.excel.TestBean bean1 = new cn.hutool.poi.excel.TestBean(); bean1.setName("张三"); bean1.setAge(22); bean1.setPass(true); bean1.setScore(66.30); bean1.setExamDate(DateUtil.date()); - TestBean bean2 = new TestBean(); + cn.hutool.poi.excel.TestBean bean2 = new cn.hutool.poi.excel.TestBean(); bean2.setName("李四"); bean2.setAge(28); bean2.setPass(false); bean2.setScore(38.50); bean2.setExamDate(DateUtil.date()); - List rows = CollUtil.newArrayList(bean1, bean2); + List rows = CollUtil.newArrayList(bean1, bean2); // 通过工具类创建writer String file = "e:/writeBeanTest.xlsx"; FileUtil.del(file); @@ -376,17 +374,17 @@ public class ExcelWriteTest { @Test @Ignore public void writeBeanTest2() { - OrderExcel order1 = new OrderExcel(); + cn.hutool.poi.excel.OrderExcel order1 = new cn.hutool.poi.excel.OrderExcel(); order1.setId("1"); order1.setNum("123"); order1.setBody("body1"); - OrderExcel order2 = new OrderExcel(); + cn.hutool.poi.excel.OrderExcel order2 = new cn.hutool.poi.excel.OrderExcel(); order1.setId("2"); order1.setNum("456"); order1.setBody("body2"); - List rows = CollUtil.newArrayList(order1, order2); + List rows = CollUtil.newArrayList(order1, order2); // 通过工具类创建writer String file = "f:/test/writeBeanTest2.xlsx"; FileUtil.del(file); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java index 279221787..10bf20af9 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/OrderExcel.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import lombok.Data; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java index 62c8405ba..a1ee1644a 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/TestBean.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.excel.test; +package cn.hutool.poi.excel; import lombok.Data; diff --git a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java index b05131edd..22effb9a8 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java @@ -1,4 +1,4 @@ -package cn.hutool.poi.word.test; +package cn.hutool.poi.word; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.FileUtil; diff --git a/hutool-poi/src/test/resources/data_for_sax_test.xls b/hutool-poi/src/test/resources/data_for_sax_test.xls index ebebc51bc0b1676a907911e2862d27cc5934857c..a5f18d6340d40a3e94a6954e02be71c8bcf4ea50 100644 GIT binary patch delta 3239 zcmbVOUuaWT82`@AO?p$>G_AHbN!wV{vQgLCrq&9zX{z9ZqYsWJ}6iODT;~KhY99E<~D*<6n&V=#-T0|={f9AASXA! z^Sj^g`+et}@7~OBDDww8)r*Es$D8%F0C4@&Yba-l)fPdFN;xmck7} zwXIW#{J=4XS($Bv{RAI?^6XVlyT#nABSdCzYsGsjF`t482cqakWBCB}QXGLH#J6bD zRG?p&aB;sB*T9qt08}gRemS0kA?XByq*NGSSjq?Rm+{=7H=}u@`bxNgeZC&g0Nlir zzBSeXn1en*yPyqX@WPJ43UbvBUF6#iy+HA`&RCh<4&DF2h!IANxp&05j_MO|3kEqc zi&I-k6#tE;npad#l0sE7FRK4Q)|7tU+d=2IIOOK5e)Y!aH3EVgr711nR^%@$;yV7O zw#By|@*BoY{HnIYaMQ%`pozN!4Lq<@1g1qGF8~oQQP!ZABb9Ud7@(dK(proX3w4<1j(>qZ!bc{o LnpIS#^j`NjY>e)( delta 2883 zcmbVOT}V_x6h3oz)w^o@r|sQ8*G;X^3R!8U3aiXqI+_mVT=%t^R?T?^9>Y>1g2nwVJ3Gz0x+ufa+oq6dluIxA8eCK>;<{WNn z0i}MS3u{rw#aPJR4gk}=_ff_~5roEZ#AdMHfpHD>9DjN;2DLClsAlp4BLCn_j#*rd z!VtkXKwUhgssa6%bq_8jxTK|5i03`V;LqtPh7T48Q6)bDNilwuxTPl`=W&Mz|vfDV1ZMD+8vfDV1BPtf>@rjDXdDNCF zB61$Ls#u)Ib8=Q|8|U$zip6>K`J{QZws9T@R4mTpq>9CPoKvwlk1dAK#D@*$vX2_g z{2kT*-FdzOhTtvFGUFV}=a;gCY7Y3Bd}uRG_$AFmN4)v+wOMGUccM6LIm&wRlVSM+ zP3yVFtdQ7YEs{RXJ@`m~NsG?9bbu*SHqgAA)3u_{&(9Zfq_Jp5$z;;BbZIORb1)d8 zm=6D_9 z8d>!*zh5nC^n{z_MrBoGO<5VSm}vBQSW!hYd!>-V{~u8Z57#yDt&$)509+G1suP;P zVsXRbkBY?&i_H;*7B?(LRV;2;WK}F~Sa|9cCuEx0k|L(l>5{9+V%7;!j9$g_^}<#B zR?l2T+H=8Z5y%{fUUO?7+OZy+)IP7t+>X7kuB4@o^a9lE$c%Qa_IVndu3US8<|HfR zDDbnLdvL7(MB_)OhF1jXgfKYCr%Us~Lt0(vreE~IU;4vN8+q@c?>;v2K`2wTYZ8s^ ze(Qkcp_}oCACN8M*|O4=9=hSy7fsV#MYr7<@#lWD(I43nzk{y)A%Bb0y)|eoaY#?y hUGbog?8ZkEr?s;?@b5$dwcz37$?8_JhrVag=Pwy3crgF~ diff --git a/hutool-poi/src/test/resources/data_for_sax_test.xlsx b/hutool-poi/src/test/resources/data_for_sax_test.xlsx index 8fb64fd8b5f1031ac5f20b8f28ac3d6994cd6e07..ecbac56a91bb6f493728d905ac3d37c2e603c416 100644 GIT binary patch delta 2823 zcmY*bX*kpm7afLS#x_ZeC5@QT46Fxc0dH?VIbe`wl=X|;MoO{yEI?P{EAutiw5|KK35J&+++=B1`6#qOa zcw}M2AG(8r7;i0l?6ZgNz^@l`3*r1b(~}u1 ze6ijRFUK2@Nl=%l_Ti8+m4=vh#%ko(+G;#D8HS|d3H5#&8J44Wo5ah`2hchD6DTtm z_T#pC)xU*20qgJ^fz~kclPG#FTJ)UbkgkBl}oE4AHKsGA@$*Y?H=FqF_p=jBxaDznJk+AQ-W(`N=O&{Ri**=?Poj|@fXuzMT zb8y?I4Uqd(QeL?Fb^4H#SpDO=Jr4$W*6nh_?4e6=xLw{-zfu9*B?QIi0WQ-8ScJ=D z*a8UN-0yvaZO1N8PKv;~px)WOx6BO&rCF`B9wz5359l>iCm^oMG9Anr`LtHZ9U<^t zgU1$y1hSXLpu5CEQ>@G6)@tY&wu>q^7^dyoGuG3g5JT~joLB%#Ck<{svMytZGWnf< z&Kxi*zxN}0`|gRpvzJMVt)U~(0mg=2HwsjJSq%2wHko#dI`}NpXTi;T!b?*V-7=3j zEtq>eEty{tcMo=WO-Q((wQyq9CB^Vb@W}zTd-h~ZKXu4oSEA)~k*4&|-F&g2O>oT; zj#+1p@$UH*v+DO{l{Y|XolBIk2WC;Mu#nKTO>(ueHXvUKN7+x&^hf}O(XM(x}TlkT5vy*jTZxIi2uCTingfSsE9T{V=na)^kx+wChThPz?Ji zh6acxT*+><_cvFYlK^0;9Lfi+(ihf0n=*cZ?>LtG57SVuhvL_q#kWk!oLw3@llC@lm`qE(?T;AZUIxpu%-C5a*99zN^vV@(AT)F-n2qBQ7-ldN+_h1I zRjg!0pjnG#$}DaIwJV=s&65VQ5`&~8x@D(ucai-zl|e4PmRlRlKGF3b?QcUr>x!ebvHzF?Mm_F=hNGInr(K z_vPo}&mIXpjGfnrr`DAH)}#i*KG3`)kP6JGjy&rFE9AN zeRFu6c9R^x24Ps2PwknS>Z^6cAnuoxtcK@@<_1MSfqrXkTd1HLPWeT2ZH^bGi{q;T z+}XjCdz-;>_mEGs1u||f=;LbSX5y}@PA}eJuXig8gm$-@w_H~9?B_HS1OK?u^l7^0 zs@zfaBWdK8IEMF{m|@G%NTfa`ngHuRAW3X(K0p1viO&F34GUw&SvIjmZ#yJ>fn3v4 zv^Um7mB#sW!SW{Q<0svVNl~4ng}>AQf`ImwLK>oxEGnhgxhb~l`t+}9unzeudWhoWNZky)l%?6!vK7_u=1ct*-etj_2*!B z!|`o<^tUz}b~`^_1rz17Ge%0^L4$Rdr}UhRC#F3sp6AB$D9${@xeW|0ILmYcy(cVo zb)@_3&)c0j`UBw@wcWxwPIl2LCcmLykemAZ#Uu~R$-2iaIr~qm847INmj0^6wF=2R z#*%`Ll34@c+&Y~*BeA`kj;aw0_H2!a)GuraOcr~cyF#A?{V;;80>`wU^t0NudN0oK zGYQd;(_%*X%|A@$nd#L&?saaE%unG_xFyKZ(wi239<0u~;CiF4H=v8*vk5Jrab$E9 zW*D=i&akv8yL9dkvpWF(M^6#F9~l_4!#zEW>#qr-=>P}gE-6IZCgUINzKFbrL#OyA zaArt-^rFs>iz1s%E_wGvW_KugP4*-+_-$f7QS{3j5eLENGW!g!EGStneFjG4E6%ui z&$W#YRb*{)o{wMo- zcY(~A03hSk6n^Z(SFd*SBZwd0kx+I^Ml?;Cl4>ntG6RmsV5#a@0>NLO+{S zg-JWE$~T6|8kUX`gl@o%Jr;UK!fc{i{31gnb%RDWe6|VjXb!zYKF`nYx9_}lc&aJ{ zg}S~ix4*4jA#F2)c=ue6D!eb R^ua>JHS~Fip2&ZD{{fpEDQ^G( delta 2651 zcmY*bc{tPy8=Yas60(g9BZRSUpQ0&^LN3F_7%`}rLU*!co3dsy%94`&kjq$V>`P)4 zCHqdul944T+$>{^ean3J-aqd5-S@BaJnwnlf8O()bDC_EY+lXt9C>JPPs4``1PX-$ zt2~nAtF{xmu)8_c9KtSI=@xK70XKsCsO~E+E$Eu0%m_dTboTqizA-u2o>CIRzKgwe zF~0F-P{cre=k|urRm+X8#}Y1{=`v7wKs!l$M6dO{pLV_YqcWO$Axbt_7M@JYo;SayZv4p8M_4h->8S zZ>jN|;nE$bMkG|RId)L~I&Jtt(!m>h=@$;0S!vb;oaQ=!x=q)4gAG(Peqv zBwBt@_^|F+Oe-3M0pW>iRtuA^c4U0+c$c8kg}$++Y(I0!e-25LcSAGTQ7_Q zrEHV^^<-iPnp)b_hO6(i8x#xOh-v+yQ{YFMx@?g&sz63_)W(clha0`ah!a7r)x`!i zl!|5Vy-YQiY5vqDhnRZE!%sJUd*fvttPl*1Q;<^5UAn~-knH6;K+d8bOX4`BBQ>5{zM~FwZ+Rj2DRhkpQ+6gIpqBSvJ*u@Z+I`hhI3gMrZTeLSG`j zM5jqiS(pzj)%f-3kMS}v3;bf$rNlq#)!;!d0PbK>criN|1)D8s&5px6gmwa{#@?I_o)^Xb@-W&s`&I6{JMajY}_e-R;?)Gbx2c%8Ri^M6uRAg>@S>}k^4y>r4p~2ksp2TwZ4x{T zT9TEl>3HI`+}N{XUK$xTA5e#k6dB?1y{(C#jL&rm)Cll`TmuF={__L8EIhq-3 zdVQT_(vCt1QddKZD2Ia|Ov4ZAh_zhxcO6?uLT+6;liDeF@}4o%GsG>IVP&Y6*Sz9Y zB+5d1bSG)~&T%7Yu|kA7(OuwcaHiI_&0hYA7{pE1h#agliQ027%)Ffb3(6+ygF&K-)2O zvPUmw5T%Bd)eN+VTo-DT8tMid{WmV$ZcX_$AVi9A(et^b@@cih747XCaQ&FBWPjw% zhuhW7wp9b?t)%IHY}~ObHU^!@g!w%#mTZ`YT~@aUD)v&pR)BL6;Wn*jXS&$q4DJA5 zBViDGHxcDZQ>VCZG9tzsrB|5}mLqMi$ok(uEE{S*x>yhRgUaN-!pJY`p{r=6CN@KukG+z`Rm z(sDbhSjS*Fdt&lu(`Bg2)P--Um(F)h+JMgxeDI!_b;U4w8O`VIsxZ8?R2Ni!(pgD# zq&#GQLdTEHp zQS~nM%J3AirkUP+#wL4)3goGG!ew8GRl>B8>SmVAjc%6(u^wNMN!gr}p8SQWQ9Jq* zK1@cDbR?q(-qoY2CiPhrQ~T++vB6+@DkU(|+iGop5mHzFOFX3ASGajTg=r#xmof9! zI8CJA0EgwT!umR0Gt(kiWQqAg1v?I@+fTpqLpIroc9-u$qQwsy$R zWy1Lf!#ZoP4e@)~Z@uEy?cGYxiz*j&_gmJ!E9@%Ymh9-!**A4fuf6jy$fYXlUS_@9 zrcgMxAliam$@wsfBcom$5xukZ{jHlNnWwDSwx@eL*FRayhSCXV)|K(6w&vM^bM3&= zoLA~Vv})~P=mzN^HkKAXpR3x^{bFYI{STwD>;vXt+PA@`LDntNT=cxrlY(Y^06b*Z zK_m=N`#qGt;IKRw052~9=B%lmiYsgtBZnxtm{$8wG3*w&uJIWl+A-S1T_XuYy~VnIjqI`7I^i z+k1Ke7Tj|zLd1M~FpXAuGo$GD&HqG1Qrv1X3md$gN^UvIV6%_dyamr!cb|5_`>y6{ zfYsZ@pChifmrd-2vMfbvm^!R{)0MY(AA^r7tTz9^elL6fVPz#jzXw3Yn|@=wkMsLM z{pi6SMRUGKN|I1Xg(4g=415|EU;-eK9wz6w*I;fDi3b8eB|nUQ|HQA{|KHNam8`)5 zfGSc8@$dBf)5rdq*ML9L4D1HHK`P7q&&xm{p??^EffWg02YH6ePYO7xe1R)U8n8kj zfedAJu4n{cEu#jo{({E=go*;<@4tdUpqqb&wdlW&`~o