随笔记录通过easy excel实现导入导出
第一步:导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.0</version>
</dependency>
第二步:创建导入导出工具类
public class ExcelUtil {
/**
* 导出数据为excel文件
*
* @param filename 文件名称
* @param sheetName sheet名称
* @param dataResult 集合内的bean对象类型要与clazz参数一致
* @param clazz 集合内的bean对象类型要与clazz参数一致
* @param response HttpServlet响应对象
*/
//有实体对象的导出方式
public static void export(String filename,String sheetName, List<?> dataResult, Class<?> clazz, HttpServletResponse response) {
response.setStatus(200);
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
OutputStream outputStream = null;
ExcelWriter excelWriter = null;
try {
if (StringUtil.isEmpty(filename)) {
throw new RuntimeException("'filename' 不能为空");
}
String fileName = filename.concat(".xls");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
outputStream = response.getOutputStream();
// 根据不同的策略生成不同的ExcelWriter对象
if (dataResult == null){
excelWriter = getTemplateExcelWriter(outputStream);
} else {
excelWriter = getExportExcelWriter(outputStream);
}
//获取表头个数
int last = clazz.getDeclaredFields().length;
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).head(clazz)
.relativeHeadRowIndex(1)
.registerWriteHandler(new MonthSheetWriteHandler(sheetName,last))//设置大标题名称及其单元格合并
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//自适应列宽
.build();
// 写出数据
excelWriter.write(dataResult,writeSheet);
} catch (Exception e) {
log.error("导出excel数据异常:", e);
throw new RuntimeException(e);
} finally {
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
log.error("导出数据关闭流异常", e);
}
}
}
}
//没有实体对象的导出方式
public static void export(String filename,String sheetName,String headName, List<?> dataResult, List<List<String>> head, HttpServletResponse response) {
response.setStatus(200);
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
OutputStream outputStream = null;
ExcelWriter excelWriter = null;
try {
if (StringUtil.isEmpty(filename)) {
throw new RuntimeException("'filename' 不能为空");
}
String fileName = filename.concat(".xls");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
outputStream = response.getOutputStream();
// 根据不同的策略生成不同的ExcelWriter对象
if (dataResult == null){
excelWriter = getTemplateExcelWriter(outputStream);
} else {
excelWriter = getExportExcelWriter(outputStream);
}
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).head(head)
.relativeHeadRowIndex(1)
.registerWriteHandler(new MonthSheetWriteHandler(headName,head.size()))//设置大标题名称及其单元格合并
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//自适应列宽
.build();
// 写出数据
excelWriter.write(dataResult,writeSheet);
} catch (Exception e) {
log.error("导出excel数据异常:", e);
throw new RuntimeException(e);
} finally {
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
log.error("导出数据关闭流异常", e);
}
}
}
}
/**
* 根据不同策略生成不同的ExcelWriter对象, 可根据实际情况修改
* @param outputStream 数据输出流
* @return 模板下载ExcelWriter对象
*/
private static ExcelWriter getTemplateExcelWriter(OutputStream outputStream){
return EasyExcel.write(outputStream)
//.registerWriteHandler(new CommentWriteHandler()) //增加批注策略
//.registerWriteHandler(new CustomSheetWriteHandler()) //增加下拉框策略
.registerWriteHandler(getStyleStrategy()) //字体居中策略
.build();
}
/**
* 根据不同策略生成不同的ExcelWriter对象, 可根据实际情况修改
* @param outputStream 数据输出流
* @return 数据导出ExcelWriter对象
*/
private static ExcelWriter getExportExcelWriter(OutputStream outputStream){
return EasyExcel.write(outputStream)
.registerWriteHandler(getStyleStrategy()) //字体居中策略
.build();
}
/**
* 设置表格内容居中显示策略
* @return
*/
private static HorizontalCellStyleStrategy getStyleStrategy(){
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.index);
//设置头字体
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)10);
headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont);
headWriteFont.setFontName("宋体");
//设置头居中
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
// 内容策略
WriteCellStyle writeCellStyle = new WriteCellStyle();
// 设置内容水平居中
writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
//垂直居中,水平居中
writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
writeCellStyle.setBorderLeft(BorderStyle.THIN);
writeCellStyle.setBorderTop(BorderStyle.THIN);
writeCellStyle.setBorderRight(BorderStyle.THIN);
writeCellStyle.setBorderBottom(BorderStyle.THIN);
writeCellStyle.setWriteFont(headWriteFont);
//设置 自动换行
//contentWriteCellStyle.setWrapped(true);
return new HorizontalCellStyleStrategy(headWriteCellStyle, writeCellStyle);
}
/**
* 根据Excel模板,批量导入数据
* @param file 导入的Excel
* @param clazz 解析的类型
* @return 解析完成的数据
*/
public static List<?> importExcel(MultipartFile file, Class<?> clazz){
if (file == null || file.isEmpty()){
throw new RuntimeException("没有文件或者文件内容为空!");
}
List<Object> dataList = null;
BufferedInputStream ipt = null;
try {
InputStream is = file.getInputStream();
// 用缓冲流对数据流进行包装
ipt = new BufferedInputStream(is);
// 数据解析监听器
ExcelListener listener = new ExcelListener();
// 读取数据
EasyExcel.read(ipt, clazz,listener).headRowNumber(2).sheet().doRead();
// 获取去读完成之后的数据
dataList = listener.getDatas();
} catch (Exception e){
log.error(String.valueOf(e));
throw new RuntimeException("数据导入失败!" + e);
}
return dataList;
}
}
第三步:表格头部设置
public class MonthSheetWriteHandler implements SheetWriteHandler {
private String titleName="";
private int last=0;
public MonthSheetWriteHandler(String titleName,int last){
this.titleName=titleName;
this.last=last;
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
Workbook workbook = writeWorkbookHolder.getWorkbook();
Sheet sheet = workbook.getSheetAt(0);
Row row1 = sheet.createRow(0);
row1.setHeight((short) 800);
Cell cell = row1.createCell(0);
//设置标题
cell.setCellValue(titleName+"表");
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setAlignment(HorizontalAlignment.CENTER);
Font font = workbook.createFont();
font.setBold(true);
font.setFontHeight((short) 400);
font.setFontName("宋体");
cellStyle.setFont(font);
cell.setCellStyle(cellStyle);
sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 0, 0, last));
}
}
第四步:创建导入的监听器
public class ExcelListener extends AnalysisEventListener {
//可以通过实例获取该值
private List<Object> datas = new ArrayList<>();
@Override
public void invoke(Object o, AnalysisContext analysisContext) {
datas.add(o);//数据存储到list,供批量处理,或后续自己业务逻辑处理。
doSomething(o);//根据自己业务做处理
}
private void doSomething(Object object) {
//1、入库调用接口
}
public List<Object> getDatas() {
return datas;
}
public void setDatas(List<Object> datas) {
this.datas = datas;
}
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// datas.clear();//解析结束销毁不用的资源
}
}
第五步:service层调用导入导出方法
//导出
/**
fileName:文件名称
sheetName:sheet名称
exportList:数据源
HouseExportVO.class:实体类对象,与数据源对应
response:HttpServlet响应对象
*/
//ExcelUtil.export(fileName,sheetName,exportList, HouseExportVO.class, response); 有实体类对象的调用方式
/**
fileName:文件名称
sheetName:sheet名称
headName:头部标题名称
dataList:数据源组装
headList:动态头部列组装
response:HttpServlet响应对象
*/
//ExcelUtil.export(fileName,sheetName,headName,dataList, headList, response);动态列调用方式
//导入
//读取文件,获取数据
/**
multipartFile:导入的文件,由前端传入
HouseImportExcelDTO.class:接受数据所对应的实体对象
读取到的数据源:excelData
*/
//List<?> excelData = ExcelUtil.importExcel(multipartFile, HouseImportExcelDTO.class);
自此通用的easyExcel导入导出就完成了,具体导出的表格样式自行设置!
如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否
我正在尝试创建一个与compass一起使用的本地配置文件,这样我们就可以处理开发人员机器上的不同导入路径。到目前为止,我已经尝试将文件导入到异常block中,以防它不存在,然后进一步使用该变量:local_config.rbVENV_FOLDER='venv'config.rbVENV_FOLDER='.'beginrequire'local_config.rb'rescueLoadErrorendputsVENV_FOLDER通常我是一名Python开发人员,所以我希望导入将VENV_FOLDER的值更改为venv,但它仍然是。之后。有没有一种方法可以导入local_config.r
最好用一个例子来解释:文件1.rb:deffooputs123end文件2.rb:classArequire'file1'endA.new.foo将给出错误“':调用了私有(private)方法'foo'”。我可以通过执行A.new.send("foo")来解决这个问题,但是有没有办法公开导入的方法?编辑:澄清一下,我没有混淆include和require。另外,我不能使用正常包含的原因(正如许多人正确指出的那样)是因为这是元编程设置的一部分。我需要允许用户在运行时添加功能;例如,他可以说“run-this-app--includefile1.rb”,应用程序的行为将根据他在file1
尝试在我的Rails应用程序中导入CSV文件时,出现错误UTF-8中的无效字节序列。一切正常,直到我添加了一个gsub方法来将其中一个CSV列与我的数据库中的一个字段进行比较。当我导入CSV文件时,我想检查每一行的地址是否包含在特定客户端的不同地址数组中。我有一个带有alt_addresses属性的客户端模型,其中包含客户端地址的几种不同可能格式。然后我有一个引用模型(如果您熟悉本地SEO,您就会知道这个术语)。引用模型没有地址字段,但它有一个nap_correct?字段(NAP代表“姓名”、“地址”、“电话号码”)。如果CSV行的名称、地址和电话号码与我在该客户的数据库中拥有的相同,
如何将Confluence的“空间”导出为pdf文件?看起来Confluence5.0可能仍然支持使用XML-RPCAPI。不过,我找不到调用什么的示例。https://developer.atlassian.com/display/CONFDEV/Remote+API+Specification+for+PDF+Export#RemoteAPISpecificationforPDFExport-XML-RPCInformation该链接表示调用应以pdfexport为前缀,但没有列出任何调用或给出示例。 最佳答案 这可以使用Bob
我在bitbucket上创建了一个私有(private)git存储库并提交了代码。现在我想导出所有(提交、代码、历史记录)并将其导入github上的gitrepo。有没有办法做到这一点?谢谢 最佳答案 在本地检查所有内容到您的计算机和gitpull。创建一个github存储库将此存储库添加为您的第二个远程(“使用gitremote添加githubURL”)推送到第二个Remote 关于ruby-git:从bitbucket导出并导入github(带提交),我们在StackOverflow
当使用RyanBates的Railscasts第362集关于导出到Excel(https://github.com/railscasts/362-exporting-csv-and-excel)的示例应用程序时,我注意到Excel2010(在Windows上)在打开.xls文件时给我一条警告消息我使用“下载为Excel”链接下载的文件。警告内容如下:“您尝试打开的文件...的格式与文件扩展名指定的格式不同。打开文件前请确认文件未损坏且来源可靠。是否要打开现在存档吗?”当我单击"is"时,我可以很好地打开文件。在使用Excel2011(在Mac上)时,我什至没有收到警告消息。但我希望能够
我正在尝试将数据从我的模型导出到Excel电子表格。我见过3种方式使用我不明白如何使用的电子表格gem,我看到的示例是写入本地文件,但我正在寻找每次用户点击链接时都会生成一个文件。创建一个名为export的方法,并在那里运行查询,然后在我看来创建一个export.xls文件,然后该文件创建我想将表格导出到excel文件,但是这种做法不允许我创建多张纸。学习了本教程,http://oldwiki.rubyonrails.org/rails/pages/HowToExportToExcel,但是这里没有显示如何将链接放在View中,在我看来我在路由中遗漏了一些东西,我可以提供github以
这是我的主要rake文件subrake='subrake'task:init=>[subrake]do#callsubrake.buildendimportsubrake我看到有关上述步骤如何工作的文档,但我无法弄清楚如何调用其他subrake文件中的任务。顺便说一句,这些任务可能与我的同名,这是个问题吗? 最佳答案 我想我回答晚了,但几分钟前我也有同样的问题。因此该解决方案可能对某些人有用。Rakefile.rbsubrake='subrake'task:default=>:inittask:init=>["#{subrake}:
我正在尝试向orientdbgem添加一些基本的rake任务,这将允许我创建数据库、创建数据库迁移和迁移数据库——类似于rails迁移。当我在本地执行rake任务时,我可以使用db:settings、db:create和db:create_migration,但是在将它们放入gem之后,我不知道如何从Sinatra访问它们使用“rake”时的应用。我有一种感觉,我要么是a)没有正确地组织gem中的文件和/或b)没有从Sinatra应用程序正确地调用东西。我的fork存储库的当前状态是https://github.com/ricaurte/orientdb-jruby我将任务文件放在li