CSVからメールフォーム作成 無料で使える「CSV TO FORM」のご紹介

メールフォームを無料で作成できる「CSV TO FORM」のご紹介

CSVを読み込みメールフォームを簡単に作成できるツールを用意しました。
メールフォーム「Lemonform」と合わせご活用ください。

メールフォームとは

メールフォームとは、ユーザーに入力をしてもらいメールの送信やデータベースに情報を登録したりする入り口となるものです。
自前で作ることもできますが、やりとりするにはセキュリティ抜きで作ることはできないため、グーグルフォームなど大手のメールフォームを使用する場面もあると思います。

今回ご紹介するのは、当サイトで配布している画像添付可能なPHPメールフォーム「LemonForm」に付随するだれでも一瞬でそこそこのフォームを作れる「CSV TO FORM」です。

CSV TO FORMとは

このサイトが用意したCSVファイルを使い読み込むことでその記述に沿ってメールフォームを出力するというツールです。

CSV(ファイル)とは

CSV(Comma Separated Values)ファイルは、データをカンマで区切って保存するテキストファイル形式です。
Microsoft ExcelやGoogle Sheetsなどの表計算ソフトで読み込んだり書き出したりする際に多用されるフォーマットです。

CSVファイルはシンプルなプレーンテキストファイルで、「,」と「改行」で構成されています。
ソフトで読み込んで表として見ることができ、表組を崩さなければ変更や修整が容易です。

サンプルCSV

CSVファイルをオンライン上でJavaScriptで読み込み表示するだけなので、安全に使用することができます。

おためし:https://rimrt.com/form/

full.csv
simple.csv

基本的な項目とフル機能が用意されたサンプルファイルも用意してありますので、自分で用意しなくてもテストが可能です。

survey.csv

アンケート用テンプレートも追加しました!
フォームの初期設定が「お名前」と「email」が必須になっているので項目がありますが、value=””にダミー@を入れたり、Lemonformのconfigからなくすことは可能です。

機能説明

基本

まずは基本的な<input>はフォームを構成する必須タグです。
inputにはtype(属性)があり、これを指定することによって表示を変えています。

<input type="text">

一番基本となるのがtextです。基本の入力はこれになります。

<input type="email">

メールフォームはアンケートフォームなど一方通行の物にも使えますが、お問い合わせのあとは基本的にメールのやり取りが普通です。
メールアドレスがないと返信ができないためメールアドレスの入力も必須です。

メールアドレス専用入力inputの属性がemailです。
メールアドレスの形式が正しいかどうかをブラウザが検証してくれるようにもなります。(「@」を含む必要があります等)

<input type="tel">

電話番号の入力専用なのがtelです。IOSなどのsafariでは自動的にキーボードが数字になります。
textでも入力はできますがスマホなどで入力するときは自動的に数字入力になったほうがやりやすいでしょう。

<input type="number">

数字入力のみを求める属性です。ブラウザによっては、増減が可能な矢印が表示される物もあります。
min=”0″ max=”100″ と追記することで範囲を指定することもできます。

<input type="range">

スライドさせて数値を入力することができる一風変わった属性です。
こちらもmin=”0″ max=”100″ step=”1″など指定ができますが、基本的には数字が表示されないためアバウトな入力方法ではあります。

CSV TO FORMでは、javascriptで数値を取得し現在の数値を表示するプログラムを用意しているため表示することができます。
本環境で使用するにはjavascriptの読み込みもセットで必要です。


   function setupRangeValueDisplay() {
  document.querySelectorAll('input[type="range"]').forEach(range => {
    const span = range.closest('.form-group').querySelector('.range-value');
    if (span) {
      span.textContent = range.value;
      range.addEventListener('input', () => {
        span.textContent = range.value;
      });
    }
  });
}
document.addEventListener('DOMContentLoaded', () => {
  setupRangeValueDisplay();
});

<input type="date">

自動でカレンダー表示が出現し、年、月、日を入力できます。

他にも以下のようなtypeがあります:

  • type=”month”
  • type=”week”
  • type=”time”
<input type="password">

パスワード入力に使う属性です。入力内容が●などで非表示になります。

<input type="text" name="項目" placeholder="" id="" value="">

name属性を追加し、送信ボタンがあればフォームとして動作します。

required

requiredを指定すると、ユーザーが空のままフォームを送信しようとしたときにブラウザが警告を出して、送信をブロックします。

CSV TO FORMでは必須 列に〇を入力して下さい。

他にはチェックボックス、ラジオボタン、そしてinputからtextareaに変わりますがテキストエリアがあります。

チェックボックス

type=”checkbox”:name属性を同じにするとグループ化できます。

<input type="checkbox" name="check_box[]" value="項目1">
<input type="checkbox" name="check_box[]" value="項目2">
<input type="checkbox" name="check_box[]" value="項目3">

CSV TO FORMでは、optionsに「項目1/項目2/項目3」のように記述します。

name="任意[]"

[]は必須です。CSV TO FORMでは自動で付かないので申し訳ありませんが手動で付与お願いします。

ラジオボタン

type=”radio”:グループ内で1つだけ選択できます。
チェックボックスと違いグループ内でひとつしか選択できないのがラジオボタンです。

<input type="radio" name="ラジオボタン" value="項目1"> 
<input type="radio" name="ラジオボタン" value="項目2">

チェックボックスと同じようにvalueに入力した内容が入力となります。
CSV TO FORMでは、上記のチェックボックスと同じようにoptionsに項目1/項目2/項目3というように/で区切って入力した項目がそれぞれ出力されるようになっています。

テキストエリア

<textarea name="message" rows="5" cols="30" placeholder="ここにメッセージを入力してください"></textarea>

<textarea>は複数行のテキスト入力用。rows・colsでサイズ調整、maxlengthで文字数制限も可能です。placeholderはガイドテキストをあらかじめ表示します。

ファイル添付(type=”file”)

<input type="file">

画像や動画などのファイルを添付できます。

今回のフォームの特徴でもある画像や動画添付は、type=”file”で読み込みこみます。

読み込むだけでは、プレビュー表示はされませんが、javascriptでプレビュー表示する機能が付いています。
本環境で使用するにはjavascriptの読み込みもセットで必要です。


document.addEventListener('DOMContentLoaded', () => {
  // 画像・動画プレビュー
  document.querySelectorAll('input[type="file"]').forEach(input => {
    input.addEventListener('change', handleFilePreview);
  });
});

function handleFilePreview(event) {
    const file = event.target.files[0];
    if (!file) return;

    let previewWrapper = event.target.parentNode.querySelector('.previewWrapper');
    if (!previewWrapper) {
        previewWrapper = document.createElement('div');
        previewWrapper.className = 'previewWrapper';
        event.target.parentNode.appendChild(previewWrapper);
    }
    previewWrapper.innerHTML = '';

    // ファイル容量をMB単位で計算して表示
    const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
    const sizeInfo = document.createElement('div');
    sizeInfo.textContent = 'ファイルサイズ: ' + fileSizeMB + ' MB';
    sizeInfo.style.fontSize = '0.9em';
    sizeInfo.style.marginTop = '5px';

    if (file.type.startsWith('image/')) {
        const img = document.createElement('img');
        img.src = URL.createObjectURL(file);
        img.width = 200;
        previewWrapper.appendChild(img);
        previewWrapper.appendChild(sizeInfo); // 画像の下に容量表示
    } else if (file.type.startsWith('video/')) {
        const video = document.createElement('video');
        video.controls = true;
        video.width = 200;
        video.src = URL.createObjectURL(file);
        previewWrapper.appendChild(video);
        previewWrapper.appendChild(sizeInfo); // 動画の下に容量表示
    } else {
        previewWrapper.appendChild(sizeInfo); // 他のファイルタイプも容量表示
    }
}

フォームタグには以下を追加する必要があります:

enctype="multipart/form-data"

複数ファイル対応の属性:

  • multiple:複数ファイル選択
  • accept:選択できるファイル形式を指定(例:<input type=”file” accept=”.pdf,application/pdf”>)

multiple を付記すると、ユーザーが複数ファイルを選択できるようになります。
Lemonformは複数ファイル添付に対応しておりません。一つずつ添付でお願いします。

accept は指定したファイルタイプだけを選択可能にします。
LemonFormでは画像と動画のみ対応しています。

サーバーへの負荷やPHPの最大容量設定にはご注意ください。

隠しフィールド

<input type="hidden" name="非表示入力" value="項目">

ユーザーには見せずに値を保持できます。

LemonForm(有料版)ではname=”hidden1″やhidden2を使うと確認画面・ユーザーへの送信から除外可能です。

「CSV TO FORM」独自の機能

基本タグの説明が長くなりましたが、CSVで独自の入力をすると、自動で「都道府県」や、「年」「月」「日」を表示することができます。

都道府県自動生成

  • input_type:select
  • name:prefecture
  • options:[自動生成]

これだけで都道府県が自動生成されます。

年・月・日 自動生成

  • input_type:select
  • name:year → 100年分の西暦
  • name:month → 1月~12月
  • name:day → 1~31日
  • options:[自動生成]

classをつける

classNameの列に、入力するとお好みのclassを指定できます。

  • input-validation

を指定するとjavascriptが入力を検知し、「OK」のバリデーションを出す機能もあります。


document.addEventListener('DOMContentLoaded', function () {
  const fields = document.querySelectorAll('.input-validation');

  fields.forEach(field => {
    const span = document.createElement('span');
    span.className = 'validation-msg';
    field.after(span);

    field.addEventListener('input', () => {
      let value = field.value.trim();
      let type = field.getAttribute('type') || field.tagName.toLowerCase();
      let isValid = false;

      // 判定ロジック
      if (type === 'email') {
        isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
      } else if (type === 'tel') {
        isValid = /^[0-9\-]{9,15}$/.test(value);
      } else {
        isValid = value.length > 0;
      }

      // 表示更新
      if (value === '') {
        span.textContent = '';
        span.className = 'validation-msg';
      } else if (isValid) {
        span.textContent = 'OK';
        span.className = 'validation-msg ok';
      } else {
        span.textContent = '×';
        span.className = 'validation-msg ng';
      }
    });
  });
});

trigger 機能

あまり使わないかもしれませんが、「指定したinputに入力があると、対応するinputが現れる」という機能もあります。

trigger列にIDを入力すると、指定したinputの入力があったとき対応するinputが表示されるようになります。
例えば「チェックボタンを押すとtextareaが現れる」ような処理ができます。


function initToggleVisibility() {
  const triggers = document.querySelectorAll('[data-toggle-target]');

  triggers.forEach(trigger => {
    const targetId = trigger.getAttribute('data-toggle-target');
    const targetElement = document.getElementById('form-group-' + targetId);

    if (targetElement) {
      targetElement.style.display = 'none'; 
    }

    const toggle = () => {
      let show = false;

      if (trigger.tagName.toLowerCase() === 'div' &&
          (trigger.classList.contains('radio-group') || trigger.classList.contains('checkbox-group'))) {
        trigger.querySelectorAll('input').forEach(input => {
          if (input.checked) show = true;
        });
      } else if (['checkbox', 'radio'].includes(trigger.type)) {
        show = trigger.checked;
      } else if (['text', 'email', 'tel', 'number', 'date', 'textarea'].includes(trigger.type) || 
                 trigger.tagName.toLowerCase() === 'select') {
        show = trigger.value.trim() !== '';
      } else if (trigger.type === 'file') {
        show = trigger.files.length > 0;
      } else if (trigger.type === 'range') {
        show = true;
      }

      if (targetElement) {
        targetElement.style.display = show ? 'block' : 'none';
        if (!show) hideDescendants(targetElement);
      }
    };

    const hideDescendants = (element) => {
      element.querySelectorAll('[data-toggle-target]').forEach(innerTrigger => {
        const innerTargetId = innerTrigger.getAttribute('data-toggle-target');
        const innerTarget = document.getElementById('form-group-' + innerTargetId);
        if (innerTarget) {
          innerTarget.style.display = 'none';
          hideDescendants(innerTarget);
        }
      });
    };

    toggle();

    if (trigger.tagName.toLowerCase() === 'div' &&
        (trigger.classList.contains('radio-group') || trigger.classList.contains('checkbox-group'))) {
      trigger.querySelectorAll('input').forEach(input => {
        input.addEventListener('change', toggle);
      });
    } else if (['checkbox', 'radio', 'select-one', 'file'].includes(trigger.type)) {
      trigger.addEventListener('change', toggle);
    } else {
      trigger.addEventListener('input', toggle);
    }
  });
}

document.addEventListener('DOMContentLoaded', function () {
  initToggleVisibility(); // 連動表示を初期化
});

郵便番号から住所に自動入力

https://zipcloud.ibsnet.co.jp/doc/api を使い、郵便番号を入力すると自動で住所が入力される物です。

  • ID:zipcode
  • ID:address

IDで判別、対応しているため別のIDだと反応しません。


const zipcodeInput = document.getElementById('zipcode');
if (zipcodeInput) { 
  zipcodeInput.addEventListener('blur', function () {
    const zip = this.value.replace(/[^0-9]/g, ''); 

    if (zip.length === 7) {
      fetch(`https://zipcloud.ibsnet.co.jp/api/search?zipcode=${zip}`)
        .then(response => response.json())
        .then(data => {
          const addressInput = document.getElementById('address');
          if (addressInput) { 
            if (data.results) {
              const result = data.results[0];
              const address = result.address1 + result.address2 + result.address3;
              addressInput.value = address;
            } else {
              addressInput.value = '住所が見つかりません';
            }
          }
        })
        .catch(() => {
          const addressInput = document.getElementById('address');
          if (addressInput) {
            addressInput.value = 'エラーが発生しました';
          }
        });
    } else {
      const addressInput = document.getElementById('address');
      if (addressInput) {
        addressInput.value = '';
      }
    }
  });
}

簡易見積もり機能

自動計算できる見積もりを作れる機能もあります。typeはnumberに、calcの列に金額を入力します。CSSはスタイルcalcを選択してください。(印刷すると印刷用CSSも適応されます。)

estimate.csv

本環境で使用するにはjavascriptの読み込みもセットで必要です。


function setupAutoCalculation() {
    const calcInputs = document.querySelectorAll('.auto-calc');
    calcInputs.forEach(input => {
        input.addEventListener('input', updateTotal);
    });
    updateTotal();
}

function updateTotal() {
    const calcInputs = document.querySelectorAll('.auto-calc');
    let total = 0;
    calcInputs.forEach(input => {
        const price = parseFloat(input.dataset.price || 0);
        const quantity = parseFloat(input.value || 0);
        total += price * quantity;
    });
    document.getElementById('calc-total').textContent = '¥' + total.toLocaleString();
}

おためしのご案内

CSV TO FORM

サンプルファイルで出力をためせますので、ぜひご確認の上ご利用ください。