| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.deepoove.poi.XWPFTemplate; |
| | | import com.deepoove.poi.config.Configure; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.device.dto.DeviceRecordDto; |
| | | import com.ruoyi.device.excel.DeviceRecordExportWord; |
| | | import com.ruoyi.device.mapper.DeviceMapper; |
| | | import com.ruoyi.device.mapper.DeviceRecordMapper; |
| | | import com.ruoyi.device.pojo.Device; |
| | | import com.ruoyi.device.pojo.DeviceRecord; |
| | | import com.ruoyi.device.service.DeviceRecordService; |
| | | import com.ruoyi.inspect.util.HackLoopTableRenderPolicy; |
| | | import com.ruoyi.system.domain.vo.SysRoleVo; |
| | | import com.ruoyi.system.mapper.SysRoleMenuMapper; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.apache.poi.xwpf.usermodel.ParagraphAlignment; |
| | | import org.apache.poi.xwpf.usermodel.TableRowAlign; |
| | | import org.apache.poi.xwpf.usermodel.UnderlinePatterns; |
| | | import org.apache.poi.xwpf.usermodel.XWPFDocument; |
| | | import org.apache.poi.xwpf.usermodel.XWPFParagraph; |
| | | import org.apache.poi.xwpf.usermodel.XWPFRun; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTable; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTableCell; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTableRow; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblCellMar; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblLayoutType; |
| | | import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.io.InputStream; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.math.BigInteger; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | |
| | | */ |
| | | @Service |
| | | public class DeviceRecordServiceImpl extends ServiceImpl<DeviceRecordMapper, DeviceRecord> implements DeviceRecordService { |
| | | @Resource |
| | | private DeviceMapper deviceMapper; |
| | | |
| | | private static final String FORM_TITLE = "仪器设备运行记录"; |
| | | private static final String RECORD_NUMBER = "LMSY-CX07-JL03"; |
| | | private static final String FONT_NAME = "宋体"; |
| | | private static final int[] COLUMN_WIDTHS = {1622, 4168, 1288, 1107, 1137, 1076, 940, 1182, 1288, 1350}; |
| | | private static final String[] HEADER_FIRST_ROW = {"使用日期", "样品编号", "时间 24 小时制", "", "设备状况", "", "环境条件", "", "使用人", "备注"}; |
| | | private static final String[] HEADER_SECOND_ROW = {"", "", "开始", "结束", "使用前", "使用后", "℃", "%RH", "", ""}; |
| | | private static final int[] COMBINED_COLUMN_WIDTHS = {1300, 2000, 1500, 1600, 2000, 900, 900, 800, 800, 650, 750, 950, 1008}; |
| | | private static final String[] COMBINED_HEADER_FIRST_ROW = {"使用日期", "设备名称", "设备型号", "设备编号", "样品编号", "时间 24 小时制", "", "设备状况", "", "环境条件", "", "使用人", "备注"}; |
| | | private static final String[] COMBINED_HEADER_SECOND_ROW = {"", "", "", "", "", "开始", "结束", "使用前", "使用后", "℃", "%RH", "", ""}; |
| | | private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); |
| | | |
| | | @Resource |
| | | private SysRoleMenuMapper sysRoleMenuMapper; |
| | |
| | | return baseMapper.deviceRecordPage(deviceId, page, sampleCode, managementNumber, testUserId); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void exportUseRecord(Integer deviceId, String exportDate, HttpServletResponse response) { |
| | | // 查询cnas设备使用记录 |
| | | List<DeviceRecord> deviceList = baseMapper.selectExportList(deviceId, exportDate); |
| | | // 设备信息 |
| | | Device device = deviceMapper.selectById(deviceId); |
| | | |
| | | |
| | | // 查询设备属于哪个实验室 |
| | | String laboratoryName = "装备线缆实验室"; |
| | | |
| | | // 要映射到word数据 |
| | | List<DeviceRecordExportWord> deviceExportList = new ArrayList<>(); |
| | | // deviceExportList 赋值 |
| | | for (DeviceRecord deviceRecord : deviceList) { |
| | | // 处理设备 开始使用时间 和 结束时间 |
| | | String startTime = ""; |
| | | String endTime = ""; |
| | | String operationDate = ""; |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); |
| | | if (deviceRecord.getUseStartDate() != null) { |
| | | startTime = deviceRecord.getUseStartDate().format(formatter); |
| | | endTime = deviceRecord.getUseEndDate().format(formatter); |
| | | String[] startTimeSplit = startTime.split(" "); |
| | | String[] endTimeSplit = endTime.split(" "); |
| | | if (startTimeSplit[0].equals(endTimeSplit[0])) { |
| | | startTime = startTimeSplit[1]; |
| | | endTime = endTimeSplit[1]; |
| | | } else { |
| | | endTime = endTimeSplit[0] + '\n' + endTimeSplit[1]; |
| | | startTime = startTimeSplit[0] + '\n' + startTimeSplit[1]; |
| | | } |
| | | DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy.M.d"); |
| | | operationDate = deviceRecord.getUseStartDate().format(formatter2); |
| | | } |
| | | // 处理使用前和使用后 |
| | | String useBeforeString = deviceRecord.getUseBefore() == 0? "异常" : "良好"; |
| | | String useAfterString = deviceRecord.getUseAfter() == 0 ? "异常" : "良好"; |
| | | |
| | | DeviceRecordExportWord deviceRecordExportWord = new DeviceRecordExportWord(); |
| | | // 进行赋值 |
| | | BeanUtils.copyProperties(deviceRecord, deviceRecordExportWord); |
| | | deviceRecordExportWord.setUseBeforeString(useBeforeString); // 使用前 |
| | | deviceRecordExportWord.setUseAfterString(useAfterString); // 使用后 |
| | | deviceRecordExportWord.setOperationDate(operationDate); // 设备操作日期 |
| | | deviceRecordExportWord.setUseStartDateString(startTime); // 开始时间 |
| | | deviceRecordExportWord.setUseEndDateString(endTime); // 结束时间 |
| | | deviceExportList.add(deviceRecordExportWord); |
| | | public void exportUseRecord(Integer deviceId, String sampleCode, String managementNumber, String exportDate, HttpServletResponse response) { |
| | | List<DeviceRecordDto> records = baseMapper.selectExportList(deviceId, sampleCode, managementNumber, exportDate); |
| | | if (records == null || records.isEmpty()) { |
| | | throw new ServiceException(exportDate == null || exportDate.isEmpty() |
| | | ? "没有可导出的使用记录,无法导出" |
| | | : exportDate + " 没有可导出的使用记录,无法导出"); |
| | | } |
| | | |
| | | // 获取路径 |
| | | InputStream inputStream = this.getClass().getResourceAsStream("/static/word/use-record.docx"); |
| | | Configure configure = Configure.builder() |
| | | .bind("useRecord", new HackLoopTableRenderPolicy()) |
| | | .build(); |
| | | String deviceName = device.getDeviceName(); |
| | | String managementNumber = device.getManagementNumber(); |
| | | XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render( |
| | | new HashMap<String, Object>() {{ |
| | | put("useRecord", deviceExportList); |
| | | put("deviceName", deviceName); |
| | | put("managementNumber", managementNumber); |
| | | put("laboratory", laboratoryName); |
| | | }}); |
| | | // 单台设备沿用截图表头; 多台设备合并到一张表, 每行带设备信息 |
| | | Map<Integer, List<DeviceRecordDto>> deviceRecords = new LinkedHashMap<>(); |
| | | for (DeviceRecordDto record : records) { |
| | | deviceRecords.computeIfAbsent(record.getDeviceId(), key -> new ArrayList<>()).add(record); |
| | | } |
| | | |
| | | try { |
| | | response.setContentType("application/msword"); |
| | | String fileName = URLEncoder.encode( |
| | | "仪器使用记录表", "UTF-8"); |
| | | response.setHeader("Content-disposition", |
| | | "attachment;filename=" + fileName + ".docx"); |
| | | OutputStream os = response.getOutputStream(); |
| | | template.write(os); |
| | | os.flush(); |
| | | os.close(); |
| | | inputStream.close(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | throw new RuntimeException("导出失败"); |
| | | try (XWPFDocument document = new XWPFDocument()) { |
| | | setupPage(document); |
| | | if (deviceRecords.size() == 1) { |
| | | List<DeviceRecordDto> group = deviceRecords.values().iterator().next(); |
| | | renderForm(document, group.get(0), group); |
| | | } else { |
| | | renderCombinedForm(document, records); |
| | | } |
| | | |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); |
| | | String fileName = URLEncoder.encode(FORM_TITLE, StandardCharsets.UTF_8).replace("+", "%20"); |
| | | response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx"); |
| | | try (OutputStream os = response.getOutputStream()) { |
| | | document.write(os); |
| | | os.flush(); |
| | | } |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导出失败", e); |
| | | } |
| | | } |
| | | |
| | | private void setupPage(XWPFDocument document) { |
| | | CTBody body = document.getDocument().getBody(); |
| | | CTSectPr sectPr = body.isSetSectPr() ? body.getSectPr() : body.addNewSectPr(); |
| | | CTPageSz pageSz = sectPr.isSetPgSz() ? sectPr.getPgSz() : sectPr.addNewPgSz(); |
| | | pageSz.setW(BigInteger.valueOf(16838)); |
| | | pageSz.setH(BigInteger.valueOf(11906)); |
| | | pageSz.setOrient(STPageOrientation.LANDSCAPE); |
| | | |
| | | CTPageMar pageMar = sectPr.isSetPgMar() ? sectPr.getPgMar() : sectPr.addNewPgMar(); |
| | | pageMar.setTop(BigInteger.valueOf(680)); |
| | | pageMar.setBottom(BigInteger.valueOf(680)); |
| | | pageMar.setLeft(BigInteger.valueOf(794)); |
| | | pageMar.setRight(BigInteger.valueOf(794)); |
| | | pageMar.setHeader(BigInteger.valueOf(851)); |
| | | pageMar.setFooter(BigInteger.valueOf(992)); |
| | | pageMar.setGutter(BigInteger.ZERO); |
| | | } |
| | | |
| | | private void renderForm(XWPFDocument document, DeviceRecordDto device, List<DeviceRecordDto> records) { |
| | | XWPFParagraph recordNumber = addParagraph(document, "记录编号:" + RECORD_NUMBER, 10.5, false, ParagraphAlignment.LEFT); |
| | | recordNumber.setSpacingAfter(240); |
| | | |
| | | XWPFParagraph title = addParagraph(document, FORM_TITLE, 22, true, ParagraphAlignment.CENTER); |
| | | title.setSpacingAfter(240); |
| | | |
| | | renderDeviceInfo(document, device); |
| | | document.createParagraph(); |
| | | |
| | | XWPFTable table = document.createTable(2 + records.size(), COLUMN_WIDTHS.length); |
| | | configureTable(table, COLUMN_WIDTHS); |
| | | |
| | | for (int i = 0; i < table.getNumberOfRows(); i++) { |
| | | XWPFTableRow row = table.getRow(i); |
| | | row.setHeight(i < 2 ? 560 : 520); |
| | | for (int j = 0; j < COLUMN_WIDTHS.length; j++) { |
| | | setCellWidth(row.getCell(j), COLUMN_WIDTHS[j]); |
| | | } |
| | | setRowProperties(row, i < 2); |
| | | } |
| | | |
| | | XWPFTableRow firstHeader = table.getRow(0); |
| | | for (int i = 0; i < HEADER_FIRST_ROW.length; i++) { |
| | | setCellText(firstHeader.getCell(i), HEADER_FIRST_ROW[i]); |
| | | } |
| | | XWPFTableRow secondHeader = table.getRow(1); |
| | | for (int i = 0; i < HEADER_SECOND_ROW.length; i++) { |
| | | setCellText(secondHeader.getCell(i), HEADER_SECOND_ROW[i]); |
| | | } |
| | | |
| | | mergeHorizontal(firstHeader, COLUMN_WIDTHS, 6, 2); |
| | | mergeHorizontal(firstHeader, COLUMN_WIDTHS, 4, 2); |
| | | mergeHorizontal(firstHeader, COLUMN_WIDTHS, 2, 2); |
| | | mergeVertical(firstHeader.getCell(0), secondHeader.getCell(0)); |
| | | mergeVertical(firstHeader.getCell(1), secondHeader.getCell(1)); |
| | | mergeVertical(firstHeader.getCell(5), secondHeader.getCell(8)); |
| | | mergeVertical(firstHeader.getCell(6), secondHeader.getCell(9)); |
| | | |
| | | for (int i = 0; i < records.size(); i++) { |
| | | XWPFTableRow row = table.getRow(2 + i); |
| | | String[] values = buildRowValues(records.get(i)); |
| | | for (int j = 0; j < values.length; j++) { |
| | | setCellText(row.getCell(j), values[j]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void renderCombinedForm(XWPFDocument document, List<DeviceRecordDto> records) { |
| | | XWPFParagraph recordNumber = addParagraph(document, "记录编号:" + RECORD_NUMBER, 10.5, false, ParagraphAlignment.LEFT); |
| | | recordNumber.setSpacingAfter(240); |
| | | |
| | | XWPFParagraph title = addParagraph(document, FORM_TITLE, 22, true, ParagraphAlignment.CENTER); |
| | | title.setSpacingAfter(240); |
| | | |
| | | XWPFTable table = document.createTable(2 + records.size(), COMBINED_COLUMN_WIDTHS.length); |
| | | configureTable(table, COMBINED_COLUMN_WIDTHS); |
| | | |
| | | for (int i = 0; i < table.getNumberOfRows(); i++) { |
| | | XWPFTableRow row = table.getRow(i); |
| | | row.setHeight(i < 2 ? 560 : 520); |
| | | for (int j = 0; j < COMBINED_COLUMN_WIDTHS.length; j++) { |
| | | setCellWidth(row.getCell(j), COMBINED_COLUMN_WIDTHS[j]); |
| | | } |
| | | setRowProperties(row, i < 2); |
| | | } |
| | | |
| | | XWPFTableRow firstHeader = table.getRow(0); |
| | | for (int i = 0; i < COMBINED_HEADER_FIRST_ROW.length; i++) { |
| | | setCellText(firstHeader.getCell(i), COMBINED_HEADER_FIRST_ROW[i]); |
| | | } |
| | | XWPFTableRow secondHeader = table.getRow(1); |
| | | for (int i = 0; i < COMBINED_HEADER_SECOND_ROW.length; i++) { |
| | | setCellText(secondHeader.getCell(i), COMBINED_HEADER_SECOND_ROW[i]); |
| | | } |
| | | |
| | | mergeHorizontal(firstHeader, COMBINED_COLUMN_WIDTHS, 9, 2); |
| | | mergeHorizontal(firstHeader, COMBINED_COLUMN_WIDTHS, 7, 2); |
| | | mergeHorizontal(firstHeader, COMBINED_COLUMN_WIDTHS, 5, 2); |
| | | mergeVertical(firstHeader.getCell(0), secondHeader.getCell(0)); |
| | | mergeVertical(firstHeader.getCell(1), secondHeader.getCell(1)); |
| | | mergeVertical(firstHeader.getCell(2), secondHeader.getCell(2)); |
| | | mergeVertical(firstHeader.getCell(3), secondHeader.getCell(3)); |
| | | mergeVertical(firstHeader.getCell(4), secondHeader.getCell(4)); |
| | | mergeVertical(firstHeader.getCell(8), secondHeader.getCell(11)); |
| | | mergeVertical(firstHeader.getCell(9), secondHeader.getCell(12)); |
| | | |
| | | for (int i = 0; i < records.size(); i++) { |
| | | XWPFTableRow row = table.getRow(2 + i); |
| | | String[] values = buildCombinedRowValues(records.get(i)); |
| | | for (int j = 0; j < values.length; j++) { |
| | | setCellText(row.getCell(j), values[j]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private XWPFParagraph addParagraph(XWPFDocument document, String text, double fontSize, boolean bold, ParagraphAlignment alignment) { |
| | | XWPFParagraph paragraph = document.createParagraph(); |
| | | paragraph.setAlignment(alignment); |
| | | addRun(paragraph, text, fontSize, bold); |
| | | return paragraph; |
| | | } |
| | | |
| | | private void addDeviceField(XWPFParagraph paragraph, String label, String value) { |
| | | addRun(paragraph, label, 10.5, false); |
| | | XWPFRun valueRun = addRun(paragraph, padUnderline(value), 10.5, false); |
| | | valueRun.setUnderline(UnderlinePatterns.SINGLE); |
| | | } |
| | | |
| | | private String padUnderline(String value) { |
| | | String content = value == null ? "" : value.trim(); |
| | | int width = 0; |
| | | for (int i = 0; i < content.length(); i++) { |
| | | width += content.charAt(i) >= 0x2E80 ? 2 : 1; |
| | | } |
| | | StringBuilder text = new StringBuilder(content); |
| | | for (int i = width; i < 20; i++) { |
| | | text.append(' '); |
| | | } |
| | | return text.toString(); |
| | | } |
| | | |
| | | private XWPFRun addRun(XWPFParagraph paragraph, String text, double fontSize, boolean bold) { |
| | | XWPFRun run = paragraph.createRun(); |
| | | run.setFontFamily(FONT_NAME); |
| | | run.setFontFamily(FONT_NAME, XWPFRun.FontCharRange.eastAsia); |
| | | run.setFontSize(fontSize); |
| | | run.setBold(bold); |
| | | run.setText(text); |
| | | return run; |
| | | } |
| | | |
| | | private void renderDeviceInfo(XWPFDocument document, DeviceRecordDto device) { |
| | | String[] labels = {"设备名称:", "设备型号:", "设备编号:"}; |
| | | String[] values = { |
| | | device == null ? "" : device.getDeviceName(), |
| | | device == null ? "" : device.getSpecificationModel(), |
| | | device == null ? "" : device.getManagementNumber() |
| | | }; |
| | | int[] widths = {5052, 5053, 5053}; |
| | | |
| | | XWPFTable table = document.createTable(1, labels.length); |
| | | CTTbl ctTbl = table.getCTTbl(); |
| | | CTTblPr tblPr = ctTbl.getTblPr() != null ? ctTbl.getTblPr() : ctTbl.addNewTblPr(); |
| | | |
| | | CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); |
| | | tblWidth.setType(STTblWidth.DXA); |
| | | tblWidth.setW(BigInteger.valueOf(totalWidth(COLUMN_WIDTHS))); |
| | | |
| | | CTTblLayoutType layoutType = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout(); |
| | | layoutType.setType(STTblLayoutType.FIXED); |
| | | |
| | | setNoBorders(tblPr); |
| | | |
| | | CTTblCellMar cellMar = tblPr.isSetTblCellMar() ? tblPr.getTblCellMar() : tblPr.addNewTblCellMar(); |
| | | setZeroWidth(cellMar.isSetLeft() ? cellMar.getLeft() : cellMar.addNewLeft()); |
| | | setZeroWidth(cellMar.isSetRight() ? cellMar.getRight() : cellMar.addNewRight()); |
| | | |
| | | CTTblGrid grid = ctTbl.getTblGrid() != null ? ctTbl.getTblGrid() : ctTbl.addNewTblGrid(); |
| | | while (grid.sizeOfGridColArray() > 0) { |
| | | grid.removeGridCol(0); |
| | | } |
| | | for (int width : widths) { |
| | | grid.addNewGridCol().setW(BigInteger.valueOf(width)); |
| | | } |
| | | |
| | | XWPFTableRow row = table.getRow(0); |
| | | for (int i = 0; i < labels.length; i++) { |
| | | XWPFTableCell cell = row.getCell(i); |
| | | setCellWidth(cell, widths[i]); |
| | | cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); |
| | | XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0); |
| | | paragraph.setAlignment(ParagraphAlignment.LEFT); |
| | | paragraph.setSpacingBefore(0); |
| | | paragraph.setSpacingAfter(0); |
| | | addDeviceField(paragraph, labels[i], values[i]); |
| | | } |
| | | } |
| | | |
| | | private void setNoBorders(CTTblPr tblPr) { |
| | | CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders(); |
| | | setNoBorder(borders.isSetTop() ? borders.getTop() : borders.addNewTop()); |
| | | setNoBorder(borders.isSetLeft() ? borders.getLeft() : borders.addNewLeft()); |
| | | setNoBorder(borders.isSetBottom() ? borders.getBottom() : borders.addNewBottom()); |
| | | setNoBorder(borders.isSetRight() ? borders.getRight() : borders.addNewRight()); |
| | | setNoBorder(borders.isSetInsideH() ? borders.getInsideH() : borders.addNewInsideH()); |
| | | setNoBorder(borders.isSetInsideV() ? borders.getInsideV() : borders.addNewInsideV()); |
| | | } |
| | | |
| | | private void setNoBorder(CTBorder border) { |
| | | border.setVal(STBorder.NIL); |
| | | border.setSz(BigInteger.ZERO); |
| | | border.setSpace(BigInteger.ZERO); |
| | | border.setColor("auto"); |
| | | } |
| | | |
| | | private void setZeroWidth(CTTblWidth width) { |
| | | width.setType(STTblWidth.DXA); |
| | | width.setW(BigInteger.ZERO); |
| | | } |
| | | |
| | | private void configureTable(XWPFTable table, int[] widths) { |
| | | table.setTableAlignment(TableRowAlign.CENTER); |
| | | CTTbl ctTbl = table.getCTTbl(); |
| | | CTTblPr tblPr = ctTbl.getTblPr() != null ? ctTbl.getTblPr() : ctTbl.addNewTblPr(); |
| | | |
| | | CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); |
| | | tblWidth.setType(STTblWidth.DXA); |
| | | tblWidth.setW(BigInteger.valueOf(totalWidth(widths))); |
| | | |
| | | CTTblLayoutType layoutType = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout(); |
| | | layoutType.setType(STTblLayoutType.FIXED); |
| | | |
| | | CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders(); |
| | | setBorder(borders.isSetTop() ? borders.getTop() : borders.addNewTop()); |
| | | setBorder(borders.isSetLeft() ? borders.getLeft() : borders.addNewLeft()); |
| | | setBorder(borders.isSetBottom() ? borders.getBottom() : borders.addNewBottom()); |
| | | setBorder(borders.isSetRight() ? borders.getRight() : borders.addNewRight()); |
| | | setBorder(borders.isSetInsideH() ? borders.getInsideH() : borders.addNewInsideH()); |
| | | setBorder(borders.isSetInsideV() ? borders.getInsideV() : borders.addNewInsideV()); |
| | | |
| | | CTTblGrid grid = ctTbl.getTblGrid() != null ? ctTbl.getTblGrid() : ctTbl.addNewTblGrid(); |
| | | while (grid.sizeOfGridColArray() > 0) { |
| | | grid.removeGridCol(0); |
| | | } |
| | | for (int width : widths) { |
| | | grid.addNewGridCol().setW(BigInteger.valueOf(width)); |
| | | } |
| | | } |
| | | |
| | | private int totalWidth(int[] widths) { |
| | | int total = 0; |
| | | for (int width : widths) { |
| | | total += width; |
| | | } |
| | | return total; |
| | | } |
| | | |
| | | private void setBorder(CTBorder border) { |
| | | border.setVal(STBorder.SINGLE); |
| | | border.setSz(BigInteger.valueOf(4)); |
| | | border.setSpace(BigInteger.ZERO); |
| | | border.setColor("000000"); |
| | | } |
| | | |
| | | private void setCellWidth(XWPFTableCell cell, int width) { |
| | | CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); |
| | | CTTblWidth tcW = tcPr.isSetTcW() ? tcPr.getTcW() : tcPr.addNewTcW(); |
| | | tcW.setType(STTblWidth.DXA); |
| | | tcW.setW(BigInteger.valueOf(width)); |
| | | } |
| | | |
| | | private void setCellText(XWPFTableCell cell, String text) { |
| | | cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); |
| | | XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0); |
| | | paragraph.setAlignment(ParagraphAlignment.CENTER); |
| | | paragraph.setSpacingBefore(0); |
| | | paragraph.setSpacingAfter(0); |
| | | addRun(paragraph, text == null ? "" : text, 10.5, false); |
| | | } |
| | | |
| | | private void setRowProperties(XWPFTableRow row, boolean repeatHeader) { |
| | | CTRow ctRow = row.getCtRow(); |
| | | CTTrPr trPr = ctRow.isSetTrPr() ? ctRow.getTrPr() : ctRow.addNewTrPr(); |
| | | trPr.addNewCantSplit(); |
| | | if (repeatHeader) { |
| | | trPr.addNewTblHeader(); |
| | | } |
| | | } |
| | | |
| | | private void mergeHorizontal(XWPFTableRow row, int[] widths, int firstIndex, int span) { |
| | | int width = 0; |
| | | for (int i = firstIndex; i < firstIndex + span; i++) { |
| | | width += widths[i]; |
| | | } |
| | | XWPFTableCell first = row.getCell(firstIndex); |
| | | setCellWidth(first, width); |
| | | CTTcPr tcPr = first.getCTTc().isSetTcPr() ? first.getCTTc().getTcPr() : first.getCTTc().addNewTcPr(); |
| | | (tcPr.isSetGridSpan() ? tcPr.getGridSpan() : tcPr.addNewGridSpan()).setVal(BigInteger.valueOf(span)); |
| | | for (int i = firstIndex + span - 1; i > firstIndex; i--) { |
| | | row.removeCell(i); |
| | | } |
| | | } |
| | | |
| | | private void mergeVertical(XWPFTableCell first, XWPFTableCell second) { |
| | | setVMerge(first, STMerge.RESTART); |
| | | setVMerge(second, STMerge.CONTINUE); |
| | | } |
| | | |
| | | private void setVMerge(XWPFTableCell cell, STMerge.Enum value) { |
| | | CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); |
| | | (tcPr.isSetVMerge() ? tcPr.getVMerge() : tcPr.addNewVMerge()).setVal(value); |
| | | } |
| | | |
| | | private String[] buildRowValues(DeviceRecordDto record) { |
| | | return new String[]{ |
| | | formatDate(record.getUseStartDate()), |
| | | valueOrEmpty(record.getSampleCode()), |
| | | formatTime(record.getUseStartDate()), |
| | | formatTime(record.getUseEndDate()), |
| | | statusText(record.getUseBefore()), |
| | | statusText(record.getUseAfter()), |
| | | valueOrEmpty(record.getTemperature()), |
| | | valueOrEmpty(record.getHumidity()), |
| | | valueOrEmpty(record.getUsePerson()), |
| | | valueOrEmpty(record.getRemark()) |
| | | }; |
| | | } |
| | | |
| | | private String[] buildCombinedRowValues(DeviceRecordDto record) { |
| | | return new String[]{ |
| | | formatDate(record.getUseStartDate()), |
| | | valueOrEmpty(record.getDeviceName()), |
| | | valueOrEmpty(record.getSpecificationModel()), |
| | | valueOrEmpty(record.getManagementNumber()), |
| | | valueOrEmpty(record.getSampleCode()), |
| | | formatTime(record.getUseStartDate()), |
| | | formatTime(record.getUseEndDate()), |
| | | statusText(record.getUseBefore()), |
| | | statusText(record.getUseAfter()), |
| | | valueOrEmpty(record.getTemperature()), |
| | | valueOrEmpty(record.getHumidity()), |
| | | valueOrEmpty(record.getUsePerson()), |
| | | valueOrEmpty(record.getRemark()) |
| | | }; |
| | | } |
| | | |
| | | private String formatDate(LocalDateTime value) { |
| | | return value == null ? "" : value.format(DATE_FORMATTER); |
| | | } |
| | | |
| | | private String formatTime(LocalDateTime value) { |
| | | return value == null ? "" : value.format(TIME_FORMATTER); |
| | | } |
| | | |
| | | private String statusText(Integer value) { |
| | | if (value == null) { |
| | | return ""; |
| | | } |
| | | return value == 0 ? "异常" : "良好"; |
| | | } |
| | | |
| | | private String valueOrEmpty(String value) { |
| | | return value == null ? "" : value; |
| | | } |
| | | } |