|
|
|
@ -2,19 +2,31 @@ package com.dsideal.base.Tools.FillData.ExcelKit;
|
|
|
|
|
|
|
|
|
|
import com.dsideal.base.DataEase.Model.ExcelReader;
|
|
|
|
|
import com.jfinal.kit.StrKit;
|
|
|
|
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
|
|
|
|
import org.apache.poi.openxml4j.util.ZipSecureFile;
|
|
|
|
|
import org.apache.poi.ss.usermodel.*;
|
|
|
|
|
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
|
|
|
|
import org.apache.poi.xssf.usermodel.XSSFFont;
|
|
|
|
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
|
|
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
|
|
import org.apache.poi.xwpf.usermodel.XWPFChart;
|
|
|
|
|
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
|
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
public class ExcelKit {
|
|
|
|
|
|
|
|
|
|
//与python交互使用的excel文件路径
|
|
|
|
|
public static String excelPath = "c:/task.xlsx";
|
|
|
|
|
//执行的python路径,这里我使用的是anaconda3的python,路径自行修改,注意要在这个环境中pip安装了python-docx,否则会报错
|
|
|
|
|
public static String python = "D:\\anaconda3\\envs\\py310\\python.exe";
|
|
|
|
|
//python脚本路径
|
|
|
|
|
public static String py = "D:\\dsWork\\YunNanDsBase\\Py\\TuBiao.py";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 将xls转换为xlsx
|
|
|
|
|
*
|
|
|
|
@ -23,7 +35,7 @@ public class ExcelKit {
|
|
|
|
|
*/
|
|
|
|
|
public static String ConvertXlsToXlsx(String sourceExcel) throws IOException {
|
|
|
|
|
if (sourceExcel.endsWith(".xls")) {
|
|
|
|
|
ExcelUtil.xlsChangeXlsx(sourceExcel, sourceExcel + "x");
|
|
|
|
|
ExcelCoreUtil.xlsChangeXlsx(sourceExcel, sourceExcel + "x");
|
|
|
|
|
//删除旧的文件
|
|
|
|
|
ExcelKit.delExcel(sourceExcel);
|
|
|
|
|
sourceExcel = sourceExcel + "x";
|
|
|
|
@ -135,12 +147,13 @@ public class ExcelKit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<List<String>> readSheet(XSSFWorkbook workbook, int skipRowCount) throws IOException {
|
|
|
|
|
XSSFSheet sheet = workbook.getSheet("Sheet1");
|
|
|
|
|
XSSFSheet sheet = workbook.getSheetAt(0);
|
|
|
|
|
List<List<String>> array = new ArrayList<>();
|
|
|
|
|
//遍历输出sheet的内容
|
|
|
|
|
int rowIndex = 0;
|
|
|
|
|
// 遍历工作表中的所有行
|
|
|
|
|
if (sheet == null) return array;
|
|
|
|
|
|
|
|
|
|
for (Row row : sheet) {
|
|
|
|
|
rowIndex++;
|
|
|
|
|
if (rowIndex <= skipRowCount) continue;//跳过指定的行数
|
|
|
|
@ -330,4 +343,149 @@ public class ExcelKit {
|
|
|
|
|
}
|
|
|
|
|
return --rlt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 调用python+com读取WORD中的图表
|
|
|
|
|
*
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws InterruptedException
|
|
|
|
|
*/
|
|
|
|
|
public static void callPythonRead() throws IOException, InterruptedException {
|
|
|
|
|
delExcel(excelPath);
|
|
|
|
|
// 创建ProcessBuilder对象,并设置Python脚本的路径
|
|
|
|
|
ProcessBuilder processBuilder = new ProcessBuilder(python, py);
|
|
|
|
|
// 重定向错误流到标准输出,这样可以在Java中捕获所有的输出
|
|
|
|
|
processBuilder.redirectErrorStream(true);
|
|
|
|
|
// 启动进程
|
|
|
|
|
Process process = processBuilder.start();
|
|
|
|
|
// 读取Python脚本的输出
|
|
|
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
System.out.println(line);
|
|
|
|
|
}
|
|
|
|
|
// 等待Python脚本执行完成
|
|
|
|
|
process.waitFor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void callPythonPrepare(String docPath, int tuBiaoNum) throws IOException {
|
|
|
|
|
String taskTxt = "c:/task.txt";
|
|
|
|
|
//如果文件存在则删除
|
|
|
|
|
if (new File(taskTxt).exists()) {
|
|
|
|
|
new File(taskTxt).delete();
|
|
|
|
|
}
|
|
|
|
|
//将docPath写入taskTxt,第一行
|
|
|
|
|
//将tuBiaoNum写入taskTxt,第二行
|
|
|
|
|
FileWriter writer = new FileWriter(taskTxt, StandardCharsets.UTF_8);
|
|
|
|
|
writer.write(docPath);
|
|
|
|
|
writer.write("\n");
|
|
|
|
|
writer.write(String.valueOf(tuBiaoNum));
|
|
|
|
|
writer.write("\n");
|
|
|
|
|
writer.flush();
|
|
|
|
|
writer.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 读取excel文件
|
|
|
|
|
* @param excelFilePath
|
|
|
|
|
* @param skipRows
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public static List<List<String>> readExcelToList(String excelFilePath, int skipRows) {
|
|
|
|
|
List<List<String>> data = new ArrayList<>();
|
|
|
|
|
try (FileInputStream inputStream = new FileInputStream(excelFilePath)) {
|
|
|
|
|
Workbook workbook = new XSSFWorkbook(inputStream);
|
|
|
|
|
Sheet sheet = workbook.getSheetAt(0); // 获取第一个Sheet
|
|
|
|
|
|
|
|
|
|
// 创建一个迭代器来遍历行,跳过指定数量的行
|
|
|
|
|
Iterator<Row> rowIterator = sheet.iterator();
|
|
|
|
|
while (skipRows > 0 && rowIterator.hasNext()) {
|
|
|
|
|
rowIterator.next();
|
|
|
|
|
skipRows--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历每一行
|
|
|
|
|
while (rowIterator.hasNext()) {
|
|
|
|
|
Row row = rowIterator.next();
|
|
|
|
|
List<String> rowData = new ArrayList<>();
|
|
|
|
|
// 遍历每一行中的每一列
|
|
|
|
|
Iterator<Cell> cellIterator = row.cellIterator();
|
|
|
|
|
|
|
|
|
|
while (cellIterator.hasNext()) {
|
|
|
|
|
Cell cell = cellIterator.next();
|
|
|
|
|
// 根据单元格的不同类型获取数据
|
|
|
|
|
switch (cell.getCellType()) {
|
|
|
|
|
case STRING:
|
|
|
|
|
rowData.add(cell.getStringCellValue());
|
|
|
|
|
break;
|
|
|
|
|
case NUMERIC:
|
|
|
|
|
if (DateUtil.isCellDateFormatted(cell)) {
|
|
|
|
|
rowData.add(cell.getDateCellValue().toString());
|
|
|
|
|
} else {
|
|
|
|
|
rowData.add(Double.toString(cell.getNumericCellValue()));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BOOLEAN:
|
|
|
|
|
rowData.add(Boolean.toString(cell.getBooleanCellValue()));
|
|
|
|
|
break;
|
|
|
|
|
case FORMULA:
|
|
|
|
|
rowData.add(cell.getCellFormula());
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rowData.add("");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
data.add(rowData);
|
|
|
|
|
}
|
|
|
|
|
workbook.close();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取指定文档中指定图表数据
|
|
|
|
|
*
|
|
|
|
|
* @param docPath 文档路径
|
|
|
|
|
* @param chartNumber 图表序号
|
|
|
|
|
* @param skipRowCount 跳过的行数
|
|
|
|
|
* @return 结果数据
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws InvalidFormatException
|
|
|
|
|
*/
|
|
|
|
|
public static List<List<String>> getChartData(String docPath, int chartNumber, int skipRowCount, int expectLimit) throws IOException, InvalidFormatException, InterruptedException {
|
|
|
|
|
InputStream is = new FileInputStream(docPath);
|
|
|
|
|
ZipSecureFile.setMinInflateRatio(-1.0d);
|
|
|
|
|
XWPFDocument doc = new XWPFDocument(is);
|
|
|
|
|
//排序后的图表
|
|
|
|
|
List<XWPFChart> charts = ExcelKit.getSortListForXWPFChart(doc.getCharts());
|
|
|
|
|
XSSFWorkbook workbook = charts.get(chartNumber).getWorkbook();
|
|
|
|
|
List<List<String>> data = ExcelKit.readSheet(workbook, skipRowCount);
|
|
|
|
|
is.close();
|
|
|
|
|
|
|
|
|
|
//如果达到目标预期的数量,就直接返回poi获取的数据列表
|
|
|
|
|
int totalRow = data.size() + skipRowCount;
|
|
|
|
|
if (totalRow < expectLimit) {
|
|
|
|
|
System.out.println("期望数量>=" + expectLimit + ",现在只有" + totalRow + "条,理解为POI读取WORD图表存在问题,使用Python进行二次获取数据...");
|
|
|
|
|
// 留出足够的com关闭word的时间长度,否则会有异常
|
|
|
|
|
Thread.sleep(3000);
|
|
|
|
|
//否则调用python+com进行再次获取数据列表,这次获取的可能才是对的
|
|
|
|
|
//写入交互文本文件
|
|
|
|
|
ExcelKit.callPythonPrepare(docPath, chartNumber);
|
|
|
|
|
//对图表进行读取
|
|
|
|
|
ExcelKit.callPythonRead();
|
|
|
|
|
//读取生成的EXCEL,使用POI就可以了
|
|
|
|
|
//使用POI
|
|
|
|
|
int skipRows = 1; // 假设我们要跳过第一行
|
|
|
|
|
data = ExcelKit.readExcelToList(ExcelKit.excelPath, skipRows);
|
|
|
|
|
System.out.println("二次获取数据条目数量:" + data.size() + ",期望数量=" + expectLimit);
|
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
System.out.println("期望数量>=" + expectLimit + ",现在有" + totalRow + "条,理解为数据读取正确,直接返回POI获取的数据列表...");
|
|
|
|
|
}
|
|
|
|
|
System.out.println("==========================================================================================================");
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|