【JS】JS で ファイル出力するCSVデータ生成ツールを作ってみる

■ はじめに

https://dk521123.hatenablog.com/entry/2022/11/23/000000

の続き。

 最近、プログラムをほとんど書いていないので
上記の関連記事の「【2】課題」の部分を修正して
もう少し発展したツールを作ってみた。
ついでに、ファイル出力もやってみたので、メモ。

目次

【1】JavaScriptによるファイル出力
 1)補足:Blobについて
【2】サンプル

【1】JavaScriptによるファイル出力

* 以下のサイトなどに載っている

https://magazine.techacademy.jp/magazine/28206

サンプルより抜粋

function outputFile() {
  const textArea = document.getElementById("testData");
  const csvData = textArea.value;
  const csvArray = csvData.split('');
  const blob = new Blob(csvArray, {type:"text/plan"});

  let link = document.createElement("a");
  link.href = URL.createObjectURL(blob);
  link.download = "output.csv"
  link.click();
}

1)補足:Blobについて

* BLOB(Binary Large Object)を扱うためJavaScriptのオブジェクト

https://developer.mozilla.org/ja/docs/Web/API/Blob

構文

const blob = new Blob(データ, ファイルタイプ);

【2】サンプル

<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<form id="mainForm">
  <div id="div0">
    <textarea id="testData" name="testData" rows="6" cols="100"></textarea><br />
    <input id="delimiter"" name="delimiter" maxlength="20" size="20" value=","><br />
    <input id="maxRow" name="maxRow" maxlength="20" size="20" value="5"><br />
    <button type="button" id="outputFile">ファイル出力</button>
  </div">
  <hr>
  <div id="div1">
    <input id="item1" name="itemName1" class="inputText" type="text" maxlength="20" size="20" placeholder="Enter your header item">
    <select name="dataTypeName1" id="dataType1">
      <option value="String" label="String"></option>
      <option value="Number" label="Number"></option>
      <option value="Boolean" label="Boolean"></option>
    </select>
  </div>
</form>
</body>
<script>
var index = 1;

function canAddInput() {
  var canAdd = true;
  console.log("Check input values");
  const inputTexts = document.querySelectorAll(".inputText");
  for(let inputText of inputTexts) {
    console.log(`Value = ${inputText.value}`);
    if (!inputText.value) {
      canAdd = false;
      break;
    }
  }
  return canAdd;
}

function addRow() {
  if (!canAddInput()) {
    console.log("No need to add inputs any more");
    return;
  }
  
  console.log("Need to add input!!");
  index = index + 1;
  const newDiv = document.createElement("div");
  newDiv.setAttribute("id", `div${index}`);
  
  const newInput = document.createElement("input");
  newInput.setAttribute("id", `item${index}`);
  newInput.setAttribute("name", `itemName${index}`);
  newInput.setAttribute("class", "inputText");
  newInput.setAttribute("type", "text");
  newInput.setAttribute("maxlength", "20");
  newInput.setAttribute("size", "20");
  newInput.setAttribute("placeholder", "Enter your header item");
  newInput.setAttribute("value", "");
  newInput.addEventListener('blur', addRow);
  newInput.addEventListener('input', createData);

  const newSelect = document.createElement("select");
  newSelect.setAttribute("name", `itemTypeName${index}`);
  newSelect.setAttribute("id", `dataType${index}`);
  newSelect.addEventListener("change", createData);

  const optionList = ["String", "Number", "Boolean"];
  for (optionType of optionList) {
    const newOption = document.createElement("option");
    newOption.setAttribute("value", optionType);
    newOption.setAttribute("label", optionType);

    newSelect.appendChild(newOption);
  }
  
  const mainForm = document.getElementById("div0");
  mainForm.appendChild(newDiv);
  newDiv.appendChild(newInput);
  newDiv.appendChild(newSelect);
}

function createData() {
  const maxRow = document.getElementById("maxRow").value;
  const delimiter = document.getElementById("delimiter").value;
  console.log(`Start to create data. ${maxRow} / ${delimiter}`);

  const inputTexts = document.querySelectorAll(".inputText");
  var headers = new Array();
  var dataTypes = new Array();
  for (var i = 0; i < inputTexts.length; i++) {
    var inputText = inputTexts[i];
    console.log(`Value = ${inputText.value}`);
    if (!inputText.value) {
      continue;
    }
    headers.push(inputText.value);
 
    var targetIndex = i + 1;
    var targetSelect = document.getElementById(`dataType${targetIndex}`);
    console.log(`DataType = ${targetSelect.value}`);
    dataTypes.push(targetSelect.value);
  }
  if (headers.length === 0) {
    console.log("No data");
    return;
  }
 
  console.log(`Creating... ${headers}`);
  
  var result = headers.join(delimiter) + "\n";
  for (var i = 0; i < maxRow; i++) {
    for (var j = 0; j < headers.length; j++) {
      if (j !== 0) {
        result = result + delimiter;
      }
      const dataType = dataTypes[j];
      var dataValue = "";
      switch (dataType) {
        case "Number":
          dataValue = 1 + Math.floor(Math.random() * 100 );
          break;
        case "Boolean":
          dataValue = Math.random() < 0.5;
          break;
        case "String":
        default:
          dataValue = Math.random().toString(36).substring(2, 12);
          break;
      }

      result = result + dataValue;
    }
    result = result + "\n";
  }
  
  console.log(`Created... ${result}`);
  const textArea = document.getElementById("testData");
  textArea.value = result;
}
function outputFile() {
  const textArea = document.getElementById("testData");
  const csvData = textArea.value;
  const csvArray = csvData.split('');
  const blob = new Blob(csvArray, {type:"text/plan"});

  let link = document.createElement("a");
  link.href = URL.createObjectURL(blob);
  link.download = "output.csv"
  link.click();
}

const inputText = document.getElementById("item1");
inputText.addEventListener('blur', addRow);
inputText.addEventListener('input', createData);

const outputButton = document.getElementById("outputFile");
outputButton.addEventListener('click', outputFile);
</script>
<html>

出力例

id,name,age,sex,remarks
3tu6vvv23h,kekbwn1g7a,26,false,14jcme128e
32vi64hozk,cjnefypat3,69,false,i1uwhcz881
oqw2luy37x,qwtrviddu1,68,true,svlf10blz1
b84zxuddct,m1z0so2uk8,12,false,bqv81v2rcu
u1apn4halt,h635vg0z6g,2,false,biwqf47upi

関連記事

JS で テスト用の超簡易なCSVデータ生成ツールを作ってみる
https://dk521123.hatenablog.com/entry/2022/11/23/000000
動的に生成したinputタグを考える
https://dk521123.hatenablog.com/entry/2022/11/24/230044
DOM ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2011/01/07/012520
DOM ~ 基本編 / オブジェクト取得 ~
https://dk521123.hatenablog.com/entry/2022/11/21/000000
DOM ~ 基本編 / オブジェクト作成 ~
https://dk521123.hatenablog.com/entry/2022/11/19/000000
DOM ~ 基本編 / オブジェクト操作 ~
https://dk521123.hatenablog.com/entry/2011/01/09/155824
JavaScriptでゼロ埋め
https://dk521123.hatenablog.com/entry/2022/11/01/000000