位置: IT常识 - 正文

Java之POI导出Excel(一):单sheet(poi java 导入导出)

发布时间:2024-01-26
相信在大部分的web项目中都会有导出导入Excel的需求,今天我们就来看看如何用Java代码去实现 用POI导出Excel表格。 一、pom引用 pom文件中,添加以下依赖 查看代码 <!--Excel工具--> <dependency> <groupId>org.apache.poi</group ...

推荐整理分享Java之POI导出Excel(一):单sheet(poi java 导入导出),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:java poi 导出多个sheet,java poi 导出多个sheet,java使用poi导出excel,java使用poi导出excel,java poi导出excel,java实现导出excel,java poi导出excel,poi java 导入导出,内容如对您有帮助,希望把文章链接给更多的朋友!

相信在大部分的web项目中都会有导出导入Excel的需求,今天我们就来看看如何用Java代码去实现 用POI导出Excel表格。

一、pom引用

pom文件中,添加以下依赖

查看代码<!--Excel工具--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version><scope>compile</scope></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version><scope>compile</scope></dependency>二、工具类util

1.ExcelClassField

查看代码package com.***;import lombok.Data;import java.util.LinkedHashMap;/*** @description: excel字段* @author: **** @date: 2022/6/21*/@Datapublic class ExcelClassField {/*** 字段名称*/private String fieldName;/*** 表头名称*/private String name;/*** 映射关系*/private LinkedHashMap<String, String> kvMap;/*** 示例值*/private Object example;/*** 排序*/private int sort;/*** 是否为注解字段:0-否,1-是*/private int hasAnnotation;}

2.ExcelExport(导出Excel用)

查看代码package com.***;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** @description: excel导出* @author: **** @date: 2022/6/21*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ExcelExport {/*** 字段名称*/String value();/*** 导出排序先后: 数字越小越靠前(默认按Java类字段顺序导出)*/int sort() default 0;/*** 导出映射,格式如:0-未知;1-男;2-女*/String kv() default "";/*** 导出模板示例值(有值的话,直接取该值,不做映射)*/String example() default "";}

3.ExcelImport(导入Excel用)

查看代码package com.***;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** @description: excel导入* @author: **** @date: 2022/6/21*/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ExcelImport {/*** 字段名称*/String value();/*** 导出映射,格式如:0-未知;1-男;2-女*/String kv() default "";/*** 是否为必填字段(默认为非必填)*/boolean required() default false;/*** 最大长度(默认255)*/int maxLength() default 255;/*** 导入唯一性验证(多个字段则取联合验证)*/boolean unique() default false;}Java之POI导出Excel(一):单sheet(poi java 导入导出)

4.ExcelUtils

查看代码package com.***;import com.***.utils.DateUtil;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import com.***.uitl.StringUtils;import org.apache.poi.hssf.usermodel.HSSFDataValidation;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.poifs.filesystem.POIFSFileSystem;import org.apache.poi.ss.usermodel.*;import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;import org.apache.poi.ss.util.CellRangeAddress;import org.apache.poi.ss.util.CellRangeAddressList;import org.apache.poi.xssf.streaming.SXSSFWorkbook;import org.apache.poi.xssf.usermodel.XSSFClientAnchor;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.lang.reflect.Field;import java.math.BigDecimal;import java.math.RoundingMode;import java.net.URL;import java.net.URLEncoder;import java.text.NumberFormat;import java.text.SimpleDateFormat;import java.util.*;import java.util.Map.Entry;import java.util.regex.Pattern;/*** @description: 导出报表util* @author: **** @date: 2022/6/21*/public class ExcelUtils {public static final String ROW_MERGE = "row_merge";public static final String COLUMN_MERGE = "column_merge";private static final String XLSX = ".xlsx";private static final String XLS = ".xls";private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";private static final String ROW_NUM = "rowNum";private static final String ROW_DATA = "rowData";private static final String ROW_TIPS = "rowTips";private static final int CELL_OTHER = 0;private static final int CELL_ROW_MERGE = 1;private static final int CELL_COLUMN_MERGE = 2;private static final int IMG_HEIGHT = 30;private static final int IMG_WIDTH = 30;private static final char LEAN_LINE = '/';private static final int BYTES_DEFAULT_LENGTH = 10240;private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance();public static <T> List<T> readFile(File file, Class<T> clazz) throws Exception {JSONArray array = readFile(file);return getBeanList(array, clazz);}public static <T> List<T> readMultipartFile(MultipartFile mFile, Class<T> clazz) throws Exception {JSONArray array = readMultipartFile(mFile);return getBeanList(array, clazz);}public static JSONArray readFile(File file) throws Exception {return readExcel(null, file);}public static JSONArray readMultipartFile(MultipartFile mFile) throws Exception {return readExcel(mFile, null);}public static Map<String, JSONArray> readFileManySheet(File file) throws Exception {return readExcelManySheet(null, file);}public static Map<String, JSONArray> readFileManySheet(MultipartFile file) throws Exception {return readExcelManySheet(file, null);}private static <T> List<T> getBeanList(JSONArray array, Class<T> clazz) throws Exception {List<T> list = new ArrayList<>();Map<Integer, String> uniqueMap = new HashMap<>(16);for (int i = 0; i < array.size(); i++) {list.add(getBean(clazz, array.getJSONObject(i), uniqueMap));}return list;}/*** 获取每个对象的数据*/private static <T> T getBean(Class<T> c, JSONObject obj, Map<Integer, String> uniqueMap) throws Exception {T t = c.newInstance();Field[] fields = c.getDeclaredFields();List<String> errMsgList = new ArrayList<>();boolean hasRowTipsField = false;StringBuilder uniqueBuilder = new StringBuilder();int rowNum = 0;for (Field field : fields) {// 行号if (field.getName().equals(ROW_NUM)) {rowNum = obj.getInteger(ROW_NUM);field.setAccessible(true);field.set(t, rowNum);continue;}// 是否需要设置异常信息if (field.getName().equals(ROW_TIPS)) {hasRowTipsField = true;continue;}// 原始数据if (field.getName().equals(ROW_DATA)) {field.setAccessible(true);field.set(t, obj.toString());continue;}// 设置对应属性值setFieldValue(t, field, obj, uniqueBuilder, errMsgList);}// 数据唯一性校验if (uniqueBuilder.length() > 0) {if (uniqueMap.containsValue(uniqueBuilder.toString())) {Set<Integer> rowNumKeys = uniqueMap.keySet();for (Integer num : rowNumKeys) {if (uniqueMap.get(num).equals(uniqueBuilder.toString())) {errMsgList.add(String.format("数据唯一性校验失败,(%s)与第%s行重复)", uniqueBuilder, num));}}} else {uniqueMap.put(rowNum, uniqueBuilder.toString());}}// 失败处理if (errMsgList.isEmpty() && !hasRowTipsField) {return t;}StringBuilder sb = new StringBuilder();int size = errMsgList.size();for (int i = 0; i < size; i++) {if (i == size - 1) {sb.append(errMsgList.get(i));} else {sb.append(errMsgList.get(i)).append(";");}}// 设置错误信息for (Field field : fields) {if (field.getName().equals(ROW_TIPS)) {field.setAccessible(true);field.set(t, sb.toString());}}return t;}private static <T> void setFieldValue(T t, Field field, JSONObject obj, StringBuilder uniqueBuilder, List<String> errMsgList) {// 获取 ExcelImport 注解属性ExcelImport annotation = field.getAnnotation(ExcelImport.class);if (annotation == null) {return;}String cname = annotation.value();if (cname.trim().length() == 0) {return;}// 获取具体值String val = null;if (obj.containsKey(cname)) {val = getString(obj.getString(cname));}if (val == null) {return;}field.setAccessible(true);// 判断是否必填boolean require = annotation.required();if (require && val.isEmpty()) {errMsgList.add(String.format("[%s]不能为空", cname));return;}// 数据唯一性获取boolean unique = annotation.unique();if (unique) {if (uniqueBuilder.length() > 0) {uniqueBuilder.append("--").append(val);} else {uniqueBuilder.append(val);}}// 判断是否超过最大长度int maxLength = annotation.maxLength();if (maxLength > 0 && val.length() > maxLength) {errMsgList.add(String.format("[%s]长度不能超过%s个字符(当前%s个字符)", cname, maxLength, val.length()));}// 判断当前属性是否有映射关系LinkedHashMap<String, String> kvMap = getKvMap(annotation.kv());if (!kvMap.isEmpty()) {boolean isMatch = false;for (String key : kvMap.keySet()) {if (kvMap.get(key).equals(val)) {val = key;isMatch = true;break;}}if (!isMatch) {errMsgList.add(String.format("[%s]的值不正确(当前值为%s)", cname, val));return;}}// 其余情况根据类型赋值String fieldClassName = field.getType().getSimpleName();try {if ("String".equalsIgnoreCase(fieldClassName)) {field.set(t, val);} else if ("boolean".equalsIgnoreCase(fieldClassName)) {field.set(t, Boolean.valueOf(val));} else if ("int".equalsIgnoreCase(fieldClassName) || "Integer".equals(fieldClassName)) {try {field.set(t, Integer.valueOf(val));} catch (NumberFormatException e) {errMsgList.add(String.format("[%s]的值格式不正确(当前值为%s)", cname, val));}} else if ("double".equalsIgnoreCase(fieldClassName)) {field.set(t, Double.valueOf(val));} else if ("long".equalsIgnoreCase(fieldClassName)) {field.set(t, Long.valueOf(val));} else if ("BigDecimal".equalsIgnoreCase(fieldClassName)) {if (StringUtils.isEmpty(val)) {field.set(t, new BigDecimal(0));} else {field.set(t, new BigDecimal(val));}} else if ("Date".equalsIgnoreCase(fieldClassName)) {field.set(t, DateUtil.getDate(val, DateUtil.YYYYMMDDHHMMSS));} else {field.set(t, val);}} catch (Exception e) {e.printStackTrace();}}private static Map<String, JSONArray> readExcelManySheet(MultipartFile mFile, File file) throws IOException {Workbook book = getWorkbook(mFile, file);if (book == null) {return Collections.emptyMap();}Map<String, JSONArray> map = new LinkedHashMap<>();for (int i = 0; i < book.getNumberOfSheets(); i++) {Sheet sheet = book.getSheetAt(i);JSONArray arr = readSheet(sheet);map.put(sheet.getSheetName(), arr);}book.close();return map;}private static JSONArray readExcel(MultipartFile mFile, File file) throws IOException {Workbook book = getWorkbook(mFile, file);if (book == null) {return new JSONArray();}JSONArray array = readSheet(book.getSheetAt(0));book.close();return array;}private static Workbook getWorkbook(MultipartFile mFile, File file) throws IOException {boolean fileNotExist = (file == null || !file.exists());if (mFile == null && fileNotExist) {return null;}// 解析表格数据InputStream in;String fileName;if (mFile != null) {// 上传文件解析in = mFile.getInputStream();fileName = getString(mFile.getOriginalFilename()).toLowerCase();} else {// 本地文件解析in = new FileInputStream(file);fileName = file.getName().toLowerCase();}Workbook book;if (fileName.endsWith(XLSX)) {book = new XSSFWorkbook(in);} else if (fileName.endsWith(XLS)) {POIFSFileSystem poifsFileSystem = new POIFSFileSystem(in);book = new HSSFWorkbook(poifsFileSystem);} else {return null;}in.close();return book;}private static JSONArray readSheet(Sheet sheet) {// 首行下标int rowStart = sheet.getFirstRowNum();// 尾行下标int rowEnd = sheet.getLastRowNum();// 获取表头行Row headRow = sheet.getRow(rowStart);if (headRow == null) {return new JSONArray();}int cellStart = headRow.getFirstCellNum();int cellEnd = headRow.getLastCellNum();Map<Integer, String> keyMap = new HashMap<>();for (int j = cellStart; j < cellEnd; j++) {// 获取表头数据String val = getCellValue(headRow.getCell(j));if (val != null && val.trim().length() != 0) {keyMap.put(j, val);}}// 如果表头没有数据则不进行解析if (keyMap.isEmpty()) {return (JSONArray) Collections.emptyList();}// 获取每行JSON对象的值JSONArray array = new JSONArray();// 如果首行与尾行相同,表明只有一行,返回表头数据if (rowStart == rowEnd) {JSONObject obj = new JSONObject();// 添加行号obj.put(ROW_NUM, 1);for (int i : keyMap.keySet()) {obj.put(keyMap.get(i), "");}array.add(obj);return array;}for (int i = rowStart + 1; i <= rowEnd; i++) {Row eachRow = sheet.getRow(i);JSONObject obj = new JSONObject();// 添加行号obj.put(ROW_NUM, i + 1);StringBuilder sb = new StringBuilder();for (int k = cellStart; k < cellEnd; k++) {if (eachRow != null) {String val = getCellValue(eachRow.getCell(k));// 所有数据添加到里面,用于判断该行是否为空sb.append(val);obj.put(keyMap.get(k), val);}}if (sb.length() > 0) {array.add(obj);}}return array;}private static String getCellValue(Cell cell) {// 空白或空if (cell == null || cell.getCellType() == CellType.BLANK) {return "";}// String类型if (cell.getCellType() == CellType.STRING) {String val = cell.getStringCellValue();if (val == null || val.trim().length() == 0) {return "";}return val.trim();}// 数字类型if (cell.getCellType() == CellType.NUMERIC) {String s = cell.getNumericCellValue() + "";// 去掉尾巴上的小数点0if (Pattern.matches(".*\\.0*", s)) {return s.split("\\.")[0];} else {return s.trim();}}// 布尔值类型if (cell.getCellType() == CellType.BOOLEAN) {return cell.getBooleanCellValue() + "";}// 错误类型return cell.getCellFormula();}public static <T> void exportTemplate(HttpServletResponse response, String fileName, Class<T> clazz, String dateFormat) {exportTemplate(response, fileName, fileName, clazz, false, dateFormat);}public static <T> void exportTemplate(HttpServletResponse response, String fileName, String sheetName,Class<T> clazz, String dateFormat) {exportTemplate(response, fileName, sheetName, clazz, false, dateFormat);}public static <T> void exportTemplate(HttpServletResponse response, String fileName, Class<T> clazz,boolean isContainExample, String dateFormat) {exportTemplate(response, fileName, fileName, clazz, isContainExample, dateFormat);}public static <T> void exportTemplate(HttpServletResponse response, String fileName, String sheetName,Class<T> clazz, boolean isContainExample, String dateFormat) {// 获取表头字段List<ExcelClassField> headFieldList = getExcelClassFieldList(clazz);// 获取表头数据和示例数据List<List<Object>> sheetDataList = new ArrayList<>();List<Object> headList = new ArrayList<>();List<Object> exampleList = new ArrayList<>();Map<Integer, List<String>> selectMap = new LinkedHashMap<>();for (int i = 0; i < headFieldList.size(); i++) {ExcelClassField each = headFieldList.get(i);headList.add(each.getName());exampleList.add(each.getExample());LinkedHashMap<String, String> kvMap = each.getKvMap();if (kvMap != null && kvMap.size() > 0) {selectMap.put(i, new ArrayList<>(kvMap.values()));}}sheetDataList.add(headList);if (isContainExample) {sheetDataList.add(exampleList);}// 导出数据export(response, fileName, sheetName, sheetDataList, selectMap, dateFormat);}private static <T> List<ExcelClassField> getExcelClassFieldList(Class<T> clazz) {// 解析所有字段Field[] fields = clazz.getDeclaredFields();boolean hasExportAnnotation = false;Map<Integer, List<ExcelClassField>> map = new LinkedHashMap<>();List<Integer> sortList = new ArrayList<>();for (Field field : fields) {ExcelClassField cf = getExcelClassField(field);if (cf.getHasAnnotation() == 1) {hasExportAnnotation = true;}int sort = cf.getSort();if (map.containsKey(sort)) {map.get(sort).add(cf);} else {List<ExcelClassField> list = new ArrayList<>();list.add(cf);sortList.add(sort);map.put(sort, list);}}Collections.sort(sortList);// 获取表头List<ExcelClassField> headFieldList = new ArrayList<>();if (hasExportAnnotation) {for (Integer sort : sortList) {for (ExcelClassField cf : map.get(sort)) {if (cf.getHasAnnotation() == 1) {headFieldList.add(cf);}}}} else {headFieldList.addAll(map.get(0));}return headFieldList;}private static ExcelClassField getExcelClassField(Field field) {ExcelClassField cf = new ExcelClassField();String fieldName = field.getName();cf.setFieldName(fieldName);ExcelExport annotation = field.getAnnotation(ExcelExport.class);// 无 ExcelExport 注解情况if (annotation == null) {cf.setHasAnnotation(0);cf.setName(fieldName);cf.setSort(0);return cf;}// 有 ExcelExport 注解情况cf.setHasAnnotation(1);cf.setName(annotation.value());String example = getString(annotation.example());if (!example.isEmpty()) {if (isNumeric(example)) {cf.setExample(Double.valueOf(example));} else {cf.setExample(example);}} else {cf.setExample("");}cf.setSort(annotation.sort());// 解析映射String kv = getString(annotation.kv());cf.setKvMap(getKvMap(kv));return cf;}private static LinkedHashMap<String, String> getKvMap(String kv) {LinkedHashMap<String, String> kvMap = new LinkedHashMap<>();if (kv.isEmpty()) {return kvMap;}String[] kvs = kv.split(";");if (kvs.length == 0) {return kvMap;}for (String each : kvs) {String[] eachKv = getString(each).split("-");if (eachKv.length != 2) {continue;}String k = eachKv[0];String v = eachKv[1];if (k.isEmpty() || v.isEmpty()) {continue;}kvMap.put(k, v);}return kvMap;}/*** 导出表格到本地** @param file 本地文件对象* @param sheetData 导出数据*/public static void exportFile(File file, List<List<Object>> sheetData, String dateFormat) {if (file == null) {System.out.println("文件创建失败");return;}if (sheetData == null) {sheetData = new ArrayList<>();}Map<String, List<List<Object>>> map = new HashMap<>();map.put(file.getName(), sheetData);export(null, file, file.getName(), map, null, dateFormat);}/*** 导出表格到本地** @param <T> 导出数据类似,和K类型保持一致* @param filePath 文件父路径(如:D:/doc/excel/)* @param fileName 文件名称(不带尾缀,如:学生表)* @param list 导出数据* @throws IOException IO异常*/public static <T> File exportFile(String filePath, String fileName, List<T> list, String dateFormat) throws IOException {File file = getFile(filePath, fileName);List<List<Object>> sheetData = getSheetData(list);exportFile(file, sheetData, dateFormat);return file;}/*** 获取文件** @param filePath filePath 文件父路径(如:D:/doc/excel/)* @param fileName 文件名称(不带尾缀,如:用户表)* @return 本地File文件对象*/private static File getFile(String filePath, String fileName) throws IOException {String dirPath = getString(filePath);String fileFullPath;if (dirPath.isEmpty()) {fileFullPath = fileName;} else {// 判定文件夹是否存在,如果不存在,则级联创建File dirFile = new File(dirPath);if (!dirFile.exists()) {dirFile.mkdirs();}// 获取文件夹全名if (dirPath.endsWith(String.valueOf(LEAN_LINE))) {fileFullPath = dirPath + fileName + XLSX;} else {fileFullPath = dirPath + LEAN_LINE + fileName + XLSX;}}System.out.println(fileFullPath);File file = new File(fileFullPath);if (!file.exists()) {file.createNewFile();}return file;}private static <T> List<List<Object>> getSheetData(List<T> list) {// 获取表头字段List<ExcelClassField> excelClassFieldList = getExcelClassFieldList(list.get(0).getClass());List<String> headFieldList = new ArrayList<>();List<Object> headList = new ArrayList<>();Map<String, ExcelClassField> headFieldMap = new HashMap<>();for (ExcelClassField each : excelClassFieldList) {String fieldName = each.getFieldName();headFieldList.add(fieldName);headFieldMap.put(fieldName, each);headList.add(each.getName());}// 添加表头名称List<List<Object>> sheetDataList = new ArrayList<>();sheetDataList.add(headList);// 获取表数据for (T t : list) {Map<String, Object> fieldDataMap = getFieldDataMap(t);Set<String> fieldDataKeys = fieldDataMap.keySet();List<Object> rowList = new ArrayList<>();for (String headField : headFieldList) {if (!fieldDataKeys.contains(headField)) {continue;}Object data = fieldDataMap.get(headField);if (data == null) {rowList.add("");continue;}// 超防止过11位的数字自动转换为科学计数法String string = data.toString();if (isNumeric(string) && string.length() > 11) {data = new BigDecimal(string).toPlainString();}ExcelClassField cf = headFieldMap.get(headField);// 判断是否有映射关系LinkedHashMap<String, String> kvMap = cf.getKvMap();if (kvMap == null || kvMap.isEmpty()) {rowList.add(data);continue;}String val = kvMap.get(data.toString());if (val == null) {rowList.add(data);continue;}if (isNumeric(val)) {rowList.add(Double.valueOf(val));} else {rowList.add(val);}}sheetDataList.add(rowList);}return sheetDataList;}private static <T> Map<String, Object> getFieldDataMap(T t) {Map<String, Object> map = new HashMap<>();Field[] fields = t.getClass().getDeclaredFields();try {for (Field field : fields) {String fieldName = field.getName();field.setAccessible(true);Object object = field.get(t);map.put(fieldName, object);}} catch (IllegalArgumentException | IllegalAccessException e) {e.printStackTrace();}return map;}public static void exportEmpty(HttpServletResponse response, String fileName, String dateFormat) {List<List<Object>> sheetDataList = new ArrayList<>();List<Object> headList = new ArrayList<>();headList.add("导出无数据");sheetDataList.add(headList);export(response, fileName, sheetDataList, dateFormat);}public static void export(HttpServletResponse response, String fileName, List<List<Object>> sheetDataList, String dateFormat) {export(response, fileName, fileName, sheetDataList, null, dateFormat);}public static void exportManySheet(HttpServletResponse response, String fileName, Map<String, List<List<Object>>> sheetMap, String dateFormat) {export(response, null, fileName, sheetMap, null, dateFormat);}public static void export(HttpServletResponse response, String fileName, String sheetName,List<List<Object>> sheetDataList, String dateFormat) {export(response, fileName, sheetName, sheetDataList, null, dateFormat);}public static void export(HttpServletResponse response, String fileName, String sheetName,List<List<Object>> sheetDataList, Map<Integer, List<String>> selectMap, String dateFormat) {Map<String, List<List<Object>>> map = new HashMap<>();map.put(sheetName, sheetDataList);export(response, null, fileName, map, selectMap, dateFormat);}public static <T, K> void export(HttpServletResponse response, String fileName, List<T> list, Class<K> template) {String dateFormat = DATE_FORMAT;// list 是否为空boolean lisIsEmpty = list == null || list.isEmpty();// 如果模板数据为空,且导入的数据为空,则导出空文件if (template == null && lisIsEmpty) {exportEmpty(response, fileName, dateFormat);return;}// 如果 list 数据,则导出模板数据if (lisIsEmpty) {exportTemplate(response, fileName, template, dateFormat);return;}// 导出数据List<List<Object>> sheetDataList = getSheetData(list);export(response, fileName, sheetDataList, dateFormat);}public static <T, K> void export(HttpServletResponse response, String fileName, List<T> list, Class<K> template, String dateFormat) {// list 是否为空boolean lisIsEmpty = list == null || list.isEmpty();// 如果模板数据为空,且导入的数据为空,则导出空文件if (template == null && lisIsEmpty) {exportEmpty(response, fileName, dateFormat);return;}// 如果 list 数据,则导出模板数据if (lisIsEmpty) {exportTemplate(response, fileName, template, dateFormat);return;}// 导出数据List<List<Object>> sheetDataList = getSheetData(list);export(response, fileName, sheetDataList, dateFormat);}public static void export(HttpServletResponse response, String fileName, List<List<Object>> sheetDataList, Map<Integer, List<String>> selectMap, String dateFormat) {export(response, fileName, fileName, sheetDataList, selectMap, dateFormat);}private static void export(HttpServletResponse response, File file, String fileName,Map<String, List<List<Object>>> sheetMap, Map<Integer, List<String>> selectMap, String dateFormat) {// 整个 Excel 表格 book 对象SXSSFWorkbook book = new SXSSFWorkbook();// 每个 Sheet 页Set<Entry<String, List<List<Object>>>> entries = sheetMap.entrySet();for (Entry<String, List<List<Object>>> entry : entries) {List<List<Object>> sheetDataList = entry.getValue();Sheet sheet = book.createSheet(entry.getKey());Drawing<?> patriarch = sheet.createDrawingPatriarch();// 设置表头背景色(灰色)CellStyle headStyle = book.createCellStyle();headStyle.setFillForegroundColor(IndexedColors.GREY_80_PERCENT.index);headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);headStyle.setAlignment(HorizontalAlignment.CENTER);headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);// 设置表身背景色(默认色)CellStyle rowStyle = book.createCellStyle();rowStyle.setAlignment(HorizontalAlignment.CENTER);rowStyle.setVerticalAlignment(VerticalAlignment.CENTER);//创建一个DataFormat对象DataFormat format = book.createDataFormat();rowStyle.setDataFormat(format.getFormat("@"));// 设置表格列宽度(默认为15个字节)sheet.setDefaultColumnWidth(15);// 创建合并算法数组int rowLength = sheetDataList.size();int columnLength = sheetDataList.get(0).size();int[][] mergeArray = new int[rowLength][columnLength];for (int i = 0; i < sheetDataList.size(); i++) {// 每个 Sheet 页中的行数据Row row = sheet.createRow(i);List<Object> rowList = sheetDataList.get(i);for (int j = 0; j < rowList.size(); j++) {// 每个行数据中的单元格数据Object o = rowList.get(j);int v = 0;if (o instanceof URL) {// 如果要导出图片的话, 链接需要传递 URL 对象setCellPicture(book, row, patriarch, i, j, (URL) o);} else {Cell cell = row.createCell(j);if (i == 0) {// 第一行为表头行,采用灰色底背景v = setCellValue(cell, o, headStyle, dateFormat);} else {// 其他行为数据行,默认白底色v = setCellValue(cell, o, rowStyle, dateFormat);}}mergeArray[i][j] = v;}}// 合并单元格mergeCells(sheet, mergeArray);// 设置下拉列表setSelect(sheet, selectMap);}// 写数据if (response != null) {// 前端导出try {write(response, book, fileName);} catch (IOException e) {e.printStackTrace();}} else {// 本地导出FileOutputStream fos;try {fos = new FileOutputStream(file);ByteArrayOutputStream ops = new ByteArrayOutputStream();book.write(ops);fos.write(ops.toByteArray());fos.close();} catch (Exception e) {e.printStackTrace();}}}/*** 合并当前Sheet页的单元格** @param sheet 当前 sheet 页* @param mergeArray 合并单元格算法*/private static void mergeCells(Sheet sheet, int[][] mergeArray) {// 横向合并for (int x = 0; x < mergeArray.length; x++) {int[] arr = mergeArray[x];boolean merge = false;int y1 = 0;int y2 = 0;for (int y = 0; y < arr.length; y++) {int value = arr[y];if (value == CELL_COLUMN_MERGE) {if (!merge) {y1 = y;}y2 = y;merge = true;} else {merge = false;if (y1 > 0) {sheet.addMergedRegion(new CellRangeAddress(x, x, (y1 - 1), y2));}y1 = 0;y2 = 0;}}if (y1 > 0) {sheet.addMergedRegion(new CellRangeAddress(x, x, (y1 - 1), y2));}}// 纵向合并int xLen = mergeArray.length;int yLen = mergeArray[0].length;for (int y = 0; y < yLen; y++) {boolean merge = false;int x1 = 0;int x2 = 0;for (int x = 0; x < xLen; x++) {int value = mergeArray[x][y];if (value == CELL_ROW_MERGE) {if (!merge) {x1 = x;}x2 = x;merge = true;} else {merge = false;if (x1 > 0) {sheet.addMergedRegion(new CellRangeAddress((x1 - 1), x2, y, y));}x1 = 0;x2 = 0;}}if (x1 > 0) {sheet.addMergedRegion(new CellRangeAddress((x1 - 1), x2, y, y));}}}private static void write(HttpServletResponse response, SXSSFWorkbook book, String fileName) throws IOException {/*response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String name = new String(fileName.getBytes("GBK"), "ISO8859_1") + XLSX;response.addHeader("Content-Disposition", "attachment;filename=" + name);*//*String formFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\";", formFileName));response.setContentType("multipart/form-data");response.setCharacterEncoding("UTF-8");*/ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();assert attributes != null;HttpServletRequest request = attributes.getRequest();response.setContentType("multipart/form-data;charset=UTF-8");String userAgent = request.getHeader("USER-AGENT");try {if (userAgent.contains("MSIE") || userAgent.contains("Edge")) {// IE浏览器fileName = URLEncoder.encode(fileName, "UTF8");} else if (userAgent.contains("Mozilla")) {// google,火狐浏览器fileName = new String(fileName.getBytes(), "ISO8859-1");} else {fileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器}response.setHeader("Content-disposition", "attachment; filename=" + fileName);} catch (UnsupportedEncodingException e) {e.printStackTrace();}ServletOutputStream out = response.getOutputStream();book.write(out);out.flush();out.close();}private static int setCellValue(Cell cell, Object o, CellStyle style, String dateFormat) {// 设置样式cell.setCellStyle(style);// 数据为空时if (o == null) {cell.setCellType(CellType.STRING);cell.setCellValue("");return CELL_OTHER;}// 是否为字符串if (o instanceof String) {String s = o.toString();if (isNumeric(s)) {if (s.length() > 11) {cell.setCellType(CellType.STRING);cell.setCellValue(s);return CELL_OTHER;} else {cell.setCellType(CellType.NUMERIC);cell.setCellValue(Double.parseDouble(s));return CELL_OTHER;}} else {cell.setCellType(CellType.STRING);cell.setCellValue(s);}if (s.equals(ROW_MERGE)) {return CELL_ROW_MERGE;} else if (s.equals(COLUMN_MERGE)) {return CELL_COLUMN_MERGE;} else {return CELL_OTHER;}}// 是否为字符串if (o instanceof Integer || o instanceof Long || o instanceof Double || o instanceof Float) {cell.setCellType(CellType.NUMERIC);cell.setCellValue(Double.parseDouble(o.toString()));return CELL_OTHER;}// 是否为Booleanif (o instanceof Boolean) {cell.setCellType(CellType.BOOLEAN);cell.setCellValue((Boolean) o);return CELL_OTHER;}// 如果是BigDecimal,则默认3位小数if (o instanceof BigDecimal) {cell.setCellType(CellType.NUMERIC);cell.setCellValue(((BigDecimal) o).setScale(3, RoundingMode.HALF_UP).doubleValue());return CELL_OTHER;}// 如果是Date数据,则显示格式化数据if (o instanceof Date) {cell.setCellType(CellType.STRING);cell.setCellValue(formatDate((Date) o, dateFormat));return CELL_OTHER;}// 如果是其他,则默认字符串类型cell.setCellType(CellType.STRING);cell.setCellValue(o.toString());return CELL_OTHER;}private static void setCellPicture(SXSSFWorkbook wb, Row sr, Drawing<?> patriarch, int x, int y, URL url) {// 设置图片宽高sr.setHeight((short) (IMG_WIDTH * IMG_HEIGHT));// (jdk1.7版本try中定义流可自动关闭)try (InputStream is = url.openStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {byte[] buff = new byte[BYTES_DEFAULT_LENGTH];int rc;while ((rc = is.read(buff, 0, BYTES_DEFAULT_LENGTH)) > 0) {outputStream.write(buff, 0, rc);}// 设置图片位置XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, y, x, y + 1, x + 1);// 设置这个,图片会自动填满单元格的长宽anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);patriarch.createPicture(anchor, wb.addPicture(outputStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));} catch (Exception e) {e.printStackTrace();}}private static String formatDate(Date date, String dateFormat) {if (date == null) {return "";}if (dateFormat == null) {dateFormat = DATE_FORMAT;}SimpleDateFormat format = new SimpleDateFormat(dateFormat);return format.format(date);}private static void setSelect(Sheet sheet, Map<Integer, List<String>> selectMap) {if (selectMap == null || selectMap.isEmpty()) {return;}Set<Entry<Integer, List<String>>> entrySet = selectMap.entrySet();for (Entry<Integer, List<String>> entry : entrySet) {int y = entry.getKey();List<String> list = entry.getValue();if (list == null || list.isEmpty()) {continue;}String[] arr = new String[list.size()];for (int i = 0; i < list.size(); i++) {arr[i] = list.get(i);}DataValidationHelper helper = sheet.getDataValidationHelper();CellRangeAddressList addressList = new CellRangeAddressList(1, 65000, y, y);DataValidationConstraint dvc = helper.createExplicitListConstraint(arr);DataValidation dv = helper.createValidation(dvc, addressList);if (dv instanceof HSSFDataValidation) {dv.setSuppressDropDownArrow(false);} else {dv.setSuppressDropDownArrow(true);dv.setShowErrorBox(true);}sheet.addValidationData(dv);}}private static boolean isNumeric(String str) {if ("0.0".equals(str)) {return true;}if ("".equals(str)) {return false;}for (int i = str.length(); --i >= 0; ) {if (!Character.isDigit(str.charAt(i))) {return false;}}return true;}private static String getString(String s) {if (s == null) {return "";}if (s.isEmpty()) {return s;}return s.trim();}}三、相关业务代码

1.service层

/*** 车运运单信息导出*/List<ExportBillVo> exportBillInfo(List<Long> billIdList);

2.impl实现类

实现类里的代码,需求各位根据自己的业务场景进行改动,将需要导出的数据查询出来

查看代码 @Overridepublic List<ExportBillVo> exportBillInfo(List<Long> billIdList) {if (StringUtils.isEmpty(billIdList)) {throw new ServiceException("车辆运单ID不能为空");}BillDto billDto = new BillDto();billDto.setBillIdList(billIdList);List<BillDto> billList = billFacadeService.queryBillList(billDto);if (StringUtils.isEmpty(billList)) {billList = new ArrayList<>();}return InvoiceWrapper.instance.convertTo(billList);}

3.controller层

controller层的代码需要注意的是:

1.因为导出Excel一般都是通过浏览器进行下载的,所以入参中需要加入HttpServletResponse

2.调用封装的工具类ExcelUtils中的export方法就可以了

查看代码 /*** 车运运单信息导出*/@Log@PostMapping("/exportBillInfo")public void exportBillInfo(@RequestBody @Valid BillListDto dto, HttpServletResponse response) {List<ExportBillVo> list = invoiceFacadeService.exportBillInfo(dto.getBillIdList());ExcelUtils.export(response, "车运运单信息", list, ExportBillVo.class);}

最终导出的Excel文件:

本文链接地址:https://www.jiuchutong.com/zhishi/310776.html 转载请保留说明!

上一篇:分享帝国cms网站优化使tags伪静态的实现方法(帝国cms wordpress)

下一篇:phpcms 不支持iframe怎么办(phpcms插件)

  • 抖音如何改名(抖音如何改名字,为什么显示我重置)

    抖音如何改名(抖音如何改名字,为什么显示我重置)

  • 别人发微信过来不显示(别人发微信过来不显示怎么设置)

    别人发微信过来不显示(别人发微信过来不显示怎么设置)

  • 苹果6gps在哪里打开(苹果6gps定位在哪里设置)

    苹果6gps在哪里打开(苹果6gps定位在哪里设置)

  • 长时间充电对电池的影响大不大(长时间充电对电池有伤害吗)

    长时间充电对电池的影响大不大(长时间充电对电池有伤害吗)

  • win10能直接装回xp吗(win10能直接重装系统吗)

    win10能直接装回xp吗(win10能直接重装系统吗)

  • 电脑主板坏了值得修吗(电脑主板坏了难修吗)

    电脑主板坏了值得修吗(电脑主板坏了难修吗)

  • 华为820处理器什么水平(华为820处理器相当于骁龙多少)

    华为820处理器什么水平(华为820处理器相当于骁龙多少)

  • 苹果se2home键是按的吗(苹果手机se2home键)

    苹果se2home键是按的吗(苹果手机se2home键)

  • 抖音第三方绑定有什么用(抖音第三方绑定微信,微信账号已绑定其他账号)

    抖音第三方绑定有什么用(抖音第三方绑定微信,微信账号已绑定其他账号)

  • vivo手机反应慢卡是什么原因怎样解决(vivo手机反应慢怎么提速)

    vivo手机反应慢卡是什么原因怎样解决(vivo手机反应慢怎么提速)

  • 华为荣耀20s返回键怎么设置(华为荣耀20s返回键怎么更换)

    华为荣耀20s返回键怎么设置(华为荣耀20s返回键怎么更换)

  • 手机的下载管理在哪(手机变成电脑下载)

    手机的下载管理在哪(手机变成电脑下载)

  • 抖音消息有已读吗(抖音消息有已读显示吗)

    抖音消息有已读吗(抖音消息有已读显示吗)

  • iqoo触感按键怎么设置(iqoo3压感按键)

    iqoo触感按键怎么设置(iqoo3压感按键)

  • 文本填充怎么设置(文本填充怎么设置阴影效果设置)

    文本填充怎么设置(文本填充怎么设置阴影效果设置)

  • 美柚怎么用(美柚怎么用淘宝账号登录)

    美柚怎么用(美柚怎么用淘宝账号登录)

  • 微信定位怎么发给别人(微信定位怎么发给QQ好友)

    微信定位怎么发给别人(微信定位怎么发给QQ好友)

  • qqsiri建议怎么关闭(苹果qq建议怎么关闭)

    qqsiri建议怎么关闭(苹果qq建议怎么关闭)

  • 小米蓝牙耳机如何充电(小米蓝牙耳机如何连接)

    小米蓝牙耳机如何充电(小米蓝牙耳机如何连接)

  • 苹果7怎么避免烧基带(苹果怎么避免半夜微信电话挂断)

    苹果7怎么避免烧基带(苹果怎么避免半夜微信电话挂断)

  • 虚拟机安装win7系统详细教程(win10虚拟机安装win7)

    虚拟机安装win7系统详细教程(win10虚拟机安装win7)

  • Win11如何设置快捷键关机 Win11设置快捷键关机的方法(Win11如何设置快捷键调音量)

    Win11如何设置快捷键关机 Win11设置快捷键关机的方法(Win11如何设置快捷键调音量)

  • win10蓝牙搜索不到设备怎么办(win10蓝牙搜索不到ps4手柄)

    win10蓝牙搜索不到设备怎么办(win10蓝牙搜索不到ps4手柄)

  • ‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序?npm i (npm install)安装不上的原因(vue-cli-service权限不够)

    ‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序?npm i (npm install)安装不上的原因(vue-cli-service权限不够)

  • 个税申报吗
  • 生产成本明细科目是材料还是产品
  • 外贸企业指的是什么
  • 百旺金赋的服务费必须交吗
  • 减免的城建税怎么计算
  • 汇算清缴交了税怎么做分录
  • 股东费用如何入账
  • 银行贷款受托支付后,钱怎么转回来
  • 保证金转租金的会计处理
  • 公司员工出差发工资吗
  • 私人出租房子发票怎么开
  • 进口免税店的东西都是正品吗
  • 保险公司多赔付的钱需要退还吗
  • 物业公司代收供暖费,可以开发票吗
  • 吊车租赁费可以开现代服务吗
  • 请问哪些福利费不用交税
  • 转账支票可不可以挂失止付
  • 小规模增值税专票税率
  • 发票开错重开怎么做账?
  • 补发工资如何缴纳工人所得税的法条
  • 设备升级改造如何开发票
  • 简述资产的概念特征以及确认条件
  • 通讯费补贴入什么科目
  • 建筑测量水准仪怎么读数
  • 有限合伙企业需要法人吗
  • 华为matex3爆料
  • 如何在Excel中添加筛选项
  • 鸿蒙系统如何截屏
  • 单位出纳的业务有哪些
  • 个人所得税算少了怎么办
  • 主营业务收入的计算公式
  • 公司收到加盟费怎么做会计分录
  • 在php中,字符串有哪些表示形式
  • window10自带商店下载位置
  • PHP:curl_multi_close()的用法_cURL函数
  • window显示我的电脑
  • php封包
  • 微信小程序 h5页面打不开
  • vue3中使用for循环引用多个组件
  • 溢价收购股权会计处理案例
  • 可视化思考
  • photo-sphere-viewer中文文档
  • input输入语句
  • 有形动产租赁个税是经营所得吗
  • 原材料用于在建工程增值税如何处理
  • 资产的账面价值大于计税基础
  • 企业所得税汇算清缴操作流程
  • 非贸备案什么意思
  • 对公账号可以绑定微信提现吗
  • 仓库物资盘盈盘亏怎么办
  • 营业收入的构成分析应该从哪些方面进行?
  • 纳税人办理普通发票流程
  • 个体工商户定期定额怎么报税
  • 印花税征收范围口诀
  • 国际货运代理免增值税
  • 新冠肺炎疫情相关的公共政策
  • 编写高质量代码改善JAVA程序的151个建议
  • mysql日志的作用
  • xp系统怎么升级版本
  • 电脑周边是什么
  • 启用guest用户
  • gcuservice.exe
  • win1021年更新
  • w8系统ie浏览器在哪
  • w10qq图标不显示
  • win10累积更新卡在正在下载
  • unityc#打不开
  • Knockout visible绑定使用方法
  • linux查找功能
  • 置顶pyq会被自己屏蔽的人看到吗
  • 表单元素的属性
  • unity system
  • Nodejs+express+ejs简单使用实例代码
  • socket python
  • js布局与css布局
  • 请问在javascript程序中
  • js面向对象的三大特性
  • python:\n
  • 地税局公务员工作内容
  • 重庆税务局app下载官网
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号