- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
信用代码、填报人,唯一时,将:信用代码、单位名称、填报人,进行 row 合并,并垂直居中对齐 。
这边不需要做列合并,所以采用了 RowWriteHandler 思路, 。
package com.vipsoft.handler;
import cn.idev.excel.write.handler.RowWriteHandler;
import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import cn.idev.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.ArrayList;
import java.util.List;
/**
* Excel导出单元格全量合并策略
*/
public class ExcelCellMergeStrategy implements RowWriteHandler {
private int mergeRowIndex;//从哪一行开始合并
private List<Integer> mergeColumnIndex = new ArrayList<>();//excel合并的列
private int[] uniqueCol;//合并的唯一标识,根据指定的列,确定数据是否相同
private int totalRow;//总行数
private int lastRow;
private int firstCol;
private int lastCol;
private int firstRow;
private int mergeCount = 1;
/**
* @param mergeRowIndex
* @param mergeColIndex 支持范围如:0-3,6,9
* @param uniqueCol 唯一标识,1列或多列 数据组成唯一值
* @param totalRow 总行数(从0开始):List.size -1 + 跳过的表头
*/
public ExcelCellMergeStrategy(int mergeRowIndex, Object[] mergeColIndex, int[] uniqueCol, int totalRow) {
this.mergeRowIndex = mergeRowIndex;
for (Object item : mergeColIndex) {
if (item.toString().contains("-")) {
String[] spCol = item.toString().split("-");
int start = Integer.parseInt(spCol[0]);
int end = Integer.parseInt(spCol[1]);
for (int i = start; i <= end; i++) {
mergeColumnIndex.add(i);
}
} else {
int colIndex = Integer.parseInt(item.toString());
mergeColumnIndex.add(colIndex);
}
}
this.uniqueCol = uniqueCol;
this.totalRow = totalRow;
}
@Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
//当前行
int curRowIndex = row.getRowNum();
//每一行的最大列数
short lastCellNum = row.getLastCellNum();
//当前行为开始合并行时,标记
if (curRowIndex == mergeRowIndex) {
//赋初值 第一行
firstRow = curRowIndex;
}
//开始合并位置
if (curRowIndex > mergeRowIndex && !row.getCell(0).getStringCellValue().equals("")) {
for (int i = 0; i < lastCellNum; i++) {
if (mergeColumnIndex.contains(i)) {
//当前行号 当前行对象 合并的标识位
mergeWithPrevAnyRow(writeSheetHolder.getSheet(), curRowIndex, row, uniqueCol);
break;//已经进入到合并单元格操作里面了,执行一次就行
}
}
}
}
public void mergeWithPrevAnyRow(Sheet sheet, int curRowIndex, Row row, int[] uniqueCol) {
Object currentData = "";
Object preData = "";
for (int col : uniqueCol) {
currentData = currentData + row.getCell(col).getStringCellValue();
Row preRow = row.getSheet().getRow(curRowIndex - 1);
preData = preData + preRow.getCell(col).getStringCellValue();
}
//判断是否合并单元格
boolean curEqualsPre = currentData.equals(preData);
//判断前一个和后一个相同 并且 标识位相同
if (curEqualsPre) {
lastRow = curRowIndex;
mergeCount++;
}
//excel过程中合并
if (!curEqualsPre && mergeCount > 1) {
mergeSheet(firstRow, lastRow, mergeColumnIndex, sheet);
mergeCount = 1;
}
//excel结尾处合并
if (mergeCount > 1 && totalRow == curRowIndex) {
mergeSheet(firstRow, lastRow, mergeColumnIndex, sheet);
mergeCount = 1;
}
//重置下一个要合并的行
if (!curEqualsPre) {
firstRow = curRowIndex;
}
}
private void mergeSheet(int firstRow, int lastRow, List<Integer> mergeColumnIndex, Sheet sheet) {
for (int colNum : mergeColumnIndex) {
firstCol = colNum;
lastCol = colNum;
CellRangeAddress cellRangeAddress = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
sheet.addMergedRegion(cellRangeAddress);
// 设置合并后的单元格样式为垂直居中
CellStyle style = sheet.getWorkbook().createCellStyle();
style.setVerticalAlignment(VerticalAlignment.CENTER);
//style.setAlignment(HorizontalAlignment.CENTER);
Cell mergedCell = sheet.getRow(firstRow).getCell(colNum, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
mergedCell.setCellStyle(style);
}
}
}
EasyExcel => FastExcel ,导入支持多种时间格式 。
package com.vipsoft.base.util;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 日期格式转换器
*/
public class ExcelDateConverter implements Converter<Date> {
private static final Logger log = LoggerFactory.getLogger(ExcelDateConverter.class);
// 定义所有要尝试的日期格式
SimpleDateFormat[] formats = {
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"),
new SimpleDateFormat("yyyy/MM/dd"),
new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyy-MM"),
new SimpleDateFormat("yyyy/MM"),
new SimpleDateFormat("yyyyMMdd")
};
@Override
public Class<Date> supportJavaTypeKey() {
return Date.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public Date convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws Exception {
String cellValue = "";
if (cellData.getType().equals(CellDataTypeEnum.NUMBER)) {
long cellIntValue = cellData.getNumberValue().longValue();
if (cellIntValue > 19900100) {
try {
// 1. 第一种解析,传入的是数字形式的日期,形如yyyyMMdd
SimpleDateFormat originalFormat = new SimpleDateFormat("yyyyMMdd");
return originalFormat.parse(String.valueOf(cellIntValue));
} catch (Exception e) {
log.warn("exception when parse numerical time with format yyyyMMdd");
cellValue=String.valueOf(cellIntValue);
}
}
// 2. 第二种解析, excel是从1900年开始计算,最终通过计算与1900年间隔的天数计算目标日期
LocalDate localDate = LocalDate.of(1900, 1, 1);
//excel 有些奇怪的bug, 导致日期数差2
localDate = localDate.plusDays(cellIntValue - 2);
// 转换为ZonedDateTime(如果需要时区信息)
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
return Date.from(zonedDateTime.toInstant());
} else if (cellData.getType().equals(CellDataTypeEnum.STRING)) {
// 3. 第三种解析
Date date = null;
cellValue = cellData.getStringValue();
for (SimpleDateFormat format : formats) {
try {
date = format.parse(cellValue);
if (date != null) {
// 这一步是将日期格式化为Java期望的格式
return date;
}
} catch (Exception e) {
// 如果有异常,捕捉异常后继续解析
//log.error(e.getMessage(), e);
}
}
}
// 没转成功,抛出异常
throw new UnsupportedOperationException("The current operation is not supported by the current converter." + cellValue);
}
@Override
public WriteCellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateValue = sdf.format(value);
return new WriteCellData<>(dateValue);
}
}
导出代码 。
package com.vipsoft.api.controller;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Map;
/**
* 企业信息
*/
@RestController
@RequestMapping("/detail")
public class CooperationDetailController extends BaseController {
/**
* 企业信息
*
* @return
*/
@PostMapping("/export")
public void exportInfo(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, Object> param) {
try {
Page page = buildPage(param, CooperationInfo.class);
QueryWrapper<SysOrganization> queryWrapper = buildQueryWrapper(SysOrganization.class, param);
cooperationDetailService.exportInfo(response, queryWrapper);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
}
}
@Service
public class SysOrganizationServiceImpl extends ServiceImpl<SysOrganizationMapper, SysOrganization> implements ISysOrganizationService {
@Override
public void exportInfo(HttpServletResponse response, QueryWrapper<SysOrganization> queryWrapper) {
String templateFileName = "";
try {
templateFileName = cuworConfig.getFilePath() + "/template/企业导出模板.xlsx";
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和 FastExcel 没有关系
String fileName = URLEncoder.encode("企业数据", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
//获取要导出的数据 DTO
List<SysOrganizationExcelDTO> dataList = data(queryWrapper);
int mergeRowIndex = 2; // 从那一行开始合并 -- 跳过表头
int[] uniqueCol = {0, 7}; //根据指定的列,确定相同的数据
Object[] mergeColIndex = {"0-1", 6, 7}; //需要合并的列
int totalRow = dataList.size() - 1 + mergeRowIndex;
// 这里需要设置不关闭流
ExcelCellMergeStrategy excelCellMergeStrategy = new ExcelCellMergeStrategy(mergeRowIndex, mergeColIndex, uniqueCol, totalRow);
FastExcel.write(response.getOutputStream(), SysOrganizationExcelDTO.class)
.needHead(false)
.withTemplate(templateFileName)
.autoCloseStream(Boolean.FALSE)
.registerWriteHandler(excelCellMergeStrategy) //合并单元格
.sheet("企业数据")
.doWrite(dataList);
} catch (Exception e) {
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
//异常时,向前端抛出 JSON
ApiResult result = new ApiResult(6001, "下载文件失败 " + templateFileName + " " + e.getMessage());
try {
response.getWriter().println(PojoUtil.pojoToJson(result));
} catch (IOException ex) {
logger.error(ex.getMessage(), ex);
throw new CustomException(ex.getMessage());
}
}
}
/**
* 获得要到出的数据
*/
private List<SysOrganizationExcelDTO> data(QueryWrapper<SysOrganization> queryWrapper) {
IPage list = this.page(new Page(1, 10000), queryWrapper);
List<SysOrganizationExcelDTO> result = new ArrayList<>();
for (Object obj : list.getRecords()) {
if (obj instanceof SysOrganization) {
SysOrganization item = (SysOrganization) obj;
SysOrganizationExcelDTO info = new SysOrganizationExcelDTO();
BeanUtils.copyProperties(item, info);
//组装数据
result.add(info);
}
}
return result;
}
}
package com.vipsoft.base.dto;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.vipsoft.base.util.ExcelDateConverter;
import java.io.Serializable;
import java.util.Date;
/**
* Excel 导出使用
*/
public class SysOrganizationExcelDTO implements Serializable {
/**
* 统一社会信用代码
*/
//@ExcelProperty(value = "统一社会信用代码")
@ExcelProperty(index = 0)
private String unifiedSocialCode;
/**
* 机构名称
*/
@ExcelProperty(index = 1)
private String orgName;
/**
* 岗位大类名称
*/
@ExcelProperty(index = 2)
private String jobBigName;
/**
* 岗位中类名称
*/
@ExcelProperty(index = 3)
private String jobMiddleName;
/**
* 岗位小类名称
*/
@ExcelProperty(index = 4)
private String jobSmallName;
/**
* 岗位数量
*/
@ExcelProperty(index = 5)
private Integer jobQty;
/**
* 填报日期*
*/
@ExcelProperty(index = 6, converter = ExcelDateConverter.class)
private Date inputDate;
/**
* 填报人
*/
@ExcelProperty(index = 7)
private String inputUser;
......省略get set
}
最后此篇关于FastExcel合并单元格(相当的行数据,进行合并)的文章就讲到这里了,如果你想了解更多关于FastExcel合并单元格(相当的行数据,进行合并)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!