現場監督が工事写真の整理を自動化した方法【追加アプリなし・無料】

目次

工事写真の整理、後回しにしていませんか?

現場で写真を撮りながらこう思ったことはないでしょうか。

「後でまとめて仕分けしよう」

やる気はあるんですよね。後でやろうって本当に思ってる。

でも夜になったらなったでその時やらなきゃいけない事があるし、

仕事の飲み会やら家族の発熱やらといったイレギュラーなイベントもおこる。

その結果、月末に大量の写真が溜まって、どの現場の写真かわからなくなる。

PCの中には未整理の写真が山積み。

現場監督あるあるだと思います。

この記事では、GoogleフォームとGASを使って工事写真の仕分けを自動化した方法を紹介します。

追加アプリなし、費用ゼロで作れます。

ヤマダ

ちょっとでも現場の皆さんのお役に立てば嬉しいです。

完成するとこうなる

Googleドライブ内にフォルダが構成されます
「工事名→工種→状況」の3階層

現場でフォームから工事名・工種・状況を入力して写真を送信するだけで、

Googleドライブに自動でフォルダ分けして保存されます。

ファイル名も「20260331_建具工事_搬入_001」のように自動でつきます。

必要なものと費用

必要なものはGoogleアカウントだけです。

費用は完全無料。追加のアプリやサービスへの登録も不要です。

今回使うのはこの3つです。

  • Googleフォーム(無料)
  • Googleスプレッドシート(無料)
  • Google Apps Script・GAS(無料)

セットアップ手順

セットアップはPCで行います。
所要時間は15〜20分程度です。

ヤマダ

一度作ってしまえば、運用はスマホだけで完結します。

①Googleフォームを作る

フォームを作ります
一度に送れる写真は10枚まで

Googleフォームを新規作成して、以下の4つの質問を追加します。

質問と回答方法の設定
  • 工事名:記述式
  • 工種:記述式
  • 状況:プルダウン(既存撤去・搬入・取付・調整など工種・現場に合わせて設定)
  • 写真:ファイルのアップロード(最大10枚)

②スプレッドシートに連携する

上のタブを「回答」に切り替えて「スプレッドシートシートにリンク」をクリック

フォームの「回答」タブを開き、「スプレッドシートにリンク」をクリックします。

「新しいスプレッドシートを作成」を選んで「作成」を押してください。

スプレッドシートが開き、タイムスタンプ・工事名・工種・状況・写真の5列が自動で作られていればOKです。

③GASにコードを貼り付ける

スプレッドシートのメニューから「拡張機能」→「Apps Script」を開きます。

最初から入っているコードを全部削除して、以下のコードを貼り付けてCtrl+Sで保存してください。

貼り付けるコード

function onFormSubmit(e) {
try {
const response = e.response;
const itemResponses = response.getItemResponses();

let workName = "";
let workType = "";
let situation = "";
let fileIds = [];

for (const item of itemResponses) {
  const title = item.getItem().getTitle();
  const answer = item.getResponse();

  if (title === "工事名") {
    workName = answer;
  } else if (title === "工種") {
    workType = answer;
  } else if (title === "状況") {
    situation = answer;
  } else if (title === "写真") {
    if (Array.isArray(answer)) {
      fileIds = answer;
    } else if (answer) {
      fileIds = [answer];
    }
  }
}

if (!workName || !workType || fileIds.length === 0) {
  console.log("工事名・工種・写真のいずれかが未入力のためスキップ");
  return;
}

const targetFolder = getOrCreateFolder(workName, workType, situation);
const today = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyyMMdd");

for (const fileId of fileIds) {
  const file = DriveApp.getFileById(fileId);
  const num = getNextNumber(targetFolder, today, workType, situation);
  const newFileName = `${today}_${workType}_${situation}_${num}`;
  file.setName(newFileName);

  targetFolder.addFile(file);

  const parents = file.getParents();
  while (parents.hasNext()) {
    const parent = parents.next();
    if (parent.getId() !== targetFolder.getId()) {
      parent.removeFile(file);
    }
  }
}

console.log(`完了: ${workName} / ${workType} / ${situation} / ${fileIds.length}枚`);

} catch (error) {
console.error(“エラー: ” + error.toString());
}
}

function getOrCreateFolder(workName, workType, situation) {
const root = DriveApp.getRootFolder();

let workFolder = getFolderByName(root, workName);
if (!workFolder) {
workFolder = root.createFolder(workName);
}

let typeFolder = getFolderByName(workFolder, workType);
if (!typeFolder) {
typeFolder = workFolder.createFolder(workType);
}

let situationFolder = getFolderByName(typeFolder, situation);
if (!situationFolder) {
situationFolder = typeFolder.createFolder(situation);
}

return situationFolder;
}

function getFolderByName(parentFolder, name) {
const folders = parentFolder.getFoldersByName(name);
return folders.hasNext() ? folders.next() : null;
}

function getNextNumber(folder, date, workType, situation) {
const prefix = ${date}_${workType}_${situation}_;
const files = folder.getFiles();
let maxNum = 0;

while (files.hasNext()) {
const fileName = files.next().getName();
if (fileName.startsWith(prefix)) {
const numStr = fileName.replace(prefix, “”).split(“.”)[0];
const num = parseInt(numStr, 10);
if (!isNaN(num) && num > maxNum) maxNum = num;
}
}

return String(maxNum + 1).padStart(3, “0”);
}

function setupTrigger() {
const triggers = ScriptApp.getProjectTriggers();
for (const trigger of triggers) {
ScriptApp.deleteTrigger(trigger);
}

const ss = SpreadsheetApp.getActiveSpreadsheet();
const formUrl = ss.getFormUrl();
const form = FormApp.openByUrl(formUrl);

ScriptApp.newTrigger(“onFormSubmit”)
.forForm(form)
.onFormSubmit()
.create();

console.log(“トリガー設定完了”);
}

④トリガーを設定する

上部の関数名を「setupTrigger」に切り替えて「実行」をクリックします。

初回は権限の承認画面が出ます。

ヤマダ

びっくりするし、心配になりますけどここで言うデペロッパー(開発者)は自分なので許可しても大丈夫

「詳細」→「安全ではないページに移動」をクリックして進んでください。自分で作ったスクリプトなので安全です。

「すべて選択」にチェックを入れて「続行」を押します。

実行ログに「トリガー設定完了」と表示されればセットアップ完了です。

実際に使ってみた

「ファイルを追加」を選択すると追加する写真を選ぶ捜査に移ります

現場でスマホからフォームを開き、工事名・工種・状況を入力して写真を送信します。

マイドライブの中に工事名のフォルダが出来ている

送信後にGoogleドライブを確認すると、「工事名→工種→状況」の3階層でフォルダが自動作成され、写真が保存されています。ファイル名も日付・工種・状況・連番で自動でつきます。

おわりに

GoogleフォームとGASを組み合わせるだけで、工事写真の自動仕分けが無料で実現できます。

一度セットアップすれば現場でフォームから送信するだけなので、事務所に戻ってからの整理作業がゼロになります。

現場が変わっても工事名を入力し直すだけで使い回せるのも便利なポイントです。

チームで使いたい場合はGoogle Workspaceの有料プランが便利です。

共有ドライブで複数人が同じフォルダにアクセスできるので写真整理がもっとはかどります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

建設業歴20年。二級建築士・一級施工管理技士。

現場も書類もほぼ一人で回す日々の中で、「もっとラクにできる」と思ったことをまとめています。

工事写真・安全書類・アプリ・経理・許可申請まで、建設業のバックオフィスを全部カバーします。

コメント

コメントする

CAPTCHA


目次