さまざまなファイルの中から、指定した文字が入ったPowerPointのファイルを抽出してみる

さまざまなファイルの中から重要なキーワードの入ったファイルだけを抽出したいことはありませんか?

キーワードがあるかないかを、ファイルを一つずつ開いて、検索をかけて見つけるのはとても苦痛です。面倒でしかありません。指定した文字(極秘や社外秘等)が入ったファイルを自動で抽出できると助かります。

そこで、「様々な種類の入ったフォルダの中から、特定のキーワードを含んだPowerPointのファイルのみを抽出する」というプログラムを、Pythonで作ってみました。

システムの説明

システム環境

今回は、それぞれ以下のバージョンを利用しました。

  • Anaconda:23.3.1
  • Python:3.10.9

Anacondaサイトから「Anaconda3-2023.03-1-Windows-x86_64.exe」をダウンロードし、PCにインストールします。

※ Anaconda3-2023.03-1-Windows-x86_64.exeをインストールすればPythonも使えます。

フォルダ及びファイルの構成とファイルの中身

フォルダ及びファイルの構成

まず、「さまざまな書類」フォルダを用意します。ここにサブフォルダを作成し、PowerPoint、Excel、Wordのファイルを配置しました。

各サブフォルダの中身はこのようになっています。

「00.提案書」フォルダ

「期限近い」フォルダ

「10.研修資料」フォルダ

このうち、いくつかのPowerPointファイルには、キーワードとして「極秘」及び「社外秘」が入っています。

ファイル名に「該当する」という文字が入っている下記のファイルが、キーワードが含まれたファイルです。

  • 提案書_テキストボックス_該当する.pptx
  • 提案書_ノート_該当する.pptx
  • 提案書_図中_該当する.pptx
  • 提案書_表中_該当する.pptx

参考までに、「さまざまな書類」フォルダの一覧も掲載しておきます。

「さまざまな書類」フォルダ
 │  エクセルのマクロ資料_セル内.xlsx
 │  持ち出し注意の資料_テキスト.docx
 │  提案書_表中_該当しない.pptx
 │  提案書_表中_該当する.pptx・・・・・・・・・・・・・・・抽出対象
 │
 ├─「00.提案書」フォルダ
 │   │  取扱注意の資料.docx
 │   │  提案書_ひな形_作成中_20230601_セル内.xlsx
 │   │  提案書_ノート_該当しない.pptx
 │   │  提案書_ノート_該当する.pptx・・・・・・・・・・・・抽出対象
 │   │
 │   └─「期限近い」フォルダ
 │           取扱注意の資料_テキスト.docx
 │           提案書_ひな形_作成中_テキスト.xlsx
 │           提案書_テキストボックス_該当しない.pptx
 │           提案書_テキストボックス_該当する.pptx・・・・・・抽出対象
 │
 └─「10.研修資料」フォルダ
         PowerAutomateの資料.docx
         円滑なチャットの活用について.xlsx
         提案書_図中_該当しない.pptx
         提案書_図中_該当する.pptx・・・・・・・・・・・・・・抽出対象

ファイルの中身について

キーワードとして「極秘」及び「社外秘」を設定したPowerPointファイルについて、どのようにキーワードが入っているかを解説します。

提案書_テキストボックス_該当する.pptx

テキストボックスに「極秘」があります

提案書_ノート_該当する.pptx

ノート欄に「社外秘」があります。

提案書_図中_該当する.pptx

図の中に、テキスト編集で入力した「極秘」があります。

提案書_表中_該当する.pptx

表の中に「極秘」があります。

PowerPointで抽出したい文字を入力

今回は、「極秘」と「社外秘」の文字の入ったPowerPointを抽出することにします。まずKEYWORDSに「極秘」と「社外秘」を入力します。

def in_the_text(text):
    for keywd in KEYWORDS:
        if keywd in text:
            return True
    return False
KEYWORDS = ['極秘','社外秘']

PowerPointで抽出したい文字が入ったファイルのあるフォルダの登録及びその移動先の登録

KEYWORDSの下に「DOCUMENT_DIR_PATH」と「OUTPUT_DIR_PATH」を記入します。

  • DOCUMENT_DIR_PATH
    • PowerPointで抽出したい文字が入ったファイルのあるフォルダを登録(ここでは、デスクトップ上の「さまざまな書類」フォルダを絶対パスで登録)
  • OUTPUT_DIR_PATH
    • PowerPointで抽出したい文字が入ったファイルの移動先フォルダを登録(ここでは、デスクトップ上の「移動先」フォルダを絶対パスで登録)
KEYWORDS = ['極秘','社外秘']
DOCUMENT_DIR_PATH = 'C:\\Users\\■■■■■\\デスクトップ\\さまざまな書類'
OUTPUT_DIR_PATH = 'C:\\Users\\■■■■■\\デスクトップ\\移動先'

プログラムの実行

「Run」をクリックして、プログラムを実行します。

・実行結果

「極秘」と「社外秘」の文字の入ったPowerPointが、自動的にデスクトップ上の「移動先」に移動します。

移動したファイルは、プログラムの下に表示されます。

Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\提案書_表中_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!
Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\00.提案書\提案書_ノート_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!
Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\00.提案書\期限近い\提案書_テキストボックス_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!
Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\10.研修資料\提案書_図中_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!

プログラムについて

プログラムは下記の通りです。

(1)モジュールos、pptx、shutilをインポートします。

import os
import pptx
import shutil

(2)Pythonでは、メインプログラムより上に関数を書きます。メインプログラムは(7)です。関数in_the_pptxを定義します。メインプログラムから読み込まれて、PowerPointの図、ノート、表、テキストボックスに文字が入っているかチェックする関数を読み込む関数です。

メインプログラムから、「さまざまな書類」フォルダ内のファイルを引数として受け取り、まずPresentationオブジェクトを取得し、PRSとします。PRSをもとにして、図及びテキストボックスをチェックするin_the_pptx_shape関数、ノートをチェックするin_the_pptx_note関数、表をチェックするin_the_pptx_table関数を実行し、どれかひとつでも戻り値がTrueであったら(キーワードが入っていたら)、戻り値として、Trueを返します。それ以外なら、Falseを返します。 

>def in_the_pptx(FILE_PATH):
    PRS = pptx.Presentation(FILE_PATH)
    if (in_the_pptx_shape(PRS) or in_the_pptx_note(PRS) or in_the_pptx_table(PRS)):
        return True
    return False

(3)関数in_the_pptx_shapeを定義します。PRSからPowerPointの図及びテキストボックスの文字を抜き出し、in_the_text関数にその文字を渡す関数です。in_the_text関数の戻り値がTureなら(キーワードが入っていたら)、戻り値としてTrueを返し、それ以外はFalseを返します。矢印などで使うshape.has_text_frameに、値がないときは、エラーになってしまうので、「if not shape.has_text_frame:」の「continue」を使い、エラーがあっても処理を続けるようにしています。

def in_the_pptx_shape(PRS):
    for slide in PRS.slides:
        for shape in slide.shapes:
            if not shape.has_text_frame:
                continue
            for parag in shape.text_frame.paragraphs:
                if in_the_text(parag.text):
                    return True
    return False

(4)関数in_the_pptx_noteを定義します。PRSからPowerPointのノート欄の文字を抜き出し、in_the_text関数にその文字を渡す関数です。in_the_text関数の戻り値がTureなら(キーワードが入っていたら)、戻り値としてTrueを返し、それ以外はFalseを返します。

def in_the_pptx_note(PRS):
    for slide in PRS.slides:
        if in_the_text(slide.notes_slide.notes_text_frame.text):
            return True
    return False

(5)関数in_the_pptx_tableを定義します。PRSからPowerPointの表内(セル)の文字を抜き出し、in_the_text関数にその文字を渡す関数です。in_the_text関数の戻り値がTureなら(キーワードが入っていたら)、戻り値としてTrueを返し、それ以外はFalseを返します。「if hasattr(shape,'table'):」を使い、PowerPointに表がないときはエラーになってしまうので、あるときだけ処理を続けるようにしています。

def in_the_pptx_table(PRS):
    for slide in PRS.slides:
        for shape in slide.shapes:
            if hasattr(shape,'table'):
                tbl = shape.table
                for cell in tbl.iter_cells():
                    if in_the_text(cell.text):
                        return True
            
    return False

(6))関数in_the_textを定義します。関数から送られてきた文字がキーワードにあるかをチェックします。指定した文字なら戻り値としてTrueを返し、それ以外はFalseを返します。

def in_the_text(text):
    for keywd in KEYWORDS:
        if keywd in text:
            return True
    return False

(7)キーワードを入力します。複数入力できます。抽出対象フォルダを指定します。移動先フォルダも指定します。

os.walkとfor文を使って、抽出対象フォルダのサブフォルダを含んだすべてのファイルを1つずつ取得し、そのファイルの拡張子がpptxなら、in_the_pptx関数を実行します。キーワードがPowerPointに含まれていたら、in_the_pptx関数でTrueが返ってくるので、shutil.moveを実行して、移動先フォルダへPowerPointを移動します。

KEYWORDS = ['極秘','社外秘']
DOCUMENT_DIR_PATH = 'C:\\Users\\■■■■■\\デスクトップ\\さまざまな書類'
OUTPUT_DIR_PATH = 'C:\\Users\\■■■■■\\デスクトップ\\移動先'
for top, dirs, files in os.walk(DOCUMENT_DIR_PATH):
    for file in files:
        FILE_PATH = os.path.join(top, file)
        EXTENSION = os.path.splitext(file)[1]
        if EXTENSION == '.pptx':
            if in_the_pptx(FILE_PATH):
                shutil.move(FILE_PATH, OUTPUT_DIR_PATH)
                print('・Target file:', FILE_PATH)
                print('→「',OUTPUT_DIR_PATH,'」へ移動したよ!!!\n')

(8)抽出対象ファイルと移動後のファイルの絶対パスで表示します。

Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\提案書_表中_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!
Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\00.提案書\提案書_ノート_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!
Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\00.提案書\期限近い\提案書_テキストボックス_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!
Target file: C:\Users\■■■■■\デスクトップ\さまざまな書類\10.研修資料\提案書_図中_該当する.pptx
→「 C:\Users\■■■■■\デスクトップ\移動先 」へ移動したよ!!!

(9)最後にプログラム全体です。

import os
import pptx
import shutil
def in_the_pptx(FILE_PATH):
    PRS = pptx.Presentation(FILE_PATH)
    if (in_the_pptx_shape(PRS) or in_the_pptx_note(PRS) or in_the_pptx_table(PRS)):
        return True
    return False
def in_the_pptx_shape(PRS):
    for slide in PRS.slides:
        for shape in slide.shapes:
            if not shape.has_text_frame:
                continue
            for parag in shape.text_frame.paragraphs:
                if in_the_text(parag.text):
                    return True
    return False
def in_the_pptx_note(PRS):
    for slide in PRS.slides:
        if in_the_text(slide.notes_slide.notes_text_frame.text):
            return True
    return False
def in_the_pptx_table(PRS):
    for slide in PRS.slides:
        for shape in slide.shapes:
            if hasattr(shape,'table'):
                tbl = shape.table
                for cell in tbl.iter_cells():
                    if in_the_text(cell.text):
                        return True
            
    return False
def in_the_text(text):
    for keywd in KEYWORDS:
        if keywd in text:
            return True
    return False
KEYWORDS = ['極秘','社外秘']
DOCUMENT_DIR_PATH = 'C:\\Users\\■■■■■\\デスクトップ\\さまざまな書類'
OUTPUT_DIR_PATH = 'C:\\Users\\■■■■■\\デスクトップ\\移動先'
for top, dirs, files in os.walk(DOCUMENT_DIR_PATH):
    for file in files:
        FILE_PATH = os.path.join(top, file)
        EXTENSION = os.path.splitext(file)[1]
        if EXTENSION == '.pptx':
            if in_the_pptx(FILE_PATH):
                shutil.move(FILE_PATH, OUTPUT_DIR_PATH)
                print('・Target file:', FILE_PATH)
                print('→「',OUTPUT_DIR_PATH,'」へ移動したよ!!!\n')

※注意※

  • ファイルを開いているとエラーになって移動できません
  • 移動先に同じ名前のファイルがあるとエラーになって移動できません
  • PowerPointのテキストボックス、ノート、図のテキスト編集、表のセルの文字が対象です

おわりに

Python初心者のため、今まで聞いたことない言葉(オブジェクト、タプル、リスト等)、ルール(インテンドに厳しい)が出てきて、まずはそれらを理解する所から入り、例文を作り、山のようにエラーを出して、ネット検索して、エラーをなくし、理解を深めました。

ひとまずプログラムができてよかったです。

Pythonはあらかじめ、オブジェクトの中に情報がたくさんあり、それを取得すればよくて、プログラムの書き方が他の言語に比べて、シンプルに書けたので、見やすいプログラムになったと思います。

最近の企業でのファイル管理は、ローカルPCよりもSharePointを使ったものが主流になりつつあると思います。残念ながら、このプログラムはOSモジュールを使っているので、ローカルPC内を検索するようになっており、SharePointには対応していません。時間があれば、SharePointも検索できるプログラムを考えたいです。

執筆担当者プロフィール
鈴木 功

鈴木 功(日本ビジネスシステムズ株式会社)

中部モダンワークプレイス部に所属。エンジニア歴数十年ですが、Microsoft 365初心者です。

担当記事一覧