派遣で働くエンジニアのスキルアップを応援するサイト

PRODUCED BY RECRUIT

日々のインプットどうしてる?【事務系プログラマー・今村ゆうこさん編】

新しい情報をインプットする重要性は理解していても、忙しい毎日の中で実践するのは難しいもの。そこでエンジニアスタイルでおなじみのエンジニアの方々に「日々のインプット」についてうかがいました。

今回は事務系プログラマー・ライターとしてご活躍されている今村ゆうこさん。仕事・執筆業に加え、家庭のこともしっかりこなす今村さんは、どのような工夫があるのでしょうか?

皆さんの「日々のインプット」についても教えてください。お寄せいただいた方の中から抽選でスキルアップに役立つ書籍をプレゼント。詳細は記事の最後に!

お話を聞いた人:今村 ゆうこさん
Excel、 Accessなどの書籍を執筆し、事務系プログラマー・ブロガー・ライターとして活動するワーキングマザー。著書に『Access 実践マスターガイド~仕事の現場で即使える』(技術評論社)など多数。

・・・

□お仕事で使用しているプログラミング言語

  • VB.NET
  • VBA
  • OfficeScripts
  • Pythonなど

□お仕事で使用しているツールやアプリ、ソフト

  • MicrosoftOffice関連のツールが多い
  • 最近は、ChatGPTも活用
 
◆Questions
  1. 情報収集に割いている時間は、一日の中でどのくらい?
  2. どのような方法で情報収集することが多い?
  3. 現在、最も重視して情報収集しているものは?
  4. 重視している理由や、重視するようになったきっかけは?
  5. 忙しい毎日の中で、情報収集する際のコツは?
  6. アウトプットはしていますか?
  7. アウトプットするようになったきっかけは?
◆Column
疲れやストレスを感じたときのリフレッシュ方法

1. 情報収集に割いている時間は、一日の中でどのくらいですか?

具体的に時間を決めているわけではありませんが、仕事に充てている時間の1/3くらいは情報収集に割いているのではないかと思います。(8時間労働なら2時間半程度でしょうか。)

WebやSNSで情報を見るのも好きなので、隙間時間にも趣味で眺めています。

2. どのような方法で情報収集されることが多いですか?

主にはWebや書籍です。そのツールの公式ドキュメントに絞って検索することが多いです

最近では常に複数の原稿を抱えているので、原稿Aのための情報収集途中で原稿Bに書きたい情報が出てきたり、原稿Cのアイデアがひらめいたりするので、その都度クラウド上にメモをとって、パソコンからもスマートフォンからも見られるようにしています。

3. 現在、最も重視して情報収集しているものは何でしょうか?

そのときどきで違うテーマを扱うことが多いのですが、共通して重視しているのは「正確性」です。

調べたことが現在でも有効なのか、どんな歴史があって今この形になっているのか、といったこともよく調べるようにしています。

4. それを重視される理由や、重視するようになったきっかけは何ですか?

勉強したことをまとめて個人ブログに書くようになったのがきっかけです。誰でも読める状態で公開するならば、不確実であいまいなままでは書けないと思ったからです。

そのブログ経由でお声がけいただいて、商業で本を書かせていただくようになってから、さらに気をつけるようにしています。


▲今村さんオリジナルのイラストとよく整理された解説は、わかりやすいと好評。(引用:らしさオンライン

5. 忙しい毎日の中で、情報収集する際のコツは何でしょうか?

収集と発信はセットで行うのがオススメです。発信するためにさらに情報収集が必要になりますし、文章力も身につくため、よいサイクルが生まれます。

今調べてできるようになったことも1年後には忘れてしまうものなので、習得した技術やそのときの環境を、できるだけ再現性があるように書き残しておくと、未来の自分にきっと役に立ちます。

6. アウトプットはされていますか?

書籍のほかでは、2012年からブログ、2022年からYouTubeチャンネルを運営しています。

7. アウトプットされるようになったきっかけは何ですか?

もともと2000年ごろから個人のWebサイト(当時はホームページという名称でした)を持っていて、学生時代には趣味のイラストを載せたり、出産してから育児絵日記や裁縫の記録をつけていたりしていたのですが、あまり人に見られることを意識していませんでした。

2010年ごろにWordPressで個人ブログを書くのが流行して、技術系ブログの素晴らしさにたいへん感銘を受けて、「私もこんなブログ作ってみたい!」と思ったのがきっかけです。

現在では動画を好む方も多いと感じてYouTubeも始めましたが、自分自身がテキスト媒体の情報が好きなので、ブログも書き続けたいと思っています。

◆Column
今村さんの疲れやストレスを感じたときのリフレッシュ方法
・・・
□仕事中

気がつくと座りっぱなしになってしまうので、少し歩いたり、ストレッチしたりすることが多いです。家で作業しているときは筋トレすると気分転換になります。

 
□休日

カラオケが大好きです!学生の頃は友達と2人で好きなアーティストの曲を「あ」から全部歌う(9時間)なんてこともやっていましたが、さすがにそこまではできなくなくなりました。

家から歩ける距離に24時間営業のカラオケ屋さんができたらいいのにな、といつも思っています。

書籍プレゼントのお知らせ

以下のアンケートより、皆さんの「日々のインプット」について教えてください。お寄せいただいた方の中から抽選でスキルアップに役立つ書籍をプレゼント。みなさまのご応募お待ちしています!

プレゼントの応募詳細

■応募締め切り
2025年8月13日(水)まで

■応募条件
リクルートスタッフィングにご登録いただいている方が対象となります。

■応募方法
こちらよりご応募ください。
※ご応募は期間中お1人様1回限りとなります。ご了承ください。

■注意事項 
・リクルートスタッフィングのご登録情報と応募時にご入力いただく【氏名】【スタッフNo.】【メールアドレス】【生年月日】の4点が一致していない場合は、抽選の対象外となります。ご登録情報のご確認は、MyPageよりお願いしております。
・当選者の発表は、賞品の発送をもって代えさせていただきます。賞品の発送は、締め切り後1ヶ月以内にお送りいたしますが、諸事情によりお時間をいただく場合もございます。ご了承ください。
・賞品は、MyPageにご登録の「住所」にお送りいたします。変更がある場合は、締め切りの2025年8月13日(水)までに「登録情報の確認・変更」よりお手続きをお願いいたします。
・個人情報やご登録状況、抽選の結果、賞品発送状況に関するお問い合わせは、お答えいたしかねます。
・ご回答いただいた内容は、「エンジニアスタイル」の企画のみに使用いたします。就業状況などに影響することはございません。

▼今村さん執筆!

【エンジニアへの挑戦状】Accessなぜ動かない?VBAコード内のSQLを修正せよ


エンジニアへの挑戦状 #05 Accessのクエリで現在庫を見える化

【インタビュイー】今村 ゆうこさん
Excel、 Accessなどの書籍を執筆し、事務系プログラマー・ブロガー・ライターとして活動するワーキングマザー。著書のイラストや図解も手掛けている。著書には、『業務アプリ作成のための Access VBA 実践サンプル集~仕事の現場で即使える』『Excel & Access 連携実践ガイド ~仕事の現場で即使える』『Access 実践マスターガイド~仕事の現場で即使える』(以上、技術評論社)など多数。
ブログ
https://ateitexe.com/
▼YouTubeチャンネル
https://www.youtube.com/@ateitexe_yt

※本記事に記載されている会社名、製品名はそれぞれ各社の商標および登録商標です。

リクルートスタッフィング

日々のインプットどうしてる?【watさん編】

新しい情報をインプットする重要性は理解していても、忙しい毎日の中で実践するのは難しいもの。そこでエンジニアスタイルでおなじみのエンジニアの方々に「日々のインプット」についてうかがいました。

皆さんの「日々のインプット」についても教えてください。お寄せいただいた方の中から抽選で書籍『いきなりプログラミング Python』をプレゼント。詳細は記事の最後に!

お話を聞いた人:watさん
メーカー勤務機械系エンジニア・WATLABブログ運営者、『いきなりプログラミング Python』(翔泳社)の著者。

・・・

□お仕事で使用しているプログラミング言語

  • Python

□お仕事で使用しているツールやアプリ、ソフト

  • Pythonで作成したもの以外のアプリとしてはMicrosoft OfficeのExcel、PowerPointが多い
  • 業務内容は設計のため、各種物理シミュレーションツール(強度計算、熱流体計算)を使う
  • シミュレーションで得られた結果を分析するためにPythonやExcelを使い、資料をPowerPointでつくることが多い
 
◆Questions
  1. 情報収集に割いている時間は、一日の中でどのくらい?
  2. どのような方法で情報収集することが多い?
  3. 現在、最も重視して情報収集しているものは?
  4. 重視している理由や、重視するようになったきっかけは?
  5. 忙しい毎日の中で、情報収集する際のコツは?
  6. アウトプットはしていますか?
  7. アウトプットするようになったきっかけは?
◆Column
疲れやストレスを感じたときのリフレッシュ方法

1. 情報収集に割いている時間は、一日の中でどれくらいですか?

平日の業務中に行う情報収集は一日1時間程度だと思います。休日は気になった技術の内容を調べますが、平均で4時間ほどだと思います(まったく何もしない日もあります)。

2. どのような方法で情報収集されることが多いですか?

ちょっとしたことであればインターネットで調べるだけですが、最近はやや難しい技術のことを調べるときは以下の流れをとっています。

(1)ChatGPT o1にその技術の学習ロードマップを書いてもらう
(2)キーワードを自分で検索、再度ChatGPTに内容を聞く
(3)関連の専門書を書店で買い、ChatGPT o1, o3-miniなどに聞きながら理解を深める

最近は生成AIに依存してしまっていますが、これが最も効率が良いと感じています。

3. 現在、最も重視して情報収集しているものは何でしょうか?

音声解析関連の機械学習技術です。

4. それを重視される理由や、重視するようになったきっかけは何ですか?

元々音の解析はやっていましたが、そのことを認知してもらっている人から音声解析の相談を受けたことがきっかけです。

5. 忙しい毎日の中で、情報収集する際のコツは何でしょうか?

おそらく多くの人がなかなか業務時間にゆっくり時間を使って情報収集することができていないのではないかと思います。

業務時間に収集すべき情報と、ゆっくり腰を落ち着かせて収集すべき情報の線引きをきっちりするのが効率的に情報収集するコツだと思います。

業務時間以外での情報収集はワークライフバランスによりますが、IT技術は日進月歩でどんどん進化しているため、スポーツ選手が試合以外で体調管理をするような感覚で、時間をかけて理解する系の情報(基礎的な技術等)は家でコツコツと勉強する方が良いと自分は思っています。

6. アウトプットはされていますか?

ブログを運営しています。
https://watlab-blog.com/

7. アウトプットされるようになったきっかけは何ですか?

ブログで学んだことを発信することで、SNSを通じて色々な人と繋がりをもてると思ったことがきっかけです。

アウトプットしてみるとわかりますが、技術は調べただけだと実は全く身に付きません。自分でやってみて、さらに文章で説明することができないと使えるようにはならないと感じました。

理解した気になっていることも、いざ文章にしようとすると筆が止まる…そして理解していないことに気づく…ということが重要です。

英語の学習も実際に会話で使わないとレベルアップしないのと同様です。また、どんなに些細なアウトプットでも継続して発信していれば誰か見てくれています。アウトプットや情報収集のモチベーションにもつながるためブログはおすすめです。

◆Column
watさんの疲れやストレスを感じたときのリフレッシュ方法
・・・
□仕事中
とにかく肩凝りがひどいので、時折肩を大きく回してリフレッシュします。 集中力を上げたい時はコーヒーを飲みます。
昼休みは好きな本を読んでいます。昼休みに仕事と全然関係ない本を読むのは精神的なリフレッシュになっていると思います。
 
□休日
よく温浴施設でゆっくりします。とにかく肩凝りがひどいので、同施設で定期的に揉みほぐしを行います。たまに遠くの温泉に旅行するのも好きです。
ピアノが趣味のため、ストレスが溜まったら思いっきり弾いて発散します。下手でも楽器は良いものです。

書籍プレゼントのお知らせ

以下のアンケートより、皆さんの「日々のインプット」について教えてください。お寄せいただいた方の中から抽選で書籍『いきなりプログラミング Python』をプレゼント。お待ちしています!

プレゼントの応募詳細

■応募締め切り
2025年7月9日(水)まで

■応募条件
リクルートスタッフィングにご登録いただいている方が対象となります。

■応募方法
こちらよりご応募ください。
※ご応募は期間中お1人様1回限りとなります。ご了承ください。

■注意事項 
・リクルートスタッフィングのご登録情報と応募時にご入力いただく【氏名】【スタッフNo.】【メールアドレス】【生年月日】の4点が一致していない場合は、抽選の対象外となります。ご登録情報のご確認は、MyPageよりお願いしております。
・当選者の発表は、賞品の発送をもって代えさせていただきます。賞品の発送は、締め切り後1ヶ月以内にお送りいたしますが、諸事情によりお時間をいただく場合もございます。ご了承ください。
・賞品は、MyPageにご登録の「住所」にお送りいたします。変更がある場合は、締め切りの2025年7月9日(水)までに「登録情報の確認・変更」よりお手続きをお願いいたします。
・個人情報やご登録状況、抽選の結果、賞品発送状況に関するお問い合わせは、お答えいたしかねます。
・ご回答いただいた内容は、「エンジニアスタイル」の企画のみに使用いたします。就業状況などに影響することはございません。

▼watさん執筆!「Pythonを実際に動かしてみよう

【インタビュイー】watさん
メーカー勤務機械系エンジニア。WATLABブログ運営者。工学計算に関する知識の習得を目指し、Pythonの学習を2019年から始める。仕事以外にも、趣味のプログラミングやPythonコミュニティへの参加を行っている。また、月間数万PVのPythonブログ「WATLAB」を立ち上げ、初心者向けに図を多くしたわかりやすい記事を作成・公開している。著書は『いきなりプログラミング Python』(翔泳社)。

※本記事に記載されている会社名、製品名はそれぞれ各社の商標および登録商標です。

リクルートスタッフィング

モダンCSS、@規則で管理が楽に?

サクッとわかるITトレンドでご紹介した「モダンCSS」。知らなかった書き方があり、使ってみたいと感じた方も多かったのではないでしょうか。

そこで、モダンCSSをさらに深掘り。今回は、2020年代に入ってから各Webブラウザで実装され、現在多くのWebブラウザでサポートされているCSSの「@規則」について紹介し、その書き方と特徴を解説します。

▼「モダンCSS」他の便利な機能についてはこちらからご覧いただけます。

CSSの「@規則」とは

CSSを作成するとき、先頭にアットマーク(@)がついている記述を見かけることがあります。これは「@規則」と呼ばれる特別な命令文で、通常のセレクタとは異なる役割を持ちます。

たとえば、以下のような役割があります。

@import:外部のスタイルシートを読み込む

@font-face:独自のフォントを定義

@media:メディアクエリ(画面の解像度や向きなどに応じて見た目を変更する技術)による条件付きスタイルを適用

具体的には、次のように指定します。

/* 外部スタイルシートの読み込み */
@import url("normalize.css");

/* 独自フォントの定義 */
@font-face {
  font-family: "CustomFont";
  src: url("CustomFont.woff2") format("woff2"),
       url("CustomFont.woff") format("woff");
}

/* メディアクエリによる条件付きスタイル */
@media (max-width: 600px) {
  body {
    font-size: 14px;
    line-height: 1.5;
  }
}

これにより、CSSとして指定する内容を柔軟に管理でき、レスポンシブデザインなどにも対応できます。今回解説する@規則もCSSの拡張機能として追加されたもので、管理が楽になることから注目されています。

従来のCSSでは、スタイルの優先順位や継承のルールが複雑になりがちでしたが、新しい@規則によりメンテナンス性が向上し、規模の大きなプロジェクトでも効率よくスタイルを管理できるようになりました。

以下では@規則の便利な機能3つをコードとあわせてご紹介します。

便利な機能1:Container Queries

レスポンシブデザインを実現するとき、これまではビューポートと呼ばれる画面の幅に基づいてスタイルを変更していました。上記の「@media」を使って、スタイルを決める幅などを指定していたのです。

しかし、画面の幅だけでなく、特定の要素の大きさなどに応じてスタイルを設定したいことがあります。このような要望に対し、柔軟にレイアウトを調整できる技術として「Container Queries」が登場しました。@containerという指定を使って、親要素のサイズに応じたスタイルを子要素に適用する手法です。

つまり、画面の幅ではなく、周囲の要素の大きさや配置に合わせて内部レイアウトを容易に変えられるようにしたのです。具体的には、対象の要素に対して@containerでルールを定義し、その内部で条件に基づく要素のスタイルを設定します。

たとえば、次のように記述すると、コンテナのサイズに応じて子要素の背景色やパディングを変更できます。ここで、container-typeとしてinline-sizeを指定しています。これは、inline 軸と呼ばれる、テキストの行が流れる方向についての寸法によって指定する方法です。

/* コンテナとして利用する要素に対して container-type を指定 */
.container {
  container-type: inline-size;
  border: 1px solid #ccc;
  padding: 16px;
}

/* コンテナのサイズに基づいて子要素のスタイルを変更 */
@container (min-width: 400px) {
  .container .item {
    background-color: lightblue;
    padding: 1em;
  }
}

このCSSでは、HTML要素のクラスとしてcontainerを指定した要素の幅が400px以上になったとき、その内側にあるitemというクラスを指定された要素に対して追加でスタイルを適用しています。

このようにレイアウトを柔軟に変化させたいときには有用な機能です。

便利な機能2:Scoped Styles

CSSで特定の要素にだけスタイルを適用したいことがあります。このとき、HTMLでID属性を指定したり、クラスを指定したりする方法が使われてきました。しかし、大規模なプロジェクトや外部のコンポーネントなどを使う場合、重複しないように指定するのは煩雑です。

そこで、あるコンポーネントだけにスタイルを適用する方法が望まれました。この方法として「Shadow DOM」や「CSS Modules」などが用意されてきましたが、追加でビルドなどの工程が必要で、純粋なCSSで実現する方法が望まれました。

そこで登場したのがScoped Stylesで、@scopeという指定によって、スタイルの適用範囲を限定できます。これにより、スタイルの競合を防ぎ、プロジェクト内でのスタイルの影響範囲を最小化できます。

たとえば、次のように記述すると、cardというクラスを指定したコンポーネント内の要素に対してのみスタイルを適用できます。

/* @scope を使用して、card クラス内の要素にのみスタイル適用 */
@scope (.card) {
  h2 {
    color: darkgreen;
    font-size: 1.5rem;
  }
  p {
    margin-top: 0.5em;
    line-height: 1.6;
  }
}

この例では、cardというクラスを指定した要素の中にあるh2pタグの要素に対して限定して適用され、他には影響を及ぼしません。このため、個別のコンポーネントとして管理できます。

執筆時点では、Google Chromeや Microsoft Edgeのほか、Safariでもサポートされていますが、Firefoxはサポートされていません(参照)。それでも、プロジェクトの規模が大きくなるにつれて管理が複雑になるCSSにおいて、直感的にカプセル化できる技術として注目されています。

便利な機能3:Cascade Layers

これまでのCSSでは、スタイルを適用する優先順位はセレクタの宣言順や読み込み順で制御することがありました。しかし、大規模なプロジェクトになると、この順番の管理が複雑で不具合の原因となっていました。

そこで、画像ソフトでレイヤーを使って管理するように、複数の層に分けてCSSを定義し、レイヤー間の優先順位を設定する方法としてCascade Layersが用意されました。@layerという指定によって論理的なレイヤーに分割することで、優先順位を明示的に管理できるようになります。

たとえば、次のように記述すると、リセット用、コンポーネント用、ユーティリティ用という3つ層に分けてスタイルを定義できます。そして、複数のレイヤーを組み合わせると、後に定義されたレイヤーが優先されます。

/* リセットスタイルを定義するレイヤー */
@layer reset {
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

/* コンポーネント固有のスタイルを定義するレイヤー */
@layer components {
  .button {
    background-color: #008CBA;
    color: white;
    border: none;
    padding: 10px 20px;
    cursor: pointer;
  }
}

/* ユーティリティクラスを定義するレイヤー */
@layer utilities {
  .hidden {
    display: none;
  }
  .m-16 {
    margin: 16px;
  }
}

このようにレイヤーごとにスタイルを分けることで、全社的なスタイルとプロジェクトごとのスタイルのような優先順位を明確に設定でき、メンテナンスしやすくなります。

Cascade LayersはCSS内でのスタイルの適用順序やグループ分けのための仕組みなので、HTML側で特別な属性を指定する必要はありません。CSSで定義したbuttonhiddenm-16といったクラス名をそれぞれの要素に指定するだけで動作します。

たとえば、次のHTMLを作成するとresetというレイヤーで指定された内容によって、Webブラウザに割り当てられている標準のマージンやパディングをリセットできます。また、componentsというレイヤーで指定したスタイルによってボタンの見た目が変わります。さらに、utilitiesというレイヤーで指定したスタイルによって、表示されないテキストやマージンなどが変わります。HTML側では、これまでと同じようにクラスを利用して要素を配置するだけです。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Cascade Layers Sample</title>
    <link href="xxx.css" rel="stylesheet" />
  </head>
  <body>
    <header>
      <h1>Cascade Layers のデモ</h1>
    </header>

    <main>
      <button class="button m-16">クリックしてください</button>
      <p class="hidden">このテキストは表示されません。</p>
      <section>
        <h2>セクションタイトル</h2>
        <p>ここに説明文が入ります。</p>
      </section>
    </main>

    <footer>
      <p>© 2025 My Example Site</p>
    </footer>
  </body>
</html>

このように、CSS側でレイヤーごとにスタイルをグループ化しておけば、HTML側では単にクラスを適用するだけで目的のスタイルが反映できるため、管理や調整が楽になります。

まとめ

CSSの「@規則」は新しいものが次から次へと登場しています。そして、これによって便利な書き方ができ、管理が楽になることが期待されています。Webブラウザの対応状況を見ながら、適用を検討してみてください。

【筆者】増井 敏克さん
増井技術士事務所代表。技術士(情報工学部門)。情報処理技術者試験にも多数合格。ビジネス数学検定1級。「ビジネス」×「数学」×「IT」を組み合わせ、コンピュータを「正しく」「効率よく」使うためのスキルアップ支援や、各種ソフトウェアの開発、データ分析などを行う。著書に『Pythonではじめるアルゴリズム入門』『図解まるわかり プログラミングのしくみ』『「技術書」の読書術 達人が教える選び方・読み方・情報発信&共有のコツとテクニック』、最新刊の『実務で役立つ バックアップの教科書』(翔泳社)がある。

リクルートスタッフィング

Python×PDF:プログラムでPDFから情報を取得してみよう

Pythonを実際に動かしてみよう!今回のお題は、Python×PDF。ビギナーも取り掛かりやすい、サンプルコードとライブラリをご紹介します。プログラムでPDFファイルからテキストや画像を抽出する方法にぜひトライしてみてください。

【筆者】 watさん
メーカー勤務機械系エンジニア。WATLABブログ運営者。工学計算に関する知識の習得を目指し、Pythonの学習を2019年から始める。仕事以外にも、趣味のプログラミングやPythonコミュニティへの参加を行っている。また、月間数万PVのPythonブログ「WATLAB」を立ち上げ、初心者向けに図を多くしたわかりやすい記事を作成・公開している。著書は『いきなりプログラミング Python』(翔泳社)。
ブログ:https://watlab-blog.com/
 

1.PDFからの情報抽出もPythonが便利

Pythonは強力な外部ライブラリのおかげで、WordやExcel、PowerPoint用のファイルも容易にプログラムから操作できます。PDFも例外ではありません。この記事ではPythonでPDFを操作する方法を紹介します。

PDF(Portable Document Format)は印刷する時のレイアウトを保持したまま閲覧したり編集したりできる、まさに電子の紙と呼ぶべき便利なファイル形式です。WordやExcel、PowerPointで作成したファイルも、配布時にはPDFに変換することがよくあり、事務仕事でPDFを扱う頻度は年々増えてきています。

また昨今ではデジタル化やAIの活用が加速しており、PDFファイルからテキストデータや画像データを自動抽出する技術も需要が高まっています。

PDFから情報を抽出することで、すでに会社が保有している膨大なデジタルデータを有効活用できるでしょう。

さて、必要なコードと、サンプルファイルはご用意しました。手元にPCがある人はサクッと手を動かして、PythonでのPDF操作を試してみてください!

2. Pythonプログラミングの準備

■Pythonプログラミング環境の構築

Pythonプログラミングの環境は「最速でPython環境を構築してプログラミングをはじめよう」を参照してください。リンク先にはPythonのインストール方法、プログラムの記述・実行方法、外部ライブラリのインストール方法をまとめています。

▼Pythonのインストールがまだの方はこちらから!

■必要なライブラリのインストール

今回は次の外部ライブラリをインストールします。

POINT
第0回:最速でPython環境を構築してプログラミングをはじめよう」から始める方は、JupyterLabを立ち上げる前の状態にしておきましょう(仮想環境を使わない場合は5節、仮想環境を使う場合は7節の、いずれもjupyter labコマンドを実行する手前)。

(1)pypdf

pypdfは、PythonでPDFファイルを扱うための外部ライブラリです。PDFの結合、分割、ページの抽出、テキストの抽出といったPDFファイルの操作が可能です。次のコマンドでインストールします。

pip install pypdf

外部ライブラリのインストールが終了したら、以下のコマンドを入力して、JupyterLabを立ち上げましょう。立ち上がったらNotebookと書かれている下のアイコンをクリックします。

jupyter lab

3. サンプルファイル

この記事のコードをすぐに試せるように、2種類の.pdfファイルをサンプルとして用意しました。手元にPDFファイルがない場合は以下のリンクからダウンロードしてお使いください。

▼クリックするとPDFファイルが表示されます。
■sample1
https://www.r-staffing.co.jp/rasisa/wp-content/uploads/2025/02/sample1.pdf

■sample2
https://www.r-staffing.co.jp/rasisa/wp-content/uploads/2025/02/sample2.pdf

サンプルファイルの中身は次の通りです。

◼️sample1.pdf
sample1.pdfは生成AIについてテキストが2ページにわたって書かれたファイルです。
◼️sample2.pdf

sample2.pdfは2枚の画像が添付されている1ページ構成のファイルです。

4. PDFからテキストを抽出する

次のPythonコードは、単一のPDFファイルからテキストを抽出し、その結果をoutput.txtというテキストファイルに保存する、というものです。

解説は後にして、まずはいきなりこのコードをNotebookのセルに書いてみましょう。sample1.pdfはプログラム実行ファイルと同じ場所に置いておきます。

from pypdf import PdfReader

# ファイル名を指定
pdf_file = 'sample1.pdf'
output_file = 'output.txt'

# PDFリーダーオブジェクトを作成
reader = PdfReader(pdf_file)

# テキストファイルを開いて書き込みする
page_num = 1
with open(output_file, 'w', encoding='utf-8') as f:
    for page in reader.pages:
        # テキスト抽出
        text = page.extract_text()
        f.write(f'--- Page {page_num} ---\n')
        f.write(text if text else '')
        f.write('\n\n')
        page_num += 1
POINT
1行目:pypdfのimport
このimport文を書くことでpypdfの機能を使うことができるようになります。
 
POINT
12行目:with文
この行ではファイルを開くopen処理を行っています。
テキストファイルの処理を行う際にwith文を使うと、ファイルオープンからメモリの解放までを自動的に行うことができます。with文を使わないと自分でclose処理まで書く必要があり、忘れてしまうとリソースの解放が適切にできずエラーなどの不具合に繋がる場合があるので積極的に使ってみましょう。
 
POINT
13〜19行目:テキストの抽出結果をファイルに書き込む
for文にreader.pagesを指定することで、PDFファイル内のすべてのページ情報にアクセスできるようになり、1ループで1ページ分の情報を新しく定義した変数pageに格納します。
そしてpage.extract_text()でpageの中からテキストを抽出し、text変数に格納します。
後は.write()を使ってテキストファイルへの書き込みを行っていますが、わかりやすいようにページ番号や改行を前後に追加しました。

このコードを実行するとoutput.txtが新規作成されます。中身は次の内容になっているはずです。

--- Page 1 ---
これはサンプルのPDFファイル1です。 ⽣成AI(Generative AI)とは、⼈⼯知能の⼀分野であり、与えられたデータを基に新たなコンテンツを⾃動的に⽣成する技術です 。例えば、テキスト、画像、⾳声、動画などを⽣成することができます 。この技術は、深層学習(ディープラーニング)に基づいたモデルを使⽤し、⼤量のデータを学習してパターンを把握することで、創造的な成果物を作り出します 。⽣成AIは、コンテンツ作成やデザイン 、翻訳、⾳楽制作、さらには医療や教育の分野にも応⽤されています 。最近では、ChatGPTのような対話型AIや、DALL·Eのような画像⽣成AIが注⽬されています 。⽣成AIは、従来のAIとは異なり、単に⼊⼒に対する出⼒を返すのではなく、過去に学習した情報を基に新しいコンテンツを⽣成する能⼒を持っています。
 
--- Page 2 ---
⽣成AIの今後については、さらなる進化が期待されています 。技術の発展により、⽣成AIはより⾼精度で多様なコンテンツを⽣成できるようになり、創造的な分野における新たな可能性を広げると予測されています 。例えば、映画やゲームの制作、広告のコピーライティング 、さらには個別化された教育コンテンツの提供など、多岐にわたる分野での利⽤が進むでしょう。加えて、⽣成AIは、デザインや芸術の分野で⼈間のクリエイティビティを補完し、これまでにないアイデアやスタイルを提案する役割を果たすことも考えられます 。しかし、倫理的な問題や著作権の問題、AIによる情報の操作といった課題も浮上するため、技術の進展と共に、規制やガイドラインの整備が必要不可⽋となるでしょう。今後は、⽣成AIが社会にどのように影響を与えるかに注⽬が集まります 。

5. PDFから画像を抽出する

続いてPDFから画像を抽出してみましょう。

画像の抽出はテキスト抽出を行う上記コードに追加する形で書いてみます。次のコードを追加してください。pdf_fileには画像が添付されているsample2.pdfを設定しましょう。

from pypdf import PdfReader
import os                   # 追加

# ファイル名を指定
pdf_file = 'sample2.pdf'
output_file = 'output.txt'
img_folder = 'img'          # 追加

# 画像保存フォルダを作成                    # ここから追加
os.makedirs(img_folder, exist_ok=True)  # ここまで追加

# PDFリーダーオブジェクトを作成
reader = PdfReader(pdf_file)

# テキストファイルを開いて書き込みする
page_num = 1
img_count = 1                           # 追加
[省略]
        f.write('\n\n')

        # 画像抽出                                      # ここから追加
        for image_file_object in page.images:
            # 画像名として、連番と元の名前を組み合わせて保存
            img_path = os.path.join(img_folder, f'{img_count}_{image_file_object.name}')
            with open(img_path, 'wb') as img_f:
                img_f.write(image_file_object.data)    # ここまで追加
            img_count += 1

        page_num += 1
 
POINT
2行目, 10行目:フォルダの作成
osをimportすることで.makedirs()によるフォルダ作成が使えるようになります。引数であるexist_okTrueにすることで、すでにフォルダがあるときは何もしなくなります。
 
POINT
27〜32行目:画像抽出
page.imagesでページに含まれる画像リストを作成しています。これをfor文で繰り返し処理し、.write()で画像を保存します。

このコードを実行すると、「img」フォルダが作成され、その中に添付されている画像がすべて抽出されることが確認できるはずです。

6. コードを関数化して複数ファイルに対応させよう

さきほどまでのコードは単一のファイルのみに処理を適用するものでした。しかし、このままでは膨大なPDFを一括で処理することができません。

そこで、これまで作成したコードを関数化し再利用できるようにして、複数のPDFファイルに対して一括で処理が適用できるように改造してみましょう。

次のコードが複数のPDFファイルに対応したものです。プログラム実行フォルダに「PDF」というフォルダを作成し、そこにsample1.pdfとsample2.pdfを入れてください。

from pypdf import PdfReader
from pathlib import Path       # osから変更

def process_pdf(pdf_path):                # これまでのコードを関数化
    """PDFのテキストと画像を抽出する関数"""

    # 出力ファイル名・フォルダ設定
    output_file = pdf_path.with_suffix('.txt')                  # 元の.pdfファイルの名前を使いつつ.txtのパスをつくる処理
    img_folder = pdf_path.with_name(pdf_path.stem + '_img')     # 拡張子を取り除いたファイル名に_imgを追加

    # 画像保存フォルダ作成
    img_folder.mkdir(parents=True, exist_ok=True)               # pathlibの書き方に変更

    # PDFリーダーオブジェクトを作成
    reader = PdfReader(pdf_path)

    page_num = 1
    img_count = 1
    with open(output_file, 'w', encoding='utf-8') as f:
        for page in reader.pages:
            # テキスト抽出
            text = page.extract_text()
            f.write(f'--- Page {page_num} ---\n')
            f.write(text if text else '')
            f.write('\n\n')

            # 画像抽出
            for image_file_object in page.images:
                img_path = img_folder / f'{img_count}_{image_file_object.name}'
                with open(img_path, 'wb') as img_f:
                    img_f.write(image_file_object.data)
                img_count += 1

            page_num += 1
    return                                      # ここまで関数化

# PDFフォルダ               # 追加
pdf_dir = Path('PDF')      # 追加

# PDFフォルダ内の全てのPDFファイルに対して処理           # ここから追加
for pdf_path in pdf_dir.glob('*.pdf'):
    process_pdf(pdf_path)
    print(f"{pdf_path.name} の処理が完了しました。")  # ここまで追加
 
POINT
2行目:pathlibに変更
osからpathlibに変更しました。pathlibはPython標準ライブラリの一つですが、ファイルパスの扱いが簡単にできます。今回のようにフォルダに入っているファイルを一括で処理する時に便利なライブラリです。
 
POINT
4〜35行目:関数化
PDFからテキストと画像を抽出する部分を関数化しました。引数に関数の外で作っているpdf_dirを指定します。pdf_dirは「PDF」というフォルダに入ったすべての.pdfファイルパスのリストです。
output_fileimg_folderは元のPDFファイルのファイル名と関連付けたパスにしています。

このコードを実行すると、PDFフォルダの中に、それぞれのPDFファイルに対応した.txtファイルと画像保存フォルダが一括で作成されました!

7. PDFから抽出したデータの活用方法は無限大

この記事ではPDFファイルからテキストデータや画像データを抽出するPythonコードを紹介しました。

テキスト抽出結果は全文検索機能を実現させる時に使われたり、キーワード抽出や、生成AIを活用した要約作成など幅広く活用ができます。

また、画像データは画像認識AIと組み合わせたり、OCR(光学式文字認識)処理を行うことで、さらに幅広く情報をテキスト化することも可能です。

Pythonは世界中の開発者が日々さまざまな知見を積み上げている活発な言語です。ぜひPythonを活用し、思った機能が簡単に実現できることを体験してみてください。

 

▼これまでの記事もあわせてチェック!

※本記事に記載されている会社名、製品名はそれぞれ各社の商標および登録商標です。
※各記事の内容は掲載時点のものです。

リクルートスタッフィング

Python×Word:複数のWordファイルを一括編集してみよう

Pythonを実際に動かしてみよう!今回のお題は、Python×Word。ビギナーも取り掛かりやすい、サンプルコードとライブラリをご紹介します。【読むだけでも、なるほど】と思っていただけるよう、関連トピックも多く記載。プログラムでWordファイルを一括編集する方法をぜひ習得してみてください。

また、本記事のご感想をお送りいただいた方に、抽選で書籍『いきなりプログラミングPython(翔泳社)』をプレゼント。詳細は記事の最後に。

【筆者】 watさん
メーカー勤務機械系エンジニア。WATLABブログ運営者。工学計算に関する知識の習得を目指し、Pythonの学習を2019年から始める。仕事以外にも、趣味のプログラミングやPythonコミュニティへの参加を行っている。また、月間数万PVのPythonブログ「WATLAB」を立ち上げ、初心者向けに図を多くしたわかりやすい記事を作成・公開している。著書は『いきなりプログラミング Python』(翔泳社)。
ブログ:https://watlab-blog.com/
 

1.「面倒だな」と思ったらプログラミングで解決しよう

現代ではどんな仕事をしていても文章を書く業務が少なからずあります。ソフトウェアの仕様を説明するドキュメント、人に業務を教えるためのマニュアル…など、その種類は多岐にわたります。文章を書くツールもさまざまありますが、Microsoft Excelを使っている会社は同じOffice製品であるWordを使うことが多いのではないでしょうか。

Word業務の中でも「文字列の置換」は使用頻度の高い操作です。単一のWordファイルであれば、Word標準の機能を使って文書内の文字列を置換できますが、大量のファイルを一括で置換するには少し工夫が必要です。

この記事ではPythonを使って複数のWordファイル内文字列を一括で置換する方法を紹介します。PythonでWordを編集する方法の第1歩として、PCをお持ちの方はぜひ実際にコードを実行してみてください。

2. Pythonプログラミングの準備

■Pythonプログラミング環境の構築

Pythonプログラミングの環境は「最速でPython環境を構築してプログラミングをはじめよう」を参照してください。リンク先にはPythonのインストール方法、プログラムの記述・実行方法、外部ライブラリのインストール方法をまとめています。

▼Pythonのインストールがまだの方はこちらから!

■必要なライブラリのインストール

POINT
第0回:最速でPython環境を構築してプログラミングをはじめよう」から始める方は、JupyterLabを立ち上げる前の状態にしておきましょう(仮想環境を使わない場合は5節、仮想環境を使う場合は7節の、いずれもjupyter labコマンドを実行する手前)。

(1)python-docx

python-docxは、PythonでWordファイルを作成・編集するための外部ライブラリです。.docxファイルを操作するためには次のコマンドでインストールします。

pip install python-docx

外部ライブラリのインストールが終了したら、以下のコマンドを入力して、JupyterLabを立ち上げましょう。立ち上がったらNotebookと書かれている下のアイコンをクリックします。

jupyter lab

3. サンプルファイル

この記事のコードをすぐに試せるように、3種類の.docxファイルをサンプルとして用意しました。手元にWordのファイルがない場合は以下のリンクからダウンロードしてお使いください。

▼クリックするとWordファイルがダウンロードされます。
■sample1
https://www.r-staffing.co.jp/rasisa/wp-content/uploads/2025/02/sample1.docx
■sample2
https://www.r-staffing.co.jp/rasisa/wp-content/uploads/2025/02/sample2.docx
■sample3
https://www.r-staffing.co.jp/rasisa/wp-content/uploads/2025/02/sample3.docx

サンプルファイルの中身は次の通りです。いずれも異なる「技術」について書かれている短い文章です。

◼️sample1.docx
Wordドキュメント1
現代の情報技術は、社会のあらゆる分野に革命をもたらしています。人工知能やビッグデータ解析などの技術は、ビジネスの効率化や新しいサービスの創出に貢献しています。これらの技術を適切に活用することで、持続可能な社会の実現が期待されています。
 
◼️sample2.docx
Wordドキュメント2
医療分野における技術の進歩は、患者の治療法や診断方法を大きく変えています。遺伝子編集技術やロボット手術など、最新の医療技術は、これまで不可能だった治療を可能にし、患者の生活の質を向上させています。技術の発展は健康な未来への鍵となります。
 
◼️sample3.docx
Wordドキュメント3
環境問題に対処するためのクリーンエネルギー技術が注目されています。太陽光発電や風力発電などの再生可能エネルギー技術は、化石燃料に依存しない持続可能なエネルギー供給を目指しています。これらの技術の普及は、地球温暖化の抑制に重要な役割を果たします。

4. まずはWordファイルを開いてみる

まずはWordのファイルである.docxを開いて中身を確認します。 次のコードを書いて実行してみましょう。

from docx import Document

# ファイル名を指定してWordファイルを読み込む
input_path = 'sample1.docx'
doc = Document(input_path)

# ドキュメントのすべての段落を表示
for para in doc.paragraphs:
    print(para.text)

コードを実行するとファイル名で指定した「sample1.docx 」の中身が出力されます。

POINT
1〜5行目:import文とドキュメントの読み込み
1行目はさきほどインストールしたpython-docxという外部ライブラリを使うためのimport文です。Pythonでは標準ライブラリ(インストール不要のライブラリ)と外部ライブラリ(標準ライブラリ以外)はともにimportしてから本文で呼びだすという使い方をします。5行目のDocument()はimportをしてはじめて使える機能で、Wordドキュメントの読み込みをしている部分です。
 
POINT
8〜9行目:ドキュメントのすべての段落を表示
forは繰り返し処理を行うときに使用します。inは「〜の中に」という意味ですが、ここではdoc.paragraphsで.docxの中のすべての段落の中身を、paraという新しい変数に格納して1つずつループを回すという処理がされます。その結果をprint()で表示させますが、9行目に半角スペース4つ分の「インデント(字下げ)」があることに注意しましょう。
Pythonのforループはこのインデントされた部分が繰り返し処理されます。

5. 単一のWordファイル内の文字を置換してみよう

ドキュメントの読み込みができたので、早速文字列の置換をしてみましょう。「技術」という単語を「テクノロジー」に変換するために、次のコードの修正を行います。

from docx import Document

# ファイル名を指定してWordファイルを読み込む
input_path = 'sample1.docx'
doc = Document(input_path)

# 置換する文字列                # ここから追加
replace_target = '技術'
replace_with = 'テクノロジー'   # ここまで追加

# 置換処理(コメント変更)
for para in doc.paragraphs:
    if replace_target in para.text:       # 追加
        para.text = para.text.replace(replace_target, replace_with)                                # 追加
    print(para.text)
 
POINT
7〜9行目:置換する文字列の設定
replace_targetが元の文章で変更したい単語、replace_withが変換後の単語です。他の単語を置換したい場合はこの部分を変更してください。
 
POINT
13〜14行目:置換処理
paraには段落のテキスト情報が1つずつ格納されていますが、「もしparaのテキストの中に、置換対象の文字replace_targetがあったら」14行目の置換処理が実行されます。ifは条件に一致した場合のみ処理を実行する制御文です。forと同様にインデントのついている行が対象になることに注意してください。

ここで実行結果を確認してみましょう。コードを実行すると次の文章が出力されているはずです。プログラムで指定した通り、「技術」が「テクノロジー」に置換されていますね。

「現代の情報テクノロジーは、社会のあらゆる分野に革命をもたらしています。人工知能やビッグデータ解析などのテクノロジーは、ビジネスの効率化や新しいサービスの創出に貢献しています。これらのテクノロジーを適切に活用することで、持続可能な社会の実現が期待されています。」

6. プログラムを関数化しよう

非常に簡単なコードでWordファイルを開き、単語の置換ができました。ここまでで基本的な置換プログラムは完了してしまいましたので、あとは複数ファイルへこの処理を適用させることができれば完成です。ただし、上記コードをファイル名を変えて何回も書くというのはナンセンス。

Pythonに限らず、プログラミングでは同じ処理をできるだけ書かないようにするのが一般的です。そのために今回はさきほどまでのコードを関数で書き換えます。

次のコードはこれまでのコードを全体的に関数に書き換えたものです。

from docx import Document

def docx_replace_text(input_path, replace_target, replace_with):
    """.docxファイル内の文字列を置換する関数"""

    # ファイル名を指定してWordファイルを読み込む
    doc = Document(input_path)

    # 置換処理
    for para in doc.paragraphs:
        if replace_target in para.text:
            para.text = para.text.replace(replace_target, replace_with)
        print(para.text)

    return

# ファイルのパスと置換する文字列
input_path = 'sample1.docx'
replace_target = '技術'
replace_with = 'テクノロジー'

# 関数の実行
docx_replace_text(input_path, replace_target, replace_with)
 
POINT
3〜15行目、17〜23行目:関数化
Pythonでは関数をdefキーワードで記述します。この場合、関数名がdocx_replace_textです。そして関数の引数にinput_path, replace_target, replace_withを設定し、関数の中で使っています。
17〜23行目は必要な設定を準備して関数を実行する部分です。あとは関数を好きなタイミングで呼び出し、引数を変更しながら使えば同じコードを何回も書かなくてよくなります。

7. 複数のWordファイルに対応させよう

複数のファイルを一括編集する処理を書くとき、その複数のファイルをすべて手入力していては本末転倒です。プログラム実行フォルダに入っているすべての.docxファイルをリストにする処理を追加しましょう。ファイルのパスを操作するにはpathlibというPython標準ライブラリを使用するのが一般的です。

次のコード修正を行います。ここではPath.cwd()でプログラム実行フォルダの場所を取得し、.glob(*.docx)でそこにある.docxファイルのみをすべて取得しています。この段階でinput_pathの行は削除しておきます。そして関数を実行する部分で取得した.docxのファイルを1つずつforで処理します。

from docx import Document
from pathlib import Path    # 追加

def docx_replace_text(input_path, replace_target, replace_with):
    <省略>
    return

# 置換する文字列
input_path = 'sample1.docx'    # 削除
replace_target = '技術'
replace_with = 'テクノロジー'

# プログラム実行フォルダ内の.docxファイルをリストする    # ここから追加
current_dir = Path.cwd()
docx_files = list(current_dir.glob("*.docx"))    # ここまで追加

# 関数の実行
for input_path in docx_files:                                   # 追加
    docx_replace_text(input_path, replace_target, replace_with) # インデントを追加

このコードを実行する場合、あらかじめ置換処理したいすべての.docxファイルをプログラム実行フォルダに置いておいてください。

コードを実行すると置換処理後のテキストがファイル数の数だけ出力されます。

8. ファイルを保存しよう

あとは置換後の.docxファイルを保存すれば完了です。同じ場所にファイルを保存してしまうと元のファイルが上書きされてしまったり、同じようなファイル名が隣り合って紛らわしくなったりするため、保存するファイルは別でフォルダを作成するという処理も追加します。

次のコードを追加しましょう。

from docx import Document
from pathlib import Path

def docx_replace_text(input_path, output_path, replace_target, replace_with): # output_pathを追加
    """.docxファイル内の文字列を置換する関数"""
    <省略>
        print(para.text)

    # ファイルを保存する     # 追加
    doc.save(output_path) # 追加

    return

<省略>
docx_files = list(current_dir.glob("*.docx"))

# 出力フォルダを作成(存在しない場合のみ)    # ここから追加
output_dir = current_dir / "replaced"
output_dir.mkdir(exist_ok=True)        # ここまで追加

# 関数の実行
for input_path in docx_files:
    output_path = output_dir / input_path.name  # 追加
    docx_replace_text(input_path, output_path, replace_target, replace_with)                          # output_pathを追加
POINT
30〜32行目:出力フォルダを作成
31行目はすでに取得済の現在のフォルダcurrent_dirと「replaced」という文字列を使ってパスの連結を行っています。32行目の.mkdir()でreplacedというフォルダを作成します。.mkdirの引数であるexist_okTrueにしておくことで、replacedフォルダが存在しない場合のみ新規フォルダを作成するという動作をします。
 
POINT
4行目、36〜37行目:保存先の引数を設定
保存先をreplacedというフォルダにして元のファイルと分ける構想なので、ファイル名は元のファイルをそのまま使います。まずはoutput_pathという保存ファイルのパスを関数の引数に新規設定します(4行目と37行目)。このoutput_path(36行目)は元のファイルの名前(input_path.name)を再利用して保存先をreplacedフォルダにしたものです。
 
POINT
17行目:ファイル保存
関数の中で.docxファイルを保存します。関数が呼びだされる度に、input_pathoutput_pathの内容が変わるので毎回新しいファイルが作成されます。

9. 全体のコードはこちらから

この記事ではPythonでWordを制御する方法とともに、簡単なファイル処理の方法も学びました。ただし、分量の都合から基本的な内容のみに絞っています。

そしてこのプログラムはまだまだ改良の余地があります。万能な置換処理プログラムにするためには、表やテキストBoxの文章も置換できるようにするのが良いでしょう。

今回は「段落」の文章のみ置換処理の対象としています。表やテキストBox内の文章も取得するように改良することでより汎用的なプログラムになるでしょう。python-docxライブラリの公式ページにはさまざまなAPIが公開されているので、Pythonに興味を持った方は是非挑戦してみてください。

python-docx公式ドキュメント:https://python-docx.readthedocs.io/en/latest/

from docx import Document
from pathlib import Path

def docx_replace_text(input_path, output_path, replace_target, replace_with):
    """.docxファイル内の文字列を置換する関数"""

    # ファイル名を指定してWordファイルを読み込む
    doc = Document(input_path)

    # 置換処理
    for para in doc.paragraphs:
        if replace_target in para.text:
            para.text = para.text.replace(replace_target, replace_with)
        print(para.text)

    # ファイルを保存する
    doc.save(output_path)

    return

# 置換する文字列
replace_target = '技術'
replace_with = 'テクノロジー'

# プログラム実行フォルダ内の.docxファイルをリストする
current_dir = Path.cwd()
docx_files = list(current_dir.glob("*.docx"))

# 出力フォルダを作成(存在しない場合のみ)
output_dir = current_dir / "replaced"
output_dir.mkdir(exist_ok=True)

# 関数の実行
for input_path in docx_files:
    output_path = output_dir / input_path.name
    docx_replace_text(input_path, output_path, replace_target, replace_with)

また、Excelの表に置換したい単語リストを記入しておき、異なる複数の置換処理を一括で行うプログラムに改良しても良いかもしれません。Pythonはとても書きやすい言語です。あなたの無限のアイデアを具現化してみてください。

Python×Excelが気になる人はこちらも

10. 書籍をプレゼント!

アンケートにご協力いただいた方の中から抽選で書籍『いきなりプログラミングPython(翔泳社)』をプレゼントします。その名の通り、「いきなり」作りはじめる入門書!ご応募お待ちしています。

プレゼントの募集は終了しました。たくさんのご応募ありがとうございました。

※本記事に記載されている会社名、製品名はそれぞれ各社の商標および登録商標です。

リクルートスタッフィング

【プレゼントが当たる!】あなたのスキルアップ事情を教えてください

皆さんのスキルアップ事情を教えてください

エンジニアスタイル読者の皆さんのスキルアップに関するアンケートを実施します。

いただいたご意見をもとに、さらに皆さんに役立つイベントやコンテンツをお届けする予定です。ぜひ声をお聞かせください。

また、アンケートにご協力いただいた方の中から抽選でスキルアップに役立つ書籍を5名様にプレゼント!みなさんのご応募お待ちしています。

プレゼントへの応募は締め切りました。たくさんのご応募ありがとうございました。

Python×PowerPoint:スライドの作成を自動化してみよう

Pythonを実際に動かしてみよう!今回のお題は、Python×PowerPoint。ビギナーも取り掛かりやすい、サンプルコードとライブラリをご紹介します。【読むだけでも、なるほど】と思っていただけるよう、関連トピックも多く記載。プログラムでスライドが作られていく面白さを体験してみませんか。

また、本記事のご感想をお送りいただいた方に、抽選で書籍『いきなりプログラミングPython(翔泳社)』をプレゼント。詳細は記事の最後に。

【筆者】 watさん
メーカー勤務機械系エンジニア。WATLABブログ運営者。工学計算に関する知識の習得を目指し、Pythonの学習を2019年から始める。仕事以外にも、趣味のプログラミングやPythonコミュニティへの参加を行っている。また、月間数万PVのPythonブログ「WATLAB」を立ち上げ、初心者向けに図を多くしたわかりやすい記事を作成・公開している。著書は『いきなりプログラミング Python』(翔泳社)。
ブログ:https://watlab-blog.com/
 

1.プレゼン資料の作成に多くの時間をかけていませんか?

私は普段会社でエンジニアとして働いていますが、社内向けや顧客向けにMicrosoft PowerPointでスライドを作成することが多くあります。ただし、凝ったスライドをつくるよりも本業に集中したいものです。PythonプログラムでPowerPointを扱うスキルを身につけることで、スライド作成にかける時間を大幅に削減しましょう。

ここではPythonを使って PowerPointのスライドを自動生成する方法を紹介します。また、せっかくPythonを使うので、Pythonの中で計算したデータをグラフ化してスライドに貼り付ける方法も紹介します。

2. Pythonプログラミングの準備

■Pythonプログラミング環境の構築

Pythonプログラミングの環境は「最速でPython環境を構築してプログラミングをはじめよう」を参照してください。リンク先にはPythonのインストール方法、プログラムの記述・実行方法、外部ライブラリのインストール方法をまとめています。

▼Pythonのインストールがまだの方はこちらから!

■必要なライブラリのインストール

まずは次の3つの外部ライブラリをインストールしておきましょう。

POINT
第0回:最速でPython環境を構築してプログラミングをはじめよう」から始める方は、JupyterLabを立ち上げる前の状態にしておきましょう(仮想環境を使わない場合は5節、仮想環境を使う場合は7節の、いずれもjupyter labコマンドを実行する手前)。

(1)python-pptx

python-pptxは、PythonでPowerPointファイルを作成・編集するための外部ライブラリです。スライドの追加、テキストや画像の挿入、レイアウトの変更など、プログラムでPowerPointを操作する際に非常に便利です。次のコマンドでインストールしましょう。

pip install python-pptx

(2)NumPy

NumPyは、高速な数値計算を可能にする外部ライブラリです。多次元配列の操作や数学関数の適用など、科学技術計算に欠かせない機能を提供します。今回はグラフ用のデータ生成や数値計算に利用します。次のコマンドでインストールしましょう。

pip install numpy

(3)Matplotlib

Matplotlibは、データの可視化を行うための外部ライブラリです。散布図、折れ線グラフ、ヒストグラムなど、多様なグラフを作成できます。今回のプレゼンテーションでは、グラフを作成してスライドに貼り付けるために使用します。次のコマンドでインストールしましょう。

pip install matplotlib

外部ライブラリのインストールが終了したら、以下のコマンドを入力して、JupyterLabを立ち上げましょう。立ち上がったらNotebookと書かれている下のアイコンをクリック。

jupyter lab

3. まずは空のスライドを作成してみる

まずは簡単に空のプレゼンテーションを作成します。次のPythonコードを書いてみましょう。

from pptx import Presentation

# 新しいプレゼンテーションを作成
prs = Presentation()

# プレゼンテーションを保存
prs.save('sample.pptx')

このコードを実行すると、プログラムの実行フォルダにsample.pptxが作成されます。ファイルを開いて確認すると、まだ何もスライドが追加されていないことがわかります。

これから追加していくため、ファイルは一度閉じておきましょう。

4. 表紙となる、タイトルスライドを追加する

動作が確認できたら次はタイトルスライドをプログラムで追加してみます。タイトルスライドを作成する部分はPythonの関数で作りましょう。次のコードを追加してください。

from pptx import Presentation

def create_title_slide(prs, title_text, subtitle_text):    # ここから追加
    """タイトルスライドを作成する関数"""

    # タイトルスライドのレイアウトを取得
    title_slide_layout = prs.slide_layouts[0]

    # タイトルスライドを追加
    slide = prs.slides.add_slide(title_slide_layout)

    # タイトルとサブタイトルのテキストを設定
    title = slide.shapes.title
    subtitle = slide.placeholders[1]
    title.text = title_text
    subtitle.text = subtitle_text

    return                                                  # ここまで追加
<省略>
POINT
3〜16行目:スライドレイアウトの取得
ここではタイトルスライドのレイアウトを.slide_layouts[0]で取得し、.add_slide()で実際に追加しています。.slide_layouts[0][0]はレイアウトのインデックスを示しています。PowerPointは下図のように複数のレイアウトをデフォルトで用意しており、タイトルスライドは0番目のレイアウトにあたるので[0]を設定しているということです。 また、タイトルスライドを追加するコードを丸ごと関数で作成しています。同じ種類のスライドを何度も作成する場合に、関数を定義しておけば再度同じコードを書く必要がないため、スライドの追加は関数で書くと効率が良いです。

次に、import文を追加します。これでインチ単位でサイズを設定できるようになります。

from pptx import Presentation
from pptx.util import Inches                               # 追加
<省略>

そして本文(関数の下)に次のコードを追加します。まず、スライドサイズをワイド版に対応させるために、Inches()でサイズを設定しましょう。先ほど作成したcreate_title_slide()を呼びだすことで関数を実行します。

<省略>
# 新しいプレゼンテーションを作成
prs = Presentation()

# スライドのサイズを16:9に設定                                 # ここから追加
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

# タイトルスライドを作成
create_title_slide(prs, "タイトル", "サブタイトル")           # ここまで追加

# プレゼンテーションを保存
prs.save('sample.pptx')

ここまでのコードを実行すると、sample.pptxにタイトルページが追加されます。

【こんなとき、どうする?】
コードを実行してもsample.pptxが変わらない
Pythonコードを変更し、コードを実行してもsample.pptxが変更されない場合は、PowerPointが開いたままになっている可能性があります。一度sample.pptxを閉じて再度実行してください。

5. 本文スライドを追加する

次に本文スライドを追加してみましょう。シンプルにページタイトルとその内容を説明する箇条書きのテキストボックスを配置させます。この処理もまずは関数としてまとめた方が良いため、次のコードを追加しましょう。

from pptx import Presentation
from pptx.util import Inches

def create_title_slide(prs, title_text, subtitle_text):
    """タイトルスライドを作成する関数"""
    <省略>
    return

def create_content_slide(prs, slide_title, list_content):    # ここから追加
    """本文スライドを作成する関数"""

    # 白紙のスライドレイアウトを取得
    blank_slide_layout = prs.slide_layouts[6]

    # スライドを追加
    slide = prs.slides.add_slide(blank_slide_layout)

    # スライドのサイズを取得
    slide_width = prs.slide_width
    slide_height = prs.slide_height

    # マージンを設定
    left_margin = Inches(0.5)
    top_margin = Inches(0.5)
    right_margin = Inches(0.5)
    bottom_margin = Inches(0.5)

    return                                                  # ここまで追加
<省略>
 
POINT
24〜28行目:白紙スライドを取得する
タイトルスライドと同じようにスライドのレイアウトを取得します。白紙スライドは[6]です。
 
POINT
30〜38行目:スライドサイズとマージンの設定
これからタイトルと箇条書きのテキストボックスを追加しますが、その前にサイズの情報を用意しましょう。.slide_widthでスライドの横幅、.slide_heightでスライドの高さを取得します。 次に、テキストボックスの位置とサイズを決めるためのマージンをInches()で設定します。マージンは下図の通り、上下左右の隙間のことです。

続いてテキストボックスの配置を行います。先ほど取得したスライドサイズとマージンを使ってテキストボックスの位置を決めます。タイトルとコンテンツのテキストボックスを追加するために、次のコードを追加しましょう。

<省略>
def create_content_slide(prs, slide_title, list_content):
    """本文スライドを作成する関数"""
    <省略>
    bottom_margin = Inches(0.5)

    # タイトルのテキストボックスを追加                # ここから追加
    title_left = left_margin
    title_top = top_margin
    title_width = slide_width - left_margin - right_margin
    title_height = Inches(1)

    title_shape = slide.shapes.add_textbox(title_left, title_top, title_width, title_height)
    title_tf = title_shape.text_frame
    title_tf.text = slide_title

    # コンテンツのテキストボックスを追加
    content_left = left_margin
    content_top = title_top + title_height + Inches(0.2)  # タイトルと本文の間に少し余白
    content_width = title_width
    content_height = slide_height - content_top - bottom_margin

    content_shape = slide.shapes.add_textbox(content_left, content_top, content_width, content_height)
    content_tf = content_shape.text_frame        # ここまで追加

    return
<省略>
 
POINT
46〜48行目テキストボックスの追加
.shapes.add_textbox()でテキストボックスの追加を行い、.text_frameでテキストフレームのオブジェクトを生成しテキストボックスを制御できるようにします。 もともとのレイアウトで設定されているテキストボックスの場合は.text_frameがなくてもテキストを書けますが、自分で設置したテキストボックスにはこれがないと.textでテキストを書けません。

content_tfに箇条書きのテキストを書くために、次のコードを追加しましょう。

<省略>

    content_tf = content_shape.text_frame

    # 箇条書きの項目を追加                          # ここから追加
    for idx, point in enumerate(list_content):
        if idx == 0:
            p = content_tf.paragraphs[0]
        else:
            p = content_tf.add_paragraph()
        p.text = point
        p.level = 0                              # ここまで追加

    return
<省略>
 
POINT
59〜66行目:箇条書きテキストの追加
Pythonではenumerate()を使うことでリストから要素を取りだすときに、要素の位置も同時に取りだせます。ここではlist_contentから順番に要素を取り出します。 0番目の要素の場合は.paragraphs[0]で新しい段落を作成し、それ以外の場合は.add_paragraph()で新しい段落を追加することで箇条書きを表現しました。 .levelは箇条書きの階層です。これはすべて0ですが、仮にこの値が1, 2, ...と増えていけばそれだけ階層が深くなっていきます(階層が深くなるというのは、Pythonにおけるインデントが付くのと同じイメージです)。

先ほどと同様に、本文で関数を実行する処理として、次のコードを追加しましょう。

<省略>
# タイトルスライドを作成
create_title_slide(prs, "タイトル", "サブタイトル")

# 本文スライドを作成(2ページ目)                                       # ここから追加
list_content1 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 1", list_content1)   # ここまで追加

# プレゼンテーションを保存
prs.save('sample.pptx')

このコードを実行すると、sample.pptxに本文スライドが追加されます。

本文は複数ページ追加するのが一般的です。次のコードは同じ関数を使って3ページ目、4ページ目を作成するためのものです。関数に渡す引数を変更することでページの内容が変わることを確認できると思います。

<省略>
# タイトルスライドを作成
create_title_slide(prs, "タイトル", "サブタイトル")

# 本文スライドを作成(2ページ目)
list_content1 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 1", list_content1)

# 本文スライドを作成(3ページ目)                                     # ここから追加
list_content2 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 2", list_content2)

# 本文スライドを作成(4ページ目)
list_content3 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 3", list_content2) # ここまで追加

# プレゼンテーションを保存
prs.save('sample.pptx')
【こんなとき、どうする?】
もっと細かくレイアウトを変更したい!

この記事ではPythonでシンプルなPowerPointの制御を紹介するだけにとどめていますが、もっと詳細にレイアウトを変更したいと思う方は、英語になりますが以下のpython-pptxライブラリ公式ドキュメントが参考になると思います。

オートシェイプをはじめとするその他の制御や、各種APIの説明が記載されているので、より洗練されたスライドにするために役立つはずです。
https://python-pptx.readthedocs.io/en/latest/index.html

6. Pythonでデータ分析した結果をスライドに追加する

ここまででPythonを使ってPowerPointのスライドを作成できるようになりました。次はPythonでデータ分析した結果をスライドに追加してみましょう。Pythonを使うことでMicrosoft Office製品ではなかなか難しい処理も容易に行い、即座にPowerPointに結果を自動追加することが可能です。 ここではPythonで3次元グラフを描いてみましょう。次のimport文と関数を追加します。これはあくまでPythonにおけるデータ処理の例であるため、詳細の説明は省略します。

from pptx import Presentation
from pptx.util import Inches
import matplotlib.pyplot as plt    # 追加
import numpy as np                 # 追加

<省略>

def create_content_slide(prs, slide_title, list_content):
    """本文スライドを作成する関数"""
    <省略>
    return

def create_surface_plot():                   # ここから追加
    """3Dプロットを作成する関数"""

    # x, y の範囲を定義
    x = np.linspace(-np.pi, np.pi, 100)
    y = np.linspace(-np.pi, np.pi, 100)
    X, Y = np.meshgrid(x, y)

    # z を計算
    Z = np.sin(X) * np.cos(Y)

    # 3Dプロットを作成
    fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, figsize=(8, 5))

    # サーフェスプロット
    surf = ax.plot_surface(X, Y, Z, cmap='jet')

    # グラフの設定
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')

    # カラーバーを追加
    fig.colorbar(surf, ax=ax)

    # グラフを画像ファイルに保存
    plt.savefig('surface_plot.png', bbox_inches='tight')
    plt.close()

    return                                 # ここまで追加

# 新しいプレゼンテーションを作成
prs = Presentation()
<省略>

そして次の関数実行コードを追加します。
<省略>
# 3Dプロットを作成        # 追加
create_surface_plot()   # 追加

# プレゼンテーションを保存
prs.save('sample.pptx')

このコードを実行すると、Pythonで作成したグラフがプログラム実行フォルダに保存されます。Pythonであればこんなに綺麗な3次元グラフが描けます。

作成した図を貼り付けるスライドを追加するために、次の関数を追加しましょう。大部分は先ほどの『5.本文スライドを追加する』の作成と同じ書き方です。

<省略>
def create_surface_plot():
    """3Dプロットを作成する関数"""
    <省略>
    return

def create_graph_slide(prs, slide_title, image_path):    # ここから追加
    """グラフを貼り付けたスライドを作成する関数"""

    # 白紙のスライドレイアウトを取得
    blank_slide_layout = prs.slide_layouts[6]

    # スライドを追加
    slide = prs.slides.add_slide(blank_slide_layout)

    # スライドのサイズを取得
    slide_width = prs.slide_width

    # マージンを設定
    left_margin = Inches(0.5)
    top_margin = Inches(0.5)
    right_margin = Inches(0.5)

    # タイトルのテキストボックスを追加
    title_left = left_margin
    title_top = top_margin
    title_width = slide_width - left_margin - right_margin
    title_height = Inches(1)

    title_shape = slide.shapes.add_textbox(title_left, title_top, title_width, title_height)
    title_tf = title_shape.text_frame
    title_tf.text = slide_title

    # グラフ画像を貼り付け
    scale = 0.5
    img_left = Inches(1.0)
    img_top = Inches(1.0)
    img_width = slide_width * scale
    slide.shapes.add_picture(image_path, img_left, img_top, width=img_width)

    return                                               # ここまで追加
<省略>
POINT
130〜135行目:画像を貼る
画像は.add_picture()で貼りますが、そのまま貼り付けると原寸になります。画像によってはスライドから大きくはみ出したり、逆に小さくなりすぎたりといったことも起こりえます。 ここではscale変数を用意して、画像の幅img_widthをスライドの幅slide_widthにかけることでサイズ調整をしています。大小さまざまな画像を貼る場合は画像処理ライブラリと組み合わせて画像のサイズを正確に取得するといったカスタマイズも有効でしょう。

関数実行のためのコードを追加すれば完成です。関数の引数にファイル名を設定してください。

<省略>
create_surface_plot()

# グラフを貼り付けたスライドを作成(5ページ目)                             # 追加
create_graph_slide(prs, "グラフスライドのタイトル", 'surface_plot.png')  # 追加

# プレゼンテーションを保存
prs.save('sample.pptx')

こちらが実行結果です。sample.pptxにグラフスライドが追加されました。

7. 全体のコードはこちらから

全世界で使用されるPowerPointもPythonなら簡単に制御可能です。これも世界中のPython開発者が便利なライブラリを用意してくれているおかげですね。この記事ではシンプルなスライド作成方法だけを紹介しましたが、以下のアイデアを実装することでより実用的なスライドを自動生成できるようになります。

社内テンプレートのpptxを編集する
各企業では独自のレイアウトを使用したテンプレートを持っているはずです。 今回はファイルを作成するところからスタートしましたが、既存のファイルを編集するようにするのも有用です。独自のレイアウトを使用していても、何番目のレイアウトが何かを把握しておけば.slide_layoutsで設定可能です。
 
Excelのデータを参照する
PowerPointでスライドを作成する場合、業務でExcelも使っている場合が多いと思います。PythonはExcelも簡単に制御できるため、この2つを合わせることでより自動化の幅が広がることでしょう。

 
自動レポート生成コードとして使用する
今回ご紹介した内容はそのまま自動レポート生成に活用できます。例えばあるデータや写真(図)を決まったフォーマットで並べてレポートを作成する業務がある職場には非常に有用です。テキストボックスや図の幅をインチ単位で制御して配置することさえできれば、面倒な作業は大幅に減るでしょう。

今回のコードは詳細な説明をあえて省きました。ご興味のある読者は是非基礎からPythonの文法を学び、何か面白いアプリを作ってみてください。最後に、この記事で紹介した全体のコードを載せます。PCで開ける方は是非コピペして遊んでみてください。

from pptx import Presentation
from pptx.util import Inches
import matplotlib.pyplot as plt
import numpy as np

def create_title_slide(prs, title_text, subtitle_text):
    """タイトルスライドを作成する関数"""

    # タイトルスライドのレイアウトを取得
    title_slide_layout = prs.slide_layouts[0]

    # タイトルスライドを追加
    slide = prs.slides.add_slide(title_slide_layout)

    # タイトルとサブタイトルのテキストを設定
    title = slide.shapes.title
    subtitle = slide.placeholders[1]
    title.text = title_text
    subtitle.text = subtitle_text

    return

def create_content_slide(prs, slide_title, list_content):
    """本文スライドを作成する関数"""

    # 白紙のスライドレイアウトを取得
    blank_slide_layout = prs.slide_layouts[6]

    # スライドを追加
    slide = prs.slides.add_slide(blank_slide_layout)

    # スライドのサイズを取得
    slide_width = prs.slide_width
    slide_height = prs.slide_height

    # マージンを設定
    left_margin = Inches(0.5)
    top_margin = Inches(0.5)
    right_margin = Inches(0.5)
    bottom_margin = Inches(0.5)

    # タイトルのテキストボックスを追加
    title_left = left_margin
    title_top = top_margin
    title_width = slide_width - left_margin - right_margin
    title_height = Inches(1)

    title_shape = slide.shapes.add_textbox(title_left, title_top, title_width, title_height)
    title_tf = title_shape.text_frame
    title_tf.text = slide_title

    # コンテンツのテキストボックスを追加
    content_left = left_margin
    content_top = title_top + title_height + Inches(0.2)  # タイトルと本文の間に少し余白
    content_width = title_width
    content_height = slide_height - content_top - bottom_margin

    content_shape = slide.shapes.add_textbox(content_left, content_top, content_width, content_height)
    content_tf = content_shape.text_frame

    # 箇条書きの項目を追加
    for idx, point in enumerate(list_content):
        if idx == 0:
            p = content_tf.paragraphs[0]
        else:
            p = content_tf.add_paragraph()
        p.text = point
        p.level = 0

    return

def create_surface_plot():
    """3Dプロットを作成する関数"""

    # x, y の範囲を定義
    x = np.linspace(-np.pi, np.pi, 100)
    y = np.linspace(-np.pi, np.pi, 100)
    X, Y = np.meshgrid(x, y)

    # z を計算
    Z = np.sin(X) * np.cos(Y)

    # 3Dプロットを作成
    fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, figsize=(8, 5))

    # サーフェスプロット
    surf = ax.plot_surface(X, Y, Z, cmap='jet')

    # グラフの設定
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')

    # カラーバーを追加
    fig.colorbar(surf, ax=ax)

    # グラフを画像ファイルに保存
    plt.savefig('surface_plot.png', bbox_inches='tight')
    plt.close()

    return

def create_graph_slide(prs, slide_title, image_path):
    """グラフを貼り付けたスライドを作成する関数"""

    # 白紙のスライドレイアウトを取得
    blank_slide_layout = prs.slide_layouts[6]

    # スライドを追加
    slide = prs.slides.add_slide(blank_slide_layout)

    # スライドのサイズを取得
    slide_width = prs.slide_width

    # マージンを設定
    left_margin = Inches(0.5)
    top_margin = Inches(0.5)
    right_margin = Inches(0.5)

    # タイトルのテキストボックスを追加
    title_left = left_margin
    title_top = top_margin
    title_width = slide_width - left_margin - right_margin
    title_height = Inches(1)

    title_shape = slide.shapes.add_textbox(title_left, title_top, title_width, title_height)
    title_tf = title_shape.text_frame
    title_tf.text = slide_title

    # グラフ画像を貼り付け
    scale = 0.5
    img_left = Inches(1.0)
    img_top = Inches(1.0)
    img_width = slide_width * scale
    slide.shapes.add_picture(image_path, img_left, img_top, width=img_width)

    return

# 新しいプレゼンテーションを作成
prs = Presentation()

# スライドのサイズを16:9に設定
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

# タイトルスライドを作成
create_title_slide(prs, "タイトル", "サブタイトル")

# 本文スライドを作成(2ページ目)
list_content1 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 1", list_content1)

# 本文スライドを作成(3ページ目)
list_content2 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 2", list_content2)

# 本文スライドを作成(4ページ目)
list_content3 = ["1番目の項目", "2番目の項目", "3番目の項目"]
create_content_slide(prs, "本文スライドのタイトル 3", list_content2)

# 3Dプロットを作成
create_surface_plot()

# グラフを貼り付けたスライドを作成(5ページ目)
create_graph_slide(prs, "グラフスライドのタイトル", 'surface_plot.png')

# プレゼンテーションを保存
prs.save('sample.pptx')

8. 書籍をプレゼント!

アンケートにご協力いただいた方の中から抽選で書籍『いきなりプログラミングPython(翔泳社)』をプレゼントします。その名の通り、「いきなり」作りはじめる入門書!ご応募お待ちしています。

プレゼントの募集は終了しました。たくさんのご応募ありがとうございました。

※本記事に記載されている会社名、製品名はそれぞれ各社の商標および登録商標です。
※各記事の内容は掲載時点のものです。

リクルートスタッフィング