Project

General

Profile

追加功能 #486

v4.0: Create excel+pdf library

Added by Xihua Fan 3 months ago. Updated 19 days ago.

Status:
已关闭
Priority:
普通
Assignee:
Target version:
IT: Easytryck (Sweden) - v4.0
Start date:
09/05/2025
Due date:
12/01/2025
% Done:

100%

Estimated time:
20.00 h

Description

Background
  1. 需要使用第三方库实现Excel编辑保存 + PDF保存
Task Details
  • 1. 封装IF基于第三方
  • 2. 验证IF
v4 coding standard:
  1. Git提交
    #xxx(redmine number): xxx(redmine title) - xxx(任意:补充内容)
      
  2. 代码规范
    2.1: 结构:Public -> Protected -> Private
    2.2: 其他代码规范同SBX
      
  3. MVCL的v3/v4物理分割
    3.1: v3/v4的代码分为两个文件,比如: order.php, order_v3.php
    3.2: system也分为两个文件,暂时只有一个user_v3
    - Note: front的$this->user在v4中会替换为$this->customer, 即v4中需要清除$this->user
    3.3: 代码中,区分v3/v4的调用,比如:new User_V3
     
  4. 前台代码
    twig, js, css (js, css尽量写在单独的css文件中)
     
  5. 后台代码
    MVCL (L:en,cn)
     
  6. 注释
    1. 类名:
      /**
       * xxx
       *
       * @copyright RedBlue-OTS 2024
       * @version v4
       *
       */
      
    2. 函数名:参数类型 + 返回值类型
          /**
           * xxx
           *
           * @param  xxx $xxx
           * @param  xxx $xxx
           * @return xxx
           */
      
Output
  • Report and Solution

Others

#1

Updated by Zhongbao Ye 3 months ago

Output(2025/09/19) 居家 + Output(2025/09/15 - 2025/09/16) 九亭 + Output(2025/09/12 居家 - 2025/09/13 九亭)

报关资料

  1. 利用php第三方库作为实现报关资料预览和保存的技术支撑:
    1. PhpSpreadsheet
    2. mPDF
  2. 封装Excel操作类:PhpExcel 提供对外接口
  3. mPdf 需要一个临时目录,存储图片和字体的缓存文件
    • DIR_DOWNLOAD .'custom_declaration/tmp'
  4. 模板存储路径:
    • DIR_DOWNLOAD . custom_declaration/templates/xxxx
  5. 实体文件存储路径:
    • DIR_DOWNLOAD .'custom_declaration/{year}/{20250916 瑞典报关 DHL2504662996}/xxxx
Todo:
  1. 如何定位电子章的位置(多页情况下) - 转niko #484
    已经在下一次提交中解决,参考以下历史记录
  2. error.log - 转 niko #484
    2025-09-16 11:17:15 - PHP Warning:  Undefined array key 5 in D:\Work\Easytryck\06-Development\ots4.0-web\web\system\library\PHPOffice\vendor\mpdf\mpdf\src\Mpdf.php on line 20724
    2025-09-16 11:17:15 - PHP Warning:  Undefined array key 6 in D:\Work\Easytryck\06-Development\ots4.0-web\web\system\library\PHPOffice\vendor\mpdf\mpdf\src\Mpdf.php on line 20724
    

    不确定具体怎么解决的(好像只发现在local),线上暂时没有发现类似错误
#2

Updated by Zhongbao Ye 3 months ago

  • Status changed from 进行中 to 已关闭
  • % Done changed from 40 to 100
#3

Updated by Zhongbao Ye 3 months ago

  • Status changed from 已关闭 to 进行中
  • % Done changed from 100 to 80
#4

Updated by Zhongbao Ye 3 months ago

  • Status changed from 进行中 to 已关闭
  • % Done changed from 80 to 100
#5

Updated by Xihua Fan 25 days ago

  • Status changed from 已关闭 to 进行中
  • % Done changed from 100 to 90
#6

Updated by Zhongbao Ye 19 days ago

Outupt(2025/12/03) 居家 + Outupt(2025/12/01 ~ 2025/12/02) 九亭
  1. 修复 水印图片位置不准确的bug
    • Old:使用excel 动态累计计算单元行的高度,跟A4 297mm 对比,确定图片的位置。
      该方案,存在一些统计误差(比如插入行内容超过默认高度,没有动态setHeight),现在已全部废弃
    • New: 使用mpdf 最后一页的高度,动态计算图片y轴坐标位置
      如果 contentHeight > imageHeight => y轴坐标 = contentHeight + topMargin - imageHeight
      如果 contentHeight < imageHeight => y轴坐标 = topMargin
  2. 解决footer部永远保持在底部。
    • 思路:当产生分页时,在footer顶部插入一个空行,空行高度 = 最后一页剩余可用高度
    • 遇到一些问题:
      1. 如何标记footer部分
        • 弯路:在excel模板footer部第一个单元格添加注释 - 注释内容在mpdf生成html时,不生成
        • 弯路:通过PhpSpreadsheet 针对footer部第一个单元格添加额外的class/属性 - 不能添加html属性,这阶段它还不是html,没有属性这一说,只能进行excel的相关操作
        • 弯路:在组装模板数据时,在footer部找一个空白单元格。插入一个tag: {fixed_footer} -(缺点:需要在生成pdf前,将其移除。后面发现添加了tag,影响数据原始高度,高度计算不准,导致再次移除tag后,位置定位有偏差)
        • 选用:在phpexcel.php类中维护一个变量:$properties 这里存储各个sheet对应的FixedfooterRow,在渲染pdf时,传递给MpdfWriter类
      2. 通过标记分割html
        • 弯路:寻求AI提供正则。尝试多次才有当前的正确匹配结果。
      3. 添加空行:
        • 弯路:添加多个空行,空行高度 = 可用高度/单独空行的高度。(单独空行的高度 = 单独渲染一个tr模板的高度)
        • 选用:添加一个空行,空行高度 = 可用高度
      4. 可用高度计算不准( 70%时间耗在这里
        • 弯路:可用高度 = 整页高度 - 内容高度 - 页眉 - 页脚。 这个公式一定没错,毕竟销售合同分毫不差。认定公式没有问题。
        • 弯路:同一套代码,Invoice/Pcaking list 有些许偏差,销售合同分毫不差。一直找不到原因 。
        • 弯路:发现销售合同缩放100%,尝试将Invoice缩放改为100%,定位分毫不差。 - 发现是scale的原因。
        • 弯路:输出打印区域/非打印区域的高度 - 发现页眉/页脚一直不变,中间内容区域高度在变 - 验证scale问题
        • 弯路:一直在找*规律*, 既然是scale,就必定有数据进行乘/除。尝试对内容区域进行放大,不够准确,总是差那么一点(要么多一点,要么少一点)。
        • 选用:在设置一个*offset*, 通过一些简单的规律,让其接近完美。这里进行多次的数据实验。得到offset = 最后一页内容高度 > 1/2的整体页面内容 ? 可用高度 * 0.1 : 可用高度 * 0.25;
    • 整体解决方案
      1. Excel处理时预先给当前sheet设置一个属性:FixedFooterRow = footer 首行数
      2. 第一次PDF渲染 > 1页且 存在 FixedFooterRow > 0:否则终止
      3. 计算最后一页剩余的可用高度 = 可用高度 + 偏移量
        • 可用高度 = 页面总高297 - 页眉高度 - 最后一页内容实际高度 - 页脚高度;
        • 偏移量 = 最后一页内容高度 > 1/1.18的整体页面内容 ? 可用高度 * 0 : 可用高度 * 0.25;
      4. 填充指定高度(No.3 计算的最终高度)的空行,插入FixedFooterRow之前,使 footer保持在底部。
      5. Note: 最多一个sheet需要完成3次渲染
        第一次:初次整体渲染 - 计算初始高度,为后面的填充提供数据
        第二次:单独渲染footer部分 - 计算footer部分的实际内容高度。针对footer 跨页的情况处理
        如footer 一半在第一页,一半在第二页,在插入空行高度时候,需要减去上一页中部分footer 高度

        第三次:最终整体渲染 - 插入空行后的渲染

#7

Updated by Zhongbao Ye 19 days ago

  • Due date changed from 09/19/2025 to 12/01/2025
  • Status changed from 进行中 to 已关闭
  • % Done changed from 90 to 100

Also available in: Atom PDF