<div id="app">
  <label for="csvUpload">CSVアップロード: </label>
  <input type="file" id="csvUpload" name="csvUpload" accept=".csv" @input="changeFile">
  <p>※ 1行目はタイトルを指定、データは2行目から</p>
  <div>
    <p>出力:</p>
    <table border="1">
      <tr>
         <th v-for="(value, key, index) in outputList[0]">{{key}}</th>
      </tr>
      <tr v-for="item in outputList">
        <td v-for="(value, key, index) in item">
          {{value}}
        </td>
      </tr>
    </table>
  </div>
</div>
const { createApp, ref } = Vue;

const app = createApp({
  setup() {
    const outputList = ref([]);
    const changeFile = async (e) => {
      const [file] = e.target.files;
      if (file) {
        const reader = new FileReader();
        reader.readAsText(file);
        await new Promise((resolve) => (reader.onload = () => resolve()));
        if (reader.result) {
          const lineList = reader.result.split("\n");
          const keyList = lineList[0].split(",");
          const resultObj = lineList
            .filter((_, index) => index !== 0)
            .map((line) => {
              const valueList = line.split(",");
              const tmpObj = {};
              keyList.map((key, index) => (tmpObj[key] = valueList[index]));
              return tmpObj;
            });
          outputList.value = resultObj;
        }
      }
    };
    return {
      outputList,
      changeFile
    };
  }
});

app.mount("#app");

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.prod.min.js