使用表和行从HTML生成PDF

时间:2018-03-07 16:04:19

标签: ios swift pdf

我正在开发一个简单的应用程序,用于在Swift for iOS中创建发票。 为此,我有一个带表和行的简单模板HTML(td / tr)。

我想将此HTML模板转换为多页PDF。由于UIPagePrintRenderer,它的工作方式就像一个魅力,但有些行在两个页面上重复,或者在两页上剪切了行。

我试图添加css" page-break"在我的模板上。当我在网络浏览器上打印模板时,我有一个很好的位置。

但是,当我将HTML导出为PDF时(感谢UIPagePrintRenderer),CSS样式没有应用于PDF文档,我的元素也是重复的。

我正在寻找将HTML转换为PDF的更好解决方案。有人遇到过类似的问题吗?

更新:

感谢回复人员,下面有关于问题和我的代码的更多信息。

  • 首先,这是我将HTML字符串转换为PDF文件的功能。

    func createPDF(formatter: UIViewPrintFormatter) -> String {
    
        let render = CustomPrintRenderer()
        render.addPrintFormatter(formatter, startingAtPageAt: 0)
        formatter.maximumContentHeight = 605.0
    
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
    
        for i in 0...render.numberOfPages {
    
            UIGraphicsBeginPDFPage()
    
            if(i != 0) {
                render.setupAfterFirstPage()
            }
            render.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
        }
        UIGraphicsEndPDFContext()
    
        pdfFilename = "\(AppDelegate().getDocDir())/Invoice-\(invoiceNumber!).pdf"
        pdfData.write(toFile: pdfFilename, atomically: true)
    
        return pdfFilename
    }
    
  • 其次,这是指定打印区域的CustomPrintRenderer()类。

    class CustomPrintRenderer: UIPrintPageRenderer {
    
    // A4 Gabarit
    let A4PageWidth: CGFloat = 595.2
    let A4PageHeight: CGFloat = 841.8
    
    let topPadding: CGFloat = 50.0
    let bottomPadding: CGFloat = 100.0
    
    let pageInset: CGFloat = 42.5
    
    //let leftPadding: CGFloat = 100.0
    //let rightPadding: CGFloat = 100.0
    
    override init() {
        super.init()
        initFrame()
    }
    
    func initFrame() {
        // Specify the frame of the A4 page.
        let pageFrame = CGRect(x: 0.0, y: 0.0, width: A4PageWidth, height: A4PageHeight)
        let printable = CGRect(x: 0.0, y: -topPadding, width : A4PageWidth, height: A4PageHeight - topPadding).insetBy(dx: pageInset, dy: pageInset)
    
        self.setValue(NSValue(cgRect: pageFrame), forKey: "paperRect")
        self.setValue(NSValue(cgRect: printable), forKey: "printableRect")
    }
    
    func setupAfterFirstPage() {
        let printable = CGRect(x: 0.0, y: topPadding, width : A4PageWidth, height: A4PageHeight - topPadding - bottomPadding).insetBy(dx: pageInset, dy: pageInset)
        self.setValue(NSValue(cgRect: printable), forKey: "printableRect")
    }
    

    }

  • 这是我在HTML上的发票(在ios应用上) enter image description here

  • 这是我的发票转换为PDF。 您可以在此屏幕截图中看到我的项目被裁剪。 所以,感谢"分页" css或其他方式的风格,如果元素不能完全放在当前页面上,我想在下一页显示一个项目。

enter image description here

更新2:

  • 这是我的HTML模板:

         主页'发票 - 发票

    body {
        max-width:90%;
        margin:auto;
        padding:30px;
        font-size:16px;
        line-height:24px;
        font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
        color:#485C74;
    }
    
    /*@media print
    {
      table { page-break-after:auto; }
      tr.items    { page-break-inside:avoid; page-break-after:auto; }
      td.items   { page-break-inside:avoid; page-break-after:auto; }
      thead { display:table-header-group; }
      tfoot { display:table-footer-group; }
    }*/
    
    /*@page {
      size: A4;
      margin: 0;
    }
    
    @media print {
      html, body {
        width: 210mm;
        height: 297mm;
      }
    }*/
    
    .middle {
        width: 50%;
    }
    
    .invoice-box table td{
        padding:5px;
        vertical-align:top;
    }
    
    .logo-images img {
        width:100%; 
        max-width:300px;
        max-height:150px;
    }
    
    .invoice-box .left-pos {
        text-align: left;
    }
    
    .invoice-box .center-pos {
        text-align: center;
    }
    
    .invoice-box .right-pos {
        text-align: right;
    }
    
    .invoice-box table thead.heading td{
        background:#fab800;
        border-bottom:1px solid #485C74;
        font-weight:bold;
    }
    
    .invoice-box table{
        width:100%;
        line-height:inherit;
        text-align:left;
    }
    
    .invoice-box table tr.top table td{
        padding-bottom:20px;
    }
    
    .invoice-box table tr.top table td.title{
        font-size:45px;
        line-height:45px;
        color:#485C74;
    }
    
    .invoice-box table tr.information table td{
        padding-bottom:40px;
    }
    
    
    .invoice-box table tr.details td{
        padding-bottom:20px;
    }
    
    .invoice-box table tr.item td, .invoice-box table tr.service td{
        border-bottom:1px solid #eee;
    }
    
    .invoice-box table tr.item.last td, .invoice-box table tr.service.last td{
        border-bottom:none;
    }
    
    .invoice-box .items-last, .invoice-box .services-last{
        border-top:2px solid #485C74;
        font-weight:bold;
    }
    
    footer {
        text-align: center;
    }
    
    @media only screen and (max-width: 600px) {
        .invoice-box table tr.top table td{
            width:100%;
            display:block;
            text-align:center;
        }
    
        .invoice-box table tr.information table td{
            width:100%;
            display:block;
            text-align:center;
        }
    }
                </style>
        </head>
        <body>
            <div class="invoice-box">
                <table cellpadding="0" cellspacing="0">
                    <tbody>
    
                        <!-- Header Top section -->
                        <tr class="top">
                            <td colspan="5">
                                <table>
                                    <tbody>
                                        <tr>
                                            <td class="logo-images"> <img src="data:image/png;base64, #LOGO_USER#"> </td>
                                            <td class="right-pos"> 
                                                Invoice : ##INVOICE_NUMBER#
                                                <br>
                                                Date : #INVOICE_DATE#
                                                <br>
                                                Due Date : #DUE_DATE# 
                                            </td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                        <!-- Payment section -->
    
                        <!-- Informations section -->
                        <tr class="information">
                            <td colspan="5">
                                <table>
                                    <tbody>
                                        <tr>
                                            <td class="middle left-pos"> #SENDER_INFO# </td>
                                            <td class="middle right-pos"> #RECIPIENT_INFO# </td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                        <!-- Informations section -->
                    </tbody>
                </table>
            </div>
    
            <div class="invoice-box">
                <table cellpadding="0" cellspacing="0">
                    <tbody>
    
                        <!-- Payment section -->
                        <thead class="heading">
                            <td> Payment Method </td>
                        </thead>
    
                        <tr class="details">
                            <td class="left-pos"> Payment desired : #PAYMENT_METHOD# <br> 
                                 A deposit of #PAYMENT_PERCENT# must be paid when signing "good for the agreement" of this invoice, is #PAYMENT_PERCENT_PRICE#.
                            </td>
                        </tr>
    
                    </tbody>
                </table>
            </div>
    
            <div class="invoice-box">
                <table cellpadding="0" cellspacing="0">
                    <tbody>
    
                        <!-- Items section -->
                        <thead class="heading">
                            <td class="left-pos"> Item / Description </td>
                            <td class="center-pos"> Reference </td>
                            <td class="center-pos"> Quantity </td>
                            <td class="center-pos"> Unit cost </td>
                            <td class="right-pos"> Total Price (excl. tax)</td>
                        </thead>
    
                        #ITEMS#
    
                        <tr class="total">
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td class="right-pos items-last">
                                Subtotal (excl. tax) : #TOTAL_AMOUNT_HT#
                                <br>
                                Sales Tax (#VAT_RAT#) : #VAT_PRICE#
                                <br> 
                                <br>
                                Total (incl. tax) : #TOTAL_AMOUNT_TTC#
                            </td>
                        </tr>
                        <!-- Items section -->
    
                    </tbody>
                </table>
            </div>
    
            <footer>
                <div class="footer_content">
                    <hr>
                    <p>Invoice powered By </p>
                    <div class="logo-images"> <img src="data:image/png;base64, #LOGO_FOOTER#"> </div>
                </div>
            </footer>
    
        </body>
    </html>
    
  • single_item.html:

    <tr class="item">
     <td class="left-pos">#ITEM_NAME# <br> #ITEM_DESC#</td>
     <td class="center-pos">#ITEM_REF#</td>
     <td class="center-pos">#ITEM_QUANTITY#</td>
     <td class="center-pos">#ITEM_UNIT_COST#</td>
     <td class="right-pos">#ITEM_TOTAL_PRICE#</td>  
    </tr>
    
  • last_item.html:

    <tr class="item last">
     <td class="left-pos">#ITEM_NAME# <br> #ITEM_DESC#</td>
     <td class="center-pos">#ITEM_REF#</td>
     <td class="center-pos">#ITEM_QUANTITY#</td>
     <td class="center-pos">#ITEM_UNIT_COST#</td>
     <td class="right-pos">#ITEM_TOTAL_PRICE#</td>  
    </tr>
    

更新3:

当我在我的&#34;项目&#34;上添加此代码时class,这些项目有一个很好的分页符,但显示不好。但是whitout&#34;显示:阻止;&#34;仍然不起作用:

    .item {
    display:block; 
    page-break-inside:avoid; 
    page-break-after: auto;
}

0 个答案:

没有答案