This commit is contained in:
Looly 2022-04-24 14:21:20 +08:00
parent 37f53e9856
commit ca03fb3411
6 changed files with 130 additions and 6 deletions

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
# 5.8.0.M4 (2022-04-23)
# 5.8.0.M4 (2022-04-24)
### ❌不兼容特性
* 【json 】 【可能兼容问题】JSONArray删除部分构造
@ -18,6 +18,7 @@
* 【json 】 添加ObjectMapper
* 【core 】 CHINESE_NAME正则条件放宽pr#599@Gitee
* 【extra 】 增加JakartaServletUtilissue#2271@Github
* 【poi 】 ExcelWriter支持重复别名的数据写出issue#I53APY@Gitee
### 🐞Bug修复
* 【core 】 修复StrUtil.firstNonX非static问题issue#2257@Github

View File

@ -27,9 +27,18 @@ import java.util.Set;
public class TableMap<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, Serializable {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_CAPACITY = 10;
private final List<K> keys;
private final List<V> values;
/**
* 构造
*/
public TableMap() {
this(DEFAULT_CAPACITY);
}
/**
* 构造
*
@ -85,11 +94,12 @@ public class TableMap<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, Ser
/**
* 根据value获得对应的key只返回找到的第一个value对应的key值
*
* @param value
* @return
* @since 5.3.3
*/
public K getKey(V value){
public K getKey(V value) {
final int index = values.indexOf(value);
if (index > -1 && index < keys.size()) {
return keys.get(index);
@ -160,7 +170,17 @@ public class TableMap<K, V> implements Map<K, V>, Iterable<Map.Entry<K, V>>, Ser
@Override
public Set<K> keySet() {
return new HashSet<>(keys);
return new HashSet<>(this.keys);
}
/**
* 获取所有键可重复不可修改
*
* @return 键列表
* @since 5.8.0
*/
public List<K> keys() {
return Collections.unmodifiableList(this.keys);
}
@Override

View File

@ -9,8 +9,11 @@ import cn.hutool.core.map.MapUtil;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -198,6 +201,15 @@ public class RowKeyTable<R, C, V> extends AbsTable<R, C, V> {
//endregion
//region getColumn
@Override
public List<C> columnKeys() {
final Collection<Map<C, V>> values = this.raw.values();
final List<C> result = new ArrayList<>(values.size() * 16);
for (Map<C, V> map : values) {
map.forEach((key, value)->{result.add(key);});
}
return result;
}
@Override
public Map<R, V> getColumn(C columnKey) {

View File

@ -1,10 +1,13 @@
package cn.hutool.core.map.multi;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.func.Consumer3;
import cn.hutool.core.map.MapUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -101,6 +104,25 @@ public interface Table<R, C, V> extends Iterable<Table.Cell<R, C, V>> {
return Opt.ofNullable(columnMap()).map(Map::keySet).get();
}
/**
* 返回所有列的key列的key如果实现Map是可重复key则返回对应不去重的List
*
* @return 列set
* @since 5.8.0
*/
default List<C> columnKeys() {
final Map<C, Map<R, V>> columnMap = columnMap();
if(MapUtil.isEmpty(columnMap)){
return ListUtil.empty();
}
final List<C> result = new ArrayList<>(columnMap.size());
for (Map.Entry<C, Map<R, V>> cMapEntry : columnMap.entrySet()) {
result.add(cMapEntry.getKey());
}
return result;
}
/**
* 返回列-行对应的map
*

View File

@ -8,6 +8,7 @@ import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.map.TableMap;
import cn.hutool.core.map.multi.RowKeyTable;
import cn.hutool.core.map.multi.Table;
import cn.hutool.core.util.CharsetUtil;
@ -1049,7 +1050,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
final Table<?, ?, ?> aliasTable = aliasTable(rowMap);
if (isWriteKeyAsHead) {
// 写出标题行并记录标题别名和列号的关系
writeHeadRow(aliasTable.columnKeySet());
writeHeadRow(aliasTable.columnKeys());
// 记录原数据key对应列号
int i = 0;
for (Object key : aliasTable.rowKeySet()) {
@ -1341,7 +1342,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* @return 别名列表
*/
private Table<?, ?, ?> aliasTable(Map<?, ?> rowMap) {
final Table<Object, Object, Object> filteredTable = new RowKeyTable<>(new LinkedHashMap<>(), LinkedHashMap::new);
final Table<Object, Object, Object> filteredTable = new RowKeyTable<>(new LinkedHashMap<>(), TableMap::new);
if (MapUtil.isEmpty(this.headerAlias)) {
rowMap.forEach((key, value)-> filteredTable.put(key, key, value));
}else{

View File

@ -2,6 +2,10 @@ package cn.hutool.poi.excel;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.poi.excel.style.StyleUtil;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Ignore;
import org.junit.Test;
@ -10,9 +14,12 @@ import java.util.Map;
public class Issue2221Test {
/**
* 设置重复别名的时候通过原key获取写出位置
*/
@Test
@Ignore
public void writeDuplicateHeaderAliasTest(){
public void writeDuplicateHeaderAliasTest() {
final ExcelWriter writer = ExcelUtil.getWriter("d:/test/duplicateAlias.xlsx");
// 设置别名
writer.addHeaderAlias("androidLc", "安卓");
@ -28,4 +35,65 @@ public class Issue2221Test {
writer.write(data, true);
writer.close();
}
@Test
@Ignore
public void writeDuplicateHeaderAliasTest2(){
// 获取写Excel的流
ExcelWriter writer = ExcelUtil.getBigWriter("d:/test/duplicateAlias2.xlsx");
// 设置头部的背景颜色
StyleUtil.setColor(writer.getHeadCellStyle(), IndexedColors.GREY_50_PERCENT, FillPatternType.SOLID_FOREGROUND);
//设置全局字体
Font font = writer.createFont();
font.setFontName("Microsoft YaHei");
writer.getStyleSet().setFont(font, false);
// 设置头部的字体为白颜色
Font headerFont = writer.createFont();
headerFont.setColor(IndexedColors.WHITE.getIndex());
writer.getHeadCellStyle().setFont(headerFont);
// 跳过多少行
writer.passRows(1);
// 冻结多少行
writer.setFreezePane(2);
// 设置别名
writer.addHeaderAlias("date", "日期");
writer.addHeaderAlias("androidLc", "安卓");
writer.addHeaderAlias("iosLc", "iOS");
writer.addHeaderAlias("androidAc", " 安卓");
writer.addHeaderAlias("iosAc", " iOS");
writer.setOnlyAlias(true);
// 设置合并的单元格
writer.merge(0, 1, 0, 0, "日期", true);
writer.merge(0, 0, 1, 2, "运行次数", true);
writer.merge(0, 0, 3, 4, "新增人数", true);
// 写入数据
List<Map<Object, Object>> data = ListUtil.of(
MapUtil.ofEntries(
MapUtil.entry("date", "2022-01-01"),
MapUtil.entry("androidLc", "1次"),
MapUtil.entry("iosLc", "2次"),
MapUtil.entry("androidAc", "3次"),
MapUtil.entry("iosAc", "4人")),
MapUtil.ofEntries(
MapUtil.entry("date", "2022-01-02"),
MapUtil.entry("androidLc", "5次"),
MapUtil.entry("iosLc", "6次"),
MapUtil.entry("androidAc", "7次"),
MapUtil.entry("iosAc", "8人"))
);
// 自动尺寸
writer.autoSizeColumnAll();
writer.write(data, true);
writer.close();
}
}