Electron + Vue.jsで画面をPDF化する手順
はじめに
Electron + Vue.jsで構築したデスクトップアプリで画面をPDF化するための手順をまとめます。
できるようになること
以下のように、ボタンをクリックすることで、その画面をPDF化して開けるようになります。
このデモのコードは以下のGitHubにあげています。
前提と環境
以下の通りです。
- OS : Ubuntu 18.04
- Vue CLI : 3.8.2
- Electron : 5.0.0
Electron + Vue.jsアプリについては、以下の手順に従って構築した前提となります。Vue CLI Plugin Electron Builderを使って作成したElectron + Vue.jsアプリが前提となりますが、その他のプラグインやツールを使用した場合でもメインのPDF化部分については共通になると思います。
ElectronはWebアプリケーションの開発に使われるJavascriptやHTML、CSSなどの技術を用いてデスクトップアプリを開発できるフレームワークです。1つのソースでクロスプラットフォーム対応(Windows、Mac OS、Linux)のデスクトップアプリを開発することができます。この記事では、Ubuntu上でElectronとさらにVue.jsを用いたデスクトップアプリ開発をはじめるために必要なツールのインストール手順と、実際にデモアプリを起動させるまでをまとめます。
参考文献
PDF化部分を以下の記事を参考にさせて頂きました。ありがとうございます。
Hi Everyone. I was caught up in a situation where I need...
PDF化の概要
Electronでは、IPC通信を使用することでとメイン処理部分(メインプロセス)と各画面内の処理(レンダラープロセス)が連携できます。PDF化の処理についても、画面上に用意したボタンをクリックすることで、メインプロセスにPDF化の処理をIPC通信でリクエストしてメインプロセスがPDFを作成します。PDF化の処理については、Electronデフォルトで使用可能なprintToPDF
というAPIを使用します。以降では、メインプロセスとレンダラープロセスそれぞれの処理を説明します。
修正するファイルについて
Vue CLI Plugin Electron BuilderでElectronアプリを構築した場合、デフォルトではアプリのディレクトリ直下にsrc
というディレクトリがあり、src
の中身は以下のようになっています。ただし、以下はVuex、Router、TypeScriptを有効化している場合です。
.
├── App.vue
├── assets
├── background.ts
├── components
├── main.ts
├── router.ts
├── shims-tsx.d.ts
├── shims-vue.d.ts
├── store.ts
└── views
上記はTypeScriptを使用するよう指定したために拡張子がts
になっています。また、shims-tsx.d.ts
とshims-vue.d.ts
もTypeScriptを使用するよう指定した場合のみ作成されます。これらのファイルは、IDEに対して.vue
ファイルとjsx
ファイルを扱えるようにするためのファイルです。
TypeScriptを使用するよう指定していない場合は、src
ディレクトリは以下のようになっていると思います。
.
├── App.vue
├── assets
├── background.js
├── components
├── main.js
├── router.js
├── store.js
└── views
background.ts
(background.js
)がメインプロセスのファイルになり、レンダラープロセスのファイルはviews
配下にあるVueファイルになります。
この記事では、TypeScriptを使っている前提としますが、JavaScriptの場合と比べて処理内容については変わらず型の指定などの違いぐらいになります。
レンダラープロセス側の処理
Vue CLI Plugin Electron Builderを使って作成したアプリのデフォルト状態のHome.vue
に少しだけ追記します。以下が追記したコードです。主に、クリックによってcreatePDF
という適当に付けた名前のメソッドを呼び出すボタンを追加しています。createPDF
によってメインプロセスにPDF化をリクエストします。
なお、Home.vue
がない場合は、他の適当な.vue
ファイルで試してみてください。
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App !!"/>
<button id='print-pdf' @click="createPDF()">Convert to PDF</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src
import { ipcRenderer } from 'electron'
@Component({
components: {
HelloWorld
}
})
export default class Home extends Vue {
pdfname: string = "mypdf"
// ボタンクリックでPDF作成をメインプロセスにリクエスト
createPDF () {
ipcRenderer.send('print-to-pdf', this.pdfname)
}
mounted () {
// mountでメインプロセスからのIPC通信待機
ipcRenderer.on('wrote-pdf', (event: any, path: any) => {
const msg = `PDFを ${path} に作成しました。`
console.log(msg)
})
}
}
</script>
次にメインプロセス側の処理を説明します。
メインプロセス側の処理
メインプロセスのbackground.ts
にPDF化部分の処理を追記します。具体的には、以下をbackground.ts
の末尾に追記します。また、import
でもいくつか追記しています。
'use strict'
import { app, protocol, BrowserWindow, ipcMain, shell } from 'electron'
import {
createProtocol,
installVueDevtools
} from 'vue-cli-plugin-electron-builder/lib'
import fs from 'fs'
import os from 'os'
import path from 'path'
const isDevelopment = process.env.NODE_ENV !== 'production'
(...途中省略...)
// 以下追記
// PDF作成処理
ipcMain.on('print-to-pdf', (event: any, arg: any) => {
// 作成するPDFの保存パスを指定
const pdfPath = path.join(os.tmpdir(), arg + '.pdf')
const win = BrowserWindow.fromWebContents(event.sender)
// Electronデフォルトで使用できるprintToPDFを使用する
win.webContents.printToPDF({}, (error, data) => {
if (error) return console.log(error.message)
fs.writeFile(pdfPath, data, err => {
if (err) return console.log(err.message)
shell.openExternal('file://' + pdfPath)
event.sender.send('wrote-pdf', pdfPath)
})
})
});
PDF化部分については、Electronでデフォルトで使用できるprintToPDF
を使用しています。printToPDF
については以下の公式ドキュメントに詳細が載っています。
なお、PDF化に関するオプションも指定できるようになっています。次節で説明します。
PDF化のオプションについて
以下のようにprintToPDF
にオプションを渡すことができます。
// PDF作成処理
ipcMain.on('print-to-pdf', (event: any, arg: any) => {
// 作成するPDFの保存パスを指定
const pdfPath = path.join(os.tmpdir(), arg + '.pdf')
const win = BrowserWindow.fromWebContents(event.sender)
// printToPDFにオプションを渡す
win.webContents.printToPDF({
marginsType: 0,
pageSize: 'A4',
printBackground: false,
printSelectionOnly: false,
landscape: false
}, (error, data) => {
if (error) return console.log(error.message)
fs.writeFile(pdfPath, data, err => {
if (err) return console.log(err.message)
shell.openExternal('file://' + pdfPath)
event.sender.send('wrote-pdf', pdfPath)
})
})
});
指定できるオプションは以下のようになっています。
オプション名 | 内容 |
---|---|
marginsType | マージンの指定。0 :デフォルトマージン, 1 :マージンなし、2 :最小マージン。
なお、具体的なマージン値については未確認ですが、これはChrominum(Chrome)での印刷時に指定できるマージンと同じものです。 |
pageSize | 用紙サイズとして次の値を指定可能。A3 、A4 、A5 、Legal 、 Letter 、Tabloid 。また、具体的な幅と高さも指定可能。例えば、{ width: 100000, height: 100000 } を渡すと幅と高さが100000マイクロメートル(10cm)の用紙でPDF化します。マイクロメートルなので注意が必要です。 |
printBackground | CSSで指定しているバックグラウンドを印刷するかの指定。false 、true で指定。 |
printSelectionOnly | 選択範囲のみを印刷するかの指定。false 、true で指定。 |
landscape | 印刷の向きを指定。false で横向き、true で縦向き。 |
page-break-before | 常に新しいページで印刷するかの指定。指定したい場合はpage-break-before: always をオプションに加える。 |
まとめ
ElectronはChrominumがベースとなっているためPDF化についてデフォルトで対応できとても簡単でした。
関連記事
- 公開日:2019/09/11 更新日:2019/09/11
Nuxt.jsで使っているBuefyのスタイルをカスタマイズする
Nuxt.jsでBuefyを使っており、部分的にスタイルをカスタマイズしたい場面がありました。この記事では、Nuxt.jsで使っているBuefyのスタイルをカスタマイズする方法をまとめます。
- 公開日:2019/06/15 更新日:2019/06/15
Electron + Vue.js アプリでSQLite3を使う手順
Electron + Vue.jsで構築したデスクトップアプリでSQLite3を使うための手順をまとめます。
- 公開日:2019/06/05 更新日:2019/06/05
Electron+Vue.jsを使ったデスクトップアプリ開発を始める手順
ElectronはWebアプリケーションの開発に使われるJavascriptやHTML、CSSなどの技術を用いてデスクトップアプリを開発できるフレームワークです。この記事では、Ubuntu上でElectronとさらにVue.jsを用いたデモアプリを起動させるまでをまとめます。
- 公開日:2018/11/30 更新日:2018/11/30
Vue.jsアプリをNow(zeit.co)にデプロイするまでの手順と使い方
Nowは非常にシンプルなPaaSです。他のPaaSと比較しても必要な設定やデプロイまでの作業が非常に簡単になっています。この記事では、ローカルにあるVue.jsアプリをNow上にデプロイし、実際にブラウザからアクセスしてみるところまでの手順をメモします。