0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

枚数の多いPDFファイルを簡単に冊子にするアプリを作った

Last updated at Posted at 2021-01-24
icon.png

序章

会議の資料を作っていたら10枚くらいまで枚数が増えてしまって、それを印刷して配ったら..
上司「資源を節約しろ!」
なんて経験ありますよね。ね。
そんなときにも活躍してほしいアプリを作りました。

動画を作ったのでぜひご覧ください

編集練習がてら作ったので説明がくどいですが、、

対応OS等

今回はPythonでアプリを開発しました。なのでMac,Windows両対応!!(ましてやios,android!?)
でもUnix採用してる意識高い系の企業ぐらいしか会社のPCにPythonの実行環境なんて整っていませんよね。なのでPyinstallerでexeファイル化もしてみました。
もちろんソースコードも載せるのでご安心を。

Pyinstallerに関しては以下を参考にさせていただきました。とても簡単なのでおすすめです。

Pyinstallerでexeファイル化

ハマったこと→解決済み

Pyinstallerでexeファイルに変換すると、セキュリティソフトにウイルスと認定されてしまうこと。

PyInstallerでexeファイル化したものがAVASTやAVGでトロイの木馬ウイルスと誤認される問題の一時的な解決法

こちらや

[Python] Pyinstallerで実行ファイルがマルウェアに分類されてしまったときの対策

こちらを参考ににさせていただいたのですが解決しませんでした。

2/2追記: WindowsUpdate をしたらなぜか解決しました。アップデートは大事ですね!

使い方

①起動

exeファイル版

このページの下部からダウンロードしたexeファイルをダブルクリックして実行

Python版

PyPDF2モジュールをインストール

例えば以下

コマンドプロンプト等
python3 -m pip install PyPDF2

モジュールをインストールした環境下にこのページ下部のソースコードを配置して実行

②ファイルを指定

起動時2.png
画像のような画面になる(exe,python共通)ので、指示に従って指定します。相対パスでいけるはずです。(たいていのプロンプトはドラッグアンドドロップでフルパス入力されます)

③Enter

元PDFファイルの総ページ数が4枚以上であれば一発で終わります。

1枚だった場合

サイズをひとつ小さく(A4→A5,B3→B4)して1枚に2つ出力(画像参照)することができます。紙を半分に切る作業が必要です。
Qiita-PDF変換1.png

2枚だった場合

表面に1枚目を2つ、裏面に2枚目を2つ出力して、元PDFファイルをそのまま両面印刷したものを小さくしたものを実現(動画参照)できます。上と同様に紙を半分に切る作業が必要です。
Qiita-PDF変換2.png

3枚だった場合

見開きに1,2枚目を持ってくるか2,3枚目を持ってくるかを選択できます。

④保存ファイル名を指定

最後カレントディレクトリに保存したとの表示がありますが、パスを指定してやることで違うディレクトリに保存することもできます。

ダウンロード

このページにアップロードしてある画像も併せてダウンロードしてぜひご活用ください。
PDFまとめるくん(Miniturization_PDF).exeをダウンロード

コード

自分で作ったつたないコードを公開するってテストの答案を公開するくらいの恥ずかしさがあります

Miniaturization_PDF.py
import PyPDF2

page_objs = [] #pdfファイルの各ページデータ収納用リスト
finaly_add = 0 #元データの最後に足すブランクページ

print("-----------------------------------")
print("製作者:Taktstock(https://qiita.com/Taktstock)")
print("使い方:(https://qiita.com/Taktstock/items/e529c9338595bc90dba9)")
print("-----------------------------------")
print("このプログラムは資源の節約のためにPDFを冊子にしたりできます。")
print("途中の説明で分かりにくい箇所があったら動画(https://youtu.be/v_K9xJTPkhs)を参照してください。")
print("-----------------------------------")
print("すべてのページが同じ大きさで、一般的な紙のサイズの場合のみ対応です。")
print("暗号化が施されているファイルには非対応です。")
print("-----------------------------------")

pdf_path = input("PDFファイルを指定(またはファイルをウィンドウにドラッグ):")
print("-----------------------------------")

try: #ファイルの読み込み
    pdf_file = open(pdf_path,'rb')
except:
    print("ファイルを開くことができませんでした。暗号化されている可能性があります。")
    input("Enterを押すことで終了します")
    quit()

pdf_reader = PyPDF2.PdfFileReader(pdf_file) #pypdf2に読み込み
pdf_writer = PyPDF2.PdfFileWriter()

first_page = pdf_reader.getPage(0) #元ファイルの情報を収集
number_of_pages = pdf_reader.getNumPages()
(width_of_page,height_of_page) = first_page.mediaBox.getUpperRight()

#完成形は縦向きに
if width_of_page > height_of_page: #元PDFが横向きだったときの処理
    width_of_paper = height_of_page
    height_of_paper = width_of_page
    angle = 0

else: #元PDFが縦だったときの処理
    width_of_paper = width_of_page
    height_of_paper = height_of_page
    angle = 270

if number_of_pages % 4 != 0: #最終的にページ数が4の倍数になるようにする
    finaly_add = 4 - number_of_pages % 4

for page in range(number_of_pages): #リストに元PDFを収納
    page_objs.append(pdf_reader.getPage(page))

#元pdfファイルのページ数が1,2,3枚の場合は例外処理
if number_of_pages == 1:
    print("検出されたPDFファイルの総ページ数が1枚でした。")
    print("大きさを半分にして1枚の紙の片面に2つ出力するには y を入力します。")
    copy_double = input("y(1枚に2枚分) or other(終了):")
    print("-----------------------------------")
    if copy_double == "y":
        page_objs.append(pdf_reader.getPage(0))
        finaly_add = 0
        number_of_pages = 2
    else:
        quit()
elif number_of_pages == 2:
    print("検出されたPDFファイルの総ページ数が2枚でした。")
    print("表面に1枚目を2つ、裏面に2枚目を2つ出力するには y を入力します。(両面印刷して半分に切ることで節約が可能)")
    print("または片面に2枚分を出力するには n を入力します。")
    copy_four = input("y(両面に2つずつ) or n(片面に2つ) or other(終了):")
    print("-----------------------------------")
    if copy_four == "y":
        page_objs.append(pdf_reader.getPage(1))
        page_objs.append(pdf_reader.getPage(0))
        finaly_add = 0
        number_of_pages = 4
    elif copy_four == "n":
        page_objs[0] = pdf_reader.getPage(1)
        page_objs[1] = pdf_reader.getPage(0)
        finaly_add = 0
    else:
        quit()
elif number_of_pages == 3:
    print("検出されたPDFファイルの総ページ数が3枚でした。")
    print("1,2枚目を見開き1ページに出力するには y を入力します。")
    print("このまま続行すると2,3枚目が見開き1ページに出力されます。")
    first_spread = input("y(1,2枚目を見開き) or other(2,3枚目を見開き):")
    print("-----------------------------------")
    if first_spread == "y":
        page_objs[0] = pdf_reader.getPage(1)
        page_objs[1] = pdf_reader.getPage(2)
        page_objs[2] = PyPDF2.pdf.PageObject.createBlankPage(width=width_of_page,height=height_of_page)
        page_objs.append(pdf_reader.getPage(0))
        finaly_add = 0
        number_of_pages = 4
    else:
        pass
else:
    pass

for i in range(finaly_add): #元PDFの最後に調整用ブランクページを挿入
    page_objs.append(PyPDF2.pdf.PageObject.createBlankPage(width=width_of_page,height=height_of_page))

number_of_pages += finaly_add

for paper in range(int(number_of_pages / 2)): #核となる部分
    base_paper = PyPDF2.pdf.PageObject.createBlankPage(width=width_of_paper,height=height_of_paper)
    if (paper + 1) % 2 == 1: #奇数枚目には下に最初から上に最後から(1枚目は下に最初のページ、上に最後のページ)
        base_paper.mergeRotatedScaledTranslatedPage(page_objs[paper], angle, 0.71, 0, height_of_paper / 2, expand=False)
        base_paper.mergeRotatedScaledTranslatedPage(page_objs[number_of_pages - paper - 1], angle, 0.71, 0, height_of_paper, expand=False)
        pdf_writer.addPage(base_paper)
    else: #偶数枚目は奇数枚目の逆
        base_paper.mergeRotatedScaledTranslatedPage(page_objs[number_of_pages - paper - 1], angle, 0.71, 0, height_of_paper / 2, expand=False)
        base_paper.mergeRotatedScaledTranslatedPage(page_objs[paper], angle, 0.71, 0, height_of_paper, expand=False)
        pdf_writer.addPage(base_paper)

print("コンパクト化に成功しました!")
output_name = input("出力するファイルの名前を決めてください(拡張子なし):")

if output_name == "": #入力ミスしたとき
    output_name = 'Miniaturized'

output_name += ".pdf"

pdf_output_file = open(output_name,'wb') #ファイルを保存
pdf_writer.write(pdf_output_file)

pdf_output_file.close()
pdf_file.close()
print("'" + output_name + "'という名前でこのプログラムと同じフォルダ(カレントディレクトリ)に保存しました。")
print("短編とじで両面印刷し、まとめて折ることで簡単に冊子にすることができます。") #両面印刷に対応していないといけないことを通告
input("Enterを押すことで終了します")

最後に

GUI版も作ってみたい

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?