Java高效實現(xiàn)excel轉(zhuǎn)pdf(支持帶圖片的轉(zhuǎn)換)
本文用java實現(xiàn)excel轉(zhuǎn)pdf文件,并且支持excel單元格中帶有圖片的轉(zhuǎn)換,使用poi來讀取excel文件數(shù)據(jù),用itext來動態(tài)生成pdf文檔,核心代碼如下:
public static byte[] excelToPdf(String excelPath, String pdfPath) throws Exception{
InputStream in = new FileInputStream(excelPath);
Workbook workbook;
if (excelPath.endsWith(".xlsx")){
workbook = new XSSFWorkbook(in);
} else {
workbook = new HSSFWorkbook(in);
}
Sheet sheet = workbook.getSheetAt(0);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Document document = new Document(PageSize.A4);//此處根據(jù)excel大小設置pdf紙張大小
PdfWriter writer = PdfWriter.getInstance(document, stream);
document.setMargins(0, 0, 15, 15);//設置也邊距
document.open();
float[] widths = getColWidth(sheet);
PdfPTable table = new PdfPTable(widths);
table.setWidthPercentage(90);
int colCount = widths.length;
BaseFont baseFont = BaseFont.createFont("C:\\Windows\\Fonts\\simsun.ttc,0", BaseFont.IDENTITY_H,
BaseFont.EMBEDDED);//設置基本字體
for (int r = sheet.getFirstRowNum(); r < sheet.getPhysicalNumberOfRows(); r++) {
Row row = sheet.getRow(r);
if (row != null) {
for (int c = row.getFirstCellNum(); (c < row.getLastCellNum() || c < colCount) && c > -1; c++) {
if (c >= row.getPhysicalNumberOfCells()) {
PdfPCell pCell = new PdfPCell(new Phrase(""));
pCell.setBorder(0);
table.addCell(pCell);
continue;
}
Cell excelCell = row.getCell(c);
String value = "";
if (excelCell != null) {
value = excelCell.toString().trim();
if (value != null && value.length() != 0){
String dataFormat = excelCell.getCellStyle().getDataFormatString();//獲取excel單元格數(shù)據(jù)顯示樣式
if (dataFormat != "General" && dataFormat != "@"){
try {
String numStyle = getNumStyle(dataFormat);
value = numFormat(numStyle, excelCell.getNumericCellValue());
} catch (Exception e) {
}
}
}
}
org.apache.poi.ss.usermodel.Font excelFont = getExcelFont(workbook, excelCell, excelPath);
//HSSFFont excelFont = excelCell.getCellStyle().getFont(workbook);
Font pdFont = new Font(baseFont, excelFont.getFontHeightInPoints(),
excelFont.getBoldweight() == 700 ? Font.BOLD : Font.NORMAL, BaseColor.BLACK);//設置單元格字體
PdfPCell pCell = new PdfPCell(new Phrase(value, pdFont));
List<PicturesInfo> infos = POIExtend.getAllPictureInfos(sheet, r, r, c, c, false);
if (!infos.isEmpty()){
pCell = new PdfPCell(Image.getInstance(infos.get(0).getPictureData()));
PicturesInfo info = infos.get(0);
System.out.println("最大行:" + info.getMaxRow() + "最小行:" + info.getMinRow() + "最大列:" + info.getMaxCol() + "最小列:" + info.getMinCol());;
}
boolean hasBorder = hasBorder(excelCell);
if (!hasBorder){
pCell.setBorder(0);
}
pCell.setHorizontalAlignment(getHorAglin(excelCell.getCellStyle().getAlignment()));
pCell.setVerticalAlignment(getVerAglin(excelCell.getCellStyle().getVerticalAlignment()));
pCell.setMinimumHeight(row.getHeightInPoints());
if (isMergedRegion(sheet, r, c)) {
int[] span = getMergedSpan(sheet, r, c);
if (span[0] == 1 && span[1] == 1) {//忽略合并過的單元格
continue;
}
pCell.setRowspan(span[0]);
pCell.setColspan(span[1]);
c = c + span[1] - 1;//合并過的列直接跳過
}
table.addCell(pCell);
}
} else {
PdfPCell pCell = new PdfPCell(new Phrase(""));
pCell.setBorder(0);
pCell.setMinimumHeight(13);
table.addCell(pCell);
}
}
document.add(table);
document.close();
byte[] pdfByte = stream.toByteArray();
stream.flush();
stream.reset();
stream.close();
FileOutputStream outputStream = new FileOutputStream(pdfPath);
outputStream.write(pdfByte);
outputStream.flush();
outputStream.close();
return pdfByte;
}//獲取字體
private static org.apache.poi.ss.usermodel.Font getExcelFont(Workbook workbook, Cell cell, String excelName){
if (excelName.endsWith(".xls")){
return ((HSSFCell)cell).getCellStyle().getFont(workbook);
}
return ((XSSFCell)cell).getCellStyle().getFont();
}
判斷excel單元格是否有邊框
/**
* 判斷excel單元格是否有邊框
* @param excelCell
* @return
*/
private static boolean hasBorder(Cell excelCell) {
short top = excelCell.getCellStyle().getBorderTop();
short bottom = excelCell.getCellStyle().getBorderBottom();
short left = excelCell.getCellStyle().getBorderLeft();
short right = excelCell.getCellStyle().getBorderRight();
return top + bottom + left + right > 2;
}
獲取excel單元格數(shù)據(jù)顯示格式
/**
* 獲取excel單元格數(shù)據(jù)顯示格式
* @param dataFormat
* @return
* @throws Exception
*/
private static String getNumStyle(String dataFormat) throws Exception {
if (dataFormat == null || dataFormat.length() == 0){
throw new Exception("");
}
if (dataFormat.indexOf("%") > -1){
return dataFormat;
} else{
return dataFormat.substring(0, dataFormat.length()-2);
}
}判斷單元格是否是合并單元格
/**
* 判斷單元格是否是合并單元格
* @param sheet
* @param row
* @param column
* @return
*/
private static boolean isMergedRegion(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
return true;
}
}
}
return false;
}計算合并單元格合并的跨行跨列數(shù)
/**
* 計算合并單元格合并的跨行跨列數(shù)
* @param sheet
* @param row
* @param column
* @return
*/
private static int[] getMergedSpan(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
int[] span = { 1, 1 };
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if (firstColumn == column && firstRow == row) {
span[0] = lastRow - firstRow + 1;
span[1] = lastColumn - firstColumn + 1;
break;
}
}
return span;
}獲取excel中每列寬度的占比
/**
* 獲取excel中每列寬度的占比
* @param sheet
* @return
*/
private static float[] getColWidth(Sheet sheet) {
int rowNum = getMaxColRowNum(sheet);
Row row = sheet.getRow(rowNum);
int cellCount = row.getPhysicalNumberOfCells();
int[] colWidths = new int[cellCount];
int sum = 0;
for (int i = row.getFirstCellNum(); i < cellCount; i++) {
Cell cell = row.getCell(i);
if (cell != null) {
colWidths[i] = sheet.getColumnWidth(i);
sum += sheet.getColumnWidth(i);
}
}
float[] colWidthPer = new float[cellCount];
for (int i = row.getFirstCellNum(); i < cellCount; i++) {
colWidthPer[i] = (float) colWidths[i] / sum * 100;
}
return colWidthPer;
}獲取excel中列數(shù)最多的行號
/**
* 獲取excel中列數(shù)最多的行號
* @param sheet
* @return
*/
private static int getMaxColRowNum(Sheet sheet) {
int rowNum = 0;
int maxCol = 0;
for (int r = sheet.getFirstRowNum(); r < sheet.getPhysicalNumberOfRows(); r++) {
Row row = sheet.getRow(r);
if (row != null && maxCol < row.getPhysicalNumberOfCells()) {
maxCol = row.getPhysicalNumberOfCells();
rowNum = r;
}
}
return rowNum;
}excel垂直對齊方式映射到pdf對齊方式
/**
* excel垂直對齊方式映射到pdf對齊方式
* @param aglin
* @return
*/
private static int getVerAglin(int aglin) {
switch (aglin) {
case 1:
return com.itextpdf.text.Element.ALIGN_MIDDLE;
case 2:
return com.itextpdf.text.Element.ALIGN_BOTTOM;
case 3:
return com.itextpdf.text.Element.ALIGN_TOP;
default:
return com.itextpdf.text.Element.ALIGN_MIDDLE;
}
}excel水平對齊方式映射到pdf水平對齊方式
/**
* excel水平對齊方式映射到pdf水平對齊方式
* @param aglin
* @return
*/
private static int getHorAglin(int aglin) {
switch (aglin) {
case 2:
return com.itextpdf.text.Element.ALIGN_CENTER;
case 3:
return com.itextpdf.text.Element.ALIGN_RIGHT;
case 1:
return com.itextpdf.text.Element.ALIGN_LEFT;
default:
return com.itextpdf.text.Element.ALIGN_CENTER;
}
}格式化數(shù)字
/**
* 格式化數(shù)字
* @param pattern
* @param num
* @return
*/
private static String numFormat(String pattern, double num){
DecimalFormat format = new DecimalFormat(pattern);
return format.format(num);
}
以下代碼是對excel轉(zhuǎn)pdf時對excel中圖片進行處理,實現(xiàn)圖片在pdf中正常顯示
//圖片基本信息
public class PicturesInfo {
private int minRow;
private int maxRow;
private int minCol;
private int maxCol;
private String ext;
private byte[] pictureData;
public PicturesInfo(int minRow, int maxRow, int minCol, int maxCol ,byte[] pictureData, String ext){
this.minRow = minRow;
this.maxRow = maxRow;
this.minCol = minCol;
this.maxCol = maxCol;
this.ext = ext;
this.pictureData = pictureData;
}
public byte[] getPictureData() {
return pictureData;
}
public void setPictureData(byte[] pictureData) {
this.pictureData = pictureData;
}
public int getMinRow() {
return minRow;
}
public void setMinRow(int minRow) {
this.minRow = minRow;
}
public int getMaxRow() {
return maxRow;
}
public void setMaxRow(int maxRow) {
this.maxRow = maxRow;
}
public int getMinCol() {
return minCol;
}
public void setMinCol(int minCol) {
this.minCol = minCol;
}
public int getMaxCol() {
return maxCol;
}
public void setMaxCol(int maxCol) {
this.maxCol = maxCol;
}
public String getExt() {
return ext;
}
public void setExt(String ext) {
this.ext = ext;
}
}以下是獲取excel中圖片數(shù)據(jù)以及位置信息代碼:
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFShapeContainer;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
public class POIExtend {
public static List<PicturesInfo> getAllPictureInfos(Sheet sheet, boolean onlyInternal) throws Exception {
return getAllPictureInfos(sheet, null, null, null, null, onlyInternal);
}
public static List<PicturesInfo> getAllPictureInfos(Sheet sheet, Integer minRow, Integer maxRow, Integer minCol,
Integer maxCol, boolean onlyInternal) throws Exception {
if (sheet instanceof HSSFSheet) {
return getXLSAllPictureInfos((HSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
} else if (sheet instanceof XSSFSheet) {
return getXLSXAllPictureInfos((XSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
} else {
throw new Exception("未處理類型,沒有為該類型添加:GetAllPicturesInfos()擴展方法!");
}
}
private static List<PicturesInfo> getXLSAllPictureInfos(HSSFSheet sheet, Integer minRow, Integer maxRow,
Integer minCol, Integer maxCol, Boolean onlyInternal) {
List<PicturesInfo> picturesInfoList = new ArrayList<>();
HSSFShapeContainer shapeContainer = sheet.getDrawingPatriarch();
if (null != shapeContainer) {
List<HSSFShape> shapeList = shapeContainer.getChildren();
for (HSSFShape shape : shapeList) {
if (shape instanceof HSSFPicture && shape.getAnchor() instanceof HSSFClientAnchor) {
HSSFPicture picture = (HSSFPicture) shape;
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),
anchor.getCol1(), anchor.getCol2(), onlyInternal)) {
picturesInfoList.add(
new PicturesInfo(anchor.getRow1(), anchor.getRow2(), anchor.getCol1(), anchor.getCol2(),
picture.getPictureData().getData(), picture.getPictureData().getMimeType()));
}
}
}
}
return picturesInfoList;
}
private static List<PicturesInfo> getXLSXAllPictureInfos(XSSFSheet sheet, Integer minRow, Integer maxRow,
Integer minCol, Integer maxCol, Boolean onlyInternal) {
List<PicturesInfo> picturesInfoList = new ArrayList<>();
List<POIXMLDocumentPart> documentPartList = sheet.getRelations();
for (POIXMLDocumentPart documentPart : documentPartList) {
if (documentPart instanceof XSSFDrawing) {
XSSFDrawing drawing = (XSSFDrawing) documentPart;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes) {
if (shape instanceof XSSFPicture) {
XSSFPicture picture = (XSSFPicture) shape;
XSSFClientAnchor anchor = picture.getPreferredSize();
if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),
anchor.getCol1(), anchor.getCol2(), onlyInternal)) {
picturesInfoList.add(new PicturesInfo(anchor.getRow1(), anchor.getRow2(), anchor.getCol1(),
anchor.getCol2(), picture.getPictureData().getData(),
picture.getPictureData().getMimeType()));
}
}
}
}
}
return picturesInfoList;
}
private static boolean isInternalOrIntersect(Integer rangeMinRow, Integer rangeMaxRow, Integer rangeMinCol,
Integer rangeMaxCol, int pictureMinRow, int pictureMaxRow, int pictureMinCol, int pictureMaxCol,
Boolean onlyInternal) {
int _rangeMinRow = rangeMinRow == null ? pictureMinRow : rangeMinRow;
int _rangeMaxRow = rangeMaxRow == null ? pictureMaxRow : rangeMaxRow;
int _rangeMinCol = rangeMinCol == null ? pictureMinCol : rangeMinCol;
int _rangeMaxCol = rangeMaxCol == null ? pictureMaxCol : rangeMaxCol;
if (onlyInternal) {
return (_rangeMinRow <= pictureMinRow && _rangeMaxRow >= pictureMaxRow && _rangeMinCol <= pictureMinCol
&& _rangeMaxCol >= pictureMaxCol);
} else {
return ((Math.abs(_rangeMaxRow - _rangeMinRow) + Math.abs(pictureMaxRow - pictureMinRow) >= Math
.abs(_rangeMaxRow + _rangeMinRow - pictureMaxRow - pictureMinRow))
&& (Math.abs(_rangeMaxCol - _rangeMinCol) + Math.abs(pictureMaxCol - pictureMinCol) >= Math
.abs(_rangeMaxCol + _rangeMinCol - pictureMaxCol - pictureMinCol)));
}
}
}以上就是Java高效實現(xiàn)excel轉(zhuǎn)pdf(支持帶圖片的轉(zhuǎn)換)的詳細內(nèi)容,更多關于Java excel轉(zhuǎn)pdf的資料請關注腳本之家其它相關文章!
相關文章
spring中@ControllerAdvice 注解的使用
@ControllerAdvice注解是Spring3.2中新增的注解,主要用于Controller的全局配置,本文就來介紹一下spring中@ControllerAdvice 注解的使用,感興趣的可以了解一下2024-09-09
SpringBoot實現(xiàn)連接nacos并支持多環(huán)境部署
這篇文章主要介紹了SpringBoot實現(xiàn)連接nacos并支持多環(huán)境部署方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
SpringSecurity?跨域資源共享(CORS)的實現(xiàn)
本文主要介紹了SpringSecurity?跨域資源共享,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-09-09
修改SpringBoot 中MyBatis的mapper.xml文件位置的過程詳解
由于MyBatis默認的mapper.xml的掃描位置是resource文件下,但是不可能整個項目的mapper.xml文件都放在resource下,如果文件較少還行,但是如果文件比較多,太麻煩了,所以本文給大家介紹了修改SpringBoot 中MyBatis的mapper.xml文件位置的過程,需要的朋友可以參考下2024-08-08

