|
@@ -26,6 +26,7 @@ import org.jsoup.nodes.Element;
|
|
|
import org.jsoup.select.Elements;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springblade.common.utils.CommonUtil;
|
|
|
import org.springblade.common.utils.SnowFlakeUtil;
|
|
|
import org.springblade.core.boot.ctrl.BladeController;
|
|
|
import org.springblade.core.log.exception.ServiceException;
|
|
@@ -345,18 +346,10 @@ public class WbsTreeContractController extends BladeController {
|
|
|
WbsTreePrivate treePrivateTab = jdbcTemplate.query("select * from m_wbs_tree_private where p_key_id = " + pKeyId, new BeanPropertyRowMapper<>(WbsTreePrivate.class)).stream().findAny().orElse(null);
|
|
|
if (treePrivateTab != null && treePrivateTab.getHtmlUrl() != null) {
|
|
|
htmlUrl = treePrivateTab.getHtmlUrl();
|
|
|
- //<开始>-----------本地测试 下载html到本地
|
|
|
-// htmlUrl = FileUtils.getNetUrl(htmlUrl);
|
|
|
-// String localFilePath = "D:\\file\\downfile\\1792757075013533696.html";
|
|
|
-// downloadHtmlAndSave(htmlUrl, localFilePath);
|
|
|
-// htmlUrl =localFilePath;
|
|
|
- //本地测试 下载html到本地-----------<结束>
|
|
|
fileName = ObjectUtil.isNotEmpty(treePrivateTab.getFullName()) ? treePrivateTab.getFullName() : treePrivateTab.getNodeName();
|
|
|
}
|
|
|
} else {
|
|
|
htmlUrl = tab.getHtmlUrl();
|
|
|
-// htmlUrl = "C:\\Users\\泓创研发01\\Desktop\\fsdownload\\1783774897227431936.html";
|
|
|
-// htmlUrl="D:\\web\\html\\1848904722870697984.html";
|
|
|
fileName = ObjectUtil.isNotEmpty(tab.getFullName()) ? tab.getFullName() : tab.getNodeName();
|
|
|
}
|
|
|
|
|
@@ -364,14 +357,14 @@ public class WbsTreeContractController extends BladeController {
|
|
|
throw new ServiceException("未获取到对应的表的html信息");
|
|
|
}
|
|
|
|
|
|
- //将html转换为excel
|
|
|
+ //将html转换为excel]
|
|
|
+
|
|
|
+ htmlUrl = CommonUtil.replaceOssUrl(htmlUrl);
|
|
|
+ InputStream htmlInputStream = FileUtils.getInputStreamByUrl(htmlUrl);
|
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
|
LoadOptions lo = new LoadOptions(LoadFormat.HTML);
|
|
|
- workbook = new Workbook(htmlUrl,lo);
|
|
|
-// InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(htmlUrl);
|
|
|
-// workbook = new com.spire.xls.Workbook();
|
|
|
-// workbook.loadFromHtml(inputStreamByUrl);
|
|
|
-// workbook.loadFromHtml("D:\\BaiduNetdiskDownload\\1783381225877012480.html");
|
|
|
+ workbook = new Workbook(htmlInputStream,lo);
|
|
|
+
|
|
|
workbook.save(byteArrayOutputStream, SaveFormat.XLSX);
|
|
|
|
|
|
//将转换的spireExcel存储到流中
|
|
@@ -384,7 +377,7 @@ public class WbsTreeContractController extends BladeController {
|
|
|
//存储需要修改的单元格和相关信息的列表
|
|
|
List<CellModificationInfo> cellsToModify = new ArrayList<>();
|
|
|
//解析html 获取合并单元格
|
|
|
- InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tab.getHtmlUrl());
|
|
|
+ InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(htmlUrl);
|
|
|
String htmlString = IoUtil.readToString(inputStreamByUrl);
|
|
|
Document doc = Jsoup.parse(htmlString);
|
|
|
Element table = doc.select("table").first();
|
|
@@ -394,25 +387,84 @@ public class WbsTreeContractController extends BladeController {
|
|
|
List<CellRangeAddress> mergedRegions = new ArrayList<>();
|
|
|
// 保存需要保留的单元格内容和样式
|
|
|
Map<CellRangeAddress, String> data = new HashMap<>();
|
|
|
+ Map<Integer,Integer> rowHeight = new HashMap<>();
|
|
|
// 记录每个单元格的位置和合并信息
|
|
|
- for (Element row1 : rows) {
|
|
|
+ for (int i=0;i<rows.size();i++) {
|
|
|
+ Element row1 = rows.get(i);
|
|
|
Elements cells = row1.select("td, th");
|
|
|
- for (Element cell : cells) {
|
|
|
-
|
|
|
- int rowspan = cell.hasAttr("rowspan") ? Integer.parseInt(cell.attr("rowspan")) : -1;
|
|
|
- int colspan = cell.hasAttr("colspan") ? Integer.parseInt(cell.attr("colspan")) : -1;
|
|
|
- int x1 = cell.hasAttr("x1") ? Integer.parseInt(cell.attr("x1")) - 1 : -1;//起始列
|
|
|
- int x2 = cell.hasAttr("x2") ? Integer.parseInt(cell.attr("x2")) - 1 : -1;//结束列
|
|
|
- int y1 = cell.hasAttr("y1") ? Integer.parseInt(cell.attr("y1")) - 1 : -1;//起始行
|
|
|
- int y2 = cell.hasAttr("y2") ? Integer.parseInt(cell.attr("y2")) - 1 : -1;//结束行
|
|
|
+ int colVal = 0;
|
|
|
+ int index = 0;
|
|
|
+ for (int j=0;j<cells.size();j++) {
|
|
|
+ Element cell = cells.get(j);
|
|
|
+ // 获取html每行的高度
|
|
|
+ String style = cell.attr("style");
|
|
|
+ Pattern pattern = Pattern.compile("height:\\s*(\\d+)px");
|
|
|
+ Matcher matcher = pattern.matcher(style);
|
|
|
+ if (matcher.find()) {
|
|
|
+ int height = Integer.parseInt(matcher.group(1));
|
|
|
+ if(height>0){
|
|
|
+ rowHeight.put(i, height); // 记录行高
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int rowspan = cell.hasAttr("rowspan") ? Integer.parseInt(cell.attr("rowspan")) : 1; //
|
|
|
+ int colspan = cell.hasAttr("colspan") ? Integer.parseInt(cell.attr("colspan")) : 1;
|
|
|
+ int x1 =-1;
|
|
|
+ int x2 =-1;
|
|
|
+ int y1 =-1;
|
|
|
+ int y2 =-1;
|
|
|
+
|
|
|
+ if(cell.hasAttr("x1") && cell.hasAttr("y1")){ //直接获取
|
|
|
+ x1 = Integer.parseInt(cell.attr("x1")) - 1; //: -1;//起始列
|
|
|
+ x2 = Integer.parseInt(cell.attr("x2")) - 1; //: -1;//结束列
|
|
|
+ y1 = Integer.parseInt(cell.attr("y1")) - 1; //: -1;//起始行
|
|
|
+ y2 = Integer.parseInt(cell.attr("y2")) - 1; //: -1;//结束行
|
|
|
+ colVal=x2+1;
|
|
|
+ }else{
|
|
|
+ Elements ids = cell.getElementsByAttribute("id");
|
|
|
+ if(ids.size()==1){
|
|
|
+ Element cell2 = ids.get(0);
|
|
|
+ x1 = Integer.parseInt(cell2.attr("x1")) - 1; //: -1;//起始列
|
|
|
+ x2 = Integer.parseInt(cell2.attr("x2")) - 1; //: -1;//结束列
|
|
|
+ y1 = Integer.parseInt(cell2.attr("y1")) - 1; //: -1;//起始行
|
|
|
+ y2 = Integer.parseInt(cell2.attr("y2")) - 1; //: -1;//结束行
|
|
|
+ colVal=x2+1;
|
|
|
+ }else{
|
|
|
+ System.out.println(cell.text());
|
|
|
+
|
|
|
+ if(i <=80) {
|
|
|
+ if (j == 0) {
|
|
|
+ x1 = 0;
|
|
|
+ x2 = colspan - 1;
|
|
|
+ y1 = i;
|
|
|
+ y2 = i + rowspan - 1;
|
|
|
+ colVal = x2 + 1;
|
|
|
+ } else {
|
|
|
+ if(colspan>=2){
|
|
|
+ x1 = colVal;
|
|
|
+ x2 = colVal + colspan - 1;
|
|
|
+ }else{
|
|
|
+ x1 = colVal;
|
|
|
+ x2 = colVal ;
|
|
|
+ }
|
|
|
+
|
|
|
+ y1 = i;
|
|
|
+ y2 = i + rowspan - 1;
|
|
|
+ colVal = x2 + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 记录合并区域
|
|
|
if (x1 != -1 && x2 != -1 && y1 != -1 && y2 != -1) {
|
|
|
- if(rowspan != -1 || colspan != -1){
|
|
|
+ if(rowspan >=2 || colspan >=2){
|
|
|
CellRangeAddress region = new CellRangeAddress(y1, y2, x1, x2);
|
|
|
mergedRegions.add(region);
|
|
|
data.put(region, cell.text());
|
|
|
}
|
|
|
}
|
|
|
+ index ++;
|
|
|
}
|
|
|
}
|
|
|
// 按顺序合并单元格(从上到下、从左到右)
|
|
@@ -426,6 +478,13 @@ public class WbsTreeContractController extends BladeController {
|
|
|
for (Row row : poiSheet) {
|
|
|
//判断当前行是否是最大列 如果不是 就补充到最大列
|
|
|
short lastCellNum = row.getLastCellNum();
|
|
|
+
|
|
|
+ int rowIndex = row.getRowNum();
|
|
|
+ if (rowHeight.containsKey(rowIndex)) {
|
|
|
+ // 将像素转换为POI的行高单位(1px ≈ 0.75 points)
|
|
|
+ row.setHeightInPoints(rowHeight.get(rowIndex) * 0.75f);
|
|
|
+ }
|
|
|
+
|
|
|
if(maxColumns > lastCellNum){
|
|
|
for (int i = maxColumns - 1; i > lastCellNum; i--) {
|
|
|
row.createCell(i);
|
|
@@ -505,6 +564,231 @@ public class WbsTreeContractController extends BladeController {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ public static void maiqqn(String[] args) throws Exception {
|
|
|
+ String htmlUrl = "/Users/hongchuangyanfa/fsdownload/1892816666778140672.html";
|
|
|
+
|
|
|
+ InputStream htmlInputStream = new FileInputStream(new File(htmlUrl));
|
|
|
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
|
+ LoadOptions lo = new LoadOptions(LoadFormat.HTML);
|
|
|
+ Workbook workbook = new Workbook(htmlInputStream,lo);
|
|
|
+
|
|
|
+ workbook.save(byteArrayOutputStream, SaveFormat.XLSX);
|
|
|
+
|
|
|
+ //将转换的spireExcel存储到流中
|
|
|
+ byte[] excelBytes = byteArrayOutputStream.toByteArray();
|
|
|
+
|
|
|
+ //把spireExcel转为poiExcel
|
|
|
+ try (InputStream inputStream = new ByteArrayInputStream(excelBytes)) {
|
|
|
+ org.apache.poi.ss.usermodel.Workbook poiWorkbook = new XSSFWorkbook(inputStream);
|
|
|
+ Sheet poiSheet = poiWorkbook.getSheetAt(0); //获取第一个工作表
|
|
|
+ //存储需要修改的单元格和相关信息的列表
|
|
|
+ List<CellModificationInfo> cellsToModify = new ArrayList<>();
|
|
|
+ //解析html 获取合并单元格
|
|
|
+ InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(htmlUrl);
|
|
|
+ String htmlString = IoUtil.readToString(inputStreamByUrl);
|
|
|
+ Document doc = Jsoup.parse(htmlString);
|
|
|
+ Element table = doc.select("table").first();
|
|
|
+ Elements rows = table.select("tr");
|
|
|
+ //最大列数
|
|
|
+ int maxColumns = calculateMaxColumns(rows);
|
|
|
+ List<CellRangeAddress> mergedRegions = new ArrayList<>();
|
|
|
+ // 保存需要保留的单元格内容和样式
|
|
|
+ Map<CellRangeAddress, String> data = new HashMap<>();
|
|
|
+ Map<Integer,Integer> rowHeight = new HashMap<>();
|
|
|
+ // 记录每个单元格的位置和合并信息
|
|
|
+
|
|
|
+ for (int i=0;i<rows.size();i++) {
|
|
|
+ Element row1 = rows.get(i);
|
|
|
+ Elements cells = row1.select("td, th");
|
|
|
+ for (int j=0;j<cells.size();j++) {
|
|
|
+ Element cell = cells.get(j);
|
|
|
+ int rowspan = cell.hasAttr("rowspan") ? Integer.parseInt(cell.attr("rowspan")) : 1;
|
|
|
+ int colspan = cell.hasAttr("colspan") ? Integer.parseInt(cell.attr("colspan")) : 1;
|
|
|
+ int x1 =-1;
|
|
|
+ int x2 =-1;
|
|
|
+ int y1 =-1;
|
|
|
+ int y2 =-1;
|
|
|
+ if(cell.hasAttr("x1") && cell.hasAttr("y1")){ //直接获取
|
|
|
+ x1 = Integer.parseInt(cell.attr("x1")) - 1; //: -1;//起始列
|
|
|
+ x2 = Integer.parseInt(cell.attr("x2")) - 1; //: -1;//结束列
|
|
|
+ y1 = Integer.parseInt(cell.attr("y1")) - 1; //: -1;//起始行
|
|
|
+ y2 = Integer.parseInt(cell.attr("y2")) - 1; //: -1;//结束行
|
|
|
+ }else{
|
|
|
+ Elements ids = cell.getElementsByAttribute("id");
|
|
|
+ if(ids.size()==1){
|
|
|
+ Element cell2 = ids.get(0);
|
|
|
+ x1 = Integer.parseInt(cell2.attr("x1")) - 1; //: -1;//起始列
|
|
|
+ x2 = Integer.parseInt(cell2.attr("x2")) - 1; //: -1;//结束列
|
|
|
+ y1 = Integer.parseInt(cell2.attr("y1")) - 1; //: -1;//起始行
|
|
|
+ y2 = Integer.parseInt(cell2.attr("y2")) - 1; //: -1;//结束行
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ for (int i=0;i<rows.size();i++) {
|
|
|
+ Element row1 = rows.get(i);
|
|
|
+ Elements cells = row1.select("td, th");
|
|
|
+ int rowVal = 0;
|
|
|
+ int colVal = 0;
|
|
|
+ int index = 0;
|
|
|
+ for (int j=0;j<cells.size();j++) {
|
|
|
+ Element cell = cells.get(j);
|
|
|
+ // 获取html每行的高度
|
|
|
+ String style = cell.attr("style");
|
|
|
+ Pattern pattern = Pattern.compile("height:\\s*(\\d+)px");
|
|
|
+ Matcher matcher = pattern.matcher(style);
|
|
|
+ if (matcher.find()) {
|
|
|
+ int height = Integer.parseInt(matcher.group(1));
|
|
|
+ if(height>0){
|
|
|
+ rowHeight.put(i, height); // 记录行高
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ int rowspan = cell.hasAttr("rowspan") ? Integer.parseInt(cell.attr("rowspan")) : 1;
|
|
|
+ int colspan = cell.hasAttr("colspan") ? Integer.parseInt(cell.attr("colspan")) : 1;
|
|
|
+ int x1 =-1;
|
|
|
+ int x2 =-1;
|
|
|
+ int y1 =-1;
|
|
|
+ int y2 =-1;
|
|
|
+
|
|
|
+ if(cell.hasAttr("x1") && cell.hasAttr("y1")){ //直接获取
|
|
|
+ x1 = Integer.parseInt(cell.attr("x1")) - 1; //: -1;//起始列
|
|
|
+ x2 = Integer.parseInt(cell.attr("x2")) - 1; //: -1;//结束列
|
|
|
+ y1 = Integer.parseInt(cell.attr("y1")) - 1; //: -1;//起始行
|
|
|
+ y2 = Integer.parseInt(cell.attr("y2")) - 1; //: -1;//结束行
|
|
|
+ colVal=x2+1;
|
|
|
+ }else{
|
|
|
+ Elements ids = cell.getElementsByAttribute("id");
|
|
|
+ if(ids.size()==1){
|
|
|
+ Element cell2 = ids.get(0);
|
|
|
+ x1 = Integer.parseInt(cell2.attr("x1")) - 1; //: -1;//起始列
|
|
|
+ x2 = Integer.parseInt(cell2.attr("x2")) - 1; //: -1;//结束列
|
|
|
+ y1 = Integer.parseInt(cell2.attr("y1")) - 1; //: -1;//起始行
|
|
|
+ y2 = Integer.parseInt(cell2.attr("y2")) - 1; //: -1;//结束行
|
|
|
+ colVal=x2+1;
|
|
|
+ }else{
|
|
|
+ System.out.println(cell.text());
|
|
|
+
|
|
|
+ if(i ==9 ) {
|
|
|
+ if (j == 0) {
|
|
|
+ x1 = 0;
|
|
|
+ x2 = colspan - 1;
|
|
|
+ y1 = i;
|
|
|
+ y2 = i + rowspan - 1;
|
|
|
+ colVal = x2 + 1;
|
|
|
+ } else {
|
|
|
+ if(colspan>=2){
|
|
|
+ x1 = colVal;
|
|
|
+ x2 = colVal + colspan - 1;
|
|
|
+ }else{
|
|
|
+ x1 = colVal;
|
|
|
+ x2 = colVal ;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(rowspan>=2){
|
|
|
+ y1 = i;
|
|
|
+ y2 = i + rowspan - 1;
|
|
|
+ }else{
|
|
|
+ y1 = i;
|
|
|
+ y2 = i ;
|
|
|
+ }
|
|
|
+ colVal = x2 + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录合并区域
|
|
|
+ if (x1 != -1 && x2 != -1 && y1 != -1 && y2 != -1) {
|
|
|
+ if(rowspan >=2 || colspan >=2){
|
|
|
+ CellRangeAddress region = new CellRangeAddress(y1, y2, x1, x2);
|
|
|
+ mergedRegions.add(region);
|
|
|
+ data.put(region, cell.text());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ index ++;
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ // 按顺序合并单元格(从上到下、从左到右)
|
|
|
+ for (int i = poiSheet.getNumMergedRegions() - 1; i >= 0; i--) {
|
|
|
+ poiSheet.removeMergedRegion(i);
|
|
|
+ }
|
|
|
+ for (CellRangeAddress region : mergedRegions) {
|
|
|
+ poiSheet.addMergedRegion(region);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Row row : poiSheet) {
|
|
|
+ //判断当前行是否是最大列 如果不是 就补充到最大列
|
|
|
+ short lastCellNum = row.getLastCellNum();
|
|
|
+
|
|
|
+ int rowIndex = row.getRowNum();
|
|
|
+ if (rowHeight.containsKey(rowIndex)) {
|
|
|
+ // 将像素转换为POI的行高单位(1px ≈ 0.75 points)
|
|
|
+ row.setHeightInPoints(rowHeight.get(rowIndex) * 0.75f);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(maxColumns > lastCellNum){
|
|
|
+ for (int i = maxColumns - 1; i > lastCellNum; i--) {
|
|
|
+ row.createCell(i);
|
|
|
+ Cell cell = row.getCell(i);
|
|
|
+ //设置新单元格的样式为第一个单元格的样式
|
|
|
+ cell.setCellStyle(row.getCell(0).getCellStyle());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Cell cell : row) {
|
|
|
+ int cellType = cell.getCellType();
|
|
|
+ if (cellType == CellType.STRING.getCode() && ObjectUtil.isNotEmpty(cell.getStringCellValue())) {
|
|
|
+ //存储需要修改的单元格信息
|
|
|
+ cellsToModify.add(new CellModificationInfo(cell, cell.getStringCellValue().trim()));
|
|
|
+ }
|
|
|
+ //获取单元格所属的合并单元格区域
|
|
|
+ CellRangeAddress mergedRegion = findMergedRegion(poiSheet, cell.getRowIndex(), cell.getColumnIndex());
|
|
|
+ if (mergedRegion != null) {
|
|
|
+ //合并单元格的数据 为之前记录的数据
|
|
|
+ cell.setCellValue(data.get(mergedRegion));
|
|
|
+
|
|
|
+ //存储需要修改的合并单元格信息
|
|
|
+ cellsToModify.add(new CellModificationInfo(cell, mergedRegion));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //遍历结束后,实际修改单元格样式和内容
|
|
|
+ for (CellModificationInfo info : cellsToModify) {
|
|
|
+ Cell cell = info.getCell();
|
|
|
+ //只更新非合并单元格的数据
|
|
|
+ if (info.getMergedRegion() == null && info.hasStringContent()) {
|
|
|
+ cell.setCellValue(info.getStringContent());
|
|
|
+ }
|
|
|
+ //复制单元格样式
|
|
|
+ CellStyle cellStyle = poiWorkbook.createCellStyle();
|
|
|
+
|
|
|
+ CellStyle sourceCellStyle = cell.getCellStyle(); //获取原单元格的样式
|
|
|
+ cellStyle.cloneStyleFrom(sourceCellStyle); //复制样式
|
|
|
+ setBlackBorder(cellStyle); //设置边框
|
|
|
+ cell.setCellStyle(cellStyle);
|
|
|
+ }
|
|
|
+
|
|
|
+ //返回响应
|
|
|
+ FileOutputStream outputStream = new FileOutputStream("/Users/hongchuangyanfa/Desktop/22222/123.xlsx");
|
|
|
+ poiWorkbook.write(outputStream);
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("下载excel时出现异常:" + e.getMessage(), e);
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
// 计算最大列数以对齐所有行
|
|
|
private static int calculateMaxColumns(Elements rows) {
|
|
|
return rows.stream()
|