Merge remote-tracking branch 'upstream/v5-dev' into v5-dev

This commit is contained in:
lzpeng723 2020-12-12 19:29:01 +08:00
commit 123ca7fd4d
9 changed files with 142 additions and 37 deletions

View File

@ -20,6 +20,7 @@
* 【core 】 修正DateUtil.betweenXXX注释错误issue#I28XGW@Gitee * 【core 】 修正DateUtil.betweenXXX注释错误issue#I28XGW@Gitee
* 【core 】 增加NioUtil * 【core 】 增加NioUtil
* 【core 】 增加GanymedUtil * 【core 】 增加GanymedUtil
* 【poi 】 增加OFD支持OfdWriter
### Bug修复 ### Bug修复
* 【cache 】 修复Cache中get重复misCount计数问题issue#1281@Github * 【cache 】 修复Cache中get重复misCount计数问题issue#1281@Github
@ -32,6 +33,7 @@
* 【poi 】 修复xdr:row标签导致的问题issue#1297@Github * 【poi 】 修复xdr:row标签导致的问题issue#1297@Github
* 【core 】 修复FileUtil.loopFiles使用FileFilter无效问题issue#I28V48@Gitee * 【core 】 修复FileUtil.loopFiles使用FileFilter无效问题issue#I28V48@Gitee
* 【extra 】 修复JschUtil.execByShell返回空的问题issue#1067@Github * 【extra 】 修复JschUtil.execByShell返回空的问题issue#1067@Github
* 【poi 】 修复特殊的excel使用sax读取时未读到值的问题issue#1303@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
@ -72,7 +74,7 @@
* 【core 】 修复HexUtil.format问题issue#I268XT@Gitee * 【core 】 修复HexUtil.format问题issue#I268XT@Gitee
* 【core 】 修复ZipUtil判断压缩文件是否位于压缩目录内的逻辑有误的问题issue#1251@Github * 【core 】 修复ZipUtil判断压缩文件是否位于压缩目录内的逻辑有误的问题issue#1251@Github
* 【json 】 修复JSONObject.accumulate问题 * 【json 】 修复JSONObject.accumulate问题
* 【core 】 修复部分xlsx文件sax方式解析空指针问题issue#1265@Github * 【poi 】 修复部分xlsx文件sax方式解析空指针问题issue#1265@Github
* 【core 】 修复PatternPool中邮编的正则issue#1274@Github * 【core 】 修复PatternPool中邮编的正则issue#1274@Github
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------

View File

@ -745,11 +745,11 @@ public class BeanUtil {
} }
/** /**
* 判断Bean是否为非空对象非空对象表示本身不为<code>null</code>或者含有非<code>null</code>属性的对象 * 判断Bean是否为非空对象非空对象表示本身不为{@code null}或者含有非{@code null}属性的对象
* *
* @param bean Bean对象 * @param bean Bean对象
* @param ignoreFiledNames 忽略检查的字段名 * @param ignoreFiledNames 忽略检查的字段名
* @return 是否为空<code>true</code> - / <code>false</code> - 非空 * @return 是否为空{@code true} - / {@code false} - 非空
* @since 5.0.7 * @since 5.0.7
*/ */
public static boolean isNotEmpty(Object bean, String... ignoreFiledNames) { public static boolean isNotEmpty(Object bean, String... ignoreFiledNames) {
@ -757,12 +757,12 @@ public class BeanUtil {
} }
/** /**
* 判断Bean是否为空对象空对象表示本身为<code>null</code>或者所有属性都为<code>null</code><br> * 判断Bean是否为空对象空对象表示本身为{@code null}或者所有属性都为{@code null}<br>
* 此方法不判断static属性 * 此方法不判断static属性
* *
* @param bean Bean对象 * @param bean Bean对象
* @param ignoreFiledNames 忽略检查的字段名 * @param ignoreFiledNames 忽略检查的字段名
* @return 是否为空<code>true</code> - / <code>false</code> - 非空 * @return 是否为空{@code true} - / {@code false} - 非空
* @since 4.1.10 * @since 4.1.10
*/ */
public static boolean isEmpty(Object bean, String... ignoreFiledNames) { public static boolean isEmpty(Object bean, String... ignoreFiledNames) {
@ -781,12 +781,12 @@ public class BeanUtil {
} }
/** /**
* 判断Bean是否包含值为<code>null</code>的属性<br> * 判断Bean是否包含值为{@code null}的属性<br>
* 对象本身为<code>null</code>也返回true * 对象本身为{@code null}也返回true
* *
* @param bean Bean对象 * @param bean Bean对象
* @param ignoreFiledNames 忽略检查的字段名 * @param ignoreFiledNames 忽略检查的字段名
* @return 是否包含值为<code>null</code>的属性<code>true</code> - 包含 / <code>false</code> - 不包含 * @return 是否包含值为<code>null</code>的属性{@code true} - 包含 / {@code false} - 不包含
* @since 4.1.10 * @since 4.1.10
*/ */
public static boolean hasNullField(Object bean, String... ignoreFiledNames) { public static boolean hasNullField(Object bean, String... ignoreFiledNames) {

View File

@ -140,7 +140,7 @@ public class ReflectUtil {
} }
/** /**
* 查找指定类中的指定name的字段包括非public字段也包括父类和Object类的字段 字段不存在则返回<code>null</code> * 查找指定类中的指定name的字段包括非public字段也包括父类和Object类的字段 字段不存在则返回{@code null}
* *
* @param beanClass 被查找字段的类,不能为null * @param beanClass 被查找字段的类,不能为null
* @param name 字段名 * @param name 字段名
@ -422,7 +422,7 @@ public class ReflectUtil {
} }
/** /**
* 查找指定Public方法 如果找不到对应的方法或方法不为public的则返回<code>null</code> * 查找指定Public方法 如果找不到对应的方法或方法不为public的则返回{@code null}
* *
* @param clazz * @param clazz
* @param methodName 方法名 * @param methodName 方法名
@ -442,7 +442,7 @@ public class ReflectUtil {
* 查找指定对象中的所有方法包括非public方法也包括父对象和Object类的方法 * 查找指定对象中的所有方法包括非public方法也包括父对象和Object类的方法
* *
* <p> * <p>
* 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回<code>null</code> * 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回{@code null}
* </p> * </p>
* *
* @param obj 被查找的对象如果为{@code null}返回{@code null} * @param obj 被查找的对象如果为{@code null}返回{@code null}
@ -459,10 +459,10 @@ public class ReflectUtil {
} }
/** /**
* 忽略大小写查找指定方法如果找不到对应的方法则返回<code>null</code> * 忽略大小写查找指定方法如果找不到对应的方法则返回{@code null}
* *
* <p> * <p>
* 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回<code>null</code> * 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回{@code null}
* </p> * </p>
* *
* @param clazz 如果为{@code null}返回{@code null} * @param clazz 如果为{@code null}返回{@code null}
@ -477,10 +477,10 @@ public class ReflectUtil {
} }
/** /**
* 查找指定方法 如果找不到对应的方法则返回<code>null</code> * 查找指定方法 如果找不到对应的方法则返回{@code null}
* *
* <p> * <p>
* 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回<code>null</code> * 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回{@code null}
* </p> * </p>
* *
* @param clazz 如果为{@code null}返回{@code null} * @param clazz 如果为{@code null}返回{@code null}
@ -494,10 +494,10 @@ public class ReflectUtil {
} }
/** /**
* 查找指定方法 如果找不到对应的方法则返回<code>null</code> * 查找指定方法 如果找不到对应的方法则返回{@code null}
* *
* <p> * <p>
* 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回<code>null</code> * 此方法为精准获取方法名即方法名和参数数量和类型必须一致否则返回{@code null}
* </p> * </p>
* *
* @param clazz 如果为{@code null}返回{@code null} * @param clazz 如果为{@code null}返回{@code null}
@ -527,7 +527,7 @@ public class ReflectUtil {
} }
/** /**
* 按照方法名查找指定方法名的方法只返回匹配到的第一个方法如果找不到对应的方法则返回<code>null</code> * 按照方法名查找指定方法名的方法只返回匹配到的第一个方法如果找不到对应的方法则返回{@code null}
* *
* <p> * <p>
* 此方法只检查方法名是否一致并不检查参数的一致性 * 此方法只检查方法名是否一致并不检查参数的一致性
@ -544,7 +544,7 @@ public class ReflectUtil {
} }
/** /**
* 按照方法名查找指定方法名的方法只返回匹配到的第一个方法如果找不到对应的方法则返回<code>null</code> * 按照方法名查找指定方法名的方法只返回匹配到的第一个方法如果找不到对应的方法则返回{@code null}
* *
* <p> * <p>
* 此方法只检查方法名是否一致忽略大小写并不检查参数的一致性 * 此方法只检查方法名是否一致忽略大小写并不检查参数的一致性
@ -561,7 +561,7 @@ public class ReflectUtil {
} }
/** /**
* 按照方法名查找指定方法名的方法只返回匹配到的第一个方法如果找不到对应的方法则返回<code>null</code> * 按照方法名查找指定方法名的方法只返回匹配到的第一个方法如果找不到对应的方法则返回{@code null}
* *
* <p> * <p>
* 此方法只检查方法名是否一致并不检查参数的一致性 * 此方法只检查方法名是否一致并不检查参数的一致性
@ -842,7 +842,7 @@ public class ReflectUtil {
* </pre> * </pre>
* *
* @param <T> 返回对象类型 * @param <T> 返回对象类型
* @param obj 对象如果执行静态方法此值为<code>null</code> * @param obj 对象如果执行静态方法此值为{@code null}
* @param method 方法对象方法或static方法都可 * @param method 方法对象方法或static方法都可
* @param args 参数对象 * @param args 参数对象
* @return 结果 * @return 结果
@ -878,7 +878,7 @@ public class ReflectUtil {
* </pre> * </pre>
* *
* @param <T> 返回对象类型 * @param <T> 返回对象类型
* @param obj 对象如果执行静态方法此值为<code>null</code> * @param obj 对象如果执行静态方法此值为{@code null}
* @param method 方法对象方法或static方法都可 * @param method 方法对象方法或static方法都可
* @param args 参数对象 * @param args 参数对象
* @return 结果 * @return 结果

View File

@ -18,7 +18,6 @@
<properties> <properties>
<!-- versions --> <!-- versions -->
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<xerces.version>2.12.0</xerces.version>
</properties> </properties>
<dependencies> <dependencies>
@ -42,9 +41,9 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>xerces</groupId> <groupId>org.ofdrw</groupId>
<artifactId>xercesImpl</artifactId> <artifactId>ofdrw-full</artifactId>
<version>${xerces.version}</version> <version>1.7.2</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>

View File

@ -137,9 +137,6 @@ public class SheetDataSaxHandler extends DefaultHandler {
// 其它标签忽略 // 其它标签忽略
} }
/**
* s标签结束的回调处理方法
*/
@Override @Override
public void characters(char[] ch, int start, int length) { public void characters(char[] ch, int start, int length) {
if (false == this.isInSheetData) { if (false == this.isInSheetData) {
@ -159,8 +156,11 @@ public class SheetDataSaxHandler extends DefaultHandler {
lastFormula.append(ch, start, length); lastFormula.append(ch, start, length);
break; break;
} }
} else{
// 按理说内容应该为"<v>内容</v>"但是某些特别的XML内容不在v或f标签中此处做一些兼容
// issue#1303@Github
lastContent.append(ch, start, length);
} }
// 其它标签忽略
} }
// --------------------------------------------------------------------------------------- Private method start // --------------------------------------------------------------------------------------- Private method start

View File

@ -0,0 +1,85 @@
package cn.hutool.poi.ofd;
import cn.hutool.core.io.IoUtil;
import org.ofdrw.font.Font;
import org.ofdrw.layout.OFDDoc;
import org.ofdrw.layout.element.Div;
import org.ofdrw.layout.element.Paragraph;
import java.io.Closeable;
import java.io.File;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.file.Path;
/**
* OFD文件生成器
*
* @author looly
* @since 5.5.3
*/
public class OfdWriter implements Serializable, Closeable {
private static final long serialVersionUID = 1L;
private final OFDDoc doc;
/**
* 构造
*
* @param file 生成的文件
*/
public OfdWriter(File file){
this(file.toPath());
}
/**
* 构造
*
* @param file 生成的文件
*/
public OfdWriter(Path file){
this.doc = new OFDDoc(file);
}
/**
* 构造
*
* @param out 需要输出的流
*/
public OfdWriter(OutputStream out){
this.doc = new OFDDoc(out);
}
/**
* 增加文本内容
*
* @param font 字体
* @param texts 文本
* @return this
*/
public OfdWriter addText(Font font, String... texts){
final Paragraph paragraph = new Paragraph();
if(null != font){
paragraph.setDefaultFont(font);
}
for (String text : texts) {
paragraph.add(text);
}
return add(paragraph);
}
/**
* 增加节点
* @param div 节点可以是段落CanvasImg或者填充
* @return this
*/
public OfdWriter add(Div div){
this.doc.add(div);
return this;
}
@Override
public void close() {
IoUtil.close(this.doc);
}
}

View File

@ -0,0 +1,6 @@
/**
* 开放版式文档Open Fixed-layout Document 封装基于ofdrwhttps://gitee.com/Trisia/ofdrw
*
* @author looly
*/
package cn.hutool.poi.ofd;

View File

@ -64,7 +64,7 @@ public class ExcelSaxReadTest {
@Test @Test
@Ignore @Ignore
public void readBySaxTest2() { public void readBySaxTest2() {
ExcelUtil.readBySax("d:/test/default.xlsx", -1, (sheetIndex, rowIndex, rowList) -> Console.log(rowList)); ExcelUtil.readBySax("d:/test/456789.xlsx", "0", (sheetIndex, rowIndex, rowList) -> Console.log(rowList));
} }
private RowHandler createRowHandler() { private RowHandler createRowHandler() {
@ -140,9 +140,7 @@ public class ExcelSaxReadTest {
public void dateReadXlsTest() { public void dateReadXlsTest() {
List<String> rows = new ArrayList<>(); List<String> rows = new ArrayList<>();
ExcelUtil.readBySax("data_for_sax_test.xls", 0, ExcelUtil.readBySax("data_for_sax_test.xls", 0,
(i, i1, list) ->{ (i, i1, list) -> rows.add(StrUtil.toString(list.get(0)))
rows.add(StrUtil.toString(list.get(0)));
}
); );
Assert.assertEquals("2020-10-09 00:00:00", rows.get(1)); Assert.assertEquals("2020-10-09 00:00:00", rows.get(1));
@ -179,8 +177,7 @@ public class ExcelSaxReadTest {
@Test @Test
@Ignore @Ignore
public void readXlsmTest(){ public void readXlsmTest(){
ExcelUtil.readBySax("d:/test/WhiteListTemplate.xlsm", -1, (sheetIndex, rowIndex, rowlist) -> { ExcelUtil.readBySax("d:/test/WhiteListTemplate.xlsm", -1,
Console.log("[{}] [{}] {}", sheetIndex, rowIndex, rowlist); (sheetIndex, rowIndex, rowlist) -> Console.log("[{}] [{}] {}", sheetIndex, rowIndex, rowlist));
});
} }
} }

View File

@ -0,0 +1,16 @@
package cn.hutool.poi.ofd;
import cn.hutool.core.io.FileUtil;
import org.junit.Ignore;
import org.junit.Test;
public class OfdWriterTest {
@Test
@Ignore
public void writeTest(){
final OfdWriter ofdWriter = new OfdWriter(FileUtil.file("d:/test/test.ofd"));
ofdWriter.addText(null, "测试文本");
ofdWriter.close();
}
}