Forráskód Böngészése

pdf导入(northern1)

zhouxingyu 1 hete
szülő
commit
0ea8b18abb

+ 18 - 1
srm-module-code/pom.xml

@@ -27,6 +27,23 @@
             <groupId>org.jeecgframework.boot</groupId>
             <artifactId>jeecg-system-biz</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>pdfbox</artifactId>
+            <version>2.0.24</version>
+        </dependency>
+        <dependency>
+            <groupId>technology.tabula</groupId>
+            <artifactId>tabula</artifactId>
+            <version>1.0.5</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>slf4j-simple</artifactId>
+                    <groupId>org.slf4j</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
     </dependencies>
 
-</project>
+</project>

+ 53 - 1
srm-module-code/src/main/java/org/jeecg/modules/saleCode/controller/SaleInterfaceSyncController.java

@@ -1,19 +1,34 @@
 package org.jeecg.modules.saleCode.controller;
 
+import java.awt.*;
+import java.io.File;
 import java.io.UnsupportedEncodingException;
 import java.io.IOException;
 import java.net.URLDecoder;
 import java.util.*;
+import java.util.List;
 import java.util.stream.Collectors;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import ch.qos.logback.core.util.Loader;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.lowagie.text.pdf.PdfDocument;
+import com.lowagie.text.pdf.PdfReader;
+import com.lowagie.text.pdf.parser.PdfTextExtractor;
 import org.apache.commons.lang.StringUtils;
 import org.jeecg.modules.baseCode.entity.BaseProductArchive;
 import org.jeecg.modules.saleCode.entity.*;
 import org.jeecg.modules.saleCode.mapper.SaleInterfaceSyncMapper;
 import org.jeecg.modules.saleCode.service.ISaleInquiryFormService;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.text.PDFTextStripper;
+import org.apache.pdfbox.text.TextPosition;
+import org.jeecg.modules.saleCode.entity.SaleInterfaceSync;
+import org.jeecg.modules.saleCode.entity.SaleOrder;
+import org.jeecg.modules.saleCode.util.PDFTableReader;
+import org.jeecg.modules.system.entity.SysDictItem;
 import org.jeecgframework.poi.excel.ExcelImportUtil;
 import org.jeecgframework.poi.excel.def.NormalExcelConstants;
 import org.jeecgframework.poi.excel.entity.ExportParams;
@@ -467,4 +482,41 @@ public class SaleInterfaceSyncController {
         return Result.OK("文件导入失败!");
     }
 
-}
+	 /**
+	  * 导入
+	  */
+	 //@RequiresPermissions("saleCode:sale_interface_sync:importCls")
+	 @ApiOperation(value="导入PDF", notes="导入PDF")
+	 @RequestMapping(value = "/importPDF", method = RequestMethod.POST)
+	 public Result<?> importCls(HttpServletRequest request, HttpServletResponse response, String type) {
+		 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+		 MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
+		 try {
+			 // ----- 读取pdf内容到字符串 -----
+//			 StringBuilder content = new StringBuilder();
+//			 PdfReader reader = new PdfReader(file.getBytes());
+//			 PdfTextExtractor pdfTextExtractor = new PdfTextExtractor(reader);
+//			 for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
+//				 content.append(pdfTextExtractor.getTextFromPage(page));
+//				 content.append("\n");
+//			 }
+//			 reader.close();
+			// Map<String, Float> point = PDFTableReader.getPoint(file, txt);
+
+
+			 PDDocument document = PDDocument.load(file.getInputStream());
+			 PDFTextStripper pdfStripper = new PDFTextStripper();
+			 String text = pdfStripper.getText(document);
+
+			 //PDFTableReader.load(document);
+			 //根据字符串解析订单
+			 saleInterfaceSyncService.parsePdfByType(type, text, file);
+			 return Result.ok("导入成功");
+		 }catch (Exception ex){
+			 return Result.error(ex.getMessage());
+		 }
+	 }
+
+
+
+ }

+ 10 - 3
srm-module-code/src/main/java/org/jeecg/modules/saleCode/service/ISaleInterfaceSyncService.java

@@ -4,6 +4,8 @@ import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.saleCode.entity.SaleInterfaceItem;
 import org.jeecg.modules.saleCode.entity.SaleInterfaceSync;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.springframework.web.multipart.MultipartFile;
+
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
@@ -24,7 +26,7 @@ public interface ISaleInterfaceSyncService extends IService<SaleInterfaceSync> {
 	 * @param saleInterfaceItemList
 	 */
 	public void saveMain(SaleInterfaceSync saleInterfaceSync,List<SaleInterfaceItem> saleInterfaceItemList) ;
-	
+
 	/**
 	 * 修改一对多
 	 *
@@ -32,14 +34,14 @@ public interface ISaleInterfaceSyncService extends IService<SaleInterfaceSync> {
    * @param saleInterfaceItemList
 	 */
 	public void updateMain(SaleInterfaceSync saleInterfaceSync,List<SaleInterfaceItem> saleInterfaceItemList);
-	
+
 	/**
 	 * 删除一对多
 	 *
 	 * @param id
 	 */
 	public void delMain (String id);
-	
+
 	/**
 	 * 批量删除一对多
 	 *
@@ -54,4 +56,9 @@ public interface ISaleInterfaceSyncService extends IService<SaleInterfaceSync> {
 	 */
 	public Result<String> actionSyncOrder (Collection<? extends Serializable> idList);
 
+	/**
+	 * 根据文件名解析pdf文件
+	 */
+	void parsePdfByType(String type, String txt, MultipartFile file) throws Exception;
+
 }

+ 229 - 1
srm-module-code/src/main/java/org/jeecg/modules/saleCode/service/impl/SaleInterfaceSyncServiceImpl.java

@@ -1,13 +1,14 @@
 package org.jeecg.modules.saleCode.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.alibaba.fastjson.JSONArray;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
 import io.micrometer.core.instrument.util.StringUtils;
 import io.swagger.annotations.ApiModelProperty;
 import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.system.vo.DictModel;
 import org.jeecg.common.system.vo.LoginUser;
@@ -23,19 +24,28 @@ import org.jeecg.modules.cuspCode.mapper.CuspCustomerProfileManMapper;
 import org.jeecg.modules.cuspCode.service.ICuspCustomerProfileService;
 import org.jeecg.modules.saleCode.entity.*;
 import org.jeecg.modules.saleCode.mapper.*;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.UUIDGenerator;
+import org.jeecg.modules.saleCode.entity.SaleInterfaceSync;
+import org.jeecg.modules.saleCode.entity.SaleInterfaceItem;
+import org.jeecg.modules.saleCode.mapper.SaleInterfaceItemMapper;
+import org.jeecg.modules.saleCode.mapper.SaleInterfaceSyncMapper;
 import org.jeecg.modules.saleCode.service.ISaleInterfaceSyncService;
 import org.jeecg.modules.saleCode.util.HttpUtils;
+import org.jeecg.modules.saleCode.util.PDFTableReader;
 import org.jeecg.modules.system.mapper.SysDictMapper;
 import org.jeecgframework.poi.excel.annotation.Excel;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.Instant;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @Description: 询价单-接口同步表
@@ -488,6 +498,224 @@ public class SaleInterfaceSyncServiceImpl extends ServiceImpl<SaleInterfaceSyncM
 
     }
 
+    @Override
+    public void parsePdfByType(String type, String txt, MultipartFile file) throws Exception{
+        switch(type) {
+            case "0" :
+                parseCSL(txt);
+            case "1" :
+                parseNorthern(txt, file);
+            case "2" :
+                parseNorthern2(txt, file);
+            case "3" :
+                parseBSM(txt, file);
+            case "7" :
+                parseWarine(txt, file);
+            default:
+                return;
+        }
+    }
+
+    public void parseCSL(String txt) {
+        String[] nodes = txt.split("\n");
+        SaleInterfaceSync saleInterfaceSync = new SaleInterfaceSync();
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        saleInterfaceSync.setCreateBy(sysUser.getUsername());
+        for(int index = 0; index < nodes.length; index ++) {
+            if(nodes[index].contains("Request For Quote No.")) {
+                saleInterfaceSync.setReferenceNumber(nodes[index].replace("Request For Quote No. ", ""));
+            }
+            if(nodes[index].contains("Spare Part Type")) {
+                saleInterfaceSync.setPriority(nodes[index - 1]);
+            }
+            if(nodes[index].contains("Account Code")) {
+                saleInterfaceSync.setBuyerName(nodes[index].replace("Account Code ", ""));
+            }
+            if(nodes[index].contains("Account Code")) {
+                saleInterfaceSync.setBuyerName(nodes[index].replace("Account Code ", ""));
+            }
+        }
+    }
+
+    public void parseNorthern(String txt, MultipartFile file) throws Exception{
+        String[] nodes = txt.split("\n");
+        SaleInterfaceSync saleInterfaceSync = new SaleInterfaceSync();
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        String id = UUIDGenerator.generate();
+        saleInterfaceSync.setId(id);
+        saleInterfaceSync.setCreateBy(sysUser.getUsername());
+        List<String> buyerNodes = PDFTableReader.getMultipleLineFields(file, "Supplier", "RFQ Details", true);
+        List<String> RFQNodes = PDFTableReader.getMultipleLineFields(file, "RFQ Details", "Buyer Message", true);
+        List<String> detailNodes = PDFTableReader.getMultipleLineFields(file, "UoM", "", true);
+        saleInterfaceSync.setBuyerName(PDFTableReader.getNextLineFields(file, "Company Name:").get(0));
+        saleInterfaceSync.setSupplierName(PDFTableReader.getNextLineFields(file, "Name:").get(1));
+        saleInterfaceSync.setBuyerContactName(PDFTableReader.getNextLineFields(file, "Contact:").get(0));
+        saleInterfaceSync.setBuyerTelephone(PDFTableReader.getNextLineFields(file, "Phone:").get(0));
+        saleInterfaceSync.setReferenceNumber(PDFTableReader.getNextLineFields(file, "Requisition No.:").get(0));
+        saleInterfaceSync.setVesselImo(PDFTableReader.getNextLineFields(file, "IMO:").get(0));
+        saleInterfaceSync.setVesselCode(PDFTableReader.getNextLineFields(file, "Vessel:").get(0));
+        saleInterfaceSync.setCurrencyCode(PDFTableReader.getNextLineFields(file, "Requested Currency:").get(0));
+
+        detailNodes = detailNodes.stream().filter(item -> !item.contains("Page")).collect(Collectors.toList());
+        int detailIndex = 0;
+        if(detailNodes != null) {
+            detailIndex = detailNodes.indexOf("1");
+            while(detailIndex + 7 <= detailNodes.size()) {
+                SaleInterfaceItem saleInterfaceItem = new SaleInterfaceItem();
+                saleInterfaceItem.setDescription(detailNodes.get(detailIndex + 1));
+                saleInterfaceItem.setQuantity(detailNodes.get(detailIndex + 5));
+                saleInterfaceItem.setSyncItemCode(detailNodes.get(detailIndex + 2));
+                saleInterfaceItem.setUnitOfMeasure(detailNodes.get(detailIndex + 6));
+                saleInterfaceItem.setHeadId(id);
+                saleInterfaceItemMapper.insert(saleInterfaceItem);
+                detailIndex += 7;
+
+            }
+
+        }
+        saleInterfaceSyncMapper.insert(saleInterfaceSync);
+
+    }
+
+    public void parseNorthern2(String txt, MultipartFile file) {
+        String[] nodes = txt.split("\n");
+        SaleInterfaceSync saleInterfaceSync = new SaleInterfaceSync();
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        String id = UUIDGenerator.generate();
+        saleInterfaceSync.setId(id);
+        saleInterfaceSync.setCreateBy(sysUser.getUsername());
+        List<String> detailNodes = PDFTableReader.getMultipleLineFields(file, "Enquiry", "Vendor Details", true);
+        saleInterfaceSync.setBuyerName(PDFTableReader.getNextLineFields(file, "Company Name:").get(0));
+        saleInterfaceSync.setSupplierName(PDFTableReader.getNextLineFields(file, "Name:").get(1));
+        saleInterfaceSync.setBuyerContactName(PDFTableReader.getNextLineFields(file, "Contact:").get(0));
+        saleInterfaceSync.setBuyerTelephone(PDFTableReader.getNextLineFields(file, "Phone:").get(0));
+        saleInterfaceSync.setReferenceNumber(PDFTableReader.getNextLineFields(file, "Requisition No.:").get(0));
+        saleInterfaceSync.setVesselImo(PDFTableReader.getNextLineFields(file, "IMO:").get(0));
+        saleInterfaceSync.setVesselCode(PDFTableReader.getNextLineFields(file, "Vessel:").get(0));
+        saleInterfaceSync.setCurrencyCode(PDFTableReader.getNextLineFields(file, "Requested Currency:").get(0));
+
+        int detailIndex = 0;
+        if(detailNodes != null) {
+            detailIndex = detailNodes.indexOf("1");
+            while(detailIndex < detailNodes.size()) {
+                SaleInterfaceItem saleInterfaceItem = new SaleInterfaceItem();
+                saleInterfaceItem.setDescription(detailNodes.get(detailIndex + 1));
+                saleInterfaceItem.setQuantity(detailNodes.get(detailIndex + 5));
+                saleInterfaceItem.setSyncItemCode(detailNodes.get(detailIndex + 2));
+                saleInterfaceItem.setUnitOfMeasure(detailNodes.get(detailIndex + 6));
+                saleInterfaceItem.setHeadId(id);
+                // saleInterfaceItemMapper.insert(saleInterfaceItem);
+                detailIndex += 7;
+
+            }
+
+        }
+        //   saleInterfaceSyncMapper.insert(saleInterfaceSync);
+
+    }
+
+    public void parseBSM(String txt, MultipartFile file) {
+        String[] nodes = txt.split("\n");
+        SaleInterfaceSync saleInterfaceSync = new SaleInterfaceSync();
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        String id = UUIDGenerator.generate();
+        saleInterfaceSync.setId(id);
+        saleInterfaceSync.setCreateBy(sysUser.getUsername());
+        //List<String> detailNodes = PDFTableReader.getMultipleLineFields(file, "Enquiry", "Vendor Details");
+//        saleInterfaceSync.setBuyerName(PDFTableReader.getNextLineFields(file, "Company Name:").get(0));
+//        saleInterfaceSync.setSupplierName(PDFTableReader.getNextLineFields(file, "Name:").get(1));
+//        saleInterfaceSync.setBuyerContactName(PDFTableReader.getNextLineFields(file, "Contact:").get(0));
+//        saleInterfaceSync.setBuyerTelephone(PDFTableReader.getNextLineFields(file, "Phone:").get(0));
+        saleInterfaceSync.setReferenceNumber(PDFTableReader.getFields(file, "Enquiry Number", "Printed On", true).get(0).trim());
+//        saleInterfaceSync.setVesselImo(PDFTableReader.getNextLineFields(file, "IMO:").get(0));
+        saleInterfaceSync.setVesselCode(PDFTableReader.getFields(file, "Vessel  Name", "Quote By", true).get(0).trim());
+        saleInterfaceSync.setCurrencyCode(PDFTableReader.getFields(file, "Currency", "", true).get(0).trim());
+
+        List<String> detailNodesPart1 = PDFTableReader.getMultipleLineFields(file, "Item Details", "1 of 2", false);
+        List<String> detailNodesPart2 = PDFTableReader.getMultipleLineFields(file, "Item Details", "Remarks To Vendor :", false);
+
+        List<String> fieldList = new ArrayList<>();
+        fieldList.add("S.No");
+        fieldList.add("Item Code");
+        fieldList.add("Item Description");
+        fieldList.add("Drawing Number");
+        fieldList.add("Part Number");
+        fieldList.add("Unit");
+        fieldList.add("Quantity");
+        fieldList.add("MD");
+        fieldList.add("SDoC");
+        fieldList.add("Origin of Product");
+        fieldList.add("MD");
+        fieldList.add("MD");
+        JSONArray table = PDFTableReader.getTable(file, fieldList);
+        List<String> strings = new ArrayList<>();
+//        int detailIndex = 0;
+//        if(detailNodes != null) {
+//            detailIndex = detailNodes.indexOf("1");
+//            while(detailIndex < detailNodes.size()) {
+//                SaleInterfaceItem saleInterfaceItem = new SaleInterfaceItem();
+//                saleInterfaceItem.setDescription(detailNodes.get(detailIndex + 1));
+//                saleInterfaceItem.setQuantity(detailNodes.get(detailIndex + 5));
+//                saleInterfaceItem.setSyncItemCode(detailNodes.get(detailIndex + 2));
+//                saleInterfaceItem.setUnitOfMeasure(detailNodes.get(detailIndex + 6));
+//                saleInterfaceItem.setHeadId(id);
+//                saleInterfaceItemMapper.insert(saleInterfaceItem);
+//                detailIndex += 7;
+//
+//            }
+//
+//        }
+//        saleInterfaceSyncMapper.insert(saleInterfaceSync);
+
+    }
+
+    public void parseWarine(String txt, MultipartFile file) {
+        String[] nodes = txt.split("\n");
+        SaleInterfaceSync saleInterfaceSync = new SaleInterfaceSync();
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        String id = UUIDGenerator.generate();
+        saleInterfaceSync.setId(id);
+        saleInterfaceSync.setCreateBy(sysUser.getUsername());
+        List<String> buyerNodes = PDFTableReader.getMultipleLineFields(file, "Supplier", "RFQ Details", true);
+        List<String> RFQNodes = PDFTableReader.getMultipleLineFields(file, "RFQ Details", "Buyer Message", true);
+        saleInterfaceSync.setBuyerName(PDFTableReader.getNextLineFields(file, "Company Name:").get(0));
+        saleInterfaceSync.setSupplierName(PDFTableReader.getNextLineFields(file, "Name:").get(1));
+        saleInterfaceSync.setBuyerContactName(PDFTableReader.getNextLineFields(file, "Contact:").get(0));
+        saleInterfaceSync.setBuyerTelephone(PDFTableReader.getNextLineFields(file, "Phone:").get(0));
+        saleInterfaceSync.setReferenceNumber(PDFTableReader.getNextLineFields(file, "Requisition No.:").get(0));
+        saleInterfaceSync.setVesselImo(PDFTableReader.getNextLineFields(file, "IMO:").get(0));
+        saleInterfaceSync.setVesselCode(PDFTableReader.getNextLineFields(file, "Vessel:").get(0));
+
+        List<String> fieldList = new ArrayList<>();
+        fieldList.add("No.");
+        fieldList.add("Description");
+        fieldList.add("Item Code/Part");
+        fieldList.add("Ref. No.");
+        fieldList.add("Drawing");
+        fieldList.add("Quantity");
+        fieldList.add("UoM");
+        JSONArray table = PDFTableReader.getTable(file, fieldList);
+
+        int detailIndex = 0;
+//        if(detailNodes != null) {
+//            detailIndex = detailNodes.indexOf("1");
+//            while(detailIndex < detailNodes.size()) {
+//                SaleInterfaceItem saleInterfaceItem = new SaleInterfaceItem();
+//                saleInterfaceItem.setDescription(detailNodes.get(detailIndex + 1));
+//                saleInterfaceItem.setQuantity(detailNodes.get(detailIndex + 5));
+//                saleInterfaceItem.setSyncItemCode(detailNodes.get(detailIndex + 2));
+//                saleInterfaceItem.setUnitOfMeasure(detailNodes.get(detailIndex + 6));
+//                saleInterfaceItem.setHeadId(id);
+//                //saleInterfaceItemMapper.insert(saleInterfaceItem);
+//                detailIndex += 7;
+//
+//            }
+//
+//        }
+        //saleInterfaceSyncMapper.insert(saleInterfaceSync);
+
+    }
+
 
     @Override
     @Transactional(rollbackFor = Exception.class)

+ 419 - 0
srm-module-code/src/main/java/org/jeecg/modules/saleCode/util/PDFTableReader.java

@@ -0,0 +1,419 @@
+package org.jeecg.modules.saleCode.util;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.logging.log4j.util.Strings;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.text.PDFTextStripper;
+import org.apache.pdfbox.text.TextPosition;
+import org.springframework.web.multipart.MultipartFile;
+import technology.tabula.*;
+import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+
+public class PDFTableReader<T> {
+    // 换行符
+    private final static String LINE_WRAP = "\r";
+    /**
+     * PDF数据缓冲器
+     */
+    private final List<Map<String, String>> dataBuff = new ArrayList<>();
+    private final transient File pdfFile;
+    /**
+     * 表格标题属性
+     */
+    private final PDFTitle[] pdfTitles;
+
+    /**
+     * 标题所在行号
+     * 默认第一行
+     */
+    private int titleRowIndex = 0;
+
+    /**
+     * 描述信息
+     */
+    private String keyInfo;
+    /**
+     * 关键信息所在页起始下标,从0开始
+     */
+    private int keyInfoPageNumber;
+    /**
+     * 关键信息所在行起始下标
+     */
+    private int keyInfoLineStartIndex;
+    /**
+     * 关键信息所在行结束下标
+     */
+    private int keyInfoLineEndIndex;
+    // 表格映射实体类
+    private final Class<T> beanClass;
+
+    private PDFTableReader(File pdfFile, Class<T> beanClass) {
+        this.pdfFile = pdfFile;
+        this.beanClass = beanClass;
+        if (beanClass == null) {
+            throw new RuntimeException("必须指定读取表格数据的实体类");
+        }
+        Field[] fields = beanClass.getDeclaredFields();
+        pdfTitles = new PDFTitle[fields.length];
+        for (int i = 0; i < fields.length; i++) {
+            Field field = fields[i];
+            TableTitle title = field.getAnnotation(TableTitle.class);
+            if (title == null) {
+                throw new RuntimeException(field.getName() + " attribute miss annotation TableTitle");
+            }
+            pdfTitles[i] = new PDFTitle(title.cellIndex(), title.value(), title.trimSpace());
+        }
+    }
+
+    public static <T> PDFTableReader<T> load(File pdfFile, Class<T> beanClass) {
+        return new PDFTableReader<T>(pdfFile, beanClass);
+    }
+
+    /**
+     * 设置PDF表格标题所在行号
+     *
+     * @param titleRowIndex - 表头标题所在行下标,从0开始
+     */
+    public PDFTableReader<T> titleRowIndex(int titleRowIndex) {
+        this.titleRowIndex = titleRowIndex;
+        return this;
+    }
+
+    /**
+     * 设置PDF描述信息
+     *
+     * @param keyInfoPageNumber     - 关键信息所在页起始下标,从0开始
+     * @param keyInfoLineStartIndex - 关键信息所在行起始下标,从0开始
+     * @param keyInfoLineEndIndex   - 关键信息所在行结束下标,从0开始
+     */
+    public PDFTableReader<T> describe(int keyInfoPageNumber, int keyInfoLineStartIndex, int keyInfoLineEndIndex) {
+        this.keyInfoPageNumber = keyInfoPageNumber;
+        this.keyInfoLineStartIndex = keyInfoLineStartIndex;
+        this.keyInfoLineEndIndex = keyInfoLineEndIndex;
+        return this;
+    }
+
+    public List<Map<String, String>> readMaps() {
+        return this.doRead();
+    }
+
+    public List<T> readBeans() {
+        List<T> beans = new ArrayList<>();
+        List<Map<String, String>> maps = this.doRead();
+        T bean;
+        try {
+            for (Map<String, String> map : maps) {
+                bean = this.beanClass.newInstance();
+                Field[] fields = bean.getClass().getDeclaredFields();
+                for (Field field : fields) {
+                    TableTitle title = field.getAnnotation(TableTitle.class);
+                    if (title == null) {
+                        continue;
+                    }
+                    if (!field.isAccessible()) {
+                        field.setAccessible(true);
+                    }
+                    field.set(bean, map.get(title.value()));
+                }
+                beans.add(bean);
+            }
+            return beans;
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    private List<Map<String, String>> doRead() {
+        try (PDDocument document = PDDocument.load(pdfFile)) {
+            // 读取描述
+            this.doReadKeyInfo(document);
+            // 读取表格
+            List<Map<String, String>> maps = new ArrayList<>();
+            SpreadsheetExtractionAlgorithm sea = new SpreadsheetExtractionAlgorithm();
+            PageIterator pi = new ObjectExtractor(document).extract();
+            Map<String, String> cellMap;
+            int rowNum = 0;// 行计数器
+            while (pi.hasNext()) {
+                Page page = pi.next();
+                List<Table> tables = sea.extract(page);
+                for (Table table : tables) {
+                    List<List<RectangularTextContainer>> rows = table.getRows();
+                    if (rows.size() <= titleRowIndex) {
+                        throw new RuntimeException("标题行不正确");
+                    }
+                    for (List<RectangularTextContainer> row : rows) {
+                        if (rowNum <= titleRowIndex) {
+                            rowNum++;
+                            continue;
+                        }
+                        // 处理表格数据
+                        cellMap = new HashMap<>(row.size());
+                        for (int k = 0; k < row.size(); k++) {
+                            RectangularTextContainer cell = row.get(k);
+                            PDFTitle pdfTitle = pdfTitles[k];
+                            // 如果标题列下标不匹配,跳过
+                            if (pdfTitle.getCellIndex() != k) {
+                                continue;
+                            }
+                            // 换行处理,此处需要调用
+                            String cellText = cell.getText();
+                            cellText = cellText == null ? "" : cellText.trim();
+                            if (pdfTitle.isTrimSpace()) {
+                                cellMap.put(pdfTitle.getName(), cellText.replace(LINE_WRAP, ""));
+                            } else {
+                                cellMap.put(pdfTitle.getName(), cellText.replace(LINE_WRAP, " "));
+                            }
+                        }
+                        maps.add(cellMap);
+                        rowNum++;
+                    }
+                }
+            }
+            this.dataBuff.addAll(maps);
+            return maps;
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    private void doReadKeyInfo(PDDocument document) throws IOException {
+        PDFTextStripper stripper = new PDFTextStripper();
+        stripper.setSortByPosition(true); //sort:设置为true 则按照行进行读取,默认是false
+        stripper.setStartPage(keyInfoPageNumber);
+        stripper.setEndPage(keyInfoPageNumber + 1);
+        String result = stripper.getText(document);
+        result = result.replaceAll("\n", "");
+        String[] split = result.split(LINE_WRAP);
+        if (keyInfoLineStartIndex >= split.length || keyInfoLineEndIndex >= split.length) {
+            throw new RuntimeException("关键信息所在列已超出读取页码行的范围");
+        }
+        StringBuilder r = new StringBuilder();
+        for (int i = keyInfoLineStartIndex; i <= keyInfoLineEndIndex; i++) {
+            String line = split[i];
+            if (line == null || line.trim().equals("")) {
+                continue;
+            }
+            r.append(line.trim());
+        }
+        this.keyInfo = r.toString();
+    }
+
+    public List<Map<String, String>> getDataBuff() {
+        return dataBuff;
+    }
+
+    public String getKeyInfo() {
+        return keyInfo;
+    }
+
+    // PDF表格标题属性
+    @Getter
+    @AllArgsConstructor
+    static class PDFTitle {
+        // 标题所在列下标,从0开始
+        private int cellIndex;
+        // 标题名称
+        private String name;
+        // 需要去掉空格
+        private boolean trimSpace;
+    }
+
+    public static Map<String, Float> getPoint(MultipartFile file, String sourceTex) {
+        Map<String, Float> points = new HashMap<>();
+        //获取文档坐标
+        try {
+            PDDocument document =  PDDocument.load(file.getInputStream());
+            PDFTextStripper textStripper = new PDFTextStripper() {
+                @Override
+                protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
+                    if (text.contains(sourceTex)) {
+                        TextPosition textPositionStart = textPositions.get(0);
+                        TextPosition textPositionEnd = textPositions.get(textPositions.size()-1);
+                        points.put("x", textPositionStart.getX());
+                        points.put("y", textPositionStart.getX());
+                    }
+                }
+            };
+
+            textStripper.setSortByPosition(true);
+            textStripper.setStartPage(1);
+            textStripper.setEndPage(document.getNumberOfPages());
+
+            textStripper.getText(document);
+
+            document.close();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return points;
+    }
+
+    public static List<String> getFields(MultipartFile file, String startText, String endText, boolean sort) {
+        //获取文档坐标
+        List<String> result = new ArrayList<>();
+        try {
+            PDDocument document =  PDDocument.load(file.getInputStream());
+            PDFTextStripper textStripper = new PDFTextStripper() {
+                @Override
+                protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
+                    if(text.contains(startText)) {
+                        int startIndex = 0;
+                        int endIndex = text.length();
+                        if(Strings.isNotBlank(startText)) {
+                            startIndex = text.indexOf(startText);
+                        }
+                        if(Strings.isNotBlank(endText)) {
+                            endIndex = text.indexOf(endText, startIndex + startText.length());
+                        }
+                        if(startIndex == -1) {
+                            startIndex = 0;
+                        }
+                        if(endIndex == -1) {
+                            endIndex = text.length();
+                        }
+                        result.add(text.substring(startIndex + startText.length(), endIndex));
+                    }
+                }
+            };
+
+            textStripper.setSortByPosition(sort);
+            textStripper.setStartPage(1);
+            textStripper.setEndPage(document.getNumberOfPages());
+
+            textStripper.getText(document);
+
+            document.close();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        if(result == null && result.size() == 0) {
+            result.add(" ");
+        }
+        return result;
+    }
+
+
+    public static List<String> getMultipleLineFields(MultipartFile file, String lineStartText, String lineEndText, boolean sort) {
+        //获取文档坐标
+        List<String> result = new ArrayList<>();
+        final boolean[] startRecord = {false};
+        try {
+            PDDocument document =  PDDocument.load(file.getInputStream());
+            PDFTextStripper textStripper = new PDFTextStripper() {
+                @Override
+                protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
+                    if(text.contains(lineStartText)) {
+                        startRecord[0] = true;
+                    }
+                    if(Strings.isNotEmpty(lineEndText)) {
+                        if(text.contains(lineEndText)) {
+                            startRecord[0] = false;
+                            return;
+                        }
+                    }
+                    if(startRecord[0]) {
+                        result.add(text);
+                    }
+                }
+            };
+
+            textStripper.setSortByPosition(sort);
+            textStripper.setStartPage(1);
+            textStripper.setEndPage(document.getNumberOfPages());
+
+            textStripper.getText(document);
+
+            document.close();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        if(result == null && result.size() == 0) {
+            result.add(" ");
+        }
+        return result;
+    }
+
+    public static List<String> getNextLineFields(MultipartFile file, String lineStartText) {
+        //获取文档坐标
+        List<String> result = new ArrayList<>();
+        final boolean[] startRecord = {false};
+        try {
+            PDDocument document =  PDDocument.load(file.getInputStream());
+            PDFTextStripper textStripper = new PDFTextStripper() {
+                @Override
+                protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
+                    if(text.contains(lineStartText)) {
+                        startRecord[0] = true;
+                        return;
+                    }
+                    if(startRecord[0]) {
+                        result.add(text);
+                        startRecord[0] = false;
+                    }
+                }
+            };
+
+            textStripper.setSortByPosition(true);
+            textStripper.setStartPage(1);
+            textStripper.setEndPage(document.getNumberOfPages());
+
+            textStripper.getText(document);
+
+            document.close();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        if(result == null && result.size() == 0) {
+            result.add(" ");
+        }
+        return result;
+    }
+
+    public static JSONArray getTable(MultipartFile file, List<String> header) {
+
+
+        JSONArray jsonArray = new JSONArray();
+        SpreadsheetExtractionAlgorithm algorithm = new SpreadsheetExtractionAlgorithm();
+
+        try (PDDocument document = PDDocument.load(file.getInputStream())) {
+            ObjectExtractor extractor = new ObjectExtractor(document);
+            PageIterator pi = extractor.extract();
+            // 遍历页
+            while (pi.hasNext()) {
+                Page page = pi.next();
+                List<Table> tableList = algorithm.extract(page);
+                // 遍历表
+                for (Table table : tableList) {
+                    List<List<RectangularTextContainer>> rowList = table.getRows();
+                    // 遍历行
+                    for (List<RectangularTextContainer> row : rowList) {
+                        JSONObject jsonObject = new JSONObject();
+                        // 遍历列
+                        for (int i = 0; i < row.size(); i++) {
+                            RectangularTextContainer cell = row.get(i);
+                            String text = cell.getText().replace("\r", "");
+                            jsonObject.put(header.get(i), text);
+                        }
+                        jsonArray.add(jsonObject);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return jsonArray;
+    }
+}

+ 26 - 0
srm-module-code/src/main/java/org/jeecg/modules/saleCode/util/TableTitle.java

@@ -0,0 +1,26 @@
+package org.jeecg.modules.saleCode.util;
+
+import java.lang.annotation.*;
+
+/**
+ * PDF Table 表头描述信息
+ */
+@Documented
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TableTitle {
+    /**
+     * 表头名称
+     */
+    String value();
+
+    /**
+     * 表头列下标,从0开始
+     */
+    int cellIndex();
+
+    /**
+     * 是否去掉单元格内容空格
+     */
+    boolean trimSpace() default true;
+}