Рубрики
Без рубрики

Конвертируйте свой файл Excel в объект JavaScript (с помощью React) – без хранения статического файла в вашей базе данных!

Моя мама работает в университете, и в конце каждого семестра она буквально копировала … Tagged with React, JavaScript.

Моя мама работает в университете, и в конце каждого семестра она буквально копировала результаты сотен студентов из файла Excel и отправила их по почте индивидуально, что стоило ей много времени. Когда я узнал о проблеме, я планировал создать массового отправителя по электронной почте, которая позволила бы им отправить всех кандидатов по почте в пределах нажатия кнопки. Я был столкнулся с несколькими незначительными проблемами с файлом Excel, и именно это заставило меня написать эту статью! Итак, давайте обсудим, как я это сделал!

Напишите следующую команду в вашем терминале, чтобы создать приложение React

npx create-react-app excel-file-converter

Вы можете дать любое имя по вашему выбору.

Итак, начнем!! 🚀

Мы будем использовать Visual Studio Code для этой демонстрации и моего рабочего пространства выглядит так

Я создал два компонентных файла: Загрузить file.js Для загрузки вашего файла и Отображать data.js Для отображения полученных данных. Я также создал несколько файлов CSS для них соответственно.

Шаг 1: Загрузка файла Excel

Сначала мы должны загрузить наш файл, и мы можем сделать это либо путем перетаскивания файла и отбросив его в нашем приложении, либо открыв файлы через наше приложение, в любом случае мы будем делать оба пути.

Внутри Uploadfile.js Мы определяем три функции для обработки и извлечения данных

  • Filedrophandler => запускается Ondrop мероприятие
  • FileDragoverHandler => запускается Ondragover мероприятие
  • uploadfilehandler => запускается Onchange Событие из поля ввода

Перетаскивание и отброшение наших файлов

Во -первых, перетаскивание и отброшение файла запускает некоторые события по умолчанию, которые нам не нужны, поэтому мы сначала предотвращаем их

const fileDragOverHandler = (event) => {
    event.preventDefault();
  };

При отбросе файлов файл Excel загружается в двоичном формате, и мы можем извлечь его из событие объект по Event.datatransfer.files [0]

const fileDropHandler = (event) => {
    event.preventDefault();
    const file = event.dataTransfer.files[0];
  };

Открытие файла через наше приложение

Это похоже на FileRoPhandler, когда мы извлекаем бинарные данные из объекта события по event.target.files [0]

const uploadFileHandler = (event) => {
    const file = event.target.files[0];
  };

Шаг 2: Обработка загруженного файла

Теперь нам понадобится пакет для обработки данных, которые мы получили сейчас. Я нашел несколько, но ни один из них не принимал подобные данные, поскольку они ожидают, что мы покажем местоположение файла Excel, но это усложняет ситуацию, поскольку нам придется хранить статический файл, используя такие службы, как AWS. Итак, я взял код из пакета NPM Exceltojson Репозиторий GitHub и обнаружил, что он получает файл Excel из данного местоположения и обрабатывает бинарные данные. Но у нас уже есть эти двоичные данные! Таким образом, все, что нам нужно сделать, это напрямую подавать данные в код, а не упоминать местоположение файла. Поэтому я изменил последние несколько строк, которые не было очень сложно сделать. Вы можете посетить их репозиторий здесь

Вот измененный код, который я хранил в файле с именем Exceltojson.js :

const XLSX = require("xlsx");
const extend = require("node.extend");

const excelToJson = (function () {
  let _config = {};

  const getCellRow = (cell) => Number(cell.replace(/[A-z]/gi, ""));
  const getCellColumn = (cell) => cell.replace(/[0-9]/g, "").toUpperCase();
  const getRangeBegin = (cell) => cell.match(/^[^:]*/)[0];
  const getRangeEnd = (cell) => cell.match(/[^:]*$/)[0];
  function getSheetCellValue(sheetCell) {
    if (!sheetCell) {
      return undefined;
    }
    if (sheetCell.t === "z" && _config.sheetStubs) {
      return null;
    }
    return sheetCell.t === "n" || sheetCell.t === "d"
      ? sheetCell.v
      : (sheetCell.w && sheetCell.w.trim && sheetCell.w.trim()) || sheetCell.w;
  }

  const parseSheet = (sheetData, workbook) => {
    const sheetName =
      sheetData.constructor === String ? sheetData : sheetData.name;
    const sheet = workbook.Sheets[sheetName];
    const columnToKey = sheetData.columnToKey || _config.columnToKey;
    const range = sheetData.range || _config.range;
    const headerRows =
      (sheetData.header && sheetData.header.rows) ||
      (_config.header && _config.header.rows);
    const headerRowToKeys =
      (sheetData.header && sheetData.header.rowToKeys) ||
      (_config.header && _config.header.rowToKeys);

    let strictRangeColumns;
    let strictRangeRows;
    if (range) {
      strictRangeColumns = {
        from: getCellColumn(getRangeBegin(range)),
        to: getCellColumn(getRangeEnd(range)),
      };

      strictRangeRows = {
        from: getCellRow(getRangeBegin(range)),
        to: getCellRow(getRangeEnd(range)),
      };
    }

    let rows = [];
    for (let cell in sheet) {
      // !ref is not a data to be retrieved || this cell doesn't have a value
      if (
        cell === "!ref" ||
        (sheet[cell].v === undefined &&
          !(_config.sheetStubs && sheet[cell].t === "z"))
      ) {
        continue;
      }

      const row = getCellRow(cell);
      const column = getCellColumn(cell);

      // Is a Header row
      if (headerRows && row <= headerRows) {
        continue;
      }

      // This column is not _configured to be retrieved
      if (columnToKey && !(columnToKey[column] || columnToKey["*"])) {
        continue;
      }

      // This cell is out of the _configured range
      if (
        strictRangeColumns &&
        strictRangeRows &&
        (column < strictRangeColumns.from ||
          column > strictRangeColumns.to ||
          row < strictRangeRows.from ||
          row > strictRangeRows.to)
      ) {
        continue;
      }

      const rowData = (rows[row] = rows[row] || {});
      let columnData =
        columnToKey && (columnToKey[column] || columnToKey["*"])
          ? columnToKey[column] || columnToKey["*"]
          : headerRowToKeys
          ? `{{${column}${headerRowToKeys}}}`
          : column;

      let dataVariables = columnData.match(/{{([^}}]+)}}/g);
      if (dataVariables) {
        dataVariables.forEach((dataVariable) => {
          let dataVariableRef = dataVariable.replace(/[\{\}]*/gi, "");
          let variableValue;
          switch (dataVariableRef) {
            case "columnHeader":
              dataVariableRef = headerRows
                ? `${column}${headerRows}`
                : `${column + 1}`;
            // break;
            default:
              variableValue = getSheetCellValue(sheet[dataVariableRef]);
          }
          columnData = columnData.replace(dataVariable, variableValue);
        });
      }

      if (columnData === "") {
        continue;
      }

      rowData[columnData] = getSheetCellValue(sheet[cell]);

      if (sheetData.appendData) {
        extend(true, rowData, sheetData.appendData);
      }
    }

    // removing first row i.e. 0th rows because first cell itself starts from A1
    rows.shift();

    // Cleaning empty if required
    if (!_config.includeEmptyLines) {
      rows = rows.filter((v) => v !== null && v !== undefined);
    }

    return rows;
  };

  const convertExcelToJson = function (config = {}) {
    _config = config.constructor === String ? JSON.parse(config) : config;

    // ignoring empty lines by default
    _config.includeEmptyLines = _config.includeEmptyLines || false;

    // source has to be defined and should have a value
    if (!(_config.source)) {
      throw new Error(":: 'source' required for _config :: ");
    }

    let workbook = XLSX.read(_config.source, {
      type: "array",
    });

    let sheetsToGet =
      _config.sheets && _config.sheets.constructor === Array
        ? _config.sheets
        : Object.keys(workbook.Sheets).slice(
            0,
            (_config && _config.sheets && _config.sheets.numberOfSheetsToGet) ||
              undefined
          );

    let parsedData = {};
    sheetsToGet.forEach((sheet) => {
      sheet =
        sheet.constructor === String
          ? {
              name: sheet,
            }
          : sheet;

      parsedData[sheet.name] = parseSheet(sheet, workbook);
    });

    return parsedData;
  };

  return convertExcelToJson;
})();

export default excelToJson;

//The MIT License (MIT)
// Copyright (c) 2015 INFOinvest http://infoinvest.com.br

Вам понадобится две зависимости для запуска кода

  • XLSX
  • node.extend

Напишите следующую команду, чтобы установить их

npm install xlsx node.extend

Теперь мы готовы обработать полученные данные. Я создаю функцию под названием Convertexceltoobject Для преобразования двоичных данных в Uint8array который наш пакет использует для преобразования данных в объект JavaScript.

const convertExcelToObject = (file) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      const data = new Uint8Array(event.target.result);
      let result = excelToJson({ source: data });
      props.onUploadExcelFile(result.Sheet1);
    };
    reader.readAsArrayBuffer(file);
  };

В этой функции мы преобразуем файл в Uint8array Тип и передавая его в Exceltojson функция, которую мы экспортировали из Exceltojson.js Анкет Результат поднят до нашего родительского компонента App.js чтобы мы могли отобразить данные данные.

Объект выглядит как:

{
  Sheet1: [
      {
        A: 'data of cell A1',
        B: 'data of cell B1',
        C: 'data of cell C1'
      },
      {
        A: 'data of cell A2',
        B: 'data of cell B2',
        C: 'data of cell C2'
      }
   ]
}

И мы передаем файл Convertexceltoobject Через наши функции мы определили ранее.

  const dropHandler = (event) => {
    event.preventDefault();
    const file = event.dataTransfer.files[0];
    convertExcelToObject(file);
  };

  const uploadFileHandler = (event) => {
    const file = event.target.files[0];
    convertExcelToObject(file);
  };

Так что, наконец, наш Uploadfile.js похоже:

import "./UploadFile.css";
import excelToJson from "./excelToJson";

const UploadFile = (props) => {
  const convertExcelToObject = (file) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      const data = new Uint8Array(event.target.result);
      let result = excelToJson({ source: data });
      props.onUploadExcelFile(result.Sheet1);
    };
    reader.readAsArrayBuffer(file);
  };
  const dropHandler = (event) => {
    event.preventDefault();
    const file = event.dataTransfer.files[0];
    convertExcelToObject(file);
  };

  const uploadFileHandler = (event) => {
    const file = event.target.files[0];
    convertExcelToObject(file);
  };

  const dragOverHandler = (event) => {
    event.preventDefault();
  };

  return (
    
); }; export default UploadFile;

Uploadfile.css :

.uploadFile > label {
  font-size: 1.4em;
}

.uploadFile > div {
  background-color: rgb(0, 211, 148);
  height: 11em;
  margin-top: 1em;
}

.uploadFile > div > label {
  border: 2px solid black;
  height: 98%;
  cursor: pointer;
  border-style: dashed;
  display: flex;
  justify-content: center;
}

.uploadFile > div > label > div {
  display: flex;
  justify-content: center;
  flex-direction: column;
}

.uploadFile input {
  margin-top: 1em;
  width: 13.2em;
}

.uploadFile input + div {
  text-align: center;
  margin-top: 0.6em;
  margin-bottom: 7px;
}

.uploadFile input::file-selector-button {
  width: 11em;
  height: 2.5em;
  border: none;
  border-radius: 5px;
  font-size: 16px;
  color: rgb(51, 51, 51);
  background-color: white;
  cursor: pointer;
  font-weight: 600;
  text-transform: uppercase;
}

.uploadFile input::file-selector-button:hover {
  background-color: rgb(235, 235, 235);
  transition: all 0.1s ease-in-out;
}

.uploadFile input::file-selector-button:active {
  background-color: rgb(214, 214, 214);
  transition: all 0.2s ease-in-out;
}

И наша часть загрузки выглядит как:

Довольно круто правильно !! 😉

Шаг 3: Хранение и отображение данных:

Теперь пойдем в наш App.js файл, который выглядит как

import { useState } from "react";
import "./App.css";
import DisplayData from "./DisplayData";
import UploadFile from "./UploadFile";

function App() {
  const [uploadedExcelData, setUploadedExcelData] = useState([]);
  const uploadedExcelDataHandler = (data) => {
    setUploadedExcelData(data);
  };
  return (
    
); } export default App;

App.css :

.container {
  padding: 1.5em 3em;
}

Здесь мы получаем данные, которые мы подняли в Uploadfile.js и хранить его в состоянии и передавать данные в DisplayData.js файл.

Внутри сначала мы должны убедиться, что это не так, если он не находит данных для отображения, добавив это:

if (!props.excelData.length) {
    return 
No File Uploaded
; }

И, наконец, мы используем данные, которые мы получили, и отображаем данные, которые мы получили в таблице:

DisplayData.js :

import "./DisplayData.css";

const DisplayData = (props) => {
  if (!props.excelData.length) {
    return 
No File Uploaded
; } const table = props.excelData; const tableBody = table?.slice(1); const tableHead = table[0]; const keys = Object.keys(tableHead); return (
{keys.map((key) => ( ))} {tableBody.map((row) => ( {keys.map((key) => ( ))} ))}
{tableHead[key]}
{row[key]}
); }; export default DisplayData;

DisplayData.css :

.displayData {
  margin-top: 2em;
  display: flex;
  justify-content: center;
}

.displayData thead th {
  text-align: left;
  transition: all 0.2s ease-in-out;
}

.displayData table {
  background-color: white;
  width: 100%;
  padding-top: 1em;
  border-spacing: 1px;
  border-collapse: collapse;
}

.displayData td,
.displayData th {
  border: 0.5px solid rgb(0, 0, 0);
  padding: 8px;
}

.displayData tr:nth-child(even) {
  background-color: #f2f2f2;
}

.displayData th {
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: rgb(0, 211, 148);
  color: white;
}

.noFileContainer {
  text-align: center;
  margin-top: 2em;
}

Вот и все!!

Я создал файл excel file test.xlsx для тестирования наше приложение, которое содержит следующую таблицу:

Первоначально наше приложение выглядит так:

Теперь я могу перетаскивать наш файл, иначе я могу открыть файл через наше приложение. После загрузки нашего test.xlsx:

Итак, это все!! Мы сделали это!! 🥳 Я знаю, что я не углубился, так как я хотел, чтобы это было четким и коротким, а не сбивающим с толку. Я надеюсь, что вы научились обрабатывать файлы Excel с помощью React. Это мой первый пост, поэтому предложения наиболее приветствуются 🙏.

Оригинал: “https://dev.to/emman1320/convert-your-excel-file-to-a-javascript-object-using-react-without-storing-the-static-file-in-your-database-24jk”