1. 实列相关依赖

     <dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>

2.EasyExcel导出常见的两种方式:

1.根据路径保存到磁盘:

2.响应Response,用户直接网页下载:

正常分为三个步骤:

(1)构建一个ExcelWriter对象。

(2)再次通过write方法写入数据。

(3)调用EasyExcel的finish

根据路径保存示例:

     private ExcelWriter excelWriter;
public EasyExcelHelper(String path) {
excelWriter = EasyExcel.write(path).build();
//固定的excel标题:
//Class类的属性必须使用`ExcelProperty`注解修饰。
//EasyExcel.write(path, Class).build()
}
//保存到本地磁盘
excelWriter.finish();

响应Respones示例:

    private ExcelWriter excelWriter;

    public EasyExcelHelper() {
excelWriter = new ExcelWriterBuilder()
.excelType(ExcelTypeEnum.XLSX)
.needHead(true)
.build();
}
public void export(HttpServletResponse response,String fileName ) {
final String exportName = fileName + ExcelTypeEnum.XLSX.getValue();
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
try {
excelWriter.finish();
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(exportName, StandardCharsets.UTF_8.name()));
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(dataBytes.length));
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new ApiException(ErrorEnum.DOWNLOAD_ERROR);
}
}

3.EaxyExcel动态标题

   /**
* @param sheetStartNum 默认为0即可
* @param sheetName sheet名称
* @param headList 动态标题,格式:List<List<String>>
* @param list 数据,格式List<List<Object>>;
*/
public void createSheet(Integer sheetStartNum, String sheetName, List headList, List list) {
WriteSheet sheet= EasyExcel.writerSheet(sheetStartNum, sheetName).build();
WriteTable table = new WriteTable();
table.setTableNo(0);
table.setHead(headList);
excelWriter.write(list, sheet, table);
}

4.EaxyExcel标题格式 策略设置

这里我使用两个策略,分别是defaultStyle、CustomerColumnWidthStyleStrategy。同时启用两个策略时,如果我们创建的excel文件有标题defaultStyle将会生效。不存在标题时,直接存入数据时,CustomerColumnWidthStyleStrategy将会适当调整excel宽度。在上面构建WriteSheet的时候我们可以添加这些策略:

 EasyExcel.writerSheet(sheetStartNum, sheetName).
registerWriteHandler(defaultStyle()).
registerWriteHandler(new CustomerColumnWidthStyleStrategy()).build();
 /**
* 设置头部样式
*
* @return
*/
private HorizontalCellStyleStrategy defaultStyle() {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
//头部样式
headWriteCellStyle.setFillForegroundColor(IndexedColors.LIME.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 12);
headWriteFont.setFontName("Arial");
headWriteFont.setBold(Boolean.FALSE);
headWriteFont.setColor(IndexedColors.WHITE.getIndex());
headWriteCellStyle.setWriteFont(headWriteFont);
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headWriteCellStyle.setWrapped(Boolean.FALSE);
headWriteCellStyle.setBorderRight(BorderStyle.NONE);
headWriteCellStyle.setBorderLeft(BorderStyle.NONE);
//内容样式
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
} /**
* 列宽设置
* memo:当数据不存在标题时,defaultStyle头部样式将失效,该设置将会生效
*/
private class CustomerColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { private static final int MAX_COLUMN_WIDTH = 7000; @Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) {
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), MAX_COLUMN_WIDTH);
} }

5.EaxyExcel 同值合并策略

上面我们添加了excel标题策略,现在我们再添加一个同值合并策略。笔者当前遇到一个需求,需要根据数据中一个字段的集合拆分成多条数据,拆分出来的数据相同值需要合并,所以添加了下面的策略。策略的添加方式与上面一致。

参数说明:

mergeRowIndex:合并开始的位置,第一行为0,正常是标题行,一般我们从1开始。

eachRow:多少行合并一次,假设我们现在根据某个属性将一条数据拆分成3条,如果我们不希望这3条以外的数据发生相同值合并,那么可以设置为3。

mergeColumnIndex:合并列的下标数据,第一列为0,假设等于[0,1,3],那么就意味着只有这3列会发生合并。

这三个参数配合使用,可以达到这样的效果:从x行开始,每y条数据发生合并,合并z[z1,z2,z3]的列。

/**
* 相同值合并策略
*/
public class ExcelMergeStrategy implements CellWriteHandler {
/**
* 合并起始行
*/
private int mergeRowIndex; /**
* 多少行合并一次
*/
private int eachRow;
/**
* 合并字段的下标
*/
private int[] mergeColumnIndex; public ExcelMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex, int eachRow) {
if (mergeRowIndex < 0) {
throw new IllegalArgumentException("mergeRowIndex must be greater than 0");
}
if (eachRow < 0) {
throw new IllegalArgumentException("eachRow must be greater than 0");
}
this.mergeRowIndex = mergeRowIndex;
this.mergeColumnIndex = mergeColumnIndex;
this.eachRow = eachRow;
} @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
int curRowIndex = cell.getRowIndex();
//当前列
int curColIndex = cell.getColumnIndex();
//合并条件:
//1.当前行>合并起始行,默认标题行(0)不参加合并
//2.间隔行(eachRow)的上下两条不参加合并
//2.1间隔行(eachRow)==0时,不设置间隔
if (isMerge(curRowIndex)) {
IntStream.range(0, mergeColumnIndex.length).anyMatch(i -> {
if (curColIndex == mergeColumnIndex[i]) {
mergeWithPrevRow(writeSheetHolder, cellData, cell, curRowIndex, curColIndex);
return true;
}
return false;
});
}
} @Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } /**
* 判断是否合并
* 1.当前位置必须大于开始位置:curRowIndex > mergeRowIndex
* 2.根据eachRow 判断数据分割的间隔
* 2.1如果根据eachRow=0,默认不合并
* 2.2如果1如果根据eachRow>0,分割后的第一条数据不会与之前的合并:(curRowIndex-mergeRowIndex)%eachRow==0
*
* @return
*/
private boolean isMerge(Integer curRowIndex) { if ((curRowIndex > mergeRowIndex) && eachRow > 0) {
if ((curRowIndex - mergeRowIndex) % eachRow == 0) {
return false;
}
return true;
} return false;
} private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, int curRowIndex, int curColIndex) {
//获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
Object curData = cellData.getType() == CellDataTypeEnum.STRING ? cellData.getStringValue() : cellData.getNumberValue();
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
preCell.getNumericCellValue();
// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
if (Objects.equals(curData, preData)) {
Sheet sheet = writeSheetHolder.getSheet();
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 若上一个单元格未被合并,则新增合并单元
if (!isMerged) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
}
}

6.动态标题拓展

使用场景:当我们需要动态设置excel标题时,但存在部分标题是固定的情况时,我们可以创建一个DemoVO对象使用DynamicColumn修饰这些属性。通过调用conver方法将DemoVO转换成一个ColumnData对象的集合。

然后通过commons-beanutils包的BeanUtils.describe()方法将查询的集合数据映射成Map。

  List<DemoVO> data = query();
List<ColumnData> columnList = conver(DemoVO.class); //excel数据
List<List<Object>> excelData = Lists.newArrayList();
for (DemoVO o : data) {
//对象转map
Map<String,String> oMap = BeanUtils.describe(o);
List<Object> baseList = Lists.newArrayList();
for (ColumnData columnData : columnList) {
//按照标题顺序设置值
baseList.add(oMap.get(columnData.getFieldName()));
}
excelData.add(baseList);
}

1.自定义动态excel注解

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicColumn {
String name();//excel标题 int index(); //标题顺序 } @Data
public class DemoVO {
@DynamicColumn(name = "库存", index = 0)
private String stockState; @DynamicColumn(name = "编码", index = 1)
private String skuCode; @DynamicColumn(name = "描述", index = 2)
private String skuDesc;
//动态拆分成多个标题
private List<String> address;
}

2.注解对应对象

@Builder
@Data
public class ColumnData { /**
* excel 标题
*/
private String columnName; /**
* 字段 属性
*/
private String fieldName; /**
* 排序
*/
private int index;
}

3.注解转对象工具类

 public static <R> List<ColumnData> conver(final Class<R> clazz) {
List<ColumnData> list = Lists.newArrayList();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
DynamicColumn annotation = field.getAnnotation(DynamicColumn.class);
if (!Objects.isNull(annotation)) {
ColumnData columnData = ColumnData.builder().
columnName(annotation.name()).
index(annotation.index()).
fieldName(field.getName()).
build();
list.add(columnData);
}
}
list.sort(Comparator.comparingInt(ColumnData :: getIndex));
return list;
}

7.实际使用

 public void export() throws Exception {
String path = "D:/mytest/mycase.xlsx";
new File(path).createNewFile();
EasyExcelHelper easyExcelHelper = new EasyExcelHelper(path); List<DemoVO> results=query();
//获取注解定义的标题
List<ColumnData> columnList = DynamicColumnUtil.conver(DemoVO.class);
//设置标题,数据
List<List<String>> titles = Lists.newArrayList();
columnList.stream().forEach(c -> titles.add(Lists.newArrayList(c.getColumnName()))); List<List<Object>> excelData = Lists.newArrayList(); //设置合并策略
int[] mergeColumnIndex = columnList.stream().mapToInt(ColumnData :: getIndex).toArray();
easyExcelHelper.mergeStrategy(1, mergeColumnIndex, 5); boolean isFirst = true;//第一次需要设置动态标题
for (DemoVO o : data) {
//对象转map
Map<String,String> oMap = BeanUtils.describe(o);
List<Object> baseList = Lists.newArrayList();
for (ColumnData columnData : columnList) {
//按照标题顺序设置值
baseList.add(oMap.get(columnData.getFieldName())); if (isFirst) {
for (String address : o.getAddress()) {
titles.add(address);
}
isFirst=false;
}
//设置值
for (String address : o.getAddress()) {
List<Object> row = Lists.newArrayList();
row.addAll(baseList);//公共部分
row.add(address));
excelData.add(row);
} }
easyExcelHelper.createSheet(0, "测试", titles, excelData);
easyExcelHelper.getExcelWriter().finish();
}

EasyExcelHelper实际是以上Eaxyexcel功能的封装,部分代码上面均有展示,下方直接给出,方便大家参考:



import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import lombok.Data;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress; import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream; /**
* @author penggaofeng
* @date 2021/1/25 13:41
* @description:1.辅助实现动态标题;2.实现行数据合并
* @modified By:
* @version: 1.0
*/
@Data
public class EasyExcelHelper { private ExcelWriter excelWriter; private ExcelMergeStrategy excelMergeStrategy; public EasyExcelHelper(String path) {
excelWriter = EasyExcel.write(path).build();
} /**
* 动态插入
*
* @param sheetStartNum
* @param sheetName sheet名称
* @param headList 动态标题,格式:List<List<String>>
* @param list 数据
*/
public void createSheet(Integer sheetStartNum, String sheetName, List headList, List list) {
WriteSheet sheet;
if (Objects.isNull(excelMergeStrategy)) {
sheet = EasyExcel.writerSheet(sheetStartNum, sheetName).
registerWriteHandler(defaultStyle()).
registerWriteHandler(new CustomerColumnWidthStyleStrategy()).build();
} else {
sheet = EasyExcel.writerSheet(sheetStartNum, sheetName).
registerWriteHandler(defaultStyle()).
registerWriteHandler(excelMergeStrategy).
registerWriteHandler(new CustomerColumnWidthStyleStrategy()).build();
} WriteTable table = new WriteTable();
table.setTableNo(0);
table.setHead(headList);
excelWriter.write(list, sheet, table);
} /**
* 创建合并策略
*
* @param mergeRowIndex 合并开始行 (从1开始,忽略标题)
* @param mergeColumnIndex 合并列(列下标,从0开始)
* @param eachRow 合并间隔,指定几条数据之间合并
*/
public void mergeStrategy(int mergeRowIndex, int[] mergeColumnIndex, int eachRow) {
excelMergeStrategy = new ExcelMergeStrategy(mergeRowIndex, mergeColumnIndex, eachRow);
} /**
* 设置头部样式
*
* @return
*/
private HorizontalCellStyleStrategy defaultStyle() {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
//头部样式
headWriteCellStyle.setFillForegroundColor(IndexedColors.LIME.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 12);
headWriteFont.setFontName("Arial");
headWriteFont.setBold(Boolean.FALSE);
headWriteFont.setColor(IndexedColors.WHITE.getIndex());
headWriteCellStyle.setWriteFont(headWriteFont);
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headWriteCellStyle.setWrapped(Boolean.FALSE);
headWriteCellStyle.setBorderRight(BorderStyle.NONE);
headWriteCellStyle.setBorderLeft(BorderStyle.NONE);
//内容样式
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
} /**
* 列宽设置
* memo:当数据不存在标题时,defaultStyle头部样式将失效,该设置将会生效
*/
private class CustomerColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { private static final int MAX_COLUMN_WIDTH = 7000; @Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) {
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), MAX_COLUMN_WIDTH);
} } /**
* 相同值合并策略
*/
public class ExcelMergeStrategy implements CellWriteHandler {
/**
* 合并起始行
*/
private int mergeRowIndex; /**
* 多少行合并一次
*/
private int eachRow;
/**
* 合并字段的下标
*/
private int[] mergeColumnIndex; public ExcelMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex, int eachRow) {
if (mergeRowIndex < 0) {
throw new IllegalArgumentException("mergeRowIndex must be greater than 0");
}
if (eachRow < 0) {
throw new IllegalArgumentException("eachRow must be greater than 0");
}
this.mergeRowIndex = mergeRowIndex;
this.mergeColumnIndex = mergeColumnIndex;
this.eachRow = eachRow;
} @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
int curRowIndex = cell.getRowIndex();
//当前列
int curColIndex = cell.getColumnIndex();
//合并条件:
//1.当前行>合并起始行,默认标题行(0)不参加合并
//2.间隔行(eachRow)的上下两条不参加合并
//2.1间隔行(eachRow)==0时,不设置间隔
if (isMerge(curRowIndex)) {
IntStream.range(0, mergeColumnIndex.length).anyMatch(i -> {
if (curColIndex == mergeColumnIndex[i]) {
mergeWithPrevRow(writeSheetHolder, cellData, cell, curRowIndex, curColIndex);
return true;
}
return false;
});
}
} @Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } /**
* 判断是否合并
* 1.当前位置必须大于开始位置:curRowIndex > mergeRowIndex
* 2.根据eachRow 判断数据分割的间隔
* 2.1如果根据eachRow=0,默认不合并
* 2.2如果1如果根据eachRow>0,分割后的第一条数据不会与之前的合并:(curRowIndex-mergeRowIndex)%eachRow==0
*
* @return
*/
private boolean isMerge(Integer curRowIndex) { if ((curRowIndex > mergeRowIndex) && eachRow > 0) {
if ((curRowIndex - mergeRowIndex) % eachRow == 0) {
return false;
}
return true;
} return false;
} private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, int curRowIndex, int curColIndex) {
//获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
Object curData = cellData.getType() == CellDataTypeEnum.STRING ? cellData.getStringValue() : cellData.getNumberValue();
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
preCell.getNumericCellValue();
// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
if (Objects.equals(curData, preData)) {
Sheet sheet = writeSheetHolder.getSheet();
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 若上一个单元格未被合并,则新增合并单元
if (!isMerged) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
}
} }

EasyExcel导出小结:动态标题、标题格式、相同值合并的更多相关文章

  1. 如何使用DAX函数解决动态图表标题

    您可能知道,Power BI中的图表(以及许多其他可视化)具有可以设置为任何静态文本的标题.您可以通过选择图表,转到“可视化对象”窗格中的“格式”选项卡,然后更改“标题”部分中的属性(如下所示)来完成 ...

  2. Format a Business Object Caption 设置业务对象标题的格式

    In this lesson, you will learn how to format the caption of a detail form that displays a business o ...

  3. Pytest 系列(28)- 参数化 parametrize + @allure.title() 动态生成标题

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 参数化 @pytest.ma ...

  4. 分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility (续3篇-导出时动态生成多Sheet EXCEL)

    ExcelUtility 类库经过我(梦在旅途)近期不断的优化与新增功能,现已基本趋向稳定,功能上也基本可以满足绝大部份的EXCEL导出需求,该类库已在我们公司大型ERP系统全面使用,效果不错,今天应 ...

  5. Au cs6怎样才能导入和导出m4a或者就是aac格式的文件呢?

        [求解]Au cs6怎样才能导入和导出m4a或者就是aac格式的文件呢?   汉化版;解决发法----首选项------常规------媒体与暂存盘-----动态链接媒体下面的启动DLMS格式 ...

  6. FineReader Mac如何设置参数让导出为DOCX/RTF/ODT格式

    Mac版ABBYY FineReader OCR文字识别软件识别文档之后,可以将已识别的文本保存到文件中,还可以通过电子邮件发送输出格式受FineReader支持的已识别文本,了解了ABBYY Fin ...

  7. easyExcel导出excel的简单使用

    easyExcel导出excel的简单使用 Java解析.生成Excel比较有名的框架有Apache poi.jxl.但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定 ...

  8. Excel模板导出之动态导出

    说明 目前Magicodes.IE已支持Excel模板导出时使用JObject.Dictionary和ExpandoObject来进行动态导出,具体使用请看本篇教程. 本功能的想法.部分实现初步源于a ...

  9. 复杂的POI导出Excel表格(多行表头、合并单元格)

    poi导出excel有两种方式: 第一种:从无到有的创建整个excel,通过HSSFWorkbook,HSSFSheet HSSFCell, 等对象一步一步的创建出工作簿,sheet,和单元格,并添加 ...

随机推荐

  1. Spring Boot中初始化资源的几种方式

    CommandLineRunner 定义初始化类 MyCommandLineRunner 实现 CommandLineRunner接口,并实现它的 run()方法,在该方法中编写初始化逻辑 注册成Be ...

  2. 第四章节 BJROBOT 线速度校正 【ROS全开源阿克曼转向智能网联无人驾驶车】

    BJROBOT 线速度校正   1.把小车平放在地板上,用卷尺作为测量刻度,选取车头或者车尾处作为小车的起点, 打开资料里的虚拟机,打开一个终端 ssh 过去主控端启动 roslaunch znjro ...

  3. 如何利用Typora编写博客,快速发布到多平台?

    在不同的平台发布同样的文章,最让人头疼的就是图片问题,如果要手动一个个去重新上传,耗时耗力,还容易搞错.下面分享的方法,可以将Typora编写的文章快速发布到CSDN.微信公众号.博客园.简书等平台. ...

  4. Hive 中的四种排序详解,再也不会混淆用法了

    Hive 中的四种排序 排序操作是一个比较常见的操作,尤其是在数据分析的时候,我们往往需要对数据进行排序,hive 中和排序相关的有四个关键字,今天我们就看一下,它们都是什么作用. 数据准备 下面我们 ...

  5. MP(MyBatis-Plus)实现乐观锁更新功能

    实现步骤 step1:添加乐观锁拦截器 MP的其他拦截器功能可以参考官网 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { ...

  6. Liunx运维(十)-网络管理命令

    文档目录: 一.ifconfig:配置或显示网络接口信息 二.ifup:激活网络接口 三.ifdown:禁用网络接口 四.route:显示或管理理由表 五.arp:管理系统的arp缓存 六.ip:网络 ...

  7. memcached的安装教程

    在windows系统上安装memcached 下载安装软件memcached-1.2.6-win32-bin.zip 解压该文件把memcached.exe 拷贝到你的 apache同一目录 安装该m ...

  8. react项目中实现搜索关键字呈现高亮状态(一)

    最近有个需求,在一个react项目中,实现搜索关键字呈现高亮状态.这个在普通的html文件中还好操作些,在react项目中有点懵逼了,因为react项目中很少操作dom,有点无从下手.但最后还是实现了 ...

  9. python函数2-函数参数

    rgb法则:

  10. 【Linux】同时插入多行数据到文本文件中

    如果想同时插入多行数据到指定的文本中,可以用下面的命令EOF cat >> test.txt <<EOF 1234 5678 GOOD EOF 将上述3行插入到 test.tx ...