ReoGrid ReoGrid Web

PDFエクスポート

v1.4.0 から、ReoGrid インスタンスはアクティブなワークシートを本物のベクター PDF(テキスト・罫線・塗り・セル結合・セルアンカー画像)に出力できます。外部ライブラリもサーバー往復も不要で、ワークシートのデータからブラウザ内で生成します。

Note: PDFエクスポートは Pro 版で利用可能です。

フォントは必須です。 PDF レンダラーはグリフ輪郭を埋め込むため、エクスポートには実際のフォントのバイト列が必要です。locale'ja' / 'zh-CN' / 'zh-TW' / 'ko')を指定すれば ReoGrid がフォントを解決します。自前のバイト列を font に渡すこともできます。どちらも指定しない場合はエクスポートが例外を投げます。これにより日本語・中国語・韓国語が正しく描画されます。

クイックスタート

import { createReogrid, preloadPdfFont } from '@reogrid/pro'

const grid = createReogrid({ workspace: '#app' })

// ロケールのフォントを一度だけ、自分で制御できる非同期地点で取得する
await preloadPdfFont('ja')

// レンダリングとダウンロードを 1 回で
grid.saveAsPdf({ locale: 'ja', filename: 'report.pdf' })

saveAsPdf() はレンダリングしてブラウザのダウンロードを起動します。生のバイト列が欲しい場合(アップロードやプレビューなど)は exportPdf() を使います。

const bytes: Uint8Array = grid.exportPdf({ locale: 'ja' })
// 例:プレビュー URL 用に Blob へラップ
const url = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' }))

なぜ preloadPdfFont を分けているのか。 エクスポートは意図的に同期です。saveAsPdf は生成したリンクのクリックで終わりますが、その前に await が入るとユーザージェスチャーのコンテキストが失われ、ポップアップブロッカーに阻まれます。そこでダウンロードは呼び出し側が選んだ時点で一度だけ行い、以降のエクスポートは即座に完了します。数 MB のフォント取得が saveAsPdf() の内部に隠れないという利点もあります。

ロケール

locale は、ReoGrid が取得方法を知っているフォントを指す名前です。標準で 4 つが登録されています。

ロケールフォント用途
'ja'Noto Sans JP日本語
'zh-CN'Noto Sans SC簡体字中国語
'zh-TW'Noto Sans TC繁体字中国語
'ko'Noto Sans KR韓国語
import { preloadPdfFont, registerPdfFont } from '@reogrid/pro'

await preloadPdfFont('zh-CN')                 // アプリ起動時に一度
grid.saveAsPdf({ locale: 'zh-CN' })           // 以降はいつでも

ロケールの選択は重要です。日本語フォントは簡体字中国語のビジネス頻出語の約 3 分の 1 しかカバーしないため、中国語のテキストを 'ja' でエクスポートすると残りが豆腐(□□□)になります。

独自のロケールも登録できます(ローダー・URL・手元のバイト列のいずれでも可)。

registerPdfFont('th', () => loadFont('/fonts/NotoSansThai-Subset.ttf'))
await preloadPdfFont('th')
grid.saveAsPdf({ locale: 'th' })

バイト列で登録した場合は即座にロード済みとなり、preload は不要です。ネットワークを完全に回避したい場合(アプリに同梱したフォントやパッケージから読み込んだフォント)はこの方法を使ってください。

関連ヘルパー(いずれも @reogrid/pro からエクスポート): isPdfFontRegisteredisPdfFontLoadedgetPdfFontgetRegisteredPdfFontTagsclearPdfFontCache

フォントパッケージ(CDN 不要・オフライン対応)

組み込みロケールは公開 CDN からフルの上流フォントを取得します。Noto Sans SC だけで約 17 MB あり、その CDN は中国本土からは低速で、しばしば到達できません。本番環境では対応するサブセットパッケージをインストールして登録してください。バイト列は npm から来るため実行時のネットワークが一切不要になり、企業導入で一般的なオフラインのイントラネットでも動作します。

npm install @reogrid/font-sc     # zh-CN — 他に font-tc / font-jp / font-kr
import { registerPdfFont, preloadPdfFont } from '@reogrid/pro'
import { loadNotoSansSC } from '@reogrid/font-sc'

registerPdfFont('zh-CN', loadNotoSansSC)   // ロケールをパッケージに向ける
await preloadPdfFont('zh-CN')              // アプリ起動時に一度

grid.saveAsPdf({ locale: 'zh-CN', filename: 'report.pdf' })
パッケージロケールローダー収録文字数転送量
@reogrid/font-sc'zh-CN'loadNotoSansSC7,709(GB 2312)約 2,593 KB
@reogrid/font-tc'zh-TW'loadNotoSansTC13,682(Big5)約 4,840 KB
@reogrid/font-jp'ja'loadNotoSansJP6,974(JIS X 0208)約 2,673 KB
@reogrid/font-kr'ko'loadNotoSansKR3,196(KS X 1001)約 494 KB

各サブセットは、その言語の伝統的な国家標準を第 2 水準まで収録しています。人名・地名は第 2 水準にあり、顧客名が豆腐になる方がダウンロードが少し大きくなるより問題が大きいためです。バイト列は動的インポートの背後に置かれるため、バンドラーは専用チャンクに分離します。PDF を出力しないアプリはダウンロードしません。

自前のフォントバイト列を渡す

ReoGrid が知らない書体を使う場合は font を指定します。生の TrueType glyf バイト列(ArrayBuffer | Uint8Array)を渡し、fontlocale の両方を指定した場合は font が優先されます。入手方法は 3 通りです。

import { loadDefaultJapaneseFont, loadFont, DEFAULT_JAPANESE_FONT_URL } from '@reogrid/pro'

// 1. 同梱の既定フォント — Noto Sans JP(約 9.6 MB、公開 CDN から取得・キャッシュ)
const a = await loadDefaultJapaneseFont()

// 2. 自前でホストするサブセット(本番推奨 — はるかに軽量)
const b = await loadFont('https://cdn.example.com/fonts/NotoSansJP-Subset.ttf')

// 3. すでに手元にあるバイト列(<input type="file"> や fetch など)
const c = new Uint8Array(await file.arrayBuffer())

どちらのヘルパーも、ダウンロードしたバイト列をメモリおよび Cache Storage にキャッシュするため、約 9.6 MB の既定フォントの取得はブラウザごとに最大 1 回です。本番環境では実際に必要なグリフだけをサブセット化してホストし、その URL を loadFont に渡してください(DEFAULT_JAPANESE_FONT_URL は同じソースからサブセットを作りたい場合に公開されています)。

font はフォントではありません。 font: 'Arial' は動作しません — このオプションはフォントファイルのバイト列を受け取ります。グリフのアウトライン自体を PDF に埋め込むことで、閲覧側の環境にフォントがインストールされていなくても同じ表示になるためです。上記の方法でファイルを読み込んでから渡してください。名前を渡した場合は次のエラーになります。

exportWorksheetPdf: `font` must be TrueType (glyf) font bytes, not a font-family
name (got "Arial"). Either name a locale — …

ロケールを誤って font に渡した場合はそれを認識し、{ locale: 'zh-CN' } として渡すよう案内します。

フォントは glyf アウトラインを持つ TrueType である必要があります。OpenType/CFF(OTTO — 多くの .otf ファイル)は未対応で、専用のエラーになります。

ExportPdfOptions

オプション既定値説明
locale'ja' | 'zh-CN' | 'zh-TW' | 'ko' または登録済みのタグ埋め込むフォント。レジストリ経由で解決されます。事前に preload が必要です。font を指定しない場合は必須。
fontArrayBuffer | Uint8Array埋め込み可能な TrueType(glyf)フォントのバイト列。locale より優先されます。locale を指定しない場合は必須。
pageSize'A3'|'A4'|'A5'|'B4'|'B5'|'Letter'|'Legal'|'Tabloid'|'Executive' または { widthMm, heightMm }'A4'用紙サイズ。
orientation'portrait' | 'landscape''portrait'ページの向き。
marginMmnumber | { top, right, bottom, left }12余白(mm、数値は全辺共通)。
rangePdfExportRange使用範囲出力するセル範囲。
showGridLinesbooleanワークシートの設定グリッド線を描画。既定では worksheet.setShowGridLines()(画面表示)に従うため、明示的に指定しない限り PDF は画面と一致します。
scalenumber1一様な内容スケール(0.1〜4)。fitToWidth 時は無視。
fitToWidthbooleanfalse全列が 1 ページ幅に収まるよう縮小。
usePageBreaksbooleanfalse画面上の改ページプレビューとまったく同じように改ページ(後述)。
imagesWorksheetImageInfo[]シートの画像セルにアンカーする画像。
showImagesbooleantrueセルアンカー画像を描画。
titlestringドキュメントタイトル(PDF メタデータ)。

saveAsPdf はさらに filename?: string を受け取ります。省略時は読み込み済みドキュメントのベース名(getDocumentName() / setDocumentName() 参照)、ファイル未読込のときは worksheet.pdf になります。

usePageBreaks による複数ページ出力

既定では exportPdf は使用範囲を pageSize / orientation / marginMm / scale オプションでページに割り付けます。usePageBreaks: true を指定すると、代わりにワークシート独自のページングモデルで改ページします — PDF は ページレイアウト の改ページプレビューとまったく同じ位置(手動改ページ・印刷範囲・フィットスケールを含む)で改ページされます。

// 用紙・向き・余白・スケール・ページ帯はすべて
// worksheet.getPrintSettings() と計算済みの改ページから取得されます。
grid.worksheet.setPrintSettings({ paperSize: 'A4', orientation: 'landscape' })
grid.worksheet.insertRowPageBreak(40)   // 40 行目から新しいページ

await preloadPdfFont('ja')
grid.saveAsPdf({ locale: 'ja', usePageBreaks: true, filename: 'ledger.pdf' })

usePageBreaks が有効なとき、オプション側の pageSize / orientation / marginMm / scale / fitToWidth / range は無視されます — 代わりに ページレイアウト で設定してください。改ページ対象が何もないシートの場合はオプション側にフォールバックします。

React の例:PDF 出力ボタン

import { useEffect, useRef } from 'react'
import { Reogrid } from '@reogrid/pro/react'
import { preloadPdfFont } from '@reogrid/pro'
import type { ReogridInstance } from '@reogrid/pro/react'

function App() {
  const gridRef = useRef<ReogridInstance>(null)

  // フォントの取得はマウント時に一度だけ。クリックハンドラ内で await すると、
  // ダウンロードリンクに必要なユーザージェスチャーが失われます。
  useEffect(() => { void preloadPdfFont('ja') }, [])

  function handleExport() {
    gridRef.current?.saveAsPdf({ locale: 'ja', usePageBreaks: true, filename: 'report.pdf' })
  }

  return (
    <>
      <button onClick={handleExport}>PDF 出力</button>
      <Reogrid ref={gridRef} style={{ flex: 1 }} />
    </>
  )
}

Vue の例:PDF 出力ボタン

Vue コンポーネントは、テンプレート ref の instance プロパティ(gridRef.value?.instance)としてグリッドを公開します。出力の呼び出し自体は他のフレームワークと同じです。

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { Reogrid, type ReogridInstance } from '@reogrid/pro/vue'
import { preloadPdfFont } from '@reogrid/pro'

const gridRef = ref<{ instance: ReogridInstance | null } | null>(null)

// フォントの取得はマウント時に一度だけ。クリックハンドラ内で await すると、
// ダウンロードリンクに必要なユーザージェスチャーが失われます。
onMounted(() => { void preloadPdfFont('ja') })

function exportPdf() {
  gridRef.value?.instance?.saveAsPdf({ locale: 'ja', usePageBreaks: true, filename: 'report.pdf' })
}
</script>

<template>
  <button @click="exportPdf">PDF 出力</button>
  <Reogrid ref="gridRef" style="width: 100%; height: 400px" />
</template>

関連項目

  • ページレイアウト — 用紙サイズ・余白と、usePageBreaks が従う改ページプレビュー。
  • 印刷 — 印刷経路の全体像と選び方。
  • HTML で印刷 — ブラウザの標準ダイアログによる簡易印刷。
  • 画像 — エクスポートした PDF に表示されるセルアンカー画像。
ニュースレター

開発の最新情報をお届けします

新しいリリース・機能追加・お知らせをいち早く受け取るには、
メーリングリストにご登録ください。