Reid  Rohan

Reid Rohan

1653028260

React-pdf: Create PDF Files using React

React renderer for creating PDF files on the browser and server 

Lost?

This package is used to create PDFs using React. If you wish to display existing PDFs, you may be looking for react-pdf.

How to install

yarn add @react-pdf/renderer

Webpack 5

Webpack 5 doesn't include node shims automatically anymore and we must opt-in to all shims we want. To do this we have to add a few dependencies to our project:

yarn add process browserify-zlib stream-browserify util buffer assert

after the modules are installed, we need to adjust our webpack.config file:

const webpack = require("webpack");

module.exports = {
  /* ... */

  resolve: {
    fallback: {
      process: require.resolve("process/browser"),
      zlib: require.resolve("browserify-zlib"),
      stream: require.resolve("stream-browserify"),
      util: require.resolve("util"),
      buffer: require.resolve("buffer"),
      assert: require.resolve("assert"),
    }
  },
  plugins: [
    new webpack.ProvidePlugin({
      Buffer: ["buffer", "Buffer"],
      process: "process/browser",
    }),
  ]

  /* ... */
}

How it works

import React from 'react';
import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer';

// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: 'row',
    backgroundColor: '#E4E4E4'
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1
  }
});

// Create Document Component
const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
      </View>
    </Page>
  </Document>
);

Web. Render in DOM

import React from 'react';
import ReactDOM from 'react-dom';
import { PDFViewer } from '@react-pdf/renderer';

const App = () => (
  <PDFViewer>
    <MyDocument />
  </PDFViewer>
);

ReactDOM.render(<App />, document.getElementById('root'));

Node. Save in a file

import React from 'react';
import ReactPDF from '@react-pdf/renderer';

ReactPDF.render(<MyDocument />, `${__dirname}/example.pdf`);

New react-pdf 2.0 was released. Read about the announcement

Author: Diegomura
Source Code: https://github.com/diegomura/react-pdf 
License: MIT license

#react #javascript #flexbox #pdf 

React-pdf: Create PDF Files using React

PyPDF2: A Utility to Read and Write PDFs with Python

PyPDF2

PyPDF2 is a pure-python PDF library capable of splitting, merging together, cropping, and transforming the pages of PDF files. It can also add custom data, viewing options, and passwords to PDF files. It can retrieve text and metadata from PDFs as well as merge entire files together.

Homepage
http://mstamy2.github.io/PyPDF2/

Examples

Please see the Sample_Code folder.

Documentation

Documentation is available at
https://pythonhosted.org/PyPDF2/

FAQ

Please see
http://mstamy2.github.io/PyPDF2/FAQ.html

Tests

PyPDF2 includes a test suite built on the unittest framework. All tests are located in the "Tests" folder. Tests can be run from the command line by:

python -m unittest Tests.tests

Author: mstamy2
Source Code: https://github.com/mstamy2/PyPDF2
License: View license

#python #pdf 

PyPDF2: A Utility to Read and Write PDFs with Python

PDFMiner: Python PDF Parser

PDFMiner

PDFMiner is a text extraction tool for PDF documents.

Warning: As of 2020, PDFMiner is not actively maintained. The code still works, but this project is largely dormant. For the active project, check out its fork pdfminer.six.

Features:

  • Pure Python (3.6 or above).
  • Supports PDF-1.7. (well, almost)
  • Obtains the exact location of text as well as other layout information (fonts, etc.).
  • Performs automatic layout analysis.
  • Can convert PDF into other formats (HTML/XML).
  • Can extract an outline (TOC).
  • Can extract tagged contents.
  • Supports basic encryption (RC4 and AES).
  • Supports various font types (Type1, TrueType, Type3, and CID).
  • Supports CJK languages and vertical writing scripts.
  • Has an extensible PDF parser that can be used for other purposes.

How to Use:

  1. > pip install pdfminer
  2. > pdf2txt.py samples/simple1.pdf

Command Line Syntax:

pdf2txt.py

pdf2txt.py extracts all the texts that are rendered programmatically. It also extracts the corresponding locations, font names, font sizes, writing direction (horizontal or vertical) for each text segment. It does not recognize text in images. A password needs to be provided for restricted PDF documents.

> pdf2txt.py [-P password] [-o output] [-t text|html|xml|tag]
             [-O output_dir] [-c encoding] [-s scale] [-R rotation]
             [-Y normal|loose|exact] [-p pagenos] [-m maxpages]
             [-S] [-C] [-n] [-A] [-V]
             [-M char_margin] [-L line_margin] [-W word_margin]
             [-F boxes_flow] [-d]
             input.pdf ...
  • -P password : PDF password.
  • -o output : Output file name.
  • -t text|html|xml|tag : Output type. (default: automatically inferred from the output file name.)
  • -O output_dir : Output directory for extracted images.
  • -c encoding : Output encoding. (default: utf-8)
  • -s scale : Output scale.
  • -R rotation : Rotates the page in degree.
  • -Y normal|loose|exact : Specifies the layout mode. (only for HTML output.)
  • -p pagenos : Processes certain pages only.
  • -m maxpages : Limits the number of maximum pages to process.
  • -S : Strips control characters.
  • -C : Disables resource caching.
  • -n : Disables layout analysis.
  • -A : Applies layout analysis for all texts including figures.
  • -V : Automatically detects vertical writing.
  • -M char_margin : Speficies the char margin.
  • -W word_margin : Speficies the word margin.
  • -L line_margin : Speficies the line margin.
  • -F boxes_flow : Speficies the box flow ratio.
  • -d : Turns on Debug output.

dumppdf.py

dumppdf.py is used for debugging PDFs. It dumps all the internal contents in pseudo-XML format.

> dumppdf.py [-P password] [-a] [-p pageid] [-i objid]
             [-o output] [-r|-b|-t] [-T] [-O directory] [-d]
             input.pdf ...
  • -P password : PDF password.
  • -a : Extracts all objects.
  • -p pageid : Extracts a Page object.
  • -i objid : Extracts a certain object.
  • -o output : Output file name.
  • -r : Raw mode. Dumps the raw compressed/encoded streams.
  • -b : Binary mode. Dumps the uncompressed/decoded streams.
  • -t : Text mode. Dumps the streams in text format.
  • -T : Tagged mode. Dumps the tagged contents.
  • -O output_dir : Output directory for extracted streams.

TODO

  • Replace STRICT variable with something better.
  • Improve the debugging functions.
  • Use logging module instead of sys.stderr.
  • Proper test cases.
  • PEP-8 and PEP-257 conformance.
  • Better documentation.
  • Crypto stream filter support.

Related Projects

Author: euske
Source Code: https://github.com/euske/pdfminer
License: MIT License

#python #pdf

PDFMiner: Python PDF Parser
Lawrence  Lesch

Lawrence Lesch

1652528280

React-pdf-viewer: A React Component to View A PDF Document

React PDF viewer

A React component to view a PDF document. It's written in TypeScript, and powered by React hooks completely.

React PDF viewer

// Core viewer
import { Viewer } from '@react-pdf-viewer/core';

// Plugins
import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';

// Import styles
import '@react-pdf-viewer/core/lib/styles/index.css';
import '@react-pdf-viewer/default-layout/lib/styles/index.css';

// Create new plugin instance
const defaultLayoutPluginInstance = defaultLayoutPlugin();

<Viewer
    fileUrl='/assets/pdf-open-parameters.pdf'
    plugins={[
        // Register plugins
        defaultLayoutPluginInstance,
        ...
    ]}
/>

Features

Basic features

  •  Support password protected document
  •  Zooming: Support custom levels such as actual size, page fit, and page width
  •  Navigation between pages
  •  Can go to the first and last pages quickly
  •  Search for text
  •  Preview page thumbnails
  •  View and navigate the table of contents
  •  List and download attachments
  •  Rotating
  •  Text selection and hand tool modes
  •  Different scrolling modes
  •  Full screen mode
  •  Can open a file from local. Users can drag and drop a local file to view it
  •  Download file
  •  View the document properties
  •  Support SSR
  •  Print
  •  Theming
  •  Dark mode
  •  Accessibility

Customization

  •  The toolbar can be customized easily
  •  All text items can be localized in another language

License

You have to purchase a Commercial License at the official website.

About

This project is developed by Nguyen Huu Phuoc. I love building products and sharing knowledge.

Be my friend on

Author: React-pdf-viewer
Source Code: https://github.com/react-pdf-viewer/react-pdf-viewer 
License: View license

#react #javascript #typescript #pdf 

React-pdf-viewer: A React Component to View A PDF Document
Nigel  Uys

Nigel Uys

1652062860

Maroto: A Maroto Way to Create PDFs

Maroto    

A Maroto way to create PDFs. Maroto is inspired in Bootstrap and uses Gofpdf. Fast and simple.

Maroto definition: Brazilian expression, means an astute/clever/intelligent person.

You can write your PDFs like you are creating a site using Bootstrap. A Row may have many Cols, and a Col may have many components. Besides that, pages will be added when content may extrapolate the useful area. You can define a header which will be added always when a new page appear, in this case, a header may have many rows, lines or tablelist.

Installation

  • With go get:
go get -u github.com/johnfercher/maroto/internal

Contributing

CommandDescriptionDependencies
make fmtFormat filesgofmt, gofumpt and goimports
make lintCheck filesgolangci-lint and goreportcard-cli
make dod(Definition of Done) Format files and check filesSame as make fmt and make lint
make installInstall all dependenciesgo, curl and git
make examplesRun all examplesgo

Features

result

Constructors

Grid System

Components To Use Inside a Col

Components To Use Outside a Row

Components To Wrap Row, TableList and Line

Saving PDF

Fonts

  • AddUTF8Font: Add a custom utf8 font and allow any character of any language.
  • SetDefaultFontFamily: Define a default font family, useful to use with a custom font.
  • SetFontLocation: Define the default path to search the custom font
  • 100% Unicode

Page

  • AddPage: Skip the current page and start the build a new one
  • SetPageMargins: Customize the page margins
  • SetAliasNbPages: Set placeholder to use in texts for total count of pages
  • SetFirstPageNb: Set first number for page numbering
  • Automatic New Page: New pages are generated automatically when needed.

Customizations

  • Properties: most of the components has properties which you can use to customize appearance and behavior
  • SetBorder: Used to draw rectangles in every row and column
  • SetBackgroundColor: Used to change the background color of one cell

Roadmap

Examples

In the PDFs folder there are the PDFs generated using Maroto, and in the examples folder there are subfolders with the code to generate the PDFs. There are examples of: barcode, billing, certificate, custom pdf size, image inside grid, qrcode inside grid, sample with almost all features together, text inside grid, custom utf8 fonts (any language) and a label zpl.

result

Other Examples

TitleMedia
How to create PDFs with Go, Maroto & GoFakeItVideo
Creating a PDF with Go, Maroto & GofakeitArticle
divrhino/fruitful-pdfRepository
Creating PDFs using GolangArticle

Code

This is part of the example billing.

// Billing example
package main

import (
    "fmt"
    "github.com/johnfercher/maroto/pkg/color"
    "github.com/johnfercher/maroto/pkg/consts"
    "github.com/johnfercher/maroto/pkg/pdf"
    "github.com/johnfercher/maroto/pkg/props"
    "os"
    "time"
)

func main() {
    begin := time.Now()

    darkGrayColor := getDarkGrayColor()
    grayColor := getGrayColor()
    whiteColor := color.NewWhite()
    header := getHeader()
    contents := getContents()

    m := pdf.NewMaroto(consts.Portrait, consts.A4)
    m.SetPageMargins(10, 15, 10)
    //m.SetBorder(true)

    m.RegisterHeader(func() {
        m.Row(20, func() {
            m.Col(3, func() {
                _ = m.FileImage("internal/assets/images/biplane.jpg", props.Rect{
                    Center:  true,
                    Percent: 80,
                })
            })

            m.ColSpace(6)

            m.Col(3, func() {
                m.Text("AnyCompany Name Inc. 851 Any Street Name, Suite 120, Any City, CA 45123.", props.Text{
                    Size:        8,
                    Align:       consts.Right,
                    Extrapolate: false,
                })
                m.Text("Tel: 55 024 12345-1234", props.Text{
                    Top:   12,
                    Style: consts.BoldItalic,
                    Size:  8,
                    Align: consts.Right,
                })
                m.Text("www.mycompany.com", props.Text{
                    Top:   15,
                    Style: consts.BoldItalic,
                    Size:  8,
                    Align: consts.Right,
                })
            })
        })
    })

    m.RegisterFooter(func() {
        m.Row(20, func() {
            m.Col(12, func() {
                m.Text("Tel: 55 024 12345-1234", props.Text{
                    Top:   13,
                    Style: consts.BoldItalic,
                    Size:  8,
                    Align: consts.Left,
                })
                m.Text("www.mycompany.com", props.Text{
                    Top:   16,
                    Style: consts.BoldItalic,
                    Size:  8,
                    Align: consts.Left,
                })
            })
        })
    })

    m.Row(10, func() {
        m.Col(12, func() {
            m.Text("Invoice ABC123456789", props.Text{
                Top:   3,
                Style: consts.Bold,
                Align: consts.Center,
            })
        })
    })

    m.SetBackgroundColor(darkGrayColor)

    m.Row(7, func() {
        m.Col(3, func() {
            m.Text("Transactions", props.Text{
                Top:   1.5,
                Size:  9,
                Style: consts.Bold,
                Align: consts.Center,
            })
        })
        m.ColSpace(9)
    })

    m.SetBackgroundColor(whiteColor)

    m.TableList(header, contents, props.TableList{
        HeaderProp: props.TableListContent{
            Size:      9,
            GridSizes: []uint{3, 4, 2, 3},
        },
        ContentProp: props.TableListContent{
            Size:      8,
            GridSizes: []uint{3, 4, 2, 3},
        },
        Align:                consts.Center,
        AlternatedBackground: &grayColor,
        HeaderContentSpace:   1,
        Line:                 false,
    })

    m.Row(20, func() {
        m.ColSpace(7)
        m.Col(2, func() {
            m.Text("Total:", props.Text{
                Top:   5,
                Style: consts.Bold,
                Size:  8,
                Align: consts.Right,
            })
        })
        m.Col(3, func() {
            m.Text("R$ 2.567,00", props.Text{
                Top:   5,
                Style: consts.Bold,
                Size:  8,
                Align: consts.Center,
            })
        })
    })

    m.Row(15, func() {
        m.Col(6, func() {
            _ = m.Barcode("5123.151231.512314.1251251.123215", props.Barcode{
                Percent: 0,
                Proportion: props.Proportion{
                    Width:  20,
                    Height: 2,
                },
            })
            m.Text("5123.151231.512314.1251251.123215", props.Text{
                Top:    12,
                Family: "",
                Style:  consts.Bold,
                Size:   9,
                Align:  consts.Center,
            })
        })
        m.ColSpace(6)
    })

    err := m.OutputFileAndClose("internal/examples/pdfs/billing.pdf")
    if err != nil {
        fmt.Println("Could not save PDF:", err)
        os.Exit(1)
    }

    end := time.Now()
    fmt.Println(end.Sub(begin))
}

Stargazers over time

Stargazers over time

Author: johnfercher
Source Code: https://github.com/johnfercher/maroto 
License: MIT license

#go #golang #pdf 

Maroto: A Maroto Way to Create PDFs
坂本  篤司

坂本 篤司

1651899688

FlutterでPDFを作成する方法

ドキュメントの共有に関しては、PDFを使用するよりも良い方法はありません。もともとドキュメントがどこで開かれたとしても同じように見える方法として開発されたPDFは、今日、世界中のほぼすべての企業で使用されています。

PDFを使用してユーザーが読み取り可能なデータを送信することは、多くの理由から適切な選択です。たとえば、PDFを開くデバイスに関係なく、ドキュメントは同じように表示されます。また、ファイルサイズの点では、PDFは比較的小さいです。

PDFのもう1つの便利な機能は、誰でもこのファイルタイプをいつでも開くことができることです。AndroidやiOSなどの主要なOSは、この機能をすぐに提供します。

このチュートリアルでは、以下を確認します。

  • PDFを生成するFlutterアプリのセットアップ
  • FlutterでPDFに要素を追加する
  • FlutterでPDFプレビューページを作成する
  • 完成品の外観

PDFを生成するFlutterアプリのセットアップ

FlutterアプリケーションからPDFを作成することは、3つの理由から実際には非常に楽しい経験です。

まず、 pub.devには、適切に呼ばれるpdf、成熟した十分にテストされたライブラリがあります。

次に、Flutter PDFライブラリは、FlutterがUI内でウィジェットをレイアウトする方法とよく似たPDF要素をレイアウトします。行と列がどのように機能するかをすでに知っている場合は、この知識を再利用して、FlutterでPDFを作成および編集できます。

第三に、と呼ばれるコンパニオンパッケージprintingを使用すると、アプリ内からPDFを簡単にプレビュー、共有、および印刷できます。

Flutter内でPDFを作成する方法の例として、顧客の請求書を作成できるアプリの作成について説明します。このサンプルアプリでは、新しい広告申込情報を指定して、支払われるべき合計金額を計算することもできます。

請求書を作成したら、PDFに変換してお客様に送信できるようになります。Flutterアプリ内からこれを実現する方法を見てみましょう!

構成pubspec.yaml

まず、pubspecファイルに2つの適切なパッケージを追加する必要があります。

  • PDFpdf制作用パッケージ
  • printing作成したPDFをプレビューするためのパッケージ

これらの2つのパッケージを使用して、作成したPDFを作成して共有します。

次のように、を追加pdfprintingます。pubspec.yaml

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  pdf: ## add this
  printing: ## also add this

請求書のモデルを設定する

次に、これらの請求書を作成して保存できるデータモデルを作成する必要があります。請求書には、関連する顧客情報が含まれ、請求されるラインアイテムのリストが表示され、これらのアイテムのコストが合計されている必要があります。

これらの要素を実現するために、次のようにデータモデルを作成しましょう。

class Invoice {
  final String customer;
  final String address;
  final List<LineItem> items;
  Invoice(this.customer, this.address, this.items);
  double totalCost() {
    return items.fold(0, (previousValue, element) => previousValue + element.cost);
  }
}

class LineItem {
  final String description;
  final double cost;

  LineItem(this.description, this.cost);
}

これは、請求書のデータを保持する非常に単純なデータクラスです。

この請求書に関連付けられているすべてのラインアイテムの合計コストを計算するために演算子をtotalCost使用する関数も宣言していることに気付いたかもしれません。.foldこの便利な関数がこの計算を処理するので、各値を手動で追加する必要はありません。

UIでの作業:請求書リストページ

アプリが起動すると、請求書のリストが表示されます。いくつかのテストデータをサンプリングして、最初に開いたときにリストにいくつかの項目が表示されるようにします。

まず、先に進んで、という名前の新しいフォルダを作成しましょうpages。そのフォルダ内に、という名前のDartファイルを作成しますinvoices.dartStatelessWidgetまた、この請求書のリストを最初に表示するためのを作成します。

このクラスでは、請求書自体のサンプルデータも宣言します。実際には、APIまたは同等のデータからこのデータをクエリする可能性がありますが、この場合、FlutterアプリでPDFを生成する方法を示すにはサンプルデータで十分です。

請求書ごとに、サンプルデータには次のものが含まれている必要があります。

  • お客様の名前と住所
  • 請求書の名前
  • それぞれの名前と費用で顧客に提供されるサービスの項目別リスト
final invoices = [
  Invoice(
      customer: 'David Thomas',
      address: '123 Fake St\r\nBermuda Triangle',
      items: [
        LineItem(
          'Technical Engagement',
          120,
        ),
        LineItem('Deployment Assistance', 200),
        LineItem('Develop Software Solution', 3020.45),
        LineItem('Produce Documentation', 840.50),
      ],
      name: 'Create and deploy software package'),
  Invoice(
    customer: 'Michael Ambiguous',
    address: '82 Unsure St\r\nBaggle Palace',
    items: [
      LineItem('Professional Advice', 100),
      LineItem('Lunch Bill', 43.55),
      LineItem('Remote Assistance', 50),
    ],
    name: 'Provide remote support after lunch',
  ),
  Invoice(
    customer: 'Marty McDanceFace',
    address: '55 Dancing Parade\r\nDance Place',
    items: [
      LineItem('Program the robots', 400.50),
      LineItem('Find tasteful dance moves for the robots', 80.55),
      LineItem('General quality assurance', 80),
    ],
    name: 'Create software to teach robots how to dance',
  )
];

クラス内InvoicePageでは、リスト内の既存のすべての請求書を表示するための非常にシンプルなUIも設計します。このリストの各アイテムには、請求書の名前、顧客の名前、合計費用など、請求書の詳細のプレビューが表示されます。

ListViewこれは、ウィジェットをListTile次のように任意のアイテムと組み合わせることによって行われます。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Invoices'),
    ),
    body: ListView(
      children: [
        ...invoices.map(
          (e) => ListTile(
            title: Text(e.name),
            subtitle: Text(e.customer),
            trailing: Text('\$${e.totalCost().toStringAsFixed(2)}'),
            onTap: () {
              Navigator.of(context).push(
                MaterialPageRoute(
                  builder: (builder) => DetailPage(invoice: e),
                ),
              );
            },
          ),
        )
      ],
    ),
  );
}

mapリストの演算子を使用してinvoices、リストをListTileアイテムに変換します。これは、に表示できますListViewtrailingまた、次の方法を使用して、表示される請求書の合計コストを設定します。

trailing: Text('\$${e.totalCost().toStringAsFixed(2)}'),

この文字列補間方法は、少し混乱する可能性があります。それをよりよく理解するためにそれを分解しましょう。

\$文字列内でドル記号としてレンダリングされます。通常、文字列補間を示す\ために使用されるため、接頭辞としてaを付ける必要があります。$この場合、実際には生のドル記号自体を使用したいので、を使用して通常の使用法を回避する必要があり\ます。

の接頭辞なしの使用法は、請求書$の関数の文字列補間を開始します。totalCost最後に、数値を文字列に変換するときに、小数点以下2桁に切り捨てます。

ウィジェットは、次のようにすべての請求書のリストを生成します。

各請求書をクリックすると、アプリはに移動しますDetailPage。ここで、サンプルの詳細ページを作成する方法を見てみましょう。

UIでの作業:請求書の詳細ページ

DetailPage請求書をパラメーターとして受け入れ、請求書オブジェクトを、PDFを作成する前にFlutterアプリでユーザーが確認できるものに変換します。

ここでも、とを使用しScaffoldListView請求書の詳細を表示します。またFloatingActionButton、Flutter独自のウィジェットであるを使用して、ユーザーが請求書情報を含むPDFを作成および共有できるようにします。

これらはFlutterで知っておくべき優れたUI要素ですが、これを生成するために使用するコードに焦点を当て続けましょうDetailPage。これは次のようになります。

class DetailPage extends StatelessWidget {
  final Invoice invoice;
  const DetailPage({
    Key? key,
    required this.invoice,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) => PdfPreviewPage(invoice: invoice),
            ),
          );
          // rootBundle.
        },
        child: Icon(Icons.picture_as_pdf),
      ),
      appBar: AppBar(
        title: Text(invoice.name),
      ),
      body: ListView(
        children: [
          Padding(
            padding: const EdgeInsets.all(15.0),
            child: Card(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Expanded(
                    child: Text(
                      'Customer',
                      style: Theme.of(context).textTheme.headline5,
                    ),
                  ),
                  Expanded(
                    child: Text(
                      invoice.customer,
                      style: Theme.of(context).textTheme.headline4,
                      textAlign: TextAlign.center,
                    ),
                  ),
                ],
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(15.0),
            child: Card(
              child: Column(
                children: [
                  Text(
                    'Invoice Items',
                    style: Theme.of(context).textTheme.headline6,
                  ),
                  ...invoice.items.map(
                    (e) => ListTile(
                      title: Text(e.description),
                      trailing: Text(
                        e.cost.toStringAsFixed(2),
                      ),
                    ),
                  ),
                  DefaultTextStyle.merge(
                    style: Theme.of(context).textTheme.headline4,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        Text("Total"),
                        Text(
                          invoice.totalCost().toStringAsFixed(2),
                        ),
                      ],
                    ),
                  )
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

このコードにより、次のような請求書プレビューページが表示されます。

FlutterでPDFに要素を追加する

請求書アプリのPDFを作成するには、最初に完成品がどのように見えるかを理解する必要があります。ほとんどの請求書には次のものが含まれます。

  • 顧客に関する情報
  • 会社のロゴ
  • 提供されたサービスのリスト
  • 最終価格(GSTを含む)
  • 支払いの詳細、または会社が請求書を処理するために必要な情報

これを作成するには、PDFに非常に複雑な視覚的レイアウトが必要です。PDFの請求書には、写真、テキスト、表、およびその線より下のすべてが買掛金部門のものであることを示す点線が含まれている必要があります。

通常、オフセットを使用する必要があり、実際には、すべてが必要な場所に正確にピクセルで表現しようとします。ただし、このpdfパッケージの主な利点の1つは、 Flutterと同じレイアウトルールを使用してPDFを作成できることです。

写真の作成ColumnsRows読み込み、パディングの設定方法をすでに知っている場合は、PDFのレイアウト方法も知っている必要があります。これにより、Flutterアプリケーション内から独自のPDFを作成および作成する際の障壁がすぐに下がります。

PDFを作成するために、という名前の新しいDartファイルを作成しますpdfexport。このクラスは、作成しているPDFのバイナリデータを返す単一の関数を公開します。

Dartファイルで関数を宣言し、makePdfタイプがパラメーターを受け入れるようにしますInvoiceDocument次に、オブジェクトを宣言し、ページを追加し、ページにを追加して、PDFドキュメントのシェルを構築しColumnます。

Future<Uint8List> makePdf(Invoice invoice) async {
  final pdf = Document();
  pdf.addPage(
    Page(
    build: (context) {
      return Column(
        children: []
      }
    );
}

必要に応じて、このページに個々の情報を追加します。PDFには、顧客の詳細、コストの内訳、買掛金に渡される伝票の3つの主要な領域が必要です。

終了すると、PDFは次のようになります。

アドレスとロゴの行を作成する

請求書の最初の行は、顧客情報とロゴの行です。当社のロゴが含まれているため、当社のロゴへの参照を追加しますpubspec.yaml。私の場合、単純なロゴを生成しただけですが、任意のPNG画像を使用できます。

assets:
   - assets/technical_logo.png

関数内に戻ってmakePdf、PDFに表示するアセットからこのPNGをロードする必要があります。幸い、これは、この特定の画像を読み込んでメモリに保存することをFlutterに伝えるのと同じくらい簡単です。

final imageLogo = MemoryImage((await rootBundle.load('assets/technical_logo.png')).buffer.asUint8List());

これで、顧客の詳細と会社のロゴを含む最初の行を作成できます。

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Column(
      children: [
        Text("Attention to: ${invoice.customer}"),
        Text(invoice.address),
      ],
      crossAxisAlignment: CrossAxisAlignment.start,
    ),
    SizedBox(
      height: 150,
      width: 150,
      child: Image(imageLogo),
    )
  ],
),

を使用して、この行の両方の子を、使用可能なスペースが許す限り互いに離れるように配置しますMainAxisAlignment.spaceBetween。次に、最初の顧客の詳細を指定し、Columnこの子をColumn左側に配置します。

Image次に、内にロードしSizedBox、サイズと高さを150に制限して、会社のロゴがあまりスペースをとらないようにします。この行の結果は次のようになります。

うまくいけば、私たちは一般的に利用可能な構造をどのように使用するかを理解し始め、RowColumnたちが好きな方法でPDFをレイアウトするのを非常に簡単にすることができます。

次に、請求書の詳細を含むテーブルを作成しましょう。

請求書テーブルの作成

請求書テーブルには、請求対象の商品またはサービスの項目別リストが表示されます。また、各アイテムの個別のコストも表示する必要があります。

適切な間隔でテーブルにアイテムを表示すると、請求書の特定のラインアイテムに関連付けられているコストを簡単に確認できます。これを支援するために、オブジェクトPaddedTextの周囲に必要なパディングの種類を指定するために呼び出される単純なヘルパークラスを追加しましょう。Text

Widget PaddedText(
  final String text, {
  final TextAlign align = TextAlign.left,
}) =>
    Padding(
      padding: EdgeInsets.all(10),
      child: Text(
        text,
        textAlign: align,
      ),
    );

パッケージTable内でこの機能を実現するために使用できます。pdfこれにより、PDF内に表示するための適切な黒い境界線を持つテーブルを設定できます。

この特定の行のレイアウトはもう少し複雑なので、これがどのように達成されるかを理解するために、以下のインラインコメントを参照できます。

Table(
  border: TableBorder.all(color: PdfColors.black),
  children: [
   // The first row just contains a phrase 'INVOICE FOR PAYMENT'
    TableRow(
      children: [
        Padding(
          child: Text(
            'INVOICE FOR PAYMENT',
            style: Theme.of(context).header4,
            textAlign: TextAlign.center,
          ),
          padding: EdgeInsets.all(20),
        ),
      ],
    ),
    // The remaining rows contain each item from the invoice, and uses the
    // map operator (the ...) to include these items in the list
    ...invoice.items.map(
    // Each new line item for the invoice should be rendered on a new TableRow
      (e) => TableRow(
        children: [
          // We can use an Expanded widget, and use the flex parameter to specify
          // how wide this particular widget should be. With a flex parameter of
          // 2, the description widget will be 66% of the available width.
          Expanded(
            child: PaddedText(e.description),
            flex: 2,
          ),
          // Again, with a flex parameter of 1, the cost widget will be 33% of the
          // available width.
          Expanded(
            child: PaddedText("\$${e.cost}"),
            flex: 1,
          )
        ],
      ),
    ),
    // After the itemized breakdown of costs, show the tax amount for this invoice
    // In this case, it's just 10% of the invoice amount
    TableRow(
      children: [
        PaddedText('TAX', align: TextAlign.right),
        PaddedText('\$${(invoice.totalCost() * 0.1).toStringAsFixed(2)}'),
      ],
    ),
    // Show the total 
    TableRow(
      children: [
        PaddedText('TOTAL', align: TextAlign.right),
        PaddedText("\$${invoice.totalCost()}"),
      ],
    )
  ],
),
Padding(
  child: Text(
    "THANK YOU FOR YOUR BUSINESS!",
    style: Theme.of(context).header2,
  ),
  padding: EdgeInsets.all(20),
),

このコードの結果は、次のように、請求書に関連付けられた商品またはサービスとそれぞれのコストの項目別リストを示しています。

支払い伝票の作成

最後に、請求書の2番目の部分を買掛金部門に転送できることを示すために点線を含める必要があります。このPDF要素には、顧客が請求書を正しく支払うことができるように、支払いの詳細も表示する必要があります。

以下のコードは、PDFで点線を指定し、別のテーブルを使用してアカウント情報を表示する方法を示しています。最後に、この請求書を支払うときに小切手に含める情報について説明します。

繰り返しになりますが、これは長いコードであるため、インラインコメントを参照して、何が起こっているのかを理解してください。

Text("Please forward the below slip to your accounts payable department."),
// Create a divider that is 1 unit high and make the appearance of
// the line dashed
Divider(
  height: 1,
  borderStyle: BorderStyle.dashed,
),
// Space out the invoice appropriately
Container(height: 50),
// Create another table with the payment details
Table(
  border: TableBorder.all(color: PdfColors.black),
  children: [
    TableRow(
      children: [
        PaddedText('Account Number'),
        PaddedText(
          '1234 1234',
        )
      ],
    ),
    TableRow(
      children: [
        PaddedText(
          'Account Name',
        ),
        PaddedText(
          'ADAM FAMILY TRUST',
        )
      ],
    ),
    TableRow(
      children: [
        PaddedText(
          'Total Amount to be Paid',
        ),
        PaddedText('\$${(invoice.totalCost() * 1.1).toStringAsFixed(2)}')
      ],
    )
  ],
),
// Add a final instruction about how checks should be created
// Center align and italicize this text to draw the reader's attention
// to it.
Padding(
  padding: EdgeInsets.all(30),
  child: Text(
    'Please ensure all checks are payable to the ADAM FAMILY TRUST.',
    style: Theme.of(context).header3.copyWith(
          fontStyle: FontStyle.italic,
        ),
    textAlign: TextAlign.center,
  ),
)

最後に、makePdf関数の最後に、生成されたPDFを呼び出し元に返す必要があります。

return pdf.save();

PdfPreview最後に、ウィジェットを表示するための基本的なページを作成する必要があります。今それをしましょう。

FlutterでPDFプレビューページを作成する

printingパッケージを使用すると、PDFプレビューアの作成が簡単になります。Scaffold(ユーザーが引き続きアプリ内をナビゲートできるように)を含めてから、の本体をScaffoldとして指定する必要がありますPdfPreview

buildの関数内で、PdfPreviewPDFを作成する関数を呼び出します。このビルド関数はPDFのバイト配列を受け入れますが、PDFのバイト配列を生成するも受け入れFutureます。

これらのオプションを使用すると、PDFを生成するコードが非同期であっても、PDFを作成する関数を簡単に呼び出すことができます。

class PdfPreviewPage extends StatelessWidget {
  final Invoice invoice;
  const PdfPreviewPage({Key? key, required this.invoice}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PDF Preview'),
      ),
      body: PdfPreview(
        build: (context) => makePdf(invoice),
      ),
    );
  }
}

完成品の外観

上記の結果は、指定したデータに基づいてPDFを生成するアプリです。PdfPreviewPageまた、PdfPreviewウィジェットには、PDFを電子メールまたは印刷してダウンロードおよび共有するためのオプションが含まれていることもわかります。

この記事の例では静的データを使用していますが、APIからこのデータを読み込んでPDFで表示するのはかなり簡単です。いつものように、GitHubからコードのコピーを取得できます。

この記事で、Flutter内からPDFを作成して共有する方法を説明できれば幸いです。Flutterレイアウトシステムについて既に理解している場合は、この知識を再利用して、アプリ内で美しく有益なPDFを作成できます。 

出典:https ://blog.logrocket.com/how-create-pdfs-flutter/

#flutter #pdf 

FlutterでPDFを作成する方法

Cómo Crear Archivos PDF En Flutter

Cuando se trata de compartir documentos, no hay mejor manera que usar un PDF. Originalmente desarrollado como una forma de que los documentos se vean iguales sin importar dónde se abrieron, los archivos PDF son utilizados por casi todas las empresas del mundo en la actualidad.

El uso de archivos PDF para transmitir datos legibles por el usuario es una buena opción por muchas razones. Por ejemplo, el documento aparecerá igual independientemente del dispositivo que abra el PDF. Además, en términos de tamaño de archivo, los archivos PDF son relativamente pequeños.

Otra característica útil de los archivos PDF es que todo el mundo siempre podrá abrir este tipo de archivo. Cualquier sistema operativo importante, como Android o iOS, proporcionará esta funcionalidad lista para usar.

En este tutorial, revisaremos:

  • Configuración de una aplicación Flutter que produce archivos PDF
  • Agregar elementos a tu PDF en Flutter
  • Crear la página de vista previa de PDF en Flutter
  • Cómo debe verse su producto terminado

Configuración de una aplicación Flutter que produce archivos PDF

Producir archivos PDF desde nuestra aplicación Flutter es en realidad una experiencia bastante agradable por tres razones.

En primer lugar, hay una biblioteca madura y bien probada disponible en pub.dev, convenientemente llamadapdf .

En segundo lugar, la biblioteca PDF de Flutter presenta elementos de PDF de forma muy similar a cómo Flutter presenta widgets dentro de la interfaz de usuario . Si ya sabe cómo funcionan las filas y las columnas, puede reutilizar este conocimiento para crear y editar su PDF en Flutter.

En tercer lugar, un paquete complementario llamadoprinting facilita la vista previa, el intercambio y la impresión de archivos PDF desde su aplicación.

Como ejemplo de cómo podemos crear archivos PDF dentro de Flutter, veremos cómo crear una aplicación que nos permita generar facturas para los clientes. Esta aplicación de ejemplo también nos permitirá especificar nuevos elementos de línea y calcular la cantidad total de dinero adeudada.

Una vez que tengamos nuestra factura creada, podremos convertirla a PDF para enviarla a nuestro cliente. ¡Veamos cómo podemos hacer que esto suceda desde nuestra aplicación Flutter!

Configurando nuestropubspec.yaml

Primero, necesitamos agregar dos paquetes apropiados a nuestro archivo pubspec:

  • El pdfpaquete para la producción de PDF
  • El printingpaquete para previsualizar los PDF que producimos

Usaremos estos dos paquetes para producir y luego compartir los archivos PDF que creamos.

Agregue pdfy printinga su pubspec.yaml, así:

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  pdf: ## add this
  printing: ## also add this

Configurando nuestro modelo para las facturas

Ahora, necesitamos crear un modelo de datos que nos permita crear y almacenar estas facturas. Una factura debe contener información relevante del cliente, mostrar una lista de los elementos de línea que se facturan y resumir el costo de estos elementos.

Para lograr estos elementos, creemos nuestro modelo de datos, así:

class Invoice {
  final String customer;
  final String address;
  final List<LineItem> items;
  Invoice(this.customer, this.address, this.items);
  double totalCost() {
    return items.fold(0, (previousValue, element) => previousValue + element.cost);
  }
}

class LineItem {
  final String description;
  final double cost;

  LineItem(this.description, this.cost);
}

Esta es una clase de datos bastante simple que contiene los datos de nuestra factura.

Es posible que haya notado que también declaramos una totalCostfunción, que utiliza el .foldoperador para calcular el costo total de todos los elementos de línea asociados con esta factura. Esta función de conveniencia manejará este cálculo por nosotros para que no tengamos que agregar manualmente cada valor.

Trabajando en nuestra interfaz de usuario: la página de lista de facturas

Cuando se inicie nuestra aplicación, debería mostrar nuestra lista de facturas. Tomaremos muestras de algunos datos de prueba para que nuestra lista muestre algunos elementos cuando la abramos por primera vez.

Para comenzar, avancemos y creemos una nueva carpeta llamada pages. Dentro de esa carpeta, cree un archivo Dart llamado invoices.dart. También crearemos un StatelessWidget, que se encargará de mostrar inicialmente esta lista de facturas.

Dentro de esta clase, también declararemos algunos datos de muestra para nuestras propias facturas. En realidad, probablemente consultaría estos datos desde una API o equivalente, pero en nuestro caso, los datos de muestra son suficientes para mostrar cómo generar archivos PDF en una aplicación de Flutter.

Para cada factura, nuestros datos de muestra deben incluir:

  • El nombre y la dirección del cliente.
  • El nombre de la factura.
  • Una lista detallada de los servicios prestados al cliente con sus respectivos nombres y costos
final invoices = [
  Invoice(
      customer: 'David Thomas',
      address: '123 Fake St\r\nBermuda Triangle',
      items: [
        LineItem(
          'Technical Engagement',
          120,
        ),
        LineItem('Deployment Assistance', 200),
        LineItem('Develop Software Solution', 3020.45),
        LineItem('Produce Documentation', 840.50),
      ],
      name: 'Create and deploy software package'),
  Invoice(
    customer: 'Michael Ambiguous',
    address: '82 Unsure St\r\nBaggle Palace',
    items: [
      LineItem('Professional Advice', 100),
      LineItem('Lunch Bill', 43.55),
      LineItem('Remote Assistance', 50),
    ],
    name: 'Provide remote support after lunch',
  ),
  Invoice(
    customer: 'Marty McDanceFace',
    address: '55 Dancing Parade\r\nDance Place',
    items: [
      LineItem('Program the robots', 400.50),
      LineItem('Find tasteful dance moves for the robots', 80.55),
      LineItem('General quality assurance', 80),
    ],
    name: 'Create software to teach robots how to dance',
  )
];

Dentro de nuestra InvoicePageclase, también diseñaremos una interfaz de usuario bastante simple para mostrar todas las facturas existentes en la lista. Cada elemento de esta lista debe mostrar una vista previa de los detalles de la factura, incluido el nombre de la factura, el nombre del cliente y el costo total.

Esto se hace combinando un ListViewwidget con cualquier ListTileelemento, así:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Invoices'),
    ),
    body: ListView(
      children: [
        ...invoices.map(
          (e) => ListTile(
            title: Text(e.name),
            subtitle: Text(e.customer),
            trailing: Text('\$${e.totalCost().toStringAsFixed(2)}'),
            onTap: () {
              Navigator.of(context).push(
                MaterialPageRoute(
                  builder: (builder) => DetailPage(invoice: e),
                ),
              );
            },
          ),
        )
      ],
    ),
  );
}

Al usar el mapoperador en la invoiceslista, convertimos la lista en ListTileelementos, que se pueden mostrar en nuestro archivo ListView. También establecemos el costo total de la factura que se mostrará utilizando el trailingmétodo:

trailing: Text('\$${e.totalCost().toStringAsFixed(2)}'),

Este método de interpolación de cadenas puede ser un poco confuso. Vamos a desglosarlo para entenderlo mejor.

\$se representa como un signo de dólar dentro de nuestra cadena. Tenemos que prefijarlo con un \porque $normalmente se usa para indicar una interpolación de cadenas. En este caso, nos gustaría usar el símbolo del dólar en sí mismo, por lo que tenemos que evitar su uso normal usando un \.

El uso sin prefijo de $comienza nuestra interpolación de cadenas para nuestra totalCostfunción para la factura. Finalmente, truncamos a dos lugares decimales cuando convertimos el número en una cadena.

El widget produce una lista de todas las facturas, así:

Cuando hacemos clic en cada factura, nuestra aplicación navega a un archivo DetailPage. Veamos cómo podemos crear una página de detalles de muestra ahora.

Trabajando en nuestra interfaz de usuario: la página de detalles de la factura

El DetailPageacepta una factura como parámetro y transforma el objeto de la factura en algo que el usuario puede verificar en su aplicación Flutter antes de producir un PDF.

Nuevamente, usamos a Scaffoldcon a ListViewpara mostrar detalles sobre la factura. También usamos un FloatingActionButton, que es un widget único en Flutter , para permitir que el usuario produzca y comparta un PDF que contiene la información de la factura.

Estos son excelentes elementos de la interfaz de usuario para conocer en Flutter, pero concentrémonos en el código que usaremos para producir esto DetailPage, que debería verse así:

class DetailPage extends StatelessWidget {
  final Invoice invoice;
  const DetailPage({
    Key? key,
    required this.invoice,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) => PdfPreviewPage(invoice: invoice),
            ),
          );
          // rootBundle.
        },
        child: Icon(Icons.picture_as_pdf),
      ),
      appBar: AppBar(
        title: Text(invoice.name),
      ),
      body: ListView(
        children: [
          Padding(
            padding: const EdgeInsets.all(15.0),
            child: Card(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Expanded(
                    child: Text(
                      'Customer',
                      style: Theme.of(context).textTheme.headline5,
                    ),
                  ),
                  Expanded(
                    child: Text(
                      invoice.customer,
                      style: Theme.of(context).textTheme.headline4,
                      textAlign: TextAlign.center,
                    ),
                  ),
                ],
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(15.0),
            child: Card(
              child: Column(
                children: [
                  Text(
                    'Invoice Items',
                    style: Theme.of(context).textTheme.headline6,
                  ),
                  ...invoice.items.map(
                    (e) => ListTile(
                      title: Text(e.description),
                      trailing: Text(
                        e.cost.toStringAsFixed(2),
                      ),
                    ),
                  ),
                  DefaultTextStyle.merge(
                    style: Theme.of(context).textTheme.headline4,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        Text("Total"),
                        Text(
                          invoice.totalCost().toStringAsFixed(2),
                        ),
                      ],
                    ),
                  )
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Este código debería dar como resultado una página de vista previa de la factura que se ve así:

Agregar elementos a tu PDF en Flutter

Para crear un PDF para nuestra aplicación de facturación, primero necesitamos tener una idea de cómo debería verse el producto terminado. La mayoría de las facturas contienen:

  • Información sobre el cliente
  • el logotipo de la empresa
  • Una lista de los servicios que se proporcionaron
  • Un precio final (incluyendo GST)
  • Detalles de pago, o qué información necesita la empresa para procesar la factura

Para producir esto, nuestro PDF requiere un diseño visual bastante complicado. Necesitamos que nuestra factura en PDF tenga imágenes, texto, tablas y una línea de puntos para indicar que todo lo que está debajo de esa línea es para el departamento de cuentas por pagar.

Normalmente, tendríamos que usar compensaciones y realmente tratar de articular en píxeles exactamente donde nos gustaría todo. Sin embargo, una de las principales ventajas del pdfpaquete es que utiliza las mismas reglas de diseño que Flutter para ayudarlo a construir sus archivos PDF.

Si ya sabe cómo crear Columnsy Rowscargar imágenes y configurar rellenos, también debería saber cómo diseñar su PDF. Esto reduce inmediatamente las barreras para crear y producir sus propios archivos PDF desde las aplicaciones de Flutter.

Para crear nuestro PDF, crearemos un nuevo archivo Dart llamado pdfexport. Nuestra clase expondrá una sola función que devuelve los datos binarios del PDF que estamos creando.

Declaremos la makePdffunción en nuestro archivo Dart y hagamos que acepte un parámetro de tipo Invoice. A continuación, construiremos el caparazón de nuestro documento PDF declarando nuestro Documentobjeto, agregando una página y agregando un Columna la página.

Future<Uint8List> makePdf(Invoice invoice) async {
  final pdf = Document();
  pdf.addPage(
    Page(
    build: (context) {
      return Column(
        children: []
      }
    );
}

Agregaremos información individual a esta página según sea necesario. El PDF necesitará tres áreas principales: los detalles del cliente, el desglose de los costos y el comprobante que se entregará a las cuentas por pagar.

Cuando hayamos terminado, nuestro PDF se verá así:

Creación de la fila de dirección y logotipo

Nuestra primera fila dentro de la factura es la información de nuestro cliente y la fila del logotipo. Debido a que incluye el logotipo de nuestra empresa, agregaremos una referencia a nuestro pubspec.yamllogotipo de nuestra empresa. En mi caso, acabo de generar un logotipo simple, pero puede usar cualquier imagen PNG que desee.

assets:
   - assets/technical_logo.png

Volviendo a nuestra makePdffunción, ahora necesitamos cargar este PNG de los activos para que se muestre en nuestro PDF. Afortunadamente, eso es tan simple como decirle a Flutter que nos gustaría cargar esta imagen en particular y almacenarla en la memoria.

final imageLogo = MemoryImage((await rootBundle.load('assets/technical_logo.png')).buffer.asUint8List());

Con esto, ahora podemos crear nuestra primera fila que contiene los detalles de nuestro cliente y el logotipo de la empresa.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Column(
      children: [
        Text("Attention to: ${invoice.customer}"),
        Text(invoice.address),
      ],
      crossAxisAlignment: CrossAxisAlignment.start,
    ),
    SizedBox(
      height: 150,
      width: 150,
      child: Image(imageLogo),
    )
  ],
),

Alineamos ambos elementos secundarios de esta fila para que estén tan alejados entre sí como lo permita el espacio disponible mediante el uso de MainAxisAlignment.spaceBetween. Luego, especificamos los detalles del cliente dentro de nuestro primero Columny alineamos los hijos de este Columna la izquierda.

A continuación, cargamos nuestro Imagedentro de un SizedBox, restringiendo el tamaño y la altura a 150 para que el logotipo de la empresa no ocupe demasiado espacio. El resultado de esta fila se ve así:

Con suerte, podemos comenzar a ver cómo el uso de construcciones comúnmente disponibles como Rowy Columnhace que sea muy fácil para nosotros diseñar un PDF de la manera que nos gusta.

A continuación, creemos una tabla para incluir los detalles de la factura.

Crear la tabla de facturas

Nuestra tabla de facturas debe presentar una lista detallada de los bienes o servicios que se facturan. También debe mostrar el costo individual de cada artículo.

Mostrar artículos en una tabla con el espacio adecuado facilita ver qué costo está asociado con un artículo de línea en particular en una factura. Para ayudar con esto, agreguemos una clase auxiliar simple llamada PaddedTextpara especificar qué tipo de relleno nos gustaría alrededor de nuestro Textobjeto.

Widget PaddedText(
  final String text, {
  final TextAlign align = TextAlign.left,
}) =>
    Padding(
      padding: EdgeInsets.all(10),
      child: Text(
        text,
        textAlign: align,
      ),
    );

Podemos usar un Tabledentro del pdfpaquete para lograr esta funcionalidad. Esto nos permitirá configurar una tabla con los bordes negros apropiados para mostrarla en nuestro PDF.

Debido a que el diseño de esta fila en particular es un poco más complicado, puede consultar los comentarios en línea a continuación para comprender cómo se logra esto.

Table(
  border: TableBorder.all(color: PdfColors.black),
  children: [
   // The first row just contains a phrase 'INVOICE FOR PAYMENT'
    TableRow(
      children: [
        Padding(
          child: Text(
            'INVOICE FOR PAYMENT',
            style: Theme.of(context).header4,
            textAlign: TextAlign.center,
          ),
          padding: EdgeInsets.all(20),
        ),
      ],
    ),
    // The remaining rows contain each item from the invoice, and uses the
    // map operator (the ...) to include these items in the list
    ...invoice.items.map(
    // Each new line item for the invoice should be rendered on a new TableRow
      (e) => TableRow(
        children: [
          // We can use an Expanded widget, and use the flex parameter to specify
          // how wide this particular widget should be. With a flex parameter of
          // 2, the description widget will be 66% of the available width.
          Expanded(
            child: PaddedText(e.description),
            flex: 2,
          ),
          // Again, with a flex parameter of 1, the cost widget will be 33% of the
          // available width.
          Expanded(
            child: PaddedText("\$${e.cost}"),
            flex: 1,
          )
        ],
      ),
    ),
    // After the itemized breakdown of costs, show the tax amount for this invoice
    // In this case, it's just 10% of the invoice amount
    TableRow(
      children: [
        PaddedText('TAX', align: TextAlign.right),
        PaddedText('\$${(invoice.totalCost() * 0.1).toStringAsFixed(2)}'),
      ],
    ),
    // Show the total 
    TableRow(
      children: [
        PaddedText('TOTAL', align: TextAlign.right),
        PaddedText("\$${invoice.totalCost()}"),
      ],
    )
  ],
),
Padding(
  child: Text(
    "THANK YOU FOR YOUR BUSINESS!",
    style: Theme.of(context).header2,
  ),
  padding: EdgeInsets.all(20),
),

El resultado de este código muestra una lista detallada de los bienes o servicios asociados a la factura y sus respectivos costos, así:

Creando el comprobante de pago

Finalmente, debemos incluir una línea punteada para indicar que la segunda parte de la factura se puede enviar al departamento de cuentas por pagar. Este elemento PDF también debe mostrar los detalles de pago para que el cliente pueda pagar la factura correctamente.

El siguiente código muestra cómo especificar una línea de puntos en nuestro PDF y usar otra tabla para mostrar la información de la cuenta. Termina con instrucciones sobre qué información incluir en el cheque al pagar esta factura.

Una vez más, como se trata de un fragmento de código más largo, consulte los comentarios en línea para comprender lo que está sucediendo.

Text("Please forward the below slip to your accounts payable department."),
// Create a divider that is 1 unit high and make the appearance of
// the line dashed
Divider(
  height: 1,
  borderStyle: BorderStyle.dashed,
),
// Space out the invoice appropriately
Container(height: 50),
// Create another table with the payment details
Table(
  border: TableBorder.all(color: PdfColors.black),
  children: [
    TableRow(
      children: [
        PaddedText('Account Number'),
        PaddedText(
          '1234 1234',
        )
      ],
    ),
    TableRow(
      children: [
        PaddedText(
          'Account Name',
        ),
        PaddedText(
          'ADAM FAMILY TRUST',
        )
      ],
    ),
    TableRow(
      children: [
        PaddedText(
          'Total Amount to be Paid',
        ),
        PaddedText('\$${(invoice.totalCost() * 1.1).toStringAsFixed(2)}')
      ],
    )
  ],
),
// Add a final instruction about how checks should be created
// Center align and italicize this text to draw the reader's attention
// to it.
Padding(
  padding: EdgeInsets.all(30),
  child: Text(
    'Please ensure all checks are payable to the ADAM FAMILY TRUST.',
    style: Theme.of(context).header3.copyWith(
          fontStyle: FontStyle.italic,
        ),
    textAlign: TextAlign.center,
  ),
)

Finalmente, al final de nuestra makePdffunción, también debemos devolver el PDF generado a la persona que llama.

return pdf.save();

Lo último que debemos hacer es crear una página básica para mostrar el PdfPreviewwidget. Hagamos eso ahora.

Crear la página de vista previa de PDF en Flutter

Crear una vista previa de PDF es simple cuando se usa el printingpaquete. Solo necesitamos incluir un Scaffold(para que el usuario aún pueda navegar dentro de nuestra aplicación) y luego especificar el cuerpo del Scaffoldas PdfPreview.

Dentro de la buildfunción de nuestro PdfPreview, llamamos a la función que crea nuestro PDF. Esta función de compilación aceptará una matriz de bytes del PDF, pero también aceptará una Futureque produzca una matriz de bytes para el PDF.

Estas opciones facilitan llamar a la función que crea nuestro PDF, incluso si el código que produce el PDF es asíncrono.

class PdfPreviewPage extends StatelessWidget {
  final Invoice invoice;
  const PdfPreviewPage({Key? key, required this.invoice}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PDF Preview'),
      ),
      body: PdfPreview(
        build: (context) => makePdf(invoice),
      ),
    );
  }
}

Cómo debe verse su producto terminado

El resultado de lo anterior es una aplicación que produce archivos PDF en función de los datos que hemos especificado. También podemos ver que en nuestro PdfPreviewPage, el PdfPreviewwidget incluye opciones que nos permiten descargar y compartir nuestro PDF enviándolo por correo electrónico o imprimiéndolo.

El ejemplo de este artículo utiliza datos estáticos, pero sería bastante sencillo cargar estos datos desde una API y luego mostrarlos en un PDF. Como siempre, puede obtener una copia del código de GitHub .

Con suerte, este artículo le ha mostrado cómo puede crear y compartir archivos PDF desde Flutter. Si ya comprende el sistema de diseño de Flutter, puede reutilizar este conocimiento para crear PDF hermosos e informativos dentro de su aplicación. 

Fuente: https://blog.logrocket.com/how-create-pdfs-flutter/

#flutter #pdf 

Cómo Crear Archivos PDF En Flutter
Veronica  Roob

Veronica Roob

1651656420

Awesome PHP: Libraries and Software for Working with PDF Files

PDF

Libraries and software for working with PDF files.

  • Dompdf - A HTML to PDF converter.
  • PHPPdf - A library for generating PDFs and images from XML.
  • Snappy - A PDF and image generation library.
  • WKHTMLToPDF - A tool to convert HTML to PDF.

Author: ziadoz
Source Code: https://github.com/ziadoz/awesome-php
License: WTFPL License

#php #pdf 

Awesome PHP: Libraries and Software for Working with PDF Files
Veronica  Roob

Veronica Roob

1651645320

Convert HTML to PDF using Webkit (QtWebKit)

wkhtmltopdf and wkhtmltoimage

wkhtmltopdf and wkhtmltoimage are command line tools to render HTML into PDF and various image formats using the QT Webkit rendering engine. These run entirely "headless" and do not require a display or display service.

See https://wkhtmltopdf.org for updated documentation.

Building

wkhtmltopdf has its own dedicated repository for building and packaging.

See https://github.com/wkhtmltopdf/packaging

Author: wkhtmltopdf
Source Code: https://github.com/wkhtmltopdf/wkhtmltopdf
License: LGPL-3.0 License

#php #cpluplus #html #pdf 

Convert HTML to PDF using Webkit (QtWebKit)
Veronica  Roob

Veronica Roob

1651637940

PHP Library Allowing Thumbnail, Snapshot or PDF Generation From A URL

Snappy

Snappy is a PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page. It uses the excellent webkit-based wkhtmltopdf and wkhtmltoimage available on OSX, linux, windows.

You will have to download wkhtmltopdf 0.12.x in order to use Snappy.

Please, check FAQ before opening a new issue. Snappy is a tiny wrapper around wkhtmltox, so lots of issues are already answered, resolved or wkhtmltox ones.

Following integrations are available:

Installation using Composer

$ composer require knplabs/knp-snappy

Usage

Initialization

<?php

require __DIR__ . '/vendor/autoload.php';

use Knp\Snappy\Pdf;

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');

// or you can do it in two steps
$snappy = new Pdf();
$snappy->setBinary('/usr/local/bin/wkhtmltopdf');

Display the pdf in the browser

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
header('Content-Type: application/pdf');
echo $snappy->getOutput('http://www.github.com');

Download the pdf from the browser

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="file.pdf"');
echo $snappy->getOutput('http://www.github.com');

Merge multiple urls into one pdf

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="file.pdf"');
echo $snappy->getOutput(array('http://www.github.com','http://www.knplabs.com','http://www.php.net'));

Generate local pdf file

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
$snappy->generateFromHtml('<h1>Bill</h1><p>You owe me money, dude.</p>', '/tmp/bill-123.pdf');

Pass options to snappy

// Type wkhtmltopdf -H to see the list of options
$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
$snappy->setOption('disable-javascript', true);
$snappy->setOption('no-background', true);
$snappy->setOption('allow', array('/path1', '/path2'));
$snappy->setOption('cookie', array('key' => 'value', 'key2' => 'value2'));
$snappy->setOption('post', array('key' => 'value'));
$snappy->setOption('cover', 'pathToCover.html');
// .. or pass a cover as html
$snappy->setOption('cover', '<h1>Bill cover</h1>');
$snappy->setOption('toc', true);
$snappy->setOption('cache-dir', '/path/to/cache/dir');

Reset options

Options can be reset to their initial values with resetOptions() method.

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
// Set some options
$snappy->setOption('copies' => 4);
// ..
// Reset options
$snappy->resetOptions();

wkhtmltopdf binary as composer dependencies

If you want to download wkhtmltopdf and wkhtmltoimage with composer you add to composer.json:

$ composer require h4cc/wkhtmltopdf-i386 0.12.x
$ composer require h4cc/wkhtmltoimage-i386 0.12.x

or this if you are in 64 bit based system:

$ composer require h4cc/wkhtmltopdf-amd64 0.12.x
$ composer require h4cc/wkhtmltoimage-amd64 0.12.x

And then you can use it

<?php

use Knp\Snappy\Pdf;

$myProjectDirectory = '/path/to/my/project';

$snappy = new Pdf($myProjectDirectory . '/vendor/h4cc/wkhtmltopdf-i386/bin/wkhtmltopdf-i386');

// or

$snappy = new Pdf($myProjectDirectory . '/vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64');

N.B. These static binaries are extracted from Debian7 packages, so it might not be compatible with non-debian based linux distros

Some use cases

If you want to generate table of contents and you want to use custom XSL stylesheet, do the following:

<?php
$snappy = new Pdf('/path/to/binary');

$snappy->setOption('toc', true);
$snappy->setOption('xsl-style-sheet', 'http://path/to/stylesheet.xsl') //or local file;

$snappy->generateFromHtml('<p>Some content</p>', 'test.pdf');

Bugs & Support

If you found a bug please fill a detailed issue with all the following points. If you need some help, please at least provide a complete reproducer so we could help you based on facts rather than assumptions.

  • OS and its version
  • Wkhtmltopdf, its version and how you installed it
  • A complete reproducer with relevant php and html/css/js code

If your reproducer is big, please try to shrink it. It will help everyone to narrow the bug.

Maintainers

KNPLabs is looking for maintainers (see why).

If you are interested, feel free to open a PR to ask to be added as a maintainer.

We’ll be glad to hear from you :)

Credits

Snappy has been originally developed by the KnpLabs team.

Author: KnpLabs
Source Code: https://github.com/KnpLabs/snappy
License: MIT License

#php #pdf 

PHP Library Allowing Thumbnail, Snapshot or PDF Generation From A URL
Veronica  Roob

Veronica Roob

1651626840

PHPPDF: PDF and Graphic Files Generator Library Written in PHP

Information

Examples

Sample documents are in the "examples" directory. "index.php" file is the web interface to browse examples, "cli.php" is a console interface. Via the web interface, the documents are available in pdf and jpeg format (the jpeg format requires Imagick).

Documentation

Introduction

PHPPdf is library that transforms an XML document to a PDF document or graphics files. The XML source document is similar to HTML, but there are lots of differences in names and properties of attributes, properties of tags, and there are a lot of not standard tags, not all tags from html are supported, stylesheet is described in an xml document, not in css.

Assumption of this library is not HTML -> PDF / JPEG / PNG, but XML -> PDF / JPEG / PNG transformation. Some tags and attributes are the same as in HTML in order decrease the learning curve of this library.

Installation

PHPPdf is available at packagist.org, so you can use composer to download this library and all dependencies.

(add to require section in your composer.json file)

    "psliwa/php-pdf": "*"

You should choose last stable version (or wildcard of stable version), wildcard char ("*") is only an example.

If you want to use as features as barcodes or image generation, you should add extra dependencies:

    "zendframework/zend-barcode": ">=2.0.0,<2.4",
    "zendframework/zend-validator": ">=2.0.0,<2.4",
    "imagine/Imagine": ">=0.2.0,<0.6.0"

Symfony2 bundle

There is a Symfony2 bundle which integrates this library with the Symfony2 framework.

FAQ

Diacritical marks are not displayed, what should I do?

You should set a font that supports the encoding that you are using, and set this encoding as "encoding" attribute for "page" and/or "dynamic-page" tags. PHPPdf provides some free fonts that support utf-8 encoding, for example, DejaVuSans. The "Font" example shows how to change the font type by using a stylesheet.

You can also add custom fonts, in order that you should prepare xml config file and configure Facade object as shown below:

    <!-- xml config file code -->
    <fonts>
        <font name="DejaVuSans">
            <normal src="%resources%/fonts/DejaVuSans/normal.ttf" /><!-- "%resources%" will be replaced by path to PHPPdf/Resources directory -->
            <bold src="%resources%/fonts/DejaVuSans/bold.ttf" />
            <italic src="%resources%/fonts/DejaVuSans/oblique.ttf" />
            <bold-italic src="%resources%/fonts/DejaVuSans/bold+oblique.ttf" />
            <light src="%resources%/fonts/DejaVuSans/light.ttf" />
            <light-italic src="%resources%/fonts/DejaVuSans/light+oblique.ttf" />
        </font>
    </fonts>
//php code
$loader = new PHPPdf\Core\Configuration\LoaderImpl();
$loader->setFontFile(/* path to fonts configuration file */);
$builder = PHPPdf\Core\FacadeBuilder::create($loader);
$facade = $builder->build();
<!-- xml document code -->
<pdf>
    <dynamic-page encoding="UTF-8" font-type="DejaVuSans">
    </dynamic-page>
</pdf>

You can find more datails in the Configuration section.

Generating of a simple pdf file with png images takes a lot of time and memory, what should I do?

PHPPdf uses the Zend_Pdf library that poorly supports png files without compression. You should compress the png files.

How can I change the page size/orientation?

To set the page dimensions you use the "page-size" attribute of the page or dynamic-page tags.

The value syntax of this attribute is "width:height".

There are however standard predefined values:

  • A format: from 4A0 to A10
  • B format: from B0 to B10
  • C format: from C0 to C10
  • US sizes: legal and letter

All formats are supported in portrait and lanscape.

Example:

<page page-size="100:50">text</page>
<page page-size="a4">text</page>
<page page-size="letter-landscape">text</page>

Document parsing and creating a pdf file

The simplest way of using the library is:

//register the PHPPdf and vendor (Zend_Pdf and other dependencies) autoloaders
require_once 'PHPPdf/Autoloader.php';
PHPPdf\Autoloader::register();
PHPPdf\Autoloader::register('/path/to/library/lib/vendor/Zend/library');

//if you want to generate graphic files
PHPPdf\Autoloader::register('sciezka/do/biblioteki/lib/vendor/Imagine/lib');

$facade = new PHPPdf\Core\Facade(new PHPPdf\Core\Configuration\Loader());

//$documentXml and $stylesheetXml are strings contains XML documents, $stylesheetXml is optional
$content = $facade->render($documentXml, $stylesheetXml);

header('Content-Type: application/pdf');
echo $content;

Basic document structure

The library bases pages on an XML format similar to HTML, but this format isn't HTML - some tags are diffrent, interpretation of some attributes is not the as same as in the HTML and CSS standards, adding attributes is also different.

A simple document has following structure:

<pdf>
    <dynamic-page>
        <h1>Header</h1>
        <p>paragraph</p>
        <div color="red">Layer</div>
        <table>
            <tr>
                <td>Column</td>
                <td>Column</td>
            </tr>
        </table>
    </dynamic-page>
</pdf>

Adding a DOCTYPE declaration is strongly recommended in order to replace html entities on values:

    <!DOCTYPE pdf SYSTEM "%resources%/dtd/doctype.dtd">

The root name of a document must be "pdf". The "dynamic-page" tag is an auto breakable page. The "page" tag is an alternative, and represents only a single, no breakable page.

The way of attribute setting is different than in HTML.

In order to set a background and border you need to use complex attributes, where first part of attribute name is a complex attribute type, and the second part is the property of this attribute.

Complex attribute parts are separated by a dot (".").

An another way of setting complex attributes is by using the "complex-attribute" tag.

Example:

<pdf>
    <dynamic-page>
        <div color="red" border.color="black" background.color="pink">
            This text is red on pink backgroun into black border
        </div>
    </dynamic-page>
</pdf>

Alternative syntax ("stylesheet" tag):

<pdf>
    <dynamic-page>
        <div>
            <stylesheet>
                <attribute color="red" />
                <complex-attribute name="border" color="black" />
                <complex-attribute name="background" color="pink" />
            </stylesheet>
            This text is red on pink backgroun into black border
        </div>
    </dynamic-page>
</pdf>

Attributes can by set as XML attributes, directly after a tag name or by using the mentioned "stylesheet" tag. The HTML "style" attribute does not exist the PHPPdf XML dialect.

The library is very strict in respecting the corectness of tags and attributes. If an unexisted tag or attribute is detected, the document parser will stop and throw an exception.

Inheritance

The "id" attribute has an different usage than in HTML. The id attribute is used to identify tags when using inheritance.

The "name" attribute can also be used as an alias to "id".

An id must by unique throughout the document, otherwise a parsing error is thrown.

Example:

<pdf>
    <dynamic-page>
        <div id="layer-1" color="red" font-type="judson" font-size="16px">
            <stylesheet>
                <complex-attribute name="border" color="green" />
            </stylesheet>
            Layer 1
        </div>
        <div extends="layer-1">
            Layer 2 inherits style (type, simple and complex attributes) from layer 1)
        </div>
    </dynamic-page>
</pdf>

The Second layer inherits all attributes (simple and complex), and also those from external stylesheets.

Priorites in attributes setting:

  1. Stylesheet tag directly in an element tag
  2. Attributes directly after a tag name (XML attributes)
  3. Attributes from external stylesheets
  4. Inherited attributes from a parent tag

Example:

<pdf>
    <page>
        <div id="1" color="#cccccc" height="100px" text-align="right">
        </div>
        <div extends="1" color="#aaaaaa" height="150px">
            <stylesheet>
                <attribute name="height" value="200px" />
            </stylesheet>
        </div>
    </page>
</pdf>

The second "div" will now have the following attributes:

  • text-align: right
  • color: #aaaaaa
  • height: 200px

Stylesheet structure

Stylesheets are defined in external files, stylesheet short and long declarations of attributes are supported.

Syntax of the stylesheet:

Short style:

<stylesheet>
    <!-- style attributes are embeded as xml attributes, class attribute has the same meaning as in HTML/CSS -->
    <div class="class" font-size="12px" color="gray" background.color="yellow">
        <!-- nested element, equivalent CSS selector syntax: "div.class p" -->
        <p margin="10px 15px">
        </p>
    </div>

    <!-- equivalent CSS selector syntax: ".another-class", "any" tag is wildcard (mean any tag) -->
    <any class="another-class" text-align="right">
    </any>

    <h2 class="header">
        <span font-size="9px">
        </span>
        
        <div font-style="bold">
        </div>
    </h2>
</stylesheet>

Long style:

<stylesheet>
    <div class="class">
        <!-- simple and complex attributes are nested in "div.class" selector path -->
        <attribute name="font-size" value="12px" />
        <attribute name="color" value="grey" />
        <!-- equivalent of background.color attribute -->
        <complex-attribute name="background" color="yellow" />

        <!-- another nested element, equivalent CSS selector syntax: "div.class p" -->
        <p>
            <attribute name="margin" value="10px 15px" />
        </p>
    </div>

    <!-- equivalent CSS selector syntax: ".another-class", "any" tag is wildcard (mean any tag) -->
    <any class="another-class">
        <attribute name="text-align" value="right" />
    </any>

    <h2 class="header">
        <span>
            <attribute name="font-size" value="9px" />
        </span>
        <div>
            <attribute name="font-style" value="bold" />
        </div>
    </h2>
</stylesheet>

Palette of colors

PHPPdf supports color palettes, - mapping of logical names to real colors.

Color palettes gives you the opportunity to create or overwrite default named colors. By default, PHPPdf supports named colors from the W3C standard (for example "black" = "#000000").

You can use a palette for the DRY principle, because information about used colors will be kept in one place. And you can also generate one document with different palettes.

Example:

<!-- colors.xml file -->
<colors>
    <color name="header-color" hex="#333333" />
    <color name="line-color" hex="#eeeeee" />
</colors>

<!-- stylesheet.xml file -->
<h2 color="header-color" />
<hr background-color="line-color" />
<table>
    <td border-color="line-color" />
</table>

<!-- document.xml file -->
<pdf>
    <page>
        <h2>Header</h2>
        <hr />
        <table>
            <tr>
                <td>Data</td>
                <td>Data</td>
            </tr>
        </table>
    </page>
</pdf>
    //php code
    use PHPPdf\DataSource\DataSource;
    
    $facade = ...;

    $content = $facade->render(
        DataSource::fromFile(__DIR__.'/document.xml'),
        DataSource::fromFile(__DIR__.'/stylesheet.xml'),
        DataSource::fromFile(__DIR__.'/colors.xml')
    );

Standard tags

The library supports primary HTML tags: div, p, table, tr, td, b, strong, span, a, h1, h2, h3, h4, h5, img, br, ul, li

In addition there are also not standard tags:

  • dynamic-page - auto breakable page
  • page - single page with fixed size
  • elastic-page - single page that accommodates its height to its children as same as another tags (for example "div"). Header, footer, watermark, template-document attribute do not work with this tag. Useful especially in graphic files generation (image engine).
  • page-break, column-break, break - breaks page or column, this tag must be direct child of "dynamic-page" or "column-layout"!
  • column-layout - separate workspace on columns, additional attributes: number-of-columns, margin-between-columns, equals-columns
  • barcode - more information in barcode chapter
  • circle - element that border and backgroud are in circle shape. Additional attributes: radius (it overwrites width and height attributes)
  • pie-chart - element that can be used to draw simple pie chart (more information in charts chapter.

There are tags that are only bags for attributes, a set of tags etc:

  • stylesheet - stylesheet for parent
  • attribute - simple attribute declaration, direct child of "stylesheet" tag. Required attributes of this element: name - attribute name, value - attribute value
  • complex-attribute - complex attribute declaration, direct child of "stylesheet" tag. Required attributes of this element: name - complex attribute name
  • placeholders - defines placeholders for parent tag. Children tags of placeholder are specyfic for every parent tag. It should be first tag in parent
  • metadata - defines metadata of pdf document, direct child of document root
  • behaviours - defines behaviours for a parent tag. Supported behaviours: href, ref, bookmark, note (action as same as for attributes with as same as name)

Attributes

  • width and height: rigidly sets height and width, supported units are described in separate section. Relative values in percent are supported.
  • max-width, max-height: sets max sizes of elements
  • margin (margin-top, margin-bottom, margin-left, margin-right): margin similar to margin from HTML/CSS. Margins of simblings are pooled. For side margins possible is "auto" value, it works similar as in HTML/CSS.
  • padding (padding-top, padding-bottom, padding-left, padding-right): works similiar as in HTML/CSS
  • font-type - font name must occurs in fonts.xml config file, otherwise exception will be thrown
  • font-size - file size in points, there are no any unit
  • font-style - allowed values: normal, bold, italic, bold-italic, light, light-italic
  • color - text color. HTML/CSS style values are supported
  • breakable - if true, element is able to be broken in several pages. Default value for most tags is true..
  • float - works similar but not the same as in HTML/CSS. Allowed values: left|none|right, default none
  • line-height - works similar as in HTML/CSS. Default value: 1.2*font-size
  • text-align - works as same as in HTML/CSS. Allowed values: left|center|right|justify, default left.
  • text-decoration - allowed values: none, underline, overline, line-through
  • break - breaks page or column in the end of the owner of this attribute. Owner of this attribute must by directly child of dynamic-page or column-layout tag!
  • colspan, rowspan - works similar as in HTML (TODO: rowspan isn't implemented yet)
  • href - external url where element should linking
  • ref - id of element where owner should linking
  • bookmark - create bookmark with given title associated with the tag
  • note - create sticky note associated with tag
  • dump - allowed values: true or false. Create sticky note with debug informations (attributes, position etc.)
  • rotate - angle of element rotation. This attribute isn't fully implemented, works corectly for watermarks (see "Watermarks" section). Possible values: XXdeg (in degrees), XX (in radians), diagonally, -diagonally.
  • alpha - possible values: from 0 to 1. Transparency for element and his children.
  • line-break - line break (true or false), by default set on true only for "br" tag
  • style - as same as in html, this attribute can be used to set another attributes, for example: style="width: 100px; height: 200px; margin: 20px 0;". Every attribute must be finished by ";" char, even the last.
  • ignore-error (only for img tag) - ignore file loading error or throw exception? False by default, that means exception will be thrown.
  • keep-ratio (only for img tag) - keeps ratio by cutting fragment of image even if ratio of setted dimension is not the same as ratio of original source image. False by default.
  • position - the same as in html. Allowed values: static (default), relative, absolute
  • left and top - the same as in html, works with position relative or absolute. Right and bottom is not supported.

Complex attributes

Complex attributes can be set by notation "attributeName.attributeProperty" or "attributeName-attributeProperty"

For example: border.color="black" or border-color="black"

border:

  • color: border color
  • style: posible values: solid (solid line), dotted (predefined dotted line) or any definition in the form of integers separated by space
  • type: which edges will be shown - default "top+bottom+left+right" (all edges). "none" value is possible (it disable border)
  • size: border size
  • radius: corner rounding in units of length (attention: if this parameter is set, type paramete will be ignored, rounded border always will be full - this will be fixed in future)
  • position: border translation relative to original position. Positive values extends border, negative values decrases border. Owing to manipulation of this parameter, you can obtain complex pattern as border if you add another borders with different styles and positions.

background:

  • color: background color
  • image: background image
  • repeat: way of image repeating (none|x|y|all)
  • radius: rounding background corners in units of length (for now only works with color background)
  • use-real-dimension: attribute only used by page (or dynamic-page). True for filling also margins, false in otherwise.
  • image-width: custom width of background image, percentage values are allowed
  • image-height: custom height of background image, percentage values are allowed
  • position-x: horizontal position for image of background, allowed values: left, center, right or numeric value (default: left)
  • position-y: vertical position for image of background, allowed values: top, center, bottom or numeric value (default: top)

It is possible to add several complex attributes in the same type (for instance 3 different borders).

You can achieve that by using the "stylesheet" tag instead of the short notation.

<pdf>
    <dynamic-page>
        <div>
            <stylesheet>
                <!-- Top and bootom edges are red, side edges are yellow-gray --> 
                <complex-attribute name="border" color="red" type="top+bottom" />
                <complex-attribute id="borderLeftAndRight" name="border" color="yellow" type="left+right" size="4px" />
                <complex-attribute id="outerBorderLeftAndRight" name="border" color="gray" type="left+right" size="2px" position="1px" />
            </stylesheet>
        </div>
    </dynamic-page>
</pdf>

In this example, the second border has a "borderLeftAndRight" indentifie, if this border had no id, the attributes from second border would be merged with the attributes from first border.

Remeber the default identifier "id" is as same as the "name" attribute. The "id" attributes for complex attributes has nothing to do with the "id" attribute of tags (used in inheritance).

It is possible to create complex borders the same as in the previous example (outerBorderLeftAndRight).

Units

Supported units for numerical attributes:

  • in (inches)
  • cm (centimeters)
  • mm (milimeters)
  • pt (points)
  • pc (pica)*
  • px (pixels)
    • % (percent - only for width and height).

Currently unsupported units are: em and ex

When the unit is missing (for example: font-size="10"), then the default unit is points (pt). 1pt = 1/72 inch

Barcodes

Barcodes are supported by the <barcode> tag.

PHPPdf uses the Zend\Barcode library in order to generate barcodes.

Example:

<pdf>
    <dynamic-page>
        <barcode type="code128" code="PHPPdf" />
    </dynamic-page>
</pdf>

<barcode> tag supports the most of standard attributes and has some other attributes:

  • type - typ of barcode, supported values: code128, code25, code25interleaved, code39, ean13, ean2, ean5, ean8, identcode, itf14, leitcode, planet, postnet, royalmail, upca, upce
  • draw-code - equivalent of drawCode option from Zend\Barcode
  • bar-height - equivalent of barHeight option from Zend\Barcode
  • with-checksum - equivalent of withChecksum option from Zend\Barcode
  • with-checksum-in-text - equivalent of withChecksumInText option from Zend\Barcode
  • bar-thin-width - equivalent of barThinWidth option from Zend\Barcode
  • bar-thick-width - equivalent of barThickWidth option from Zend\Barcode
  • rotate - equivalent of orientation option from Zend\Barcode

You can find the description of these options and there default values in the Zend\Barcode documentation.

In order to render textual barcodes, you can't use to following embeded pdf fonts: courier, times-roman and helvetica. This will soon be fixed.

Charts

PHPPdf supports drawing simple charts.

For now there is only support for s simple pie chart.

Example:

<pdf>
    <dynamic-page>
        <pie-chart radius="200px" chart-values="10|20|30|40" chart-colors="black|red|green|blue"></pie-chart>
    </dynamic-page>
</pdf>

The <pie-chart> tag has three extra attributes:

  • radius - radius of the chart
  • chart-values - values of the chart, together they must be summing to 100. Each value must be separated by "|".
  • chart-colors - colors of each value. Each color must be separated by "|".

Hyperlinks

The library supports external and internal hyperlinks.

External hyperlinks link to url's, while internal links link to other tags inside the pdf document.

Example:

<pdf>
    <dynamic-page>
        <a href="http://google.com">go to google.com</a>
        <br />
        <a ref="some-id">go to another tag</a>
        <a href="#some-id">go to another tag</a> <!-- anchor style ref -->
        <page-break />
        <p id="some-id">Yep, this is another tag! ;)</p>
    </dynamic-page>
</pdf>

Every element has a "href" and "ref" attribute, even div. You can't nest elements inside an "a" tag.

If you want to use img elements as a link, you should use the href (external link) or ref (internal link) attribute directly in img tag.

Bookmarks

The preferred way of creating bookmarks is by using the "behaviours" tag.

This doesn't restrict the structure of the document, the owner of a parent bookmark doesn't have to be a parent of a child's bookmark owner.

Example:

<pdf>
    <dynamic-page>
	    <div>
	        <behaviours>
	            <bookmark id="1">parent bookmark</bookmark>
	        </behaviours>
	        Some content
	    </div>
	    <div>
	        <behaviours>
	            <bookmark parentId="1">children bookmark</bookmark>
	        </behaviours>
	        Some another content
	    </div>
	    <div>
	        <behaviours>
	            <bookmark parentId="1">another children bookmark</bookmark>
	        </behaviours>
	        Some another content
	    </div>
	    <div>
	        <behaviours>
	            <bookmark>another parent bookmark</bookmark>
	        </behaviours>
	       Some content
	    </div>
	</dynamic-page>
</pdf>

A shortcut for the "bookmark" behaviour is the "bookmark" attribute, if you assign some value to this attribute, bookmarks that refers to this tag will be automatically created.

The bookmark of a parent tag is also the parent of a children's bookmarks.

Example:

<pdf>
    <dynamic-page>
	    <div bookmark="parent bookmark">
	        Some content
	        <div bookmark="children bookmark">
	            Some another content
	        </div>
	        <div bookmark="another children bookmark">
	            Some another content
	        </div>
	    </div>
	    <div bookmark="another parent bookmark">
	       Some content
	    </div>
	</dynamic-page>
</pdf>

The above structures (both examples) will create this bookmarks structure:

  • parent bookmark
    • children bookmark
    • another children bookmark
  • another parent bookmark

Sticky notes

Sticky notes can be created by using the "note" attribute.

Example:

<pdf>
    <dynamic-page>
        <div note="note text"></div>
    </dynamic-page>
</pdf>

The XML parser normalizes values of attributes, wich results ignoring new line characters.

If you want to add a note with new line characters, you should use this syntax:

<pdf>
    <dynamic-page>
        <div>
            <behaviours>
                <note>note text</note>
            </behaviours>
        </div>
    </dynamic-page>
</pdf>

Repetitive headers and footers

"placeholders" can be used in for adding a repetitive header or/and footer.

Some elements have special "placeholders": page has header and footer, table also has header and footer (TODO: not implemented yet) etc.

<pdf>
    <dynamic-page>
        <placeholders>
            <header>
                <div height="50px" width="100%">
                    Header
                </div>
            </header>
            <footer>
                <div height="50px" width="100%">
                    Footer
                </div>
            </footer>
        </placeholders>
    </dynamic-page>
</pdf>

Header and footer need to have a height attribute set. This height is pooled with page top and bottom margins.

Workspace is the page size reduced by page margins and placeholders (footer and header) height.

Watermarks

Page can have a "watermark" placeholder.

The watermark may be set on block's and container elements, for instance: div, p, h1 (no span, plain text or img).

If you want to use an image as a watermark, you should wrap the img tag in a div.

Example:

<pdf>
    <dynamic-page>
        <placeholders>
            <watermark>
                <!-- rotate can have absolute values (45deg - in degrees, 0.123 - in radians) or relative values ("diagonally" and "-diagonally" - angle between diagonal and base side of the page) -->
                <div rotate="diagonally" alpha="0.1">
                    <img src="path/to/image.png" />
                </div>
            </watermark>
        </placeholders>
    </dynamic-page>
</pdf>

Page numbering

There are two tags that can be used to show page information in a footer, header or watermark: page-info and page-number.

This element only works with dynamic-page, not single pages. Page-info shows the current and total page number, page-number shows only the current page number.

Attributes of this tags:

  • format - format of output string that will be used as argument of sprintf function. Default values: "%s." for page-number, "%s / %s" for page-info.
  • offset - value that will be added to current page number and total page number. Usefull if you want to count pages from a diffrent value than zero. Default: 0.

Example:

<pdf>
    <dynamic-page>
        <placeholders>
            <header>
                <div height="20px">
                    <page-info format="page %s for %s" />

                    <!-- when we would like to number from 2 -->
                    <page-info offset="1" format="page %s for %s" />

                    <!-- when we would like to display only current page number -->
                    <page-info format="%1$s." />
                    <!-- or -->
                    <page-number />

                    <!-- when we would like to display only total pages number -->
                    <page-info format="%2$s pages" />
                </div>
            </header>
        </placeholders>
        Some text
    </dynamic-page>
</pdf>

Using a pdf document as a template

The "page" and "dynamic-page" tags can have a "document-template" attribute, that allows you to use an external pdf document as a template.

For the "page" tag, the page's template will be the first page of an external document.

For the "dynamic-page" tag, the template for each page will be the corresponding page of an external document.

Example:

<pdf>
    <dynamic-page document-template="path/to/file.pdf">
        <div>Some content</div>
    </dynamic-page>
</pdf>

Separate page on columns

Page can be separated on columns:

<pdf>
    <dynamic-page>
        <column-layout>
            <div width="100%" height="2500px" background.color="green">
            </div>
        </column-layout>
    </dynamic-page>
</pdf>

The above XML describes several pages of the pdf document, with green rectangles separated on two columns.

The "column-layout" tag has three additional parameters: number-of-columns, margin-between-columns and equals-columns.

Default values for this attributes are 2, 10 and false respectlivy. If the equals-columns attribute is set, columns will have more or less equals height.

Breaking pages and columns

Page and column may by manually broken using one of these tags: page-break, column-break, break.

All these tags are the same. These tags need to be direct children of the breaking element (dynamic-page or column-layout).

If you want to avoid automatic page or column break on certain tags, you should set the "breakable" attribute of this tag to "off.

Example:

<pdf>
    <dynamic-page>
        <div breakable="false">this div won't be automatically broken</div>
    </dynamic-page>
</pdf>

Metadata

Metadata can be added by attributes at the document's root.

Supported metadata is: Creator, Keywords, Subject, Author, Title, ModDate, CreationDate and Trapped.

** These attribute names are case sensitive. **

Example:

<pdf Author="Piotr Sliwa" Title="Test document">
    <!-- some other elements -->
</pdf>

Configuration

The library has four primary config files that allow you to adopt the library for specyfic needs and extending.

  • complex-attributes.xml - declarations of complex attributes classes to logical names that identify attribute in whole library.
  • nodes.xml - definitions of allowed tags in xml document with default attributes and formatting objects.
  • fonts.xml - definitions of fonts and assigning them to logical names that identify font in whole library.
  • colors.xml - palette of colors definitions

In order to change default the config files, you must pass to Facade constructor configured Loader object:

    $loader = new PHPPdf\Core\Configuration\LoaderImpl(
        '/path/to/file/nodes.xml',
        '/path/to/file/enhancements.xml',
        '/path/to/file/fonts.xml',
        '/path/to/file/colors.xml'
    );
    
    $facade = new PHPPdf\Core\Facade($loader);

If you want to change only one config file, you should use LoaderImpl::set* method:

$loader = new PHPPdf\Core\Configuration\LoaderImpl();
$loader->setFontFile(
'/path/to/file/fonts.xml'); //there are setFontFile, setNodeFile, setComplexAttributeFile and setColorFile methods
$facade = new PHPPdf\Core\Facade($loader);

FacadeBuilder can be uset to build and configure Facade. FacadeBuilder is able to configure cache, rendering engine and document parser.

$builder = PHPPdf\Core\FacadeBuilder::create(/* you can pass specyfic configuration loader object */)
                                        ->setCache('File', array('cache_dir' => './cache'))
                                        ->setUseCacheForStylesheetConstraint(true); //stylesheets will be also use cache

$facade = $builder->build();

Markdown support

Library supports basic (official) markdown syntax. To convert markdown document to pdf, you should configure Facade object by MarkdownDocumentParser. You also might to use FacadeBuilder to do this for you.

Example:

$facade = PHPPdf\Core\FacadeBuilder::create()
                                   ->setDocumentParserType(PHPPdf\Core\FacadeBuilder::PARSER_MARKDOWN)
                                   ->setMarkdownStylesheetFilepath(/** optionaly path to stylesheet in xml format */)
                                   ->build();

By default, in markdown pdf document, helvetica font is used. If you want to use utf-8 characters or customize a pdf document, you should provide your own stylesheet by using the FacadeBuilder::setMarkdownStylesheetFilepath method.

The stylesheet structure has been described in the stylesheet chapter. By default the stylesheet is empty, if you want to set another font type, the stylesheet should look like this:

<stylesheet>
    <any font-type="DejaVuSans" />
</stylesheet>

Internally the MarkdownDocumentParser converts a markdown document to html (via the PHP markdown library), then converts html to xml, and at last xml to a pdf document.

Be aware of that, if you in a markdown document use raw html that will be incompatible with the xml syntax of PHPPdf (for example unexistend attributes or tags), the parser will throw an exception then.

Not all tags used in the markdown implementation are propertly supported by PHPPdf, for example "pre" and "code" tags.
For now "pre" tag is an alias for "div", and "code" tag is an alias for "span", be aware of that.

Image generation engine

PHPPdf is able to generate image (jpg or png) files insted of a pdf document. To achieve that, you must configure the FacadeBuilder, example:

$facade = PHPPdf\Core\FacadeBuilder::create()
                                   ->setEngineType('image')
                                   ->build();

//render method returns array of images' sources, one pdf page is generated to single image file 
$images = $facade->render(...);

By default the GD library is used to render an image.

But you can also use Imagick, which offers a better quality, so it is recommended that if you have the opportiunity to install Imagick on your server. To switch the graphic library, you must configure the FacadeBuilder object using the setEngineOptions method:

$builder = ...;
$builder->setEngineOptions(array(
    'engine' => 'imagick',
    'format' => 'png',//png, jpeg or wbmp
    'quality' => 60,//int from 0 to 100
));

Supported graphic libraries are: GD (default), imagick, gmagick. PHPPdf uses the Imagine library as an interface for graphics file generation.

Known limitations

Below is a list of known limitations of the current version of the library:

  • there no way to inject an image into a text with floating - will be introduced in the next releases
  • partial support for float attribute within table element (floats might work improperly within a table)
  • vertical-align attribute works improperly if in element with this attribute set, are more than one element
  • border doesn't change dimensions of the element (while in HTML they do)
  • png files (expecially without compression) are inefficient. png files with high compression (compression level 6 or higher) or jpeg should be used instead
  • not all tags are propertly supported, for example the "pre" tag is an alias to "div" and the "code" tag is an alias for "span"
  • nesting of linear tags (text, span, code, page-info, page-number, a, b, i, em) is not properly supported. If one linear tag contains another, only text within this tags is merged, styles are taken from the most outher linear tag.

TODO - plans

  • automatic generating of "table of contents"
  • improve table, header and footer for table, rowspan. Fix calculation of cell's min height when colspan is used.
  • support for simple bar and pie charts

Technical requirements

This library works with php 5.3 and up.

Author: psliwa
Source Code: https://github.com/psliwa/PHPPdf
License: MIT License

#php #pdf 

PHPPDF: PDF and Graphic Files Generator Library Written in PHP
Veronica  Roob

Veronica Roob

1651615380

DomPDF: HTML to PDF Converter for PHP

Dompdf

Dompdf is an HTML to PDF converter

At its heart, dompdf is (mostly) a CSS 2.1 compliant HTML layout and rendering engine written in PHP. It is a style-driven renderer: it will download and read external stylesheets, inline style tags, and the style attributes of individual HTML elements. It also supports most presentational HTML attributes.

This document applies to the latest stable code which may not reflect the current release. For released code please navigate to the appropriate tag.

Check out the demo and ask any question on StackOverflow or in Discussions.Features

  • Handles most CSS 2.1 and a few CSS3 properties, including @import, @media & @page rules
  • Supports most presentational HTML 4.0 attributes
  • Supports external stylesheets, either local or through http/ftp (via fopen-wrappers)
  • Supports complex tables, including row & column spans, separate & collapsed border models, individual cell styling
  • Image support (gif, png (8, 24 and 32 bit with alpha channel), bmp & jpeg)
  • No dependencies on external PDF libraries, thanks to the R&OS PDF class
  • Inline PHP support
  • Basic SVG support (see "Limitations" below)

Requirements

  • PHP version 7.1 or higher
  • DOM extension
  • MBString extension
  • php-font-lib
  • php-svg-lib

Note that some required dependencies may have further dependencies (notably php-svg-lib requires sabberworm/php-css-parser).

Recommendations

  • OPcache (OPcache, XCache, APC, etc.): improves performance
  • GD (for image processing)
  • IMagick or GMagick extension: improves image processing performance

Visit the wiki for more information: https://github.com/dompdf/dompdf/wiki/Requirements

About Fonts & Character Encoding

PDF documents internally support the following fonts: Helvetica, Times-Roman, Courier, Zapf-Dingbats, & Symbol. These fonts only support Windows ANSI encoding. In order for a PDF to display characters that are not available in Windows ANSI, you must supply an external font. Dompdf will embed any referenced font in the PDF so long as it has been pre-loaded or is accessible to dompdf and reference in CSS @font-face rules. See the font overview for more information on how to use fonts.

The DejaVu TrueType fonts have been pre-installed to give dompdf decent Unicode character coverage by default. To use the DejaVu fonts reference the font in your stylesheet, e.g. body { font-family: DejaVu Sans; } (for DejaVu Sans). The following DejaVu 2.34 fonts are available: DejaVu Sans, DejaVu Serif, and DejaVu Sans Mono.

Easy Installation

Install with composer

To install with Composer, simply require the latest version of this package.

composer require dompdf/dompdf

Make sure that the autoload file from Composer is loaded.

// somewhere early in your project's loading, require the Composer autoloader
// see: http://getcomposer.org/doc/00-intro.md
require 'vendor/autoload.php';

Download and install

Download a packaged archive of dompdf and extract it into the directory where dompdf will reside

Use the packaged release autoloader to load dompdf, libraries, and helper functions in your PHP:

// include autoloader
require_once 'dompdf/autoload.inc.php';

Note: packaged releases are named according using semantic versioning (dompdf_MAJOR-MINOR-PATCH.zip). So the 1.0.0 release would be dompdf_1-0-0.zip. This is the only download that includes the autoloader for Dompdf and all its dependencies.

Install with git

From the command line, switch to the directory where dompdf will reside and run the following commands:

git clone https://github.com/dompdf/dompdf.git
cd dompdf/lib

git clone https://github.com/PhenX/php-font-lib.git php-font-lib
cd php-font-lib
git checkout 0.5.1
cd ..

git clone https://github.com/PhenX/php-svg-lib.git php-svg-lib
cd php-svg-lib
git checkout v0.3.2
cd ..

git clone https://github.com/sabberworm/PHP-CSS-Parser.git php-css-parser
cd php-css-parser
git checkout 8.1.0

Require dompdf and it's dependencies in your PHP. For details see the autoloader in the utils project.

Quick Start

Just pass your HTML in to dompdf and stream the output:

// reference the Dompdf namespace
use Dompdf\Dompdf;

// instantiate and use the dompdf class
$dompdf = new Dompdf();
$dompdf->loadHtml('hello world');

// (Optional) Setup the paper size and orientation
$dompdf->setPaper('A4', 'landscape');

// Render the HTML as PDF
$dompdf->render();

// Output the generated PDF to Browser
$dompdf->stream();

Setting Options

Set options during dompdf instantiation:

use Dompdf\Dompdf;
use Dompdf\Options;

$options = new Options();
$options->set('defaultFont', 'Courier');
$dompdf = new Dompdf($options);

or at run time

use Dompdf\Dompdf;

$dompdf = new Dompdf();
$options = $dompdf->getOptions();
$options->setDefaultFont('Courier');
$dompdf->setOptions($options);

See Dompdf\Options for a list of available options.

Resource Reference Requirements

In order to protect potentially sensitive information Dompdf imposes restrictions on files referenced from the local file system or the web.

Files accessed through web-based protocols have the following requirements:

  • The Dompdf option "isRemoteEnabled" must be set to "true"
  • PHP must either have the curl extension enabled or the allow_url_fopen setting set to true

Files accessed through the local file system have the following requirement:

  • The file must fall within the path(s) specified for the Dompdf "chroot" option

Limitations (Known Issues)

  • Dompdf is not particularly tolerant to poorly-formed HTML input. To avoid any unexpected rendering issues you should either enable the built-in HTML5 parser at runtime ($options->setIsHtml5ParserEnabled(true);) or run your HTML through a HTML validator/cleaner (such as Tidy or the W3C Markup Validation Service).
  • Table cells are not pageable, meaning a table row must fit on a single page.
  • Elements are rendered on the active page when they are parsed.
  • Embedding "raw" SVG's (<svg><path...></svg>) isn't working yet, you need to either link to an external SVG file, or use a DataURI like this:
$html = '<img src="data:image/svg+xml;base64,' . base64_encode($svg) . '" ...>';
  • Watch #320 for progress

If you find this project useful, please consider making a donation. Any funds donated will be used to help further development on this project.)

Author: dompdf
Source Code: https://github.com/dompdf/dompdf
License: LGPL-2.1 License

#php #pdf #html 

DomPDF: HTML to PDF Converter for PHP
Bongani  Ngema

Bongani Ngema

1651163100

PDFKit: A JavaScript PDF Generation Library for Node and The Browser

PDFKit

A JavaScript PDF generation library for Node and the browser.

Description

PDFKit is a PDF document generation library for Node and the browser that makes creating complex, multi-page, printable documents easy. The API embraces chainability, and includes both low level functions as well as abstractions for higher level functionality. The PDFKit API is designed to be simple, so generating complex documents is often as simple as a few function calls.

Check out some of the documentation and examples to see for yourself! You can also read the guide as a self-generated PDF with example output displayed inline. If you'd like to see how it was generated, check out the README in the docs folder.

You can also try out an interactive in-browser demo of PDFKit here.

Installation

Installation uses the npm package manager. Just type the following command after installing npm.

npm install pdfkit

Features

  • Vector graphics
    • HTML5 canvas-like API
    • Path operations
    • SVG path parser for easy path creation
    • Transformations
    • Linear and radial gradients
  • Text
    • Line wrapping
    • Text alignments
    • Bulleted lists
  • Font embedding
    • Supports TrueType (.ttf), OpenType (.otf), WOFF, WOFF2, TrueType Collections (.ttc), and Datafork TrueType (.dfont) fonts
    • Font subsetting
    • See fontkit for more details on advanced glyph layout support.
  • Image embedding
    • Supports JPEG and PNG files (including indexed PNGs, and PNGs with transparency)
  • Annotations
    • Links
    • Notes
    • Highlights
    • Underlines
    • etc.
  • AcroForms
  • Outlines
  • PDF security
    • Encryption
    • Access privileges (printing, copying, modifying, annotating, form filling, content accessibility, document assembly)
  • Accessibility support (marked content, logical structure, Tagged PDF, PDF/UA)

Coming soon!

  • Patterns fills
  • Higher level APIs for creating tables and laying out content
  • More performance optimizations
  • Even more awesomeness, perhaps written by you! Please fork this repository and send me pull requests.

Example

const PDFDocument = require('pdfkit');
const fs = require('fs');

// Create a document
const doc = new PDFDocument();

// Pipe its output somewhere, like to a file or HTTP response
// See below for browser usage
doc.pipe(fs.createWriteStream('output.pdf'));

// Embed a font, set the font size, and render some text
doc
  .font('fonts/PalatinoBold.ttf')
  .fontSize(25)
  .text('Some text with an embedded font!', 100, 100);

// Add an image, constrain it to a given size, and center it vertically and horizontally
doc.image('path/to/image.png', {
  fit: [250, 300],
  align: 'center',
  valign: 'center'
});

// Add another page
doc
  .addPage()
  .fontSize(25)
  .text('Here is some vector graphics...', 100, 100);

// Draw a triangle
doc
  .save()
  .moveTo(100, 150)
  .lineTo(100, 250)
  .lineTo(200, 250)
  .fill('#FF3300');

// Apply some transforms and render an SVG path with the 'even-odd' fill rule
doc
  .scale(0.6)
  .translate(470, -380)
  .path('M 250,75 L 323,301 131,161 369,161 177,301 z')
  .fill('red', 'even-odd')
  .restore();

// Add some text with annotations
doc
  .addPage()
  .fillColor('blue')
  .text('Here is a link!', 100, 100)
  .underline(100, 100, 160, 27, { color: '#0000FF' })
  .link(100, 100, 160, 27, 'http://google.com/');

// Finalize PDF file
doc.end();

The PDF output from this example (with a few additions) shows the power of PDFKit — producing complex documents with a very small amount of code. For more, see the demo folder and the PDFKit programming guide.

Browser Usage

There are three ways to use PDFKit in the browser:

In addition to PDFKit, you'll need somewhere to stream the output to. HTML5 has a Blob object which can be used to store binary data, and get URLs to this data in order to display PDF output inside an iframe, or upload to a server, etc. In order to get a Blob from the output of PDFKit, you can use the blob-stream module.

The following example uses Browserify or webpack to load PDFKit and blob-stream. See here and here for examples of prebuilt version usage.

// require dependencies
const PDFDocument = require('pdfkit');
const blobStream = require('blob-stream');

// create a document the same way as above
const doc = new PDFDocument();

// pipe the document to a blob
const stream = doc.pipe(blobStream());

// add your content to the document here, as usual

// get a blob when you are done
doc.end();
stream.on('finish', function() {
  // get a blob you can do whatever you like with
  const blob = stream.toBlob('application/pdf');

  // or get a blob URL for display in the browser
  const url = stream.toBlobURL('application/pdf');
  iframe.src = url;
});

You can see an interactive in-browser demo of PDFKit here.

Note that in order to Browserify a project using PDFKit, you need to install the brfs module with npm, which is used to load built-in font data into the package. It is listed as a devDependency in PDFKit's package.json, so it isn't installed by default for Node users. If you forget to install it, Browserify will print an error message.

Documentation

For complete API documentation and more examples, see the PDFKit website.

Author: foliojs
Source Code: https://github.com/foliojs/pdfkit 
License: MIT License

#node #pdf #browser #javascript 

PDFKit: A JavaScript PDF Generation Library for Node and The Browser
宇野  和也

宇野 和也

1650938400

【Pythonで自動化】コピペしていない?大量PDFからテキスト情報を一瞬で取得

仕事をしていると、PDFの中に書かれているテキストを、別の書類に使いたいという場面はないでしょうか。    
PDFファイルのごく一部を取り出すだけであれば、コピペでもできますが、選択範囲が多く、何ページにもわたるようなときはかなり面倒な作業です。  
しかも画像をPDF化したファイルですと、文字や表などをコピペしようとしても、うまくできないことが多いかと思います。  
そんなときに、テキストファイルに読み込むことができると、かなりの業務効率化につながるでしょう。   
PDF形式でもらった文書の内容をテキスト化することで、携帯にメールで転送するなど、文書の一部をテキストで保存・転送・管理したりすることも可能になります。   
この動画では、Pythonでpdfを読み取り、テキストファイルに書き起こす方法について説明します。  
使用するライブラリは、日本語に対応しているPDFminerというライブラリです。

 

▼目次
00:00 ダイジェスト
00:15 はじめに
01:14 PDF読み取りのライブラリについて
02:38 プログラムに使用するライブラリのインストール
03:25 プログラムの説明
08:08 おわりに

 #python #pdf 

【Pythonで自動化】コピペしていない?大量PDFからテキスト情報を一瞬で取得
Alfie Mellor

Alfie Mellor

1650696172

How to Generate a PDF File in Laravel 9 with DomPDF

I will give you a simple example of how to generate a pdf file in laravel 9. we will use DomPDF composer package to generate a pdf file in laravel 9. just follow the below step and get a simple pdf using laravel 9.

Step 1: Install Laravel 9

This step is not required; however, if you have not created the laravel app, then you may go ahead and execute the below command:

composer create-project laravel/laravel example-app

Step 2: Install DomPDF Package

next, we will install DomPDF package using following composer command, let's run bellow command:

composer require barryvdh/laravel-dompdf

Step 3: Create Controller

In this step, we will create PDFController with generatePDF() where we write code of generate pdf. so let's create controller using bellow command.

php artisan make:controller PDFController

in PDFController, we also get users table data and display them into pdf file. so you can add some dummy data on the users table by using the following tinker command:

php artisan tinker

User::factory()->count(10)->create()

Now, update the code on the controller file.

app/Http/Controllers/PDFController.php

<?php
  
namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
use App\Models\User;
use PDF;
  
class PDFController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function generatePDF()
    {
        $users = User::get();
  
        $data = [
            'title' => 'Welcome to codequs.com',
            'date' => date('m/d/Y'),
            'users' => $users
        ]; 
            
        $pdf = PDF::loadView('myPDF', $data);
     
        return $pdf->download('codequs.pdf');
    }
}

Step 4: Add Route

Furthermore, open routes/web.php file and update code on it.

routes/web.php

<?php
  
use Illuminate\Support\Facades\Route;
  
use App\Http\Controllers\PDFController;
  
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
  
Route::get('generate-pdf', [PDFController::class, 'generatePDF']);

Step 5: Create View File

In Last step, let's create myPDF.blade.php(resources/views/myPDF.blade.php) for layout of pdf file and put following code:

resources/views/myPDF.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>Laravel 9 Generate PDF Example - codequs.com</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
    <h1>{{ $title }}</h1>
    <p>{{ $date }}</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua.</p>
  
    <table class="table table-bordered">
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Email</th>
        </tr>
        @foreach($users as $user)
        <tr>
            <td>{{ $user->id }}</td>
            <td>{{ $user->name }}</td>
            <td>{{ $user->email }}</td>
        </tr>
        @endforeach
    </table>
  
</body>
</html>

Run Laravel App:

All the required steps have been done, now you have to type the given below command and hit enter to run the Laravel app:

php artisan serve

Now, Go to your web browser, type the given URL and view the app output:

http://localhost:8000/generate-pdf

I hope it can help you...

#laravel #laravel9 #php #pdf #programming 

How to Generate a PDF File in Laravel 9 with DomPDF