Java实现Excel图片URL筛选与大小检测

在数据处理场景中,我们常需筛选Excel中的图片URL。本文分享一个完整的Java方案,涵盖从读取图片URL到检测有效性、筛选大小,再到生成新Excel文件的全过程,同时讲解开发与优化过程,帮助你解决实际业务中的数据筛选和清洗需求。

一、问题背景

客户现场图片数据,要求如下:

  1. 读取Excel的图片URL。
  2. 检测URL有效性并获取图片大小。
  3. 筛选大于1MB或无法访问(404)的图片记录。
  4. 保留原始数据格式,尤其是日期类型数据。
  5. 生成筛选后的新Excel文件。

二、核心实现方案

(一)技术选型

为实现上述目标,我们主要采用以下技术:

  1. Apache POI :用于读取和写入Excel文件,支持对单元格数据的操作及格式处理,能方便地处理XLSX文件。
  2. HttpURLConnection :用于检测图片URL的有效性并获取图片大小,通过发送HEAD请求获取资源信息,避免下载整个图片浪费带宽。

(二)关键代码实现

1. Excel文件读取与写入
package cn.api.server;import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;public class ImageSizeFilter {private static final Logger LOGGER = Logger.getLogger(ImageSizeFilter.class.getName());private static final int CONNECT_TIMEOUT = 5000;private static final int READ_TIMEOUT = 5000;private static final double BYTES_TO_MEGABYTES = 1024.0 * 1024.0;private static final double SIZE_THRESHOLD = 1.0;private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");public static void main(String[] args) {String inputFilePath = "C:/Users/admin/Desktop/图片数据.xlsx";String outputFilePath = "C:/Users/admin/Desktop/图片数据_筛选后.xlsx";System.out.println("开始处理Excel文件...");System.out.println("输入文件: " + inputFilePath);long startTime = System.currentTimeMillis();int processedCount = 0;int filteredCount = 0;try (FileInputStream inputStream = new FileInputStream(new File(inputFilePath));Workbook workbook = new XSSFWorkbook(inputStream)) {Sheet sheet = workbook.getSheetAt(0);int totalRows = sheet.getLastRowNum();System.out.println("发现 " + totalRows + " 条数据记录");try (Workbook newWorkbook = new XSSFWorkbook()) {Sheet newSheet = newWorkbook.createSheet();Row headerRow = sheet.getRow(0);Row newHeaderRow = newSheet.createRow(0);// 复制表头并添加新列copyRow(headerRow, newHeaderRow);createHeaderCell(newHeaderRow, "图片大小(M)");createHeaderCell(newHeaderRow, "状态");int newRowIndex = 1;for (int i = 1; i <= totalRows; i++) {if (i % 100 == 0) {System.out.println("已处理 " + i + "/" + totalRows + " 行");}Row row = sheet.getRow(i);if (row != null) {Cell urlCell = row.getCell(7);if (urlCell != null) {String imageUrl = getCellValue(urlCell);if (isValidUrl(imageUrl)) {processedCount++;long sizeInBytes = getImageSize(imageUrl);double sizeInMegabytes = sizeInBytes / BYTES_TO_MEGABYTES;boolean is404 = sizeInBytes == 0 && isUrl404(imageUrl);if (sizeInMegabytes > SIZE_THRESHOLD || is404) {filteredCount++;Row newRow = newSheet.createRow(newRowIndex++);copyRowWithDateHandling(row, newRow, workbook, newWorkbook);newRow.createCell(headerRow.getLastCellNum()).setCellValue(sizeInMegabytes);newRow.createCell(headerRow.getLastCellNum() + 1).setCellValue(is404 ? "404" : "图片过大");}}}}}try (FileOutputStream outputStream = new FileOutputStream(new File(outputFilePath))) {newWorkbook.write(outputStream);}long endTime = System.currentTimeMillis();System.out.println("筛选完成!耗时:" + (endTime - startTime) / 1000 + " 秒");System.out.println("处理记录数:" + processedCount);System.out.println("筛选出的记录数:" + filteredCount);System.out.println("结果保存至:" + outputFilePath);}} catch (IOException e) {LOGGER.log(Level.SEVERE, "处理文件时出错", e);}}
}

在上述代码中,我们通过FileInputStream读取原始Excel文件,利用XSSFWorkbook将其加载为Workbook对象。然后获取第一个工作表(Sheet),并遍历其行数据。对于筛选出的符合条件的行,我们创建新的Workbook对象(newWorkbook),并在其中创建新的工作表(newSheet),将原始表头复制过来并添加新列 “图片大小(M)” 和 “状态”,用于存储图片大小信息和筛选状态。

2. URL检测与图片大小获取
// 获取图片大小(字节)
private static long getImageSize(String imageUrl) {HttpURLConnection connection = null;try {URL url = new URL(imageUrl);connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("HEAD");connection.setConnectTimeout(CONNECT_TIMEOUT);connection.setReadTimeout(READ_TIMEOUT);connection.connect();return connection.getResponseCode() == HttpURLConnection.HTTP_OK ? connection.getContentLength() : 0;} catch (IOException e) {LOGGER.log(Level.SEVERE, "获取图片大小异常", e);return 0;} finally {if (connection != null) {connection.disconnect();}}
}// 判断URL是否404
private static boolean isUrl404(String imageUrl) {HttpURLConnection connection = null;try {URL url = new URL(imageUrl);connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("HEAD");connection.setConnectTimeout(CONNECT_TIMEOUT);connection.setReadTimeout(READ_TIMEOUT);connection.connect();return connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND;} catch (IOException e) {LOGGER.log(Level.SEVERE, "检测404异常", e);return false;} finally {if (connection != null) {connection.disconnect();}}
}

这里,我们使用HttpURLConnection发送HEAD请求到指定的图片URL。HEAD请求不会下载资源实体内容,只请求资源的头部信息,这样可以快速获取图片的相关信息,如大小等。通过调用connection.getContentLength()方法可获取图片大小(以字节为单位)。同时,我们还定义了isUrl404()方法来判断URL是否返回404状态码,以便识别无法访问的图片。

3. 单元格数据读取与处理
// 获取单元格值(处理日期格式)
private static String getCellValue(Cell cell) {if (cell == null) {return "";}int cellType = cell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:return cell.getStringCellValue();case Cell.CELL_TYPE_NUMERIC:return DateUtil.isCellDateFormatted(cell) ? DATE_FORMAT.format(cell.getDateCellValue()) : String.valueOf(cell.getNumericCellValue());case Cell.CELL_TYPE_BOOLEAN:return String.valueOf(cell.getBooleanCellValue());case Cell.CELL_TYPE_FORMULA:return cell.getCellFormula();default:return "";}
}

在读取Excel单元格数据时,需考虑不同类型的数据处理方式。对于字符串类型单元格,直接获取其字符串值;对于数值型单元格,若其为日期格式(通过DateUtil.isCellDateFormatted(cell)判断),则将其转换为Date对象并按照指定格式(yyyy - MM - dd)格式化为字符串,否则以常规数值形式返回;对于布尔型单元格,返回对应的布尔值字符串;对于公式型单元格,返回其公式内容。

4. 行数据复制
// 复制行(表头专用,不处理日期)
private static void copyRow(Row sourceRow, Row targetRow) {for (int i = 0; i < sourceRow.getLastCellNum(); i++) {Cell sourceCell = sourceRow.getCell(i);Cell targetCell = targetRow.createCell(i);if (sourceCell != null) {int cellType = sourceCell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:targetCell.setCellValue(sourceCell.getStringCellValue());break;case Cell.CELL_TYPE_NUMERIC:targetCell.setCellValue(sourceCell.getNumericCellValue());break;case Cell.CELL_TYPE_BOOLEAN:targetCell.setCellValue(sourceCell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA:targetCell.setCellFormula(sourceCell.getCellFormula());break;}}}
}// 复制行(数据行专用,处理日期格式)
private static void copyRowWithDateHandling(Row sourceRow, Row targetRow, Workbook sourceWorkbook, Workbook targetWorkbook) {for (int i = 0; i < sourceRow.getLastCellNum(); i++) {Cell sourceCell = sourceRow.getCell(i);Cell targetCell = targetRow.createCell(i);if (sourceCell != null) {int cellType = sourceCell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:targetCell.setCellValue(sourceCell.getStringCellValue());break;case Cell.CELL_TYPE_NUMERIC:if (DateUtil.isCellDateFormatted(sourceCell)) {targetCell.setCellValue(sourceCell.getDateCellValue());CellStyle newCellStyle = targetWorkbook.createCellStyle();newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());targetCell.setCellStyle(newCellStyle);} else {targetCell.setCellValue(sourceCell.getNumericCellValue());}break;case Cell.CELL_TYPE_BOOLEAN:targetCell.setCellValue(sourceCell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA:targetCell.setCellFormula(sourceCell.getCellFormula());break;}}}
}

为实现行数据的复制,我们定义了两个方法。copyRow()方法用于复制表头行数据,直接根据单元格类型设置目标单元格的值;copyRowWithDateHandling()方法用于复制数据行,在处理数值型单元格时,会判断其是否为日期格式,若是,则将其作为日期处理并复制对应的单元格样式,以确保日期格式在新Excel文件中正确显示。

三、优化过程详解

(一)初始实现问题

在最初的实现中,我们遇到了以下问题:

  1. 日期格式处理不当 :数值型日期被转为普通数字,导致数据展示不符合预期,例如原本在Excel中显示为 “2024 - 05 - 20” 的日期,在读取后变为一串数字。
  2. Java 8兼容性问题 :最初代码使用了Java 12+的switch表达式,但在实际部署环境中需兼容Java 8,导致代码无法正常运行。
  3. 缺少完整的行复制方法 :在复制行数据时,未能全面处理各种单元格类型及样式,导致新生成的Excel文件数据格式混乱。

(二)日期格式处理优化

通过引入DateUtil.isCellDateFormatted()方法检测单元格是否为日期格式,并使用SimpleDateFormat将Date对象格式化为指定字符串形式,成功解决了日期格式处理问题。优化后的代码如下:

private static String getCellValue(Cell cell) {if (cell == null) {return "";}int cellType = cell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:return cell.getStringCellValue();case Cell.CELL_TYPE_NUMERIC:return DateUtil.isCellDateFormatted(cell) ? DATE_FORMAT.format(cell.getDateCellValue()) : String.valueOf(cell.getNumericCellValue());case Cell.CELL_TYPE_BOOLEAN:return String.valueOf(cell.getBooleanCellValue());case Cell.CELL_TYPE_FORMULA:return cell.getCellFormula();default:return "";}
}

(三)Java 8兼容性改造

将枚举和switch表达式改为传统写法,使用Cell.CELL_TYPE_* 常量,并重构行复制方法,使其在Java 8环境下稳定运行。改造后的行复制方法如下:

private static void copyRowWithDateHandling(Row sourceRow, Row targetRow, Workbook sourceWorkbook, Workbook targetWorkbook) {for (int i = 0; i < sourceRow.getLastCellNum(); i++) {Cell sourceCell = sourceRow.getCell(i);Cell targetCell = targetRow.createCell(i);if (sourceCell != null) {int cellType = sourceCell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:targetCell.setCellValue(sourceCell.getStringCellValue());break;case Cell.CELL_TYPE_NUMERIC:if (DateUtil.isCellDateFormatted(sourceCell)) {targetCell.setCellValue(sourceCell.getDateCellValue());CellStyle newCellStyle = targetWorkbook.createCellStyle();newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());targetCell.setCellStyle(newCellStyle);} else {targetCell.setCellValue(sourceCell.getNumericCellValue());}break;case Cell.CELL_TYPE_BOOLEAN:targetCell.setCellValue(sourceCell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA:targetCell.setCellFormula(sourceCell.getCellFormula());break;}}}
}

(四)完整功能实现

经过上述优化后,我们的代码实现了以下功能:

  1. 准确读取Excel文件中的数据,包括各种类型单元格数据,特别是正确处理了日期格式数据,避免了数据变形问题。
  2. 通过HttpURLConnection有效检测图片URL的合法性及获取图片大小,能够精准筛选出大于1MB或无法访问(404)的图片记录。
  3. 在生成新Excel文件时,完整保留了原始数据的格式,并新增列存储图片大小信息和筛选状态,方便用户查看筛选结果。
  4. 兼容Java 8环境,确保代码在不同版本的JDK下稳定运行,适应更多实际应用场景。

四、使用说明

(一)环境准备

  1. JDK版本 :需安装JDK 8或以上版本。
  2. Maven依赖 :在项目中引入以下Apache POI相关依赖,用于操作Excel文件。
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>

(二)运行方式

  1. 根据实际需求修改main方法中的输入文件路径(inputFilePath)和输出文件路径(outputFilePath),指定待处理的Excel文件和生成结果的保存位置。
  2. 编译项目,运行ImageSizeFilter类的main方法,程序将自动开始处理Excel文件,并在控制台输出处理进度和结果信息。

(三)自定义配置

  1. 图片大小阈值 :可通过修改SIZE_THRESHOLD常量的值来调整图片大小筛选阈值,例如将其改为2.0,则筛选出大于2MB的图片。
  2. 网络连接超时时间 :根据网络状况调整CONNECT_TIMEOUT和READ_TIMEOUT常量的值,以优化图片URL检测过程中的网络连接性能。
  3. 日期显示格式 :若需更改日期在新Excel文件中的显示格式,可修改DATE_FORMAT常量对应的SimpleDateFormat模式,如改为 “yyyy/MM/dd HH:mm:ss” 以包含时间信息。

五、技术总结与扩展方向

(一)关键技术点总结

  1. POI操作Excel :熟练掌握POI对Excel文件的读写操作,包括工作簿、工作表、行、单元格的创建、获取及数据读写,是实现本功能的核心基础。通过合理使用CellStyle等类,可有效控制单元格数据的显示格式。
  2. HttpURLConnection网络请求 :利用HttpURLConnection发送HEAD请求检测图片URL的有效性及获取图片大小,是一种高效且节省带宽的方法。正确设置请求方法、超时时间等参数,可确保网络请求的稳定性和准确性。
  3. Java 8兼容性编程 :在实际项目开发中,考虑到不同环境的兼容性需求,避免使用过高版本的Java特性,采用传统语法结构和常量,能提高代码的通用性和可移植性。
  4. 数据格式处理 :对于Excel中的日期等特殊数据类型,需深入了解其存储和展示原理,通过合理的判断和转换逻辑,确保数据在程序处理过程中及最终结果中的准确性。

(二)可能的扩展方向

  1. 多线程处理 :针对大规模数据处理场景,可考虑引入多线程技术,将Excel文件的行数据分配到多个线程同时进行图片URL检测和筛选操作,从而显著提高处理效率,减少程序运行时间。
  2. 图片预览功能 :在筛选出不符合要求的图片后,为进一步方便用户查看和分析,可增加图片预览功能。例如,利用图像处理库将图片缩略图嵌入到生成的新Excel文件中,或开发一个简单的界面程序展示图片预览。
  3. 支持多种文件格式 :除了Excel文件(.xlsx),还可扩展程序支持CSV等其他常见数据文件格式,以适应更广泛的数据处理需求。这需要根据不同文件格式的特点,调整数据读取、写入及格式处理等相关代码逻辑。
  4. 数据库存储与查询 :对于经过筛选的图片数据及相关信息,可考虑将其存储到数据库中,实现数据的持久化。同时,借助数据库的查询功能,能够方便地对筛选结果进行后续的统计分析、数据检索等操作,为用户提供了一种更灵活的数据管理方式。

六、结语

通过本案例,我们深刻体会到Java在数据处理领域的强大能力以及在实际业务开发中的广泛应用。借助Apache POI和HttpURLConnection等工具和技术,能够高效地实现Excel图片URL的筛选与大小检测功能,并解决实际业务中的数据清洗问题。在开发过程中,注重细节处理,如数据格式保留、跨版本兼容性等,是提升程序质量和用户体验的关键。未来,随着业务需求的不断拓展和技术的持续发展,我们可以对现有程序进行进一步优化和扩展,以满足更多样化的数据处理场景。

希望本文对你有所帮助,如果你在实现过程中遇到任何问题或有任何改进建议,欢迎在评论区留言交流。

附录,所有代码:

package cn.api.server;import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;public class ImageSizeFilter {private static final Logger LOGGER = Logger.getLogger(ImageSizeFilter.class.getName());// 设置连接超时时间(毫秒)private static final int CONNECT_TIMEOUT = 5000;// 设置读取超时时间(毫秒)private static final int READ_TIMEOUT = 5000;// 定义字节到兆字节的转换系数private static final double BYTES_TO_MEGABYTES = 1024.0 * 1024.0;// 图片大小阈值(MB)private static final double SIZE_THRESHOLD = 1.0;// 日期格式private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");public static void main(String[] args) {String inputFilePath = "C:/Users/admin/Desktop/图片数据.xlsx";String outputFilePath = "C:/Users/admin/Desktop/图片数据_筛选后.xlsx";System.out.println("开始处理Excel文件...");System.out.println("输入文件: " + inputFilePath);long startTime = System.currentTimeMillis();int processedCount = 0;int filteredCount = 0;try (FileInputStream inputStream = new FileInputStream(new File(inputFilePath));Workbook workbook = new XSSFWorkbook(inputStream)) {Sheet sheet = workbook.getSheetAt(0);int totalRows = sheet.getLastRowNum();System.out.println("发现 " + totalRows + " 条数据记录");try (Workbook newWorkbook = new XSSFWorkbook()) {Sheet newSheet = newWorkbook.createSheet();// 复制表头,并新增图片大小列和状态列Row headerRow = sheet.getRow(0);Row newHeaderRow = newSheet.createRow(0);copyRow(headerRow, newHeaderRow);createHeaderCell(newHeaderRow, "图片大小(M)");createHeaderCell(newHeaderRow, "状态");int newRowIndex = 1;for (int i = 1; i <= totalRows; i++) {if (i % 100 == 0) {System.out.println("已处理 " + i + "/" + totalRows + " 行");}Row row = sheet.getRow(i);if (row != null) {// 根据实践的Excel表设置数字,这里是第8列Cell urlCell = row.getCell(7);if (urlCell != null) {String imageUrl = getCellValue(urlCell);if (isValidUrl(imageUrl)) {processedCount++;long sizeInBytes = getImageSize(imageUrl);double sizeInMegabytes = sizeInBytes / BYTES_TO_MEGABYTES;boolean is404 = false;if (sizeInBytes == 0) {is404 = isUrl404(imageUrl);}if (sizeInMegabytes > SIZE_THRESHOLD || is404) {filteredCount++;Row newRow = newSheet.createRow(newRowIndex++);copyRowWithDateHandling(row, newRow, workbook, newWorkbook);// 在新行的倒数第二列写入图片大小(M)newRow.createCell(headerRow.getLastCellNum()).setCellValue(sizeInMegabytes);// 在新行的最后一列写入状态newRow.createCell(headerRow.getLastCellNum() + 1).setCellValue(is404 ? "404" : "图片过大");}} else {LOGGER.log(Level.WARNING, "发现不合法的URL (行 {0}): {1}", new Object[]{i, imageUrl});}}}}try (FileOutputStream outputStream = new FileOutputStream(new File(outputFilePath))) {newWorkbook.write(outputStream);}long endTime = System.currentTimeMillis();System.out.println("筛选完成!");System.out.println("处理时间: " + (endTime - startTime) / 1000 + " 秒");System.out.println("处理记录数: " + processedCount);System.out.println("筛选出的记录数: " + filteredCount);System.out.println("结果保存到: " + outputFilePath);} catch (IOException e) {LOGGER.log(Level.SEVERE, "写入输出文件时出错", e);System.err.println("错误: 无法写入输出文件: " + outputFilePath);}} catch (IOException e) {LOGGER.log(Level.SEVERE, "读取输入文件时出错", e);System.err.println("错误: 无法读取输入文件: " + inputFilePath);}}private static long getImageSize(String imageUrl) {HttpURLConnection connection = null;try {URL url = new URL(imageUrl);connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("HEAD");connection.setConnectTimeout(CONNECT_TIMEOUT);connection.setReadTimeout(READ_TIMEOUT);connection.connect();int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {return connection.getContentLength();} else {LOGGER.log(Level.WARNING, "获取图片大小失败,URL: {0},响应码: {1}", new Object[]{imageUrl, responseCode});return 0;}} catch (IOException e) {LOGGER.log(Level.SEVERE, "获取图片大小IO异常,URL: " + imageUrl, e);return 0;} finally {if (connection != null) {connection.disconnect();}}}private static boolean isUrl404(String imageUrl) {HttpURLConnection connection = null;try {URL url = new URL(imageUrl);connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("HEAD");connection.setConnectTimeout(CONNECT_TIMEOUT);connection.setReadTimeout(READ_TIMEOUT);connection.connect();return connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND;} catch (IOException e) {LOGGER.log(Level.SEVERE, "判断 URL 是否 404 时发生 IO 异常,URL: " + imageUrl, e);return false;} finally {if (connection != null) {connection.disconnect();}}}private static String getCellValue(Cell cell) {if (cell == null) {return "";}// 兼容Java 8的写法int cellType = cell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:return cell.getStringCellValue();case Cell.CELL_TYPE_NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {Date date = cell.getDateCellValue();return DATE_FORMAT.format(date);} else {return String.valueOf(cell.getNumericCellValue());}case Cell.CELL_TYPE_BOOLEAN:return String.valueOf(cell.getBooleanCellValue());case Cell.CELL_TYPE_FORMULA:return cell.getCellFormula();default:return "";}}private static boolean isValidUrl(String url) {if (url == null || url.trim().isEmpty()) {return false;}try {new URL(url);return true;} catch (MalformedURLException e) {return false;}}/*** 复制行(用于表头复制,不处理日期格式)*/private static void copyRow(Row sourceRow, Row targetRow) {for (int i = 0; i < sourceRow.getLastCellNum(); i++) {Cell sourceCell = sourceRow.getCell(i);Cell targetCell = targetRow.createCell(i);if (sourceCell != null) {int cellType = sourceCell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:targetCell.setCellValue(sourceCell.getStringCellValue());break;case Cell.CELL_TYPE_NUMERIC:targetCell.setCellValue(sourceCell.getNumericCellValue());break;case Cell.CELL_TYPE_BOOLEAN:targetCell.setCellValue(sourceCell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA:targetCell.setCellFormula(sourceCell.getCellFormula());break;default:break;}}}}/*** 复制行并处理日期格式(用于数据行复制)*/private static void copyRowWithDateHandling(Row sourceRow, Row targetRow, Workbook sourceWorkbook, Workbook targetWorkbook) {for (int i = 0; i < sourceRow.getLastCellNum(); i++) {Cell sourceCell = sourceRow.getCell(i);Cell targetCell = targetRow.createCell(i);if (sourceCell != null) {int cellType = sourceCell.getCellType();switch (cellType) {case Cell.CELL_TYPE_STRING:targetCell.setCellValue(sourceCell.getStringCellValue());break;case Cell.CELL_TYPE_NUMERIC:if (DateUtil.isCellDateFormatted(sourceCell)) {targetCell.setCellValue(sourceCell.getDateCellValue());CellStyle newCellStyle = targetWorkbook.createCellStyle();newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());targetCell.setCellStyle(newCellStyle);} else {targetCell.setCellValue(sourceCell.getNumericCellValue());}break;case Cell.CELL_TYPE_BOOLEAN:targetCell.setCellValue(sourceCell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA:targetCell.setCellFormula(sourceCell.getCellFormula());break;default:break;}}}}private static void createHeaderCell(Row headerRow, String headerValue) {Cell headerCell = headerRow.createCell(headerRow.getLastCellNum());headerCell.setCellValue(headerValue);CellStyle style = headerCell.getSheet().getWorkbook().createCellStyle();Font font = headerCell.getSheet().getWorkbook().createFont();font.setBold(true);style.setFont(font);headerCell.setCellStyle(style);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84156.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84156.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84156.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 实现后端调用 Chromium 浏览器无头模式截图的方案

Java 实现后端调用 Chromium 浏览器无头模式截图的方案 1. 使用 Playwright 优点&#xff1a;功能强大、支持多浏览器&#xff08;Chromium/Firefox/WebKit&#xff09;、支持异步操作。实现方式&#xff1a; 利用 Playwright 创建无头浏览器实例&#xff1b;使用 Java 的调度…

基于多模态文档解析与RAG的行业知识库构建技术指南

1. 技术背景 随着企业非结构化数据&#xff08;扫描件、PDF、图像等&#xff09;占比超过80%&#xff0c;传统关键词检索已无法满足精准问答需求。本文提出融合**计算机视觉&#xff08;CV&#xff09;与大语言模型&#xff08;LLM&#xff09;**的解决方案&#xff0c;关键技…

基于YOLOv11+PP-OCRv5深度学习的智能车牌检测与识别系统python源码+pytorch模型+评估指标曲线+精美GUI界面

【算法介绍】 智能车牌检测与识别系统借助当下前沿的 YOLOv11 算法以及 PP-OCRv5 算法&#xff0c;能够在复杂多样的环境场景中&#xff0c;快速且精准地达成实时车牌检测与识别任务。在现代交通管理领域&#xff0c;该技术意义重大&#xff0c;它能够推动涉及车辆识别与记录的…

[深度学习]全连接神经网络

目录 一、实验目的 二、实验环境 三、实验内容 3.1 完成解压数据集相关操作 3.2分析代码结构并运行代码查看结果 3.3修改超参数&#xff08;批量大小、学习率、Epoch&#xff09;并对比分析不同结果 3.4修改网络结构&#xff08;隐藏层数、神经元个数&#xff09;并对比分…

openEuler安装BenchmarkSQL

BenchmarkSQL是一个用于评估数据库性能的开源工具。它模拟TPC-C&#xff08;Transaction Processing Performance Council&#xff09;基准测试场景&#xff0c;该场景主要用于衡量数据库在处理大量并发事务时的能力。TPC-C测试场景模拟了一个典型的批发分销商的业务环境&#…

分库分表之优缺点分析

大家好&#xff0c;我是工藤学编程 &#x1f989;一个正在努力学习的小博主&#xff0c;期待你的关注实战代码系列最新文章&#x1f609;C实现图书管理系统&#xff08;Qt C GUI界面版&#xff09;SpringBoot实战系列&#x1f437;【SpringBoot实战系列】Sharding-Jdbc实现分库…

【2025年超详细】Git 系列笔记-4 git版本号及git相关指令运用。

系列笔记 【2025年超详细】Git 系列笔记-1 Git简述、Windows下git安装、Linux下git安装_displaying 2e144 commits. adjust this setting in -CSDN博客 【2025年超详细】Git 系列笔记-2 github连接超时问题解决_2025访问github-CSDN博客 【2025年超详细】Git 系列笔记-3 Git…

图像特征检测算法SuperPoint和SuperGlue

SuperPoint 背景与概述 &#xff1a;SuperPoint 是一个自监督的全卷积神经网络&#xff0c;用于提取图像中的兴趣点及其描述子。它在 2018 年由 Magic Leap 提出&#xff0c;通过在合成数据集上预训练一个基础检测器 MagicPoint&#xff0c;然后利用同胚适应技术对真实图像数据…

nginx 和 springcloud gateway cors 跨域如何设置

在跨域资源共享(CORS)配置中,Nginx 和 API Gateway(如Spring Cloud Gateway、Kong等)是两种常见的解决方案,它们的配置逻辑和适用场景有所不同。以下是详细对比和配置示例: 一、核心区别 维度NginxAPI Gateway定位反向代理/Web服务器微服务流量入口配置位置基础设施层应…

电路笔记(信号):一阶低通RC滤波器 一阶线性微分方程推导 拉普拉斯域表达(传递函数、频率响应)分析

目录 RC 低通滤波器电路一阶线性微分方程推导拉普拉斯域表达&#xff08;传递函数&#xff09;传递函数 H ( s ) H(s) H(s)频率响应&#xff08;令 s j ω s j\omega sjω&#xff09;幅频特性&#xff1a;相位特性&#xff1a;Bode 图&#xff08;线性系统频率响应&#x…

【Git】删除远程分支时,本地分支还能看到

当远程仓库的分支被删除后&#xff0c;本地通过 git branch -a 或 git remote show origin 仍能看到这些分支的引用&#xff0c;是因为本地存储的远程跟踪分支&#xff08;位于 refs/remotes/origin/&#xff09;未被同步更新。以下是解决方法&#xff1a; 解决方案&#xff1…

Cubase 通过 MIDIPLUS MIDI 键盘进行走带控制的设置方法

第一步&#xff0c;在官网下载xml配置文件。 https://midiplus.com/upload/202101/29/Xpro & Xpro_mini控制脚本(Cubase).zip 第二步&#xff0c;Cubase中按如图步骤添加映射。 将MIDI键盘连接到电脑后打开Cubase软件&#xff0c;点选菜单“工作室”->“工作室设置”&…

第十八章 Linux之Python定制篇——Python开发平台Ununtu

1. Ubuntu介绍 Ubuntu&#xff08;友帮拓、优般图、乌班图&#xff09;是一个以桌面应用为主的开源GUN/Linux操作系统&#xff0c;Ubuntu基于GUN/Linux&#xff0c;支持x86、amd64&#xff08;即x64&#xff09;和ppc架构&#xff0c;有全球专业开发团队&#xff08;Canonical…

推荐轻量级文生视频模型(Text-to-Video)

1. ModelScope T2V by 阿里达摩院&#xff08;推荐&#xff09; 模型名&#xff1a;damo/text-to-video-synthesis 输入&#xff1a;一句文字描述&#xff08;如&#xff1a;"a panda is dancing"&#xff09; 输出&#xff1a;2秒视频&#xff08;16帧&#xff0c…

流编辑器sed

sed简介 sed是一种流编辑器&#xff0c;处理时&#xff0c;把当前处理的行存储在临时缓冲区中&#xff0c;称为模式空间&#xff0c;接着用sed命令处理缓冲区中的内容&#xff0c;处理完成后&#xff0c;把缓冲区的内容送往屏幕。接着处理下行&#xff0c;这样不断重复&#xf…

商用密码基础知识介绍(上)

一、密码的基础知识 1、密码分类 根据《中华人民共和国密码法》&#xff0c;国家对密码实行分类管理&#xff0c;分为密码分为核心密码、普通密码和商用密码。 &#xff08;1&#xff09;核心密码、普通密码 核心密码、普通密码用于保护国家秘密信息&#xff0c;核心密码保护…

PROFINET主站S7-1500通过协议网关集成欧姆龙NJ系列TCP/IP主站

一、项目背景 某大型新能源电池生产企业&#xff0c;致力于提升电池生产的自动化水平和智能化程度。其生产线上&#xff0c;部分关键设备采用了不同的通信协议。在电池生产的前段工序&#xff0c;如原材料搅拌、涂布等环节&#xff0c;使用了西门子S7-1500系列PLC作为ROFINET协…

Vue3 + TypeScript + Element Plus + el-input 输入框列表按回车聚焦到下一行

应用效果&#xff1a;从第一行输入1&#xff0c;按回车&#xff0c;聚焦到第二行输入2&#xff0c;按回车&#xff0c;聚焦到第三行…… 一、通过元素 id&#xff0c;聚焦到下一行的输入框 关键技术点&#xff1a; 1、动态设置元素 id 属性为&#xff1a;:id"input-appl…

FramePack 全面测评:革新视频生成体验

在 AI 视频生成领域&#xff0c;FramePack 自问世便备受瞩目&#xff0c;它凭借独特的技术架构&#xff0c;号称能打破传统视频生成对高端硬件的依赖&#xff0c;让普通电脑也能产出高质量视频。此次测评&#xff0c;我们将全方位剖析 FramePack&#xff0c;探究它在实际应用中…

html中的table标签以及相关标签

表格标签可以通过指定的标签完成数据展示 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>表格标签</title> </head> <body><table border"2"><!-- tr是表行 r…