一、导出操作
1、简单数据导出
1.1 导出示例
java">
@SneakyThrows
@GetMapping ( "/exportReport" )
public void exportReport ( HttpServletResponse response) { String fileNameOri = "销售信息报表.xlsx" ; String fileName = URLEncoder . encode ( fileNameOri, "UTF-8" ) ; String contentType = MediaTypeFactory . getMediaType ( fileName) . map ( MimeType :: toString ) . orElse ( "application/vnd.ms-excel" ) ; response. setContentType ( contentType) ; response. setCharacterEncoding ( "utf-8" ) ; response. setHeader ( "Content-Disposition" , "attachment;filename=" + fileName) ; WriteCellStyle headWriteCellStyle = new WriteCellStyle ( ) ; headWriteCellStyle. setFillForegroundColor ( IndexedColors . WHITE. getIndex ( ) ) ; headWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; WriteFont headWriteFont = new WriteFont ( ) ; headWriteFont. setFontHeightInPoints ( ( short ) 11 ) ; headWriteCellStyle. setWriteFont ( headWriteFont) ; WriteCellStyle contentWriteCellStyle = new WriteCellStyle ( ) ; WriteFont contentWriteFont = new WriteFont ( ) ; contentWriteFont. setFontHeightInPoints ( ( short ) 10 ) ; contentWriteCellStyle. setWriteFont ( contentWriteFont) ; contentWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy ( headWriteCellStyle, contentWriteCellStyle) ; List < WebSalesReportExportVO > webSalesReportExportVOS = new ArrayList < > ( ) ; EasyExcel . write ( response. getOutputStream ( ) , WebSalesReportExportVO . class ) . autoCloseStream ( Boolean . FALSE) . excelType ( ExcelTypeEnum . XLSX) . registerWriteHandler ( horizontalCellStyleStrategy) . registerWriteHandler ( new LongestMatchColumnWidthStyleStrategy ( ) ) . sheet ( "销售信息" ) . doWrite ( webSalesReportExportVOS) ;
}
1.2 导出实体
java">@Data
public class WebSalesReportExportVO { @ExcelProperty ( value = "序号" ) private Integer rowNum; @JsonFormat ( pattern = "yyyy-MM-dd" , timezone = "GMT+8" ) @DateTimeFormat ( "yyyy-MM-dd" ) @ExcelProperty ( "日期" ) private Date sendGoodsDate; @ExcelProperty ( "占用天数" ) private Integer moneyFundDay; @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( "毛利率%" ) private String dayProfitRatio; }
2、带下拉列表的模板导出
2.1 导出示例
java">
@SneakyThrows @ApiOperation ( "下载订单信息模板" ) @GetMapping ( "/downloadTemp" ) public void downloadTemp ( HttpServletResponse response) { String fileNameOri = "订单信息模板.xlsx" ; String fileName = URLEncoder . encode ( fileNameOri, "UTF-8" ) ; String contentType = MediaTypeFactory . getMediaType ( fileName) . map ( MimeType :: toString ) . orElse ( "application/vnd.ms-excel" ) ; response. setContentType ( contentType) ; response. setCharacterEncoding ( "utf-8" ) ; response. setHeader ( "Content-Disposition" , "attachment;filename=" + fileName) ; WriteCellStyle headWriteCellStyle = new WriteCellStyle ( ) ; headWriteCellStyle. setFillForegroundColor ( IndexedColors . WHITE. getIndex ( ) ) ; headWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; WriteFont headWriteFont = new WriteFont ( ) ; headWriteFont. setFontHeightInPoints ( ( short ) 11 ) ; headWriteCellStyle. setWriteFont ( headWriteFont) ; WriteCellStyle contentWriteCellStyle = new WriteCellStyle ( ) ; WriteFont contentWriteFont = new WriteFont ( ) ; contentWriteFont. setFontHeightInPoints ( ( short ) 10 ) ; contentWriteCellStyle. setWriteFont ( contentWriteFont) ; contentWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStytleStrategy ( headWriteCellStyle, contentWriteCellStyle) ; TmpVO tmpVO = new TmpVO ( ) ; tmpVO. setOrderNo ( "示例" ) ; tmpVO. setProductCode ( "11148000001" ) ; tmpVO. setBatch ( "批次" ) ; tmpVO. setProductionDate ( new Date ( ) ) ; List < TmpVO > dataList = Collections . singletonList ( tmpVO) ; EasyExcel . write ( response. getOutputStream ( ) , TmpVO . class ) . autoCloseStream ( Boolean . FALSE) . excelType ( ExcelTypeEnum . XLSX) . registerWriteHandler ( horizontalCellStyleStrategy) . registerWriteHandler ( new LongestMatchColumnWidthStyleStrategy ( ) ) . registerWriteHandler ( new SalesOrderExcelWriteHandler ( ) ) . sheet ( "订单信息" ) . doWrite ( dataList) ; }
2.2 导出模板实体
java">@Data
@ColumnWidth ( 15 )
public class TmpVO { @NotBlank ( message = "商品编码不能为空" ) @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "*商品编码" , index = 0 ) private String productCode; @NotBlank ( message = "订单号不能为空" ) @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "*订单号" , index = 2 ) private String orderNo; @NotBlank ( message = "批次不能为空" ) @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "*批次" , index = 3 ) private String batch; @JsonFormat ( timezone = "GMT+8" , pattern = "yyyy-MM-dd" ) @DateTimeFormat ( "yyyy-MM-dd" )
@ExcelProperty ( value = "生产日期" , index = 4 ) private Date productionDate;
}
2.2 下拉列表数据处理(SalesOrderExcelWriteHandler)
2.2.1 简单的下拉(数据量小)
java">import cn. hutool. extra. spring. SpringUtil ;
import com. alibaba. excel. write. handler. SheetWriteHandler ;
import com. alibaba. excel. write. metadata. holder. WriteSheetHolder ;
import com. alibaba. excel. write. metadata. holder. WriteWorkbookHolder ;
import org. apache. poi. ss. usermodel. DataValidation ;
import org. apache. poi. ss. usermodel. DataValidationConstraint ;
import org. apache. poi. ss. usermodel. DataValidationHelper ;
import org. apache. poi. ss. usermodel. Sheet ;
import org. apache. poi. ss. util. CellRangeAddress ;
import org. apache. poi. ss. util. CellRangeAddressList ;
import org. springframework. util. CollectionUtils ; import java . util. HashMap ;
import java . util. List ;
import java . util. stream. Collectors ;
public class SalesOrderExcelWriteHandler implements SheetWriteHandler { @Override public void beforeSheetCreate ( WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { } @Override public void afterSheetCreate ( WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { Sheet sheet = writeSheetHolder. getSheet ( ) ; DataValidationHelper helper = sheet. getDataValidationHelper ( ) ; List < HashMap < String , Object > > unitByNames = new ArrayList < > ( ) ; if ( ! CollectionUtils . isEmpty ( unitByNames) ) { List < String > unitNames = unitByNames. stream ( ) . map ( stringObjectHashMap -> stringObjectHashMap. get ( "name" ) . toString ( ) ) . collect ( Collectors . toList ( ) ) ; String [ ] unitNameArray = unitNames. toArray ( new String [ 0 ] ) ; CellRangeAddress areaAddr = new CellRangeAddress ( 1 , 1000 , 6 , 6 ) ; CellRangeAddressList areaRangeList = new CellRangeAddressList ( ) ; areaRangeList. addCellRangeAddress ( areaAddr) ; DataValidationConstraint areaConstraint = helper. createExplicitListConstraint ( unitNameArray) ; DataValidation areaValidation = helper. createValidation ( areaConstraint, areaRangeList) ; sheet. addValidationData ( areaValidation) ; } }
}
2.2.2 复杂的下拉(数据量大,采用隐藏sheet页方式)
java">import cn. hutool. extra. spring. SpringUtil ;
import com. alibaba. excel. write. handler. SheetWriteHandler ;
import com. alibaba. excel. write. metadata. holder. WriteSheetHolder ;
import com. alibaba. excel. write. metadata. holder. WriteWorkbookHolder ;
import com. baomidou. mybatisplus. core. conditions. query. LambdaQueryWrapper ;
import org. apache. poi. ss. usermodel. * ;
import org. apache. poi. ss. util. CellRangeAddressList ;
import org. apache. poi. xssf. usermodel. XSSFDataValidationConstraint ; import java . util. List ;
import java . util. stream. Collectors ;
public class SalesOrderExcelWriteHandler implements SheetWriteHandler { @Override public void beforeSheetCreate ( WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { } @Override public void afterSheetCreate ( WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { Sheet sheet = writeSheetHolder. getSheet ( ) ; DataValidationHelper helper = sheet. getDataValidationHelper ( ) ; List < Estate > estateList = new ArrayList < > ( ) ; List < String > estateName = estateList. stream ( ) . map ( Estate :: getEstateName ) . collect ( Collectors . toList ( ) ) ; String [ ] estateNameArray = estateName. toArray ( new String [ 0 ] ) ; Workbook workbook = writeWorkbookHolder. getWorkbook ( ) ; if ( estateNameArray. length > 0 ) { String estateHiddenName = "下拉信息" ; Sheet estateHidden = workbook. createSheet ( estateHiddenName) ; Cell estateCell = null ; for ( int i = 0 , length = estateNameArray. length; i < length; i++ ) { String name = estateNameArray[ i] ; Row row = estateHidden. createRow ( i) ; estateCell = row. createCell ( 0 ) ; estateCell. setCellValue ( name) ; } Name estateNamedCell = workbook. createName ( ) ; estateNamedCell. setNameName ( estateHiddenName) ; Integer estateNameFormulaName = estateNameArray. length; if ( estateNameArray. length == 0 ) { estateNameFormulaName = 1 ; } estateNamedCell. setRefersToFormula ( estateHiddenName + "!$A$1:$A$" + estateNameFormulaName) ; XSSFDataValidationConstraint estateConstraint = new XSSFDataValidationConstraint ( DataValidationConstraint. ValidationType . LIST, estateNamedCell. getRefersToFormula ( ) ) ; CellRangeAddressList estateAddr = new CellRangeAddressList ( 1 , 1000 , 8 , 8 ) ; DataValidation estateValidation = helper. createValidation ( estateConstraint, estateAddr) ; workbook. setSheetHidden ( workbook. getSheetIndex ( estateHidden) , false ) ; sheet. addValidationData ( estateValidation) ; } List < HashMap < String , Object > > unitByNames = new ArrayList < > ( ) ; if ( ! CollectionUtils . isEmpty ( unitByNames) ) { List < String > unitNames = unitByNames. stream ( ) . map ( stringObjectHashMap -> stringObjectHashMap. get ( "name" ) . toString ( ) ) . collect ( Collectors . toList ( ) ) ; String [ ] unitNameArray = unitNames. toArray ( new String [ 0 ] ) ; CellRangeAddress areaAddr = new CellRangeAddress ( 1 , 1000 , 6 , 6 ) ; CellRangeAddressList areaRangeList = new CellRangeAddressList ( ) ; areaRangeList. addCellRangeAddress ( areaAddr) ; DataValidationConstraint areaConstraint = helper. createExplicitListConstraint ( unitNameArray) ; DataValidation areaValidation = helper. createValidation ( areaConstraint, areaRangeList) ; sheet. addValidationData ( areaValidation) ; } }
}
3、自定义标题导出
3.1 导出示例
java">
@SneakyThrows @Override public R exportFeePayTmp ( FeePayTmpPO feePayTmpPO) { String dateTitle = "" 收费记录表"(截止到" + LocalDateTimeUtil . formatNormal ( LocalDateTime . now ( ) ) + ")" ; HttpServletResponse response = WebUtils . getResponse ( ) ; String fileNameOri = "收费记录.xlsx" ; String fileName = URLEncoder . encode ( fileNameOri, "UTF-8" ) ; String contentType = MediaTypeFactory . getMediaType ( fileName) . map ( MimeType :: toString ) . orElse ( "application/vnd.ms-excel" ) ; response. setContentType ( contentType) ; response. setCharacterEncoding ( "utf-8" ) ; response. setHeader ( "Content-Disposition" , "attachment;filename=" + fileName) ; try { List < PayTmpVO > payTmpVoList = new ArrayList < > ( ) ; WriteCellStyle headWriteCellStyle = new WriteCellStyle ( ) ; headWriteCellStyle. setFillForegroundColor ( IndexedColors . WHITE. getIndex ( ) ) ; headWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; WriteFont headWriteFont = new WriteFont ( ) ; headWriteFont. setFontHeightInPoints ( ( short ) 11 ) ; headWriteCellStyle. setWriteFont ( headWriteFont) ; WriteCellStyle contentWriteCellStyle = new WriteCellStyle ( ) ; WriteFont contentWriteFont = new WriteFont ( ) ; contentWriteFont. setFontHeightInPoints ( ( short ) 10 ) ; contentWriteCellStyle. setWriteFont ( contentWriteFont) ; contentWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy ( headWriteCellStyle, contentWriteCellStyle) ; List < FeeTempExcelExportVO > dataList = new ArrayList < > ( ) ; payTmpVoList. forEach ( feePayTmpVO -> { FeeTempExcelExportVO feeTempExcelExportVO = new FeeTempExcelExportVO ( ) ; BeanUtils . copyProperties ( feePayTmpVO, feeTempExcelExportVO) ; dataList. add ( feeTempExcelExportVO) ; } ) ; EasyExcel . write ( response. getOutputStream ( ) ) . autoCloseStream ( Boolean . FALSE) . registerWriteHandler ( horizontalCellStyleStrategy) . registerWriteHandler ( new FeeTempExcelExportVO. CustomizeColumnWidth ( ) ) . head ( FeeTempExcelExportVO . myriadPeopleHead ( title) ) . sheet ( "收费统计" ) . doWrite ( dataList) ; return null ; } catch ( Exception e) { e. printStackTrace ( ) ; response. reset ( ) ; response. setContentType ( "application/json" ) ; response. setCharacterEncoding ( "utf-8" ) ; } return R . failed ( "导出失败" ) ; }
3.2 导出模板实体(自定义标题处理)
java">import cn. hutool. core. date. DateUtil ;
import com. alibaba. excel. annotation. ExcelProperty ;
import com. alibaba. excel. annotation. write. style. ColumnWidth ;
import com. alibaba. excel. metadata. CellData ;
import com. alibaba. excel. metadata. Head ;
import com. alibaba. excel. write. metadata. holder. WriteSheetHolder ;
import com. alibaba. excel. write. style. column. AbstractColumnWidthStyleStrategy ;
import lombok. Data ;
import org. apache. poi. ss. usermodel. Cell ;
import org. apache. poi. ss. usermodel. CellStyle ;
import org. apache. poi. ss. usermodel. CellType ;
import java . io. Serializable ;
import java . util. ArrayList ;
import java . util. Date ;
import java . util. List ;
@Data
@ColumnWidth ( 15 )
public class FeeTempExcelExportVO implements Serializable { private static final long serialVersionUID = 1911240458081823913L ; @ExcelProperty ( value = "收款金额" , index = 0 ) private String price; @ExcelProperty ( value = "付款方式" , index = 1 ) private String payType; @ExcelProperty ( value = "应收" , index = 2 ) private String payPrice; @ExcelProperty ( value = "实收" , index = 3 ) private String realPrice; @ExcelProperty ( value = "备注" , index = 4 ) private String remark; public static class CustomizeColumnWidth extends AbstractColumnWidthStyleStrategy { @Override protected void setColumnWidth ( WriteSheetHolder writeSheetHolder, List < CellData > list, Cell cell, Head head, Integer integer, Boolean isHead) { CellStyle cellStyle = cell. getCellStyle ( ) ; if ( isHead && cell. getRowIndex ( ) == 1 ) { int columnWidth = cell. getStringCellValue ( ) . getBytes ( ) . length; int cellIndex = cell. getColumnIndex ( ) ; switch ( cellIndex) { case 0 : columnWidth = 25 ; break ; case 4 : columnWidth = 25 ; break ; default : columnWidth = 15 ; break ; } writeSheetHolder. getSheet ( ) . setColumnWidth ( cellIndex, columnWidth * 200 ) ; } else if ( ! isHead && cell. getRowIndex ( ) != 1 ) { int cellIndex = cell. getColumnIndex ( ) ; if ( cellIndex == 0 ) { cell. setCellValue ( DateUtil . format ( DateUtil . parse ( cell. getStringCellValue ( ) ) , "yyyy/MM/dd HH:mm:ss" ) ) ; cell. setCellType ( CellType . STRING) ; cellStyle. setDataFormat ( ( short ) 164 ) ; } if ( cellIndex == 5 ) { cell. setCellType ( CellType . STRING) ; cellStyle. setDataFormat ( ( short ) 49 ) ; } } if ( cell. getRowIndex ( ) == 0 ) { writeSheetHolder. getSheet ( ) . getRow ( 0 ) . setHeight ( ( short ) 600 ) ; } } } public static List < List < String > > myriadPeopleHead ( String title) { List < List < String > > list = new ArrayList < > ( ) ; List < String > head0 = new ArrayList < > ( ) ; head0. add ( title) ; head0. add ( "收款金额" ) ; List < String > head1 = new ArrayList < > ( ) ; head1. add ( title) ; head1. add ( "付款方式" ) ; List < String > head2 = new ArrayList < > ( ) ; head2. add ( title) ; head2. add ( "应收" ) ; List < String > head3 = new ArrayList < > ( ) ; head3. add ( title) ; head3. add ( "实收" ) ; List < String > head4 = new ArrayList < > ( ) ; head4. add ( title) ; head4. add ( "备注" ) ; list. add ( head0) ; list. add ( head1) ; list. add ( head2) ; list. add ( head3) ; list. add ( head4) ; return list; }
}
4、自定义表头导出
4.1 导出示例
java">
@SneakyThrows @Override public R statisticsAreaExport ( ) { String fileName = "estate类型统计表.xlsx" ; fileName = URLEncoder . encode ( fileName, "UTF-8" ) ; String contentType = MediaTypeFactory . getMediaType ( fileName) . map ( MimeType :: toString ) . orElse ( "application/vnd.ms-excel" ) ; HttpServletResponse response = WebUtils . getResponse ( ) ; response. setContentType ( contentType) ; response. setCharacterEncoding ( "utf-8" ) ; response. setHeader ( "Content-Disposition" , "attachment;filename=" + fileName) ; try { Map < String , List < EstateTypeAreaStatisticVO > > statisticsAreaAllMap = new HashMap < > ( ) ; WriteCellStyle headWriteCellStyle = new WriteCellStyle ( ) ; headWriteCellStyle. setFillForegroundColor ( IndexedColors . WHITE. getIndex ( ) ) ; headWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; WriteFont headWriteFont = new WriteFont ( ) ; headWriteFont. setFontHeightInPoints ( ( short ) 11 ) ; headWriteCellStyle. setWriteFont ( headWriteFont) ; WriteCellStyle contentWriteCellStyle = new WriteCellStyle ( ) ; WriteFont contentWriteFont = new WriteFont ( ) ; contentWriteFont. setFontHeightInPoints ( ( short ) 10 ) ; contentWriteCellStyle. setWriteFont ( contentWriteFont) ; contentWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy ( headWriteCellStyle, contentWriteCellStyle) ; List < List < String > > dataListResult = new ArrayList < > ( ) ; List < EstateTypeAreaStatisticVO > estateTypeAreaStatisticHeaderList = new ArrayList < > ( ) ; for ( Map. Entry < String , List < EstateTypeAreaStatisticVO > > entity : statisticsAreaAllMap. entrySet ( ) ) { String marketName = entity. getKey ( ) ; List < EstateTypeAreaStatisticVO > estateTypeAreaStatisticVOS = entity. getValue ( ) ; if ( estateTypeAreaStatisticHeaderList. size ( ) == 0 ) { estateTypeAreaStatisticHeaderList = estateTypeAreaStatisticVOS; } List < String > data = new ArrayList < > ( ) ; data. add ( marketName) ; for ( EstateTypeAreaStatisticVO estateTypeAreaStatisticVO : estateTypeAreaStatisticVOS) { String estateTypeName = estateTypeAreaStatisticVO. getEstateTypeName ( ) ; String buildingArea = estateTypeAreaStatisticVO. getBuildingArea ( ) ; String saledArea = estateTypeAreaStatisticVO. getSaledArea ( ) ; String canRentArea = estateTypeAreaStatisticVO. getCanRentArea ( ) ; String rentedArea = estateTypeAreaStatisticVO. getRentedArea ( ) ; String selfUseArea = estateTypeAreaStatisticVO. getSelfUseArea ( ) ; String backRentArea = estateTypeAreaStatisticVO. getBackRentArea ( ) ; String backRentedArea = estateTypeAreaStatisticVO. getBackRentedArea ( ) ; String canRentRatio = estateTypeAreaStatisticVO. getCanRentRatio ( ) ; String averageRent = estateTypeAreaStatisticVO. getAverageRent ( ) ; String propertyFee = estateTypeAreaStatisticVO. getPropertyFee ( ) ; if ( "公共" . equals ( estateTypeName) ) { data. add ( buildingArea) ; data. add ( estateTypeAreaStatisticVO. getUseArea ( ) ) ; } else { data. add ( buildingArea) ; data. add ( saledArea) ; data. add ( canRentArea) ; data. add ( rentedArea) ; data. add ( selfUseArea) ; data. add ( backRentArea) ; data. add ( backRentedArea) ; data. add ( canRentRatio) ; data. add ( averageRent) ; data. add ( propertyFee) ; } } dataListResult. add ( data) ; } EasyExcel . write ( response. getOutputStream ( ) ) . autoCloseStream ( Boolean . FALSE) . registerWriteHandler ( horizontalCellStyleStrategy) . registerWriteHandler ( new EstateTypeAreaStatisticExcelExportVO. CustomizeColumnWidth ( ) ) . head ( EstateTypeAreaStatisticExcelExportVO . myriadPeopleHead ( estateTypeAreaStatisticHeaderList) ) . sheet ( "物业类型统计表" ) . doWrite ( dataListResult) ; return null ; } catch ( Exception e) { e. printStackTrace ( ) ; response. reset ( ) ; response. setContentType ( "application/json" ) ; response. setCharacterEncoding ( "utf-8" ) ; } return R . failed ( "导出失败" ) ; }
4.2 导出模板实体(自定义标题处理)
java">import com. alibaba. excel. metadata. CellData ;
import com. alibaba. excel. metadata. Head ;
import com. alibaba. excel. write. metadata. holder. WriteSheetHolder ;
import com. alibaba. excel. write. style. column. AbstractColumnWidthStyleStrategy ;
import lombok. Data ;
import org. apache. poi. ss. usermodel. Cell ;
import org. apache. poi. ss. usermodel. CellStyle ; import java . util. ArrayList ;
import java . util. List ;
@Data
public class EstateTypeAreaStatisticExcelExportVO { public static class CustomizeColumnWidth extends AbstractColumnWidthStyleStrategy { @Override protected void setColumnWidth ( WriteSheetHolder writeSheetHolder, List < CellData > list, Cell cell, Head head, Integer integer, Boolean isHead) { CellStyle cellStyle = cell. getCellStyle ( ) ; if ( isHead && cell. getRowIndex ( ) == 1 ) { int columnWidth = cell. getStringCellValue ( ) . getBytes ( ) . length; int cellIndex = cell. getColumnIndex ( ) ; switch ( cellIndex) { case 0 : columnWidth = 25 ; break ; default : columnWidth = 15 ; break ; } writeSheetHolder. getSheet ( ) . setColumnWidth ( cellIndex, columnWidth * 200 ) ; } } } public static List < List < String > > myriadPeopleHead ( List < EstateTypeAreaStatisticVO > estateTypeAreaStatisticVOList) { String title = "estate类型报表" ; List < List < String > > list = new ArrayList < > ( ) ; List < String > head0 = new ArrayList < > ( ) ; head0. add ( title) ; head0. add ( "项目" ) ; list. add ( head0) ; estateTypeAreaStatisticVOList. forEach ( estateTypeAreaStatisticVO -> { String estateTypeName = estateTypeAreaStatisticVO. getEstateTypeName ( ) ; if ( "公共" . equals ( estateTypeName) ) { for ( int i = 0 ; i < 2 ; i++ ) { List < String > head1 = new ArrayList < > ( ) ; head1. add ( title) ; head1. add ( estateTypeAreaStatisticVO. getEstateTypeName ( ) ) ; String headerName; switch ( i) { case 0 : headerName = "建筑面积(㎡)" ; break ; case 1 : headerName = "使用面积(㎡)" ; break ; default : headerName = "建筑面积(㎡)" ; break ; } head1. add ( headerName) ; list. add ( head1) ; } } else { for ( int i = 0 ; i < 10 ; i++ ) { List < String > head1 = new ArrayList < > ( ) ; head1. add ( title) ; head1. add ( estateTypeAreaStatisticVO. getEstateTypeName ( ) ) ; String headerName; switch ( i) { case 0 : headerName = "建筑面积(㎡)" ; break ; case 1 : headerName = "已售面积(㎡)" ; break ; case 2 : headerName = "自持可租总面积(㎡)" ; break ; case 3 : headerName = "自持已租总面积(㎡)" ; break ; case 4 : headerName = "自持自用总面积(㎡)" ; break ; case 5 : headerName = "已售返租面积(㎡)" ; break ; case 6 : headerName = "返租已租面积(㎡)" ; break ; case 7 : headerName = "可租出租率" ; break ; case 8 : headerName = "平均租金(元/年)" ; break ; case 9 : headerName = "物业费标准(元/年)" ; break ; default : headerName = "建筑面积(㎡)" ; break ; } head1. add ( headerName) ; list. add ( head1) ; } } } ) ; return list; }
}
4.3 参考内容实体
java">import io. swagger. annotations. ApiModelProperty ;
import lombok. Data ;
@Data
public class EstateTypeAreaStatisticVO { @ApiModelProperty ( value = "类型名称" ) private String estateTypeName; @ApiModelProperty ( value = "建筑面积" ) private String buildingArea; @ApiModelProperty ( value = "使用面积" ) private String useArea; @ApiModelProperty ( value = "已售面积" ) private String saledArea; @ApiModelProperty ( value = "可租总面积" ) private String canRentArea; @ApiModelProperty ( value = "已租总面积" ) private String rentedArea; @ApiModelProperty ( value = "自用总面积-未售+自用" ) private String selfUseArea; @ApiModelProperty ( value = "已售返租总面积" ) private String backRentArea; @ApiModelProperty ( value = "返租已租总面积" ) private String backRentedArea; @ApiModelProperty ( value = "可租出租率" ) private String canRentRatio; @ApiModelProperty ( value = "平均租金" ) private String averageRent; @ApiModelProperty ( value = "物业费标准" ) private String propertyFee;
}
5、合并列导出
5.1 导出示例
java">
@SneakyThrows @Override public void exportPayDetail ( ) { String fileName = "收费明细.xlsx" ; fileName = URLEncoder . encode ( fileName, "UTF-8" ) ; String contentType = MediaTypeFactory . getMediaType ( fileName) . map ( MimeType :: toString ) . orElse ( "application/vnd.ms-excel" ) ; HttpServletResponse response = WebUtils . getResponse ( ) ; response. setContentType ( contentType) ; response. setCharacterEncoding ( "utf-8" ) ; response. setHeader ( "Content-Disposition" , "attachment;filename=" + fileName) ; try { List < DetailVO > detailVOList = new ArrayList < > ( ) ; WriteCellStyle headWriteCellStyle = new WriteCellStyle ( ) ; headWriteCellStyle. setFillForegroundColor ( IndexedColors . WHITE. getIndex ( ) ) ; headWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; WriteFont headWriteFont = new WriteFont ( ) ; headWriteFont. setFontHeightInPoints ( ( short ) 11 ) ; headWriteCellStyle. setWriteFont ( headWriteFont) ; WriteCellStyle contentWriteCellStyle = new WriteCellStyle ( ) ; WriteFont contentWriteFont = new WriteFont ( ) ; contentWriteFont. setFontHeightInPoints ( ( short ) 10 ) ; contentWriteCellStyle. setWriteFont ( contentWriteFont) ; contentWriteCellStyle. setHorizontalAlignment ( HorizontalAlignment . CENTER) ; HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy ( headWriteCellStyle, contentWriteCellStyle) ; List < PayDetailExportVO > dataList = new ArrayList < > ( ) ; for ( DetailVO detailVO : detailVOList) { PayDetailExportVO p = new PayDetailExportVO ( ) ; BeanUtils . copyProperties ( detailVO, p) ; dataList. add ( p) ; } int [ ] mergeColumeIndex = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } ; int mergeRowIndex = 1 ; EasyExcel . write ( response. getOutputStream ( ) , DetailExportVO . class ) . autoCloseStream ( Boolean . FALSE) . registerWriteHandler ( horizontalCellStyleStrategy) . registerWriteHandler ( new MultiColumnMergeStrategyHandler ( mergeRowIndex, mergeColumeIndex) ) . sheet ( "收费明细" ) . doWrite ( dataList) ; } catch ( Exception e) { e. printStackTrace ( ) ; response. reset ( ) ; response. setContentType ( "application/json" ) ; response. setCharacterEncoding ( "utf-8" ) ; } }
5.2 导出模板实体
java">package com. entity4cloud. entity. admin. api. vo. excel ; import com. alibaba. excel. annotation. ExcelProperty ;
import com. alibaba. excel. annotation. format. DateTimeFormat ;
import com. alibaba. excel. annotation. write. style. ColumnWidth ;
import com. alibaba. excel. annotation. write. style. ContentStyle ;
import io. swagger. annotations. ApiModel ;
import lombok. Data ; import java . math. BigDecimal ;
import java . util. Date ;
@Data
@ColumnWidth ( 15 )
@ApiModel ( value = "收费单含明细导出数据" )
public class DetailExportVO { @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "合同名称" ) private String contractName; @DateTimeFormat ( "yyyy/MM/dd" ) @ExcelProperty ( value = "合同开始日期" ) private Date contractStartDate; @DateTimeFormat ( "yyyy/MM/dd" ) @ExcelProperty ( value = "合同结束日期" ) private Date contractEndDate;
}
5.3 合并列处理(MultiColumnMergeStrategyHandler)
java">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. holder. WriteSheetHolder ;
import com. alibaba. excel. write. metadata. holder. WriteTableHolder ;
import org. apache. poi. ss. usermodel. Cell ;
import org. apache. poi. ss. usermodel. CellType ;
import org. apache. poi. ss. usermodel. Row ;
import org. apache. poi. ss. usermodel. Sheet ;
import org. apache. poi. ss. util. CellRangeAddress ;
import java . util. List ;
public class MultiColumnMergeStrategyHandler implements CellWriteHandler { private int [ ] mergeColumnIndex; private int mergeRowIndex; public MultiColumnMergeStrategyHandler ( ) { } public MultiColumnMergeStrategyHandler ( int mergeRowIndex, int [ ] mergeColumnIndex) { this . mergeRowIndex = mergeRowIndex; this . mergeColumnIndex = mergeColumnIndex; } @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) { } @Override public void afterCellDispose ( WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List < CellData > cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { int curRowIndex = cell. getRowIndex ( ) ; int curColIndex = cell. getColumnIndex ( ) ; if ( curRowIndex > mergeRowIndex) { for ( int i = 0 ; i < mergeColumnIndex. length; i++ ) { if ( curColIndex == mergeColumnIndex[ i] - 1 ) { mergeWithPrevRow ( writeSheetHolder, cell, curRowIndex, curColIndex) ; break ; } } } } private void mergeWithPrevRow ( WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { Object curData = cell. getCellTypeEnum ( ) == CellType . STRING ? cell. getStringCellValue ( ) : cell. getNumericCellValue ( ) ; Cell preCell = cell. getSheet ( ) . getRow ( curRowIndex) . getCell ( curColIndex) ; Object preData = preCell. getCellTypeEnum ( ) == CellType . STRING ? preCell. getStringCellValue ( ) : preCell. getNumericCellValue ( ) ; Boolean dataBool = preData. equals ( curData) ; Boolean bool = cell. getRow ( ) . getCell ( 0 ) . getStringCellValue ( ) . equals ( cell. getSheet ( ) . getRow ( curRowIndex - 1 ) . getCell ( 0 ) . getStringCellValue ( ) ) ; if ( dataBool && bool) { 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) ; } } }
}
二、导入操作
1 导入示例
java"> @SneakyThrows @ApiOperation ( "导入订单信息" ) @PostMapping ( "/import" ) public R < List < AgencySalesOrderDetailVO > > importSaleOrderDetails ( @RequestPart MultipartFile file, HttpServletRequest request) { ListAnalysisEventListener < AgencySalesOrderDetailTmpVO > readListener = BeanUtils . instantiateClass ( ListAnalysisEventListener . class ) ; EasyExcel . read ( file. getInputStream ( ) , AgencySalesOrderDetailTmpVO . class , readListener) . registerConverter ( LocalDateStringConverter . INSTANCE) . registerConverter ( LocalDateTimeStringConverter . INSTANCE) . ignoreEmptyRow ( true ) . sheet ( ) . doRead ( ) ; List < AgencySalesOrderDetailTmpVO > dataRowList = readListener. getList ( ) ; String errors = readListener. getErrorInfo ( ) ; if ( ! StrUtil . isEmpty ( errors) ) { return R . failed ( errors) ; } if ( CollectionUtils . isEmpty ( dataRowList) ) { return R . failed ( "内容为空" ) ; } return agencySalesOrderDetailVOR; }
2 导入日期转换(LocalDateStringConverter)
java">import com. alibaba. excel. converters. Converter ;
import com. alibaba. excel. enums. CellDataTypeEnum ;
import com. alibaba. excel. metadata. GlobalConfiguration ;
import com. alibaba. excel. metadata. data. CellData ;
import com. alibaba. excel. metadata. data. WriteCellData ;
import com. alibaba. excel. metadata. property. ExcelContentProperty ;
import java . text. ParseException ;
import java . time. LocalDate ;
import java . time. format. DateTimeFormatter ;
public enum LocalDateStringConverter implements Converter < LocalDate > { INSTANCE; private LocalDateStringConverter ( ) { } @Override public Class supportJavaTypeKey ( ) { return LocalDate . class ; } @Override public CellDataTypeEnum supportExcelTypeKey ( ) { return CellDataTypeEnum . STRING; } public LocalDate convertToJavaData ( CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { if ( contentProperty != null && contentProperty. getDateTimeFormatProperty ( ) != null ) { DateTimeFormatter formatter = DateTimeFormatter . ofPattern ( contentProperty. getDateTimeFormatProperty ( ) . getFormat ( ) ) ; return LocalDate . parse ( cellData. getStringValue ( ) , formatter) ; } else { return LocalDate . parse ( cellData. getStringValue ( ) ) ; } } @Override public WriteCellData < String > convertToExcelData ( LocalDate value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { DateTimeFormatter formatter; if ( contentProperty != null && contentProperty. getDateTimeFormatProperty ( ) != null ) { formatter = DateTimeFormatter . ofPattern ( contentProperty. getDateTimeFormatProperty ( ) . getFormat ( ) ) ; } else { formatter = DateTimeFormatter . ISO_LOCAL_DATE; } return new WriteCellData ( value. format ( formatter) ) ; }
}
javascript">import com. alibaba. excel. converters. Converter;
import com. alibaba. excel. enums. CellDataTypeEnum;
import com. alibaba. excel. metadata. GlobalConfiguration;
import com. alibaba. excel. metadata. data. CellData;
import com. alibaba. excel. metadata. data. WriteCellData;
import com. alibaba. excel. metadata. property. ExcelContentProperty;
import java . text. ParseException;
import java . time. LocalDateTime;
import java . time. format. DateTimeFormatter;
public enum LocalDateTimeStringConverter implements Converter < LocalDateTime> { INSTANCE ; private static final String MINUS = "-" ; private LocalDateTimeStringConverter ( ) { } @Overridepublic Class supportJavaTypeKey ( ) { return LocalDateTime. class; } @Overridepublic CellDataTypeEnum supportExcelTypeKey ( ) { return CellDataTypeEnum. STRING ; } public LocalDateTime convertToJavaData ( CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { String stringValue = cellData. getStringValue ( ) ; String pattern; if ( contentProperty != null && contentProperty. getDateTimeFormatProperty ( ) != null ) { pattern = contentProperty. getDateTimeFormatProperty ( ) . getFormat ( ) ; } else { pattern = switchDateFormat ( stringValue) ; } DateTimeFormatter formatter = DateTimeFormatter. ofPattern ( pattern) ; return LocalDateTime. parse ( cellData. getStringValue ( ) , formatter) ; } @Overridepublic WriteCellData< String> convertToExcelData ( LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration ) { String pattern; if ( contentProperty != null && contentProperty. getDateTimeFormatProperty ( ) != null ) { pattern = contentProperty. getDateTimeFormatProperty ( ) . getFormat ( ) ; } else { pattern = "yyyy-MM-dd HH:mm:ss" ; } DateTimeFormatter formatter = DateTimeFormatter. ofPattern ( pattern) ; return new WriteCellData ( value. format ( formatter) ) ; } private static String switchDateFormat ( String dateString ) { int length = dateString. length ( ) ; switch ( length) { case 10 : return "yyyy-MM-dd" ; case 11 : case 12 : case 13 : case 15 : case 16 : case 18 : default : throw new IllegalArgumentException ( "can not find date format for:" + dateString) ; case 14 : return "yyyyMMddHHmmss" ; case 17 : return "yyyyMMdd HH:mm:ss" ; case 19 : return dateString. contains ( "-" ) ? "yyyy-MM-dd HH:mm:ss" : "yyyy/MM/dd HH:mm:ss" ; } }
}
3 导入解析事件监听器(ListAnalysisEventListener)
java">import com. alibaba. excel. context. AnalysisContext ;
import com. alibaba. excel. event. AnalysisEventListener ;
import org. slf4j. Logger ;
import org. slf4j. LoggerFactory ;
import java x. validation. ConstraintViolation ;
import java x. validation. Validation ;
import java x. validation. Validator ;
import java x. validation. ValidatorFactory ;
import java . util. ArrayList ;
import java . util. List ;
import java . util. Set ;
import java . util. stream. Collectors ;
public class ListAnalysisEventListener < T > extends AnalysisEventListener < T > { private static final Logger log = LoggerFactory . getLogger ( ListAnalysisEventListener . class ) ; private final List < T > list = new ArrayList < > ( ) ; private final List < ErrorMessage > errorMessageList = new ArrayList < > ( ) ; private Long lineNum = 1L ; public ListAnalysisEventListener ( ) { } @Override public void invoke ( T o, AnalysisContext analysisContext) { Long var3 = this . lineNum; Long var4 = this . lineNum = this . lineNum + 1L ; Set < ConstraintViolation < Object > > violations = Validators . validate ( o) ; if ( ! violations. isEmpty ( ) ) { Set < String > messageSet = ( Set ) violations. stream ( ) . map ( ConstraintViolation :: getMessage ) . collect ( Collectors . toSet ( ) ) ; this . errorMessageList. add ( new ErrorMessage ( this . lineNum, messageSet) ) ; } else { this . list. add ( o) ; } } @Override public void doAfterAllAnalysed ( AnalysisContext analysisContext) { log. debug ( "Excel read analysed" ) ; } public List < T > getList ( ) { return this . list; } public List < ErrorMessage > getErrors ( ) { return this . errorMessageList; } public String getErrorInfo ( ) { List < ErrorMessage > errors = this . errorMessageList; if ( errors. size ( ) > 0 ) { StringBuilder sb = new StringBuilder ( ) ; for ( ErrorMessage error : errors) { Long lineNum = error. getLineNum ( ) ; Set < String > errorSet = error. getErrors ( ) ; String errMsg = errorSet. iterator ( ) . next ( ) ; sb. append ( "第" ) . append ( lineNum) . append ( "行" ) . append ( errMsg) . append ( ";" ) ; } return sb. toString ( ) ; } return null ; } public static class Validators { private static final Validator validator; public Validators ( ) { } public static < T > Set < ConstraintViolation < T > > validate ( T object) { return validator. validate ( object) ; } static { ValidatorFactory factory = Validation . buildDefaultValidatorFactory ( ) ; validator = factory. getValidator ( ) ; } }
}
1.4 模板示例
java">import com. alibaba. excel. annotation. ExcelProperty ;
import com. alibaba. excel. annotation. format. DateTimeFormat ;
import com. alibaba. excel. annotation. format. NumberFormat ;
import com. alibaba. excel. annotation. write. style. ColumnWidth ;
import com. alibaba. excel. annotation. write. style. ContentStyle ;
import com. fasterxml. jackson. annotation. JsonFormat ;
import lombok. Data ;
import java x. validation. constraints. NotBlank ;
import java x. validation. constraints. NotNull ;
import java . util. Date ;
@Data
@ColumnWidth ( 15 )
public class AgencySalesOrderDetailTmpVO { @NotBlank ( message = "商品编码不能为空" ) @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "*商品编码" , index = 0 ) private String productCode; @NotBlank ( message = "产地不能为空" ) @ExcelProperty ( value = "*产地" , index = 1 ) private String place; @NotBlank ( message = "订单号不能为空" ) @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "*订单号" , index = 2 ) private String orderNo; @NotBlank ( message = "批次/厂号不能为空" ) @ContentStyle ( dataFormat = 49 ) @ExcelProperty ( value = "*批次/厂号" , index = 3 ) private String batch; @JsonFormat ( timezone = "GMT+8" , pattern = "yyyy-MM-dd" ) @DateTimeFormat ( "yyyy-MM-dd" ) @ExcelProperty ( value = "生产日期" , index = 4 ) private Date productionDate;
}