はじめに
みなさん印刷してますか?
私は印刷していません。
印刷しようがしまいが、エンドユーザからは印刷機能を求められるものです。
今日は電子データ化、電子署名など一切を忘れましょう。
さて、帳票を印刷する際に使うツールとしてまず思いつくのはPDF、Excelでしょうか。
しかし、システムをユーザへ提供するし易さ、スピードで最も良いインターフェースはWebアプリケーションです。
というわけで React.js
で帳票を印刷します。
Webアプリケーションで印刷するということ
Webアプリケーションで印刷を行う際に真っ先に思いつくのは、BackEndで印刷用ファイル(PDF)を生成し、FrontEndはそれをダウンロード・PDFViewerで印刷といった流れでしょうか。
今回はこれは行いません。
一方で、Webブラウザにはそれ独自の印刷機能が付いています。
この印刷機能はWebページ=DOMを直接印刷してくれるようです。
というわけで DOMを印刷します。
つかうもの
- React.js 16.9.0
- react-to-print 2.4.0
react-to-print を選択した理由としては、SampleCodeで Class Component/Functional Component の両者に言及されていたからです。
React Hook
その他、簡易的なデザイン付けのため、いつもお世話になっている material-uiを使用します。
成果物
Demoについて
プロフィールカードに「プレビュー」と「印刷」ボタンが表示されています。
- プレビュー:プレビュー画面を出してから印刷出来ます
- 印刷:直接印刷画面を出します。
印刷画面はブラウザの機能に依存します。
概要
プレビュー画面
<DialogTitle id="alert-dialog-title">{`${src.name}のプロフィールを印刷しますか?`}</DialogTitle>
<DialogContent>
<Print ref={componentRef} src={src} />
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
キャンセル
</Button>
<ReactToPrint
trigger={() => (
<Button size="small" color="primary">
印刷
</Button>
)}
content={() => componentRef.current}
/>
</DialogActions>
プレビュー画面はDialogで表示しています。
印刷対象のComponentは Print
で定義しています。
<Print ref={componentRef} src={src} />
印刷機能を提供してくれるのは ReactToPrint
です。
<ReactToPrint
trigger={() => (
<Button size="small" color="primary">
印刷
</Button>
)}
content={() => componentRef.current}
/>
ReactToPrint
のcontentに先ほどの Print
を渡します。
その際、componentRef
を経由していますが、これはuseRef()
でrefオブジェクトを渡しています。
印刷画面
<CardActions>
<ReactToPrint
trigger={() => (
<Button size="small" color="primary">
印刷
</Button>
)}
content={() => componentRef.current}
/>
<div style={{ display: "none" }}>
<Print ref={componentRef} src={src} />
</div>
</CardActions>
直接印刷する際にはPrint
を表示する必要がないのでdisplay: "none"
で非表示にしています。
<div style={{ display: "none" }}>
<Print ref={componentRef} src={src} />
</div>
メリット
- 画面構成と印刷内容構成を同時に実装できる
- CSSでデザインできる
- なんかおしゃれな気がする
- BackEnd処理が軽くなる
デメリット
- 印刷設定ができない(?)
※今回使用したreact-to-print単体ではできませんが、CSSを駆使すれば出来るかも
【補足】実はプレビューしないとCSSの反映が完璧ではない
今回、display: "none"
を使用してプレビューを出さずに印刷する方法を提示しましたが、そうするとCSSが想定とずれることがあります。
プレビューしてから印刷 | 直接印刷 |
---|---|
上図では氏名とoutlineが重なっています。
# ただ、プレビューせずに印刷することは力技でやっているので自業自得感はあります
おわりに
React.jsに印刷機能を持たせてみました。
自作の職務経歴書くらいはかんたんに作れそうですね
みなさんも良き印刷ライフを