見出し画像

Google Apps ScriptとJavaScriptを使ってPDFを分割したり結合するwebページを作成する。

webアプリの表示画面

必要な時に作成したコードを参照できるように、作成したコードを置いておくためのノートです。自分用に作成したものですが、参考にしていただければ幸いです。

機能としては、2つのみです。
PDFを2つに分割することができる。
2つのPDFを結合することができる。

GAS(Google Apps Script)を使って、簡単なWebページ・Webアプリを作成する際には、htmlにcssもjsも含めて1つのファイルにしてしまうことがオススメです。
GAS上では、GASのスクリプトファイルか、htmlファイルしか作成できないためです。

コード.gs

GAS(Google Apps Script)を使って、HTMLコンテンツを生成し表示させるコードです。

function doGet(e) {
  const template = HtmlService.createTemplateFromFile('index');
  const htmlOutput = template.evaluate();
  return htmlOutput;
}

ChatGPTにコードを解説してもらった結果。
このコードはGoogle Apps Scriptで書かれており、特定のウェブアプリケーションでHTTP GETリクエストを処理するためのものです。以下に各部分の詳細な説明を示します。

doGet(e) 関数
doGet(e) はGoogle Apps Scriptで特定のURLに対してGETリクエストが送られたときに実行されるハンドラ関数です。引数 e にはリクエストの詳細情報が含まれます。

const template = HtmlService.createTemplateFromFile('index');
HtmlService はGoogle Apps Scriptのクラスで、HTMLコンテンツの生成や表示をサポートします。
createTemplateFromFile('index') は、プロジェクト内にある index.html という名前のファイルをテンプレートとして読み込みます。このテンプレートは、HTML形式で動的にコンテンツを生成するために使用されます。
template は index.html ファイルをテンプレートオブジェクトとして保持します。
const htmlOutput = template.evaluate();
template.evaluate() はテンプレートを実行し、最終的なHTMLコンテンツを生成します。
htmlOutput は生成されたHTMLコンテンツを含むオブジェクトです。このオブジェクトは後にHTTPレスポンスとして返されます。

return htmlOutput;
htmlOutput を関数の戻り値として返します。これにより、ウェブアプリケーションがHTTP GETリクエストに対して適切なHTMLレスポンスを返すことができます。

index.html

Gasを使う場合は、cssやjavascriptをhtmlの中に書き込んだ方が実装が簡単なので、全て盛り込みます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PDF Splitter and Merger</title>
</head>
<body>
    <h1>PDF Splitter</h1>
    <input type="file" id="pdf-upload" accept="application/pdf">
    <input type="number" id="split-page" placeholder="Page number to split after">
    <button id="split-button">Split PDF</button>
    <a id="download-link" style="display: none;">Download Part 1</a>
    
    <h1>PDF Merger</h1>
    <input type="file" id="file1" accept="application/pdf">
    <input type="file" id="file2" accept="application/pdf">
    <button id="merge-button">Merge PDFs</button>
    <a id="download-link-merge" style="display: none;">Download Merged PDF</a>

    <!-- Include pdf-lib from CDN -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
    <script>
        document.getElementById('split-button').addEventListener('click', async () => {
            const fileInput = document.getElementById('pdf-upload');
            const splitPageInput = document.getElementById('split-page');
            const downloadLink = document.getElementById('download-link');
            
            if (fileInput.files.length === 0) {
                alert('Please select a PDF file.');
                return;
            }
            
            const file = fileInput.files[0];
            const splitPage = parseInt(splitPageInput.value, 10);
            
            if (isNaN(splitPage) || splitPage <= 0) {
                alert('Please enter a valid page number.');
                return;
            }

            const arrayBuffer = await file.arrayBuffer();
            const pdfDoc = await PDFLib.PDFDocument.load(arrayBuffer);
            const totalPages = pdfDoc.getPageCount();

            if (splitPage >= totalPages) {
                alert('The split page number must be less than the total number of pages.');
                return;
            }

            const pdfDoc1 = await PDFLib.PDFDocument.create();
            const pdfDoc2 = await PDFLib.PDFDocument.create();

            for (let i = 0; i < splitPage; i++) {
                const [copiedPage] = await pdfDoc1.copyPages(pdfDoc, [i]);
                pdfDoc1.addPage(copiedPage);
            }

            for (let i = splitPage; i < totalPages; i++) {
                const [copiedPage] = await pdfDoc2.copyPages(pdfDoc, [i]);
                pdfDoc2.addPage(copiedPage);
            }

            const pdfBytes1 = await pdfDoc1.save();
            const pdfBytes2 = await pdfDoc2.save();

            const blob1 = new Blob([pdfBytes1], { type: 'application/pdf' });
            const blob2 = new Blob([pdfBytes2], { type: 'application/pdf' });

            const url1 = URL.createObjectURL(blob1);
            const url2 = URL.createObjectURL(blob2);

            downloadLink.href = url1;
            downloadLink.download = 'part1.pdf';
            downloadLink.textContent = 'Download Part 1';
            downloadLink.style.display = 'block';

            const downloadLink2 = document.createElement('a');
            downloadLink2.href = url2;
            downloadLink2.download = 'part2.pdf';
            downloadLink2.textContent = 'Download Part 2';
            downloadLink2.style.display = 'block';

            downloadLink.insertAdjacentElement('afterend', downloadLink2);
        });

        document.getElementById('merge-button').addEventListener('click', async () => {
            const file1 = document.getElementById('file1').files[0];
            const file2 = document.getElementById('file2').files[0];

            if (file1 && file2) {
                const mergedPdf = await mergePdfs(file1, file2);
                downloadPdf(mergedPdf);
            } else {
                alert('Please select two PDF files.');
            }
        });

        async function mergePdfs(file1, file2) {
            const pdf1Bytes = await file1.arrayBuffer();
            const pdf2Bytes = await file2.arrayBuffer();

            const pdfDoc1 = await PDFLib.PDFDocument.load(pdf1Bytes);
            const pdfDoc2 = await PDFLib.PDFDocument.load(pdf2Bytes);

            const mergedPdfDoc = await PDFLib.PDFDocument.create();

            const copiedPages1 = await mergedPdfDoc.copyPages(pdfDoc1, pdfDoc1.getPageIndices());
            copiedPages1.forEach((page) => mergedPdfDoc.addPage(page));

            const copiedPages2 = await mergedPdfDoc.copyPages(pdfDoc2, pdfDoc2.getPageIndices());
            copiedPages2.forEach((page) => mergedPdfDoc.addPage(page));

            const mergedPdfBytes = await mergedPdfDoc.save();
            return new Blob([mergedPdfBytes], { type: 'application/pdf' });
        }

        function downloadPdf(pdfBlob) {
            const url = URL.createObjectURL(pdfBlob);
            const downloadLink = document.getElementById('download-link-merge');
            downloadLink.href = url;
            downloadLink.download = 'merged.pdf';
            downloadLink.style.display = 'block';
        }
    </script>
</body>
</html>

ChatGPTにコードの解説をしてもらった結果

このHTMLファイルは、PDFファイルを分割および結合するための簡単なウェブアプリケーションを実装しています。以下はこのファイルの各部分の説明です。

HTML構造

<!DOCTYPE html>
ドキュメントがHTML5であることを指定しています。

<html lang="ja">
HTMLのルート要素であり、言語を日本語(ja)に設定しています。

<head>
メタデータを含むセクション。

<meta charset="UTF-8">
ドキュメントの文字エンコーディングをUTF-8に設定します。

<meta name="viewport" content="width=device-width, initial-scale=1.0">
ビューポートの設定を行い、レスポンシブデザインをサポートします。

<title>PDF Splitter and Merger</title>
ウェブページのタイトルを設定します。
※ただし、GAS上では、htmlファイルのhead部分の内容がいくつか無視されるので、webアプリのタイトルとして表示されない。

<body>
ウェブページのコンテンツを含むセクション。

PDF分割部分

<h1>PDF Splitter</h1>
「PDF Splitter」という見出しを表示します。

<input type="file" id="pdf-upload" accept="application/pdf">
ユーザーがPDFファイルをアップロードするためのファイル入力フィールド。

<input type="number" id="split-page" placeholder="Page number to split after">
分割するページ番号を入力するための数値入力フィールド。

<button id="split-button">Split PDF</button>
PDF分割を開始するボタン。

<a id="download-link" style="display: none;">Download Part 1</a>
分割後のPDFファイルをダウンロードするためのリンク(初期状態では非表示)。

PDF結合部分

<h1>PDF Merger</h1>
「PDF Merger」という見出しを表示します。

<input type="file" id="file1" accept="application/pdf">
ユーザーが結合する最初のPDFファイルをアップロードするためのファイル入力フィールド。

<input type="file" id="file2" accept="application/pdf">
ユーザーが結合する二つ目のPDFファイルをアップロードするためのファイル入力フィールド。

<button id="merge-button">Merge PDFs</button>
PDF結合を開始するボタン。

<a id="download-link-merge" style="display: none;">Download Merged PDF</a>
結合後のPDFファイルをダウンロードするためのリンク(初期状態では非表示)。

JavaScript

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
pdf-libライブラリをCDNから読み込みます。このライブラリはPDFの操作を行うために使用されます。

<script>
JavaScriptコードを含むセクション。

PDF分割の処理

ファイルをアップロードし、ページ番号を指定してPDFを分割するための処理が含まれています。
split-buttonのクリックイベントリスナーを設定し、分割処理を実行します。

PDF結合の処理
二つのPDFファイルをアップロードし、結合するための処理が含まれています。
merge-buttonのクリックイベントリスナーを設定し、結合処理を実行します。

JavaScript関数

mergePdfs
二つのPDFを結合する非同期関数。

downloadPdf
結合されたPDFをダウンロードリンクに設定し、表示する関数。

このファイル全体で、PDFの分割および結合の機能を実装し、ユーザーが簡単にこれらの操作を行えるようになっています。

いいなと思ったら応援しよう!