[サイトリニューアル]記事URLが変更になりました。旧URLへのアクセスはトップページへ転送されます。お探しの記事は「サイト内検索」をご利用ください。

【薬局DX】スマホ初回アンケートから自動印刷までの実装プロセス(後編)

ウラ
スポンサーリンク

前回の記事では、薬局の初回アンケートを患者さんのスマートフォンで入力してもらい、それを薬局のプリンターで自動的に「見慣れた紙のレイアウト」で印刷する、というシステムの全体像とそのメリットについてお話ししました。

レセコンへの直接連携という高いハードルを避けつつ、現場のスタッフが最も見やすい「いつもの紙」という形に落とし込む。これによって、字が読めないストレスや手入力の手間から解放されるという流れです。

今回はその後編として、具体的にどのようにこのシステムを構築したのか、その裏側と実装手順を公開します。

繰り返しになりますが、私自身はプログラミング言語のコードをゼロから書くことは一切できません。GAS(Google Apps Script)もPowerShellも、文法すらまともに理解していません。すべてAI(ChatGPTやGeminiなど)に書いてもらっています。

「自分がやりたい業務フロー」を正確に言語化し、AIに指示を出してコードを作ってもらい、それを貼り付けただけ。この記事では、私が実際にAIにどのような指示を出したのかという「プロンプト」の部分も含めて、システムの作り方をステップ・バイ・ステップで解説していきます。

ステップ1:Googleフォームとテンプレートの準備

まずはデータの入り口となるGoogleフォームと、出力の土台となるテンプレートを用意します。

  1. Googleフォームの作成:患者さんに入力していただくアンケート項目を作成します。「お薬手帳の有無」「副作用歴」「アレルギー」「現在治療中の疾患」など、今まで紙で聞いていた内容をそのままフォームの質問に落とし込んでいきます。
  2. 差し込み用テンプレートの作成:次に、印刷するためのレイアウト枠を作ります。WordやExcelでも可能ですが、今回はGoogleドライブ内で完結させるため、Googleスプレッドシートを使用して今までの初回アンケート用紙のレイアウトを再現しました。スプレッドシートを利用したのは、当薬局で使用している初回アンケートが日薬作成のものをベースにしていて、それがエクセルファイルだからです。WordファイルであればGoogleドキュメントで作成する方が良いですね。

Googleフォーム「新しいフォームを作成」から進み、設問を作っていきます。

設問の作成

ここで入力されたデータは、自動的にGoogleスプレッドシートに蓄積(スプレッドシートにリンク)されるように設定しておきます。

スプレッドシートにリンク
作成されたスプレッドシートの一部
初回アンケートは日薬作成のものをアレンジして使用

ここが最初のポイントです。患者さんの回答を自動で差し込みたい場所には、目印となる「変数」を置いておきます。 例えば、お名前を入れたい場所には {{名前}} 、お薬手帳の有無を入れたい場所には {{お薬手帳}} というように、二重の中括弧などで囲んだ独自のキーワードを配置しておきます。

差し込み用テンプレート(ドキュメントまたはスプレッドシートで作成)

ステップ2:GASでPDFを自動生成する

ここからが自動化の要、GAS(Google Apps Script)の出番です。スプレッドシートに新しい回答が送信されたら、先ほどのテンプレートをコピーして、変数の部分を実際の回答内容に置き換え、PDFとして特定のフォルダに保存する。この一連の作業をGASに担ってもらいます。

私がAIに投げた指示(プロンプト)は、おおむね次のような内容です。

「Googleフォームからスプレッドシートに回答が送信された時、以下の処理を自動で行うGASのコードを書いてください。

  1. 指定したGoogleスプレッドシートのテンプレート(差し込み用ひな形)を複製する。
  2. スプレッドシートの『名前』列のデータを、(ひな形)スプレッドシート内の {{名前}} と置換する。
  3. 同様に、『お薬手帳』列のデータを {{お薬手帳}} と置換する(必要な項目の数だけ列挙)。
  4. 置換が終わったスプレッドシートをPDF化して、指定したGoogleドライブのフォルダに保存する。
  5. 作業が終わったら、複製した一時的なスプレッドシートは削除する。」

このように、やりたいことを箇条書きで明確に伝えると、AIは完璧なコードを返してくれます。実際に使用しているGASのコードのベースは以下のようになります。

function onFormSubmit(e) {
  // 1. 各種IDの設定(必ず書き換えてください!)
  // ▼ご自身で作った「ひな形(〇〇薬局初回質問票)」のID
  const templateId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; 
  
  // ▼Googleドライブに作った「自動印刷用フォルダ」のID
  const folderId = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'; 

  // 2. フォームの回答を取得
  const responses = e.namedValues;

  // 3. ひな形をコピーして作業用ファイルを作る
  const templateFile = DriveApp.getFileById(templateId);
  const targetFolder = DriveApp.getFolderById(folderId);
  
  // ファイル名を「初回質問票_〇〇様」にする
  let patientName = (responses['お名前'] && responses['お名前'][0] !== '') ? responses['お名前'][0] : '名前なし';
  const tempFile = templateFile.makeCopy('初回質問票_' + patientName + '様', targetFolder);
  const tempSpreadsheet = SpreadsheetApp.openById(tempFile.getId());
  const sheet = tempSpreadsheet.getSheets()[0];

  // 4. ひな形の {{〇〇}} をフォームの回答に置き換える
  // 書き方: replaceText(シート, 'ひな形の文字', フォームの回答, '空欄時の文字(省略可能)');
  // ※空欄時の文字を省略した場合は、自動的に「回答なし」になります。

  replaceText(sheet, '{{来局日}}', responses['タイムスタンプ']); // ※1
  replaceText(sheet, '{{お薬手帳}}', responses['お薬手帳をお持ちですか?(1/9)']);
  replaceText(sheet, '{{副作用}}', responses['おくすりを使用して副作用が現れたことがありますか。(2/9)']);
  replaceText(sheet, '{{副作用詳細}}', responses['(「はい」を選んだ方)医薬品名や具体的な副作用の内容をご記載ください。'], '該当なし');
  replaceText(sheet, '{{アレルギー}}', responses['アレルギー体質ですか。(3/9)']);
  replaceText(sheet, '{{アレルギー詳細}}', responses['(「はい」を選んだ方)具体的なアレルギーの内容を教えてください。'], '該当なし');
  replaceText(sheet, '{{既往歴}}', responses['現在治療中の病気、または過去にかかった病気はありますか? (4/9)']);
  replaceText(sheet, '{{併用薬}}', responses['他に飲んでいるお薬や健康食品はありますか?(5/9)']);
  replaceText(sheet, '{{併用薬詳細}}', responses['(「はい」を選んだ方)具体的な名前をご記載ください。'], '該当なし');
  replaceText(sheet, '{{体質}}', responses['当てはまる体質はありますか?(6/9)']);
  replaceText(sheet, '{{嗜好品}}', responses['当てはまるものをお選びください。(7/9)']);
  replaceText(sheet, '{{生活習慣}}', responses['当てはまるものをお選びください。(8/9)']);
  replaceText(sheet, '{{妊娠授乳}}', responses['[女性の方へ]妊娠または授乳中ですか?(9/9)'], '該当なし');
  replaceText(sheet, '{{名前}}', responses['お名前'], '未入力');
  replaceText(sheet, '{{郵便番号}}', responses['郵便番号'], '未入力');
  replaceText(sheet, '{{住所}}', responses['ご住所'], '未入力');
  replaceText(sheet, '{{電話番号}}', responses['電話番号'], '未入力');

  // 変更を反映させる
  SpreadsheetApp.flush();

  // 5. PDF化してフォルダに保存
  const pdfBlob = tempFile.getAs('application/pdf');
  pdfBlob.setName(tempFile.getName() + '.pdf');
  targetFolder.createFile(pdfBlob);

  // 6. 作業用の一時スプレッドシートをゴミ箱に入れる
  tempFile.setTrashed(true);
}

// 置き換え用の補助機能
function replaceText(sheet, placeholder, valueArray, defaultText = '回答なし') {
  // 配列が空、または中身が空文字('')の場合は defaultText を採用する
  let value = (valueArray && valueArray[0] !== '') ? valueArray[0] : defaultText;
  
  // ※1 タイムスタンプ(来局日)の場合は、日付だけの表記に直す
  // (万が一タイムスタンプが取得できなかった際のエラーを防ぐ条件を追加)
  if (placeholder === '{{来局日}}' && value !== defaultText) {
    let date = new Date(value);
    value = date.getFullYear() + '年' + (date.getMonth() + 1) + '月' + date.getDate() + '日';
  }

  sheet.createTextFinder(placeholder).replaceAllWith(value);
}

注意点としては右側の[]内は、Googleフォームの設問をそのまま持ってくる必要があるところです。ここが違ってしまうとうまく対応ができないので、コピペで一言一句違わぬようにしてください。もう一つのポイントはコードを貼り付けるところです。当該スプレッドシートの「拡張機能」>「Apps Script」から貼り付る必要があります。

あとは「トリガー」を設定するだけです。実行する関数を「createPDFFromForm」にし、イベントのソースを「スプレッドシートから」、イベントの種類を「フォーム送信時」に設定します。

ステップ3:PowerShellでフォルダを監視して自動印刷

GASの働きにより、患者さんがスマホで送信ボタンを押すと、Googleドライブの特定フォルダに綺麗なPDFが自動で生成されるようになりました。

最後は、これを薬局のプリンターで自動印刷する仕組みです。 これには、以前LINEでの処方箋送信システムを構築した時にも活躍した、Windowsの標準機能である「PowerShell」を使います。

その時の記事はこちら。

準備として、薬局のパソコンに「パソコン版 Google ドライブ」をインストールし、PDFが保存されるフォルダがローカルのパソコン上(Gドライブなど)で直接同期・参照できるようにしておきます。

そして、再びAIにお願いをします。前回書いてもらったコードを提示、それを改変する形でオーダーします。

「現在使っているコードをPDFにも対応できる形にしてください。具体的には、WindowsのPowerShellを使って、特定のフォルダ(例: G:\GoogleDrive\Rx_Inbox)を監視、そのフォルダに新しい画像またはPDFファイルが追加されたら、直ちに既定のプリンターで印刷し、印刷が終わったファイルは別の『印刷済みフォルダ(Rx_Done)』に移動させる処理にしてください。」

事前準備としてはSumatra PDFというアプリをPowerShellが常駐するPCにインストールしておくことです。AdobeなどのPDFリーダーでもいいのですが、このSumatra PDFは起動が爆速で動作が極めて軽量、かつ無料という点からオススメです。ポータブル版で十分です。

AIが生成(改変)してくれたPowerShellのスクリプトは、以下のような構成になります。これをテキストエディタに貼り付けて、拡張子を .ps1 にして保存します。

# ▼設定エリア
$watchPath = "G:\マイドライブ\Rx_Inbox"
$movePath  = "G:\マイドライブ\Rx_Done"

# 【重要】ここにプリンターの「IPアドレス」を入れてください
$targetIP = "192.168.ZZ.AA" 

# 【追加】SumatraPDFの場所
$sumatraPath = "C:\Users\SumatraPDF.exe"
# ▲設定エリア終了

# 文字化け対策
[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding(932)

Write-Host "処方箋 自動印刷システム(IP指定+JPG/PDF両対応版)を起動中..." -ForegroundColor Cyan
Write-Host "ターゲットIP: $targetIP"
Write-Host "PC起動後の待機中(30秒)..." -ForegroundColor Gray

# 起動直後のドライバ読み込み待ち
Start-Sleep -Seconds 30

Write-Host "監視を開始します: $watchPath"

while ($true) {
    if (Test-Path $watchPath) {
        # 【変更点1】JPGだけでなく、PDFも一緒に探すように変更しました
        $files = Get-ChildItem -Path $watchPath | Where-Object { $_.Extension -match "\.(jpg|pdf)$" }
        
        foreach ($file in $files) {
            try {
                # IPアドレスから、現在のプリンター名を探し出す
                $printer = Get-WmiObject Win32_Printer | Where-Object { $_.PortName -like "*$targetIP*" } | Select-Object -First 1
                
                if ($printer) {
                    Write-Host "検知: $($file.Name)" -ForegroundColor Yellow
                    Write-Host "  └ プリンター名判明: $($printer.Name)" -ForegroundColor Cyan
                    
                    # 【変更点2】ファイルの拡張子(種類)によって印刷方法を分ける
                    if ($file.Extension -match "\.jpg$") {
                        # ▼ JPG画像の場合の印刷処理(今まで通り)
                        $arg = "C:\WINDOWS\system32\shimgvw.dll,ImageView_PrintTo `"$($file.FullName)`" `"$($printer.Name)`""
                        Start-Process -FilePath "rundll32.exe" -ArgumentList $arg -Wait
                    }
                    elseif ($file.Extension -match "\.pdf$") {
                        # ▼ PDFの場合の印刷処理(スマトラPDFを使用)
                        # ※見つけ出したプリンター名を指定して(-print-to)、画面を出さずに(-silent)印刷します
                        $sumatraArgs = "-print-to `"$($printer.Name)`" -silent `"$($file.FullName)`""
                        Start-Process -FilePath $sumatraPath -ArgumentList $sumatraArgs -Wait -NoNewWindow
                    }
                    
                    Start-Sleep -Seconds 6
                    
                    Move-Item -Path $file.FullName -Destination $movePath -Force
                    Write-Host "  └ 完了: 移動しました" -ForegroundColor Green
                } else {
                    Write-Host "エラー: 指定されたIP($targetIP)を持つプリンターが見つかりません" -ForegroundColor Red
                }
            }
            catch {
                Write-Host "エラー: $($_.Exception.Message)" -ForegroundColor Red
            }
        }
    } else {
        Write-Host "エラー: Googleドライブが見つかりません" -ForegroundColor Red
    }
    Start-Sleep -Seconds 5
}

このスクリプトを実行(常駐)し、黒い画面が立ち上がり「フォルダの監視を開始しました」と表示されれば準備完了。あとは裏で勝手に働き続けてくれます。

最後に:アイデアとAIがあれば、現場の課題は解決できる

いかがだったでしょうか。一見すると難しそうな「スマホ初回アンケートから自動印刷」という連携システムも、Googleフォーム、GAS、PowerShellという既存のツールを組み合わせるだけで、低コストかつ実用的なレベルで構築できてしまいます。

現場で「ここが不便だな」「もっとこうなればいいのに」という課題を見つける力と、それをAIにわかりやすく説明してコードを書いてもらう力。この2つがあれば、薬局のDXは自分たちの手でどんどん進めていくことができます。

今回の記事で紹介したGASやPowerShellのコードは、ご自身の薬局の環境に合わせてフォルダIDやファイルパスを書き換えるだけで、そのままコピペして使用いただけます。この記事が、毎日の業務改善に悩む全国の薬剤師や薬局経営者の皆さまのヒントになれば幸いです。

Anout us

このブログを書いている人
くま☆

薬局で働く薬剤師
「薬局のオモテとウラ」(2006~)
日経DI:熊谷信の「薬剤師的にどうでしょう」連載中(2009~)
詳しくはこちら

くま☆をフォローする

定期購読にオススメの1冊


調剤と情報 薬局 Rp.+(レシピプラス) 日経DI 月刊薬事
タイトルとURLをコピーしました