Skip to content

Commit

Permalink
feature1:支持excel转换为PDF
Browse files Browse the repository at this point in the history
  • Loading branch information
jipengfei-jpf committed Dec 2, 2024
1 parent d686f61 commit 587971c
Show file tree
Hide file tree
Showing 70 changed files with 995 additions and 5 deletions.
Binary file added doc/font/SimHei.ttf
Binary file not shown.
46 changes: 46 additions & 0 deletions fastexcel-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
<name>fastexcel-core</name>
<version>${revision}</version>

<properties>
<itext.version>7.1.15</itext.version>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
Expand Down Expand Up @@ -61,5 +65,47 @@
<artifactId>fastexcel-support</artifactId>
<version>0.0.1</version>
</dependency>
<!-- itext7 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>${itext.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>io</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>forms</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>pdfa</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>pdftest</artifactId>
<version>${itext.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>${itext.version}</version>
</dependency>
</dependencies>
</project>
19 changes: 19 additions & 0 deletions fastexcel-core/src/main/java/cn/idev/excel/FastExcel.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
package cn.idev.excel;

import cn.idev.excel.fileconvertor.ExcelConverter;
import cn.idev.excel.fileconvertor.FileConverterContext;

import java.io.File;

/**
* This is actually {@link FastExcelFactory}, and short names look better.
*
* @author jipengfei
*/
public class FastExcel extends FastExcelFactory {

/**
* Convert excel to pdf
*
* @param excelFile excel file
* @param pdfFile pdf file
* @param fontPath font path for pdf can be null
* @param sheets sheet index to convert, if null convert all sheets
*/
public static void convertToPdf(File excelFile, File pdfFile, String fontPath, int[] sheets) {
FileConverterContext context = new FileConverterContext(excelFile, pdfFile, fontPath, sheets);
ExcelConverter excelConverter = context.getExcelConverter();
excelConverter.convertToPdf();
}

}
21 changes: 21 additions & 0 deletions fastexcel-core/src/main/java/cn/idev/excel/FastExcelFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,25 @@ public static ExcelReaderSheetBuilder readSheet(Integer sheetNo, String sheetNam
}
return excelReaderSheetBuilder;
}

/**
* Build excel the 'readSheet'
* @param sheetNo Index of sheet,0 base.
* @param sheetName The name of sheet.
* @param numRows The number of rows to read, the default is all, start with 0.
* @return
*/
public static ExcelReaderSheetBuilder readSheet(Integer sheetNo, String sheetName,Integer numRows) {
ExcelReaderSheetBuilder excelReaderSheetBuilder = new ExcelReaderSheetBuilder();
if (sheetNo != null) {
excelReaderSheetBuilder.sheetNo(sheetNo);
}
if (sheetName != null) {
excelReaderSheetBuilder.sheetName(sheetName);
}
if (numRows !=null) {
excelReaderSheetBuilder.numRows(numRows);
}
return excelReaderSheetBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package cn.idev.excel.fileconvertor;

import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.TextAlignment;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.IOException;
import java.util.List;

public abstract class BaseExcelConverter implements ExcelConverter {

private final FileConverterContext context;

public BaseExcelConverter(FileConverterContext context) {
this.context = context;
}

@Override
public void convertToPdf() {
try {
for (int sheetIndex : context.getSheets()) {
processSheet(sheetIndex);
}
context.getDocument().close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void processSheet(int sheetIndex) throws IOException {
Sheet sheet = context.getWorkbook().getSheetAt(sheetIndex);
if (sheet == null || sheet.getRow(0) == null) {
return;
}
float[] columnWidths = getColumnWidths(sheet);
Table table = new Table(columnWidths);

addRowsToTable(table, sheet, columnWidths, context.getFountPath());
// addPicsToTable(table, sheet);

context.getDocument().add(table);
}

protected abstract void addPicsToTable(Table table, Sheet sheet);

private void addRowsToTable(Table table, Sheet sheet, float[] columnWidths, String fontPath) throws IOException {
int lastRowNum = sheet.getLastRowNum() + 1;
int lastCellNum = sheet.getRow(0).getLastCellNum();
for (int i = 0; i < lastRowNum; i++) {
Row row = sheet.getRow(i);
addRowToTable(table, row, lastCellNum, columnWidths, fontPath);
}
}

private void addRowToTable(Table table, Row row, int lastCellNum, float[] columnWidths, String fontPath) throws IOException {
if (row == null) {
addEmptyCells(table, lastCellNum); // 0 for empty row
return;
}

for (int j = 0; j < lastCellNum; j++) {
Cell cell = row.getCell(j);
if (cell != null && !isCellProcessed(cell)) {
// addCellToTable(table, cell, columnWidths, fontPath);
CellRangeAddress cellRange = getCellRangeAddress(cell);
int rowspan = (cellRange != null) ? (cellRange.getLastRow() - cellRange.getFirstRow() + 1) : 1;
int colspan = (cellRange != null) ? (cellRange.getLastColumn() - cellRange.getFirstColumn() + 1) : 1;
if ((cellRange != null)) {
j = cellRange.getLastColumn();
}
float maxWidth = (cellRange != null) ? calculateMaxWidth(columnWidths, cellRange) : columnWidths[j];

com.itextpdf.layout.element.Cell pdfCell = convertCell(cell, rowspan, colspan, maxWidth, fontPath);
table.addCell(pdfCell);
} else if (cell == null) {
addEmptyCell(table);
}
}
}

private float calculateMaxWidth(float[] columnWidths, CellRangeAddress cellRange) {
float maxWidth = 0;
for (int k = cellRange.getFirstColumn(); k < cellRange.getLastColumn(); k++) {
maxWidth += columnWidths[k];
}
return maxWidth;
}

private void addEmptyCell(Table table) {
com.itextpdf.layout.element.Cell pdfCell = new com.itextpdf.layout.element.Cell();
pdfCell.setBorder(com.itextpdf.layout.borders.Border.NO_BORDER);
table.addCell(pdfCell);
}

private void addEmptyCells(Table table, int numberOfCells) {
for (int j = 0; j < numberOfCells; j++) {
addEmptyCell(table);
}
}

protected abstract com.itextpdf.layout.element.Cell convertCell(Cell cell, int rowspan, int colspan, float maxWidth, String fontPath) throws IOException;

public static com.itextpdf.layout.property.VerticalAlignment getVerticalAlignment(VerticalAlignment verticalAlignment) {
switch (verticalAlignment) {
case TOP:
return com.itextpdf.layout.property.VerticalAlignment.TOP;
case BOTTOM:
return com.itextpdf.layout.property.VerticalAlignment.BOTTOM;
case JUSTIFY:
case CENTER:
return com.itextpdf.layout.property.VerticalAlignment.MIDDLE;
}
return com.itextpdf.layout.property.VerticalAlignment.MIDDLE;
}

public static TextAlignment getTextAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment alignment, CellType cellType) {
switch (alignment) {
case LEFT:
return TextAlignment.LEFT;
case RIGHT:
return TextAlignment.RIGHT;
case CENTER:
return TextAlignment.CENTER;
case JUSTIFY:
return TextAlignment.JUSTIFIED;
case GENERAL:
if (cellType == CellType.NUMERIC) {
return TextAlignment.RIGHT;
} else if (cellType == CellType.BOOLEAN) {
return TextAlignment.CENTER;
}
}
return TextAlignment.LEFT;
}

private float[] getColumnWidths(Sheet sheet) {
short lastCellNum = sheet.getRow(0).getLastCellNum();
float[] widths = new float[lastCellNum];
for (int i = 0; i < lastCellNum; i++) {
widths[i] = sheet.getColumnWidthInPixels(i);
}
return widths;
}

private boolean isCellProcessed(Cell cell) {
List<CellRangeAddress> mergedRegions = cell.getSheet().getMergedRegions();
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();

for (CellRangeAddress cellAddresses : mergedRegions) {
if (cellAddresses.getFirstRow() <= rowIndex && cellAddresses.getLastRow() >= rowIndex
&& cellAddresses.getFirstColumn() <= columnIndex && cellAddresses.getLastColumn() >= columnIndex) {
return !(cellAddresses.getFirstRow() == rowIndex && cellAddresses.getFirstColumn() == columnIndex);
}
}
return false;
}

private CellRangeAddress getCellRangeAddress(Cell cell) {
List<CellRangeAddress> mergedRegions = cell.getSheet().getMergedRegions();
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();

for (CellRangeAddress cellAddresses : mergedRegions) {
if (cellAddresses.getFirstRow() == rowIndex && cellAddresses.getFirstColumn() == columnIndex) {
return cellAddresses;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cn.idev.excel.fileconvertor;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;

import java.text.SimpleDateFormat;

public class Excel2PdfUtils {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; // 日期格式
private static final String TRUE_STRING = "TRUE";
private static final String FALSE_STRING = "FALSE";
private static final String EMPTY_STRING = "";

// 使用单例模式确保 SimpleDateFormat 只被创建一次
private static final ThreadLocal<SimpleDateFormat> DATE_FORMATTER = ThreadLocal.withInitial(() ->
new SimpleDateFormat(DATE_FORMAT, LocaleUtil.getUserLocale())
);

public static String getValue(Cell cell) {
if (cell == null) {
return EMPTY_STRING;
}

CellType cellType = cell.getCellType();
switch (cellType) {
case BOOLEAN:
return cell.getBooleanCellValue() ? TRUE_STRING : FALSE_STRING;
case NUMERIC:
return getNumericCellValue(cell);
case STRING:
return cell.getStringCellValue();
default:
return EMPTY_STRING;
}
}

private static String getNumericCellValue(Cell cell) {
if (DateUtil.isCellDateFormatted(cell)) {
return DATE_FORMATTER.get().format(cell.getDateCellValue());
}
return String.valueOf(cell.getNumericCellValue());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cn.idev.excel.fileconvertor;

import java.io.File;

/**
* Excel convert to other file
* @author jipengfei
*/
public interface ExcelConverter {

/**
* excel to pdf
*
*/
void convertToPdf();

}
Loading

0 comments on commit 587971c

Please sign in to comment.