前端univer创建、编辑excel

前端univer创建、编辑excel

源码在线demo:https://codesandbox.io/p/sandbox/univer-q87kqg?file=/src/Demo.jsx

univer官网地址:https://univer.ai/zh-CN/guides/sheet/introduction

安装univer

npm install @univerjs/core @univerjs/design @univerjs/docs @univerjs/docs-ui @univerjs/engine-formula @univerjs/engine-render @univerjs/sheets @univerjs/sheets-formula @univerjs/sheets-ui @univerjs/ui @univerjs/facade

安装xlsx处理数据

npm install xlsx

创建实例

  1. 引入 Univer 的样式文件、语言包,插件
import "@univerjs/design/lib/index.css";
import "@univerjs/ui/lib/index.css";
import "@univerjs/docs-ui/lib/index.css";
import "@univerjs/sheets-ui/lib/index.css";
import "@univerjs/sheets-formula/lib/index.css";
import { LocaleType, Tools, Univer } from "@univerjs/core";
import { defaultTheme } from "@univerjs/design";
import { UniverFormulaEnginePlugin } from "@univerjs/engine-formula";
import { UniverRenderEnginePlugin } from "@univerjs/engine-render";
import { UniverUIPlugin } from "@univerjs/ui";
import { UniverDocsPlugin } from "@univerjs/docs";
import { UniverDocsUIPlugin } from "@univerjs/docs-ui";
import { UniverSheetsPlugin } from "@univerjs/sheets";
import { UniverSheetsFormulaPlugin } from "@univerjs/sheets-formula";
import { UniverSheetsUIPlugin } from "@univerjs/sheets-ui";
import DesignZhCN from "@univerjs/design/locale/zh-CN";
import UIZhCN from "@univerjs/ui//locale/zh-CN";
import DocsUIZhCN from "@univerjs/docs-ui/locale/zh-CN";
import SheetsZhCN from "@univerjs/sheets/locale/zh-CN";
import SheetsUIZhCN from "@univerjs/sheets-ui/locale/zh-CN";
import { UniverInstanceType } from "@univerjs/core";
import { FUniver } from "@univerjs/facade";
  1. 创建sheet实例,挂载到dom元素上
  const workbookConfig = {
    id: 'workbook',
    locale: "zhCN",
  }

  const univerAPI = useRef();
  const univer = useRef();
  
  useEffect(() => {
    createSheet()
    return () => {
      univerAPI.current.disposeUnit(workbookConfig.id);
    };
  }, []);
  const createSheet = (config = workbookConfig) => {
    if (univerAPI.current) {
      univerAPI.current.disposeUnit(workbookConfig.id);
    }
    univer.current = new Univer({
      theme: defaultTheme,
      locale: LocaleType.ZH_CN,
      locales: {
        [LocaleType.ZH_CN]: Tools.deepMerge(
          SheetsZhCN,
          DocsUIZhCN,
          SheetsUIZhCN,
          UIZhCN,
          DesignZhCN
        ),
      },
    });
    univer.current.registerPlugin(UniverRenderEnginePlugin);
    univer.current.registerPlugin(UniverFormulaEnginePlugin);
    univer.current.registerPlugin(UniverUIPlugin, {
      container: "univer-sheet-container-id",
    });
    univer.current.registerPlugin(UniverDocsPlugin);
    univer.current.registerPlugin(UniverDocsUIPlugin);
    univer.current.registerPlugin(UniverSheetsPlugin);
    univer.current.registerPlugin(UniverSheetsUIPlugin);
    univer.current.registerPlugin(UniverSheetsFormulaPlugin);
    univer.current.createUnit(UniverInstanceType.UNIVER_SHEET, config);
    univerAPI.current = FUniver.newAPI(univer.current);
  }


    // 挂在实例
	<div id="univer-sheet-container-id" className="univer-sheet-container" style={{height: "500px" }} />

导入excel文件、通过xlsx对文件进行处理,通过@univerjs/facade导入数据

  /** 上传文件 */
  const handleChangeUploadExcel = async (fileData) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const data = e.target.result;
      const workbook = XLSX.read(data, { type: "binary" });
      const excelData = convertWorkbookToJson(workbook);
      console.log(
        "%c [ excelData ]-87",
        "font-size:13px; background:pink; color:#bf2c9f;",
        excelData
      );
      createSheet(excelData);
    };
    reader.readAsBinaryString(fileData.file);
  };

  /** 将sheet数据转换为json */
  const convertWorkbookToJson = (workbook) => {
    const sheets = {};
    const sheetOrder = [];
    workbook.SheetNames.forEach((sheetName, sheetIndex) => {
      const worksheet = workbook.Sheets[sheetName];
      const jsonSheet = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
      const cellData = {};
      let maxColumnCount = 0;
      jsonSheet.forEach((row, rowIndex) => {
        row.forEach((cell, colIndex) => {
          if (cell !== null && cell !== undefined && cell !== "") {
            if (!cellData[rowIndex]) {
              cellData[rowIndex] = [];
            }
            cellData[rowIndex][colIndex] = { v: cell };
            if (colIndex + 1 > maxColumnCount) {
              maxColumnCount = colIndex + 1;
            }
          }
        });
      });
      const sheetId = `sheet_${sheetIndex}`;
      sheets[sheetId] = {
        id: sheetId,
        name: sheetName,
        rowCount: jsonSheet.length + 50,
        columnCount: maxColumnCount + 50,
        zoomRatio: 1,
        cellData: cellData,
        showGridlines: 1,
      };
      sheetOrder.push(sheetId);
    });
    return {
      ...workbookConfig,
      sheetOrder: sheetOrder,
      sheets: sheets,
    };
  };
 
  <Upload
    accept=".xls,.xlsx"
     onChange={handleChangeUploadExcel}
     beforeUpload={() => false}
     showUploadList={false}
     multiple={false}
   >
     <Button type="primary" className="upload-btn">
       选择excel文件
     </Button>
   </Upload>

获取表格数据

univerAPI.current.getActiveWorkbook().save()

效果:

初始化
在这里插入图片描述
导入数据

在这里插入图片描述
获取表格数据
在这里插入图片描述

完整代码:

import React, { useEffect, useRef, useState } from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Button, Upload } from "antd";
import "@univerjs/design/lib/index.css";
import "@univerjs/ui/lib/index.css";
import "@univerjs/docs-ui/lib/index.css";
import "@univerjs/sheets-ui/lib/index.css";
import "@univerjs/sheets-formula/lib/index.css";
import { LocaleType, Tools, Univer } from "@univerjs/core";
import { defaultTheme } from "@univerjs/design";
import { UniverFormulaEnginePlugin } from "@univerjs/engine-formula";
import { UniverRenderEnginePlugin } from "@univerjs/engine-render";
import { UniverUIPlugin } from "@univerjs/ui";
import { UniverDocsPlugin } from "@univerjs/docs";
import { UniverDocsUIPlugin } from "@univerjs/docs-ui";
import { UniverSheetsPlugin } from "@univerjs/sheets";
import { UniverSheetsFormulaPlugin } from "@univerjs/sheets-formula";
import { UniverSheetsUIPlugin } from "@univerjs/sheets-ui";
import DesignZhCN from "@univerjs/design/locale/zh-CN";
import UIZhCN from "@univerjs/ui//locale/zh-CN";
import DocsUIZhCN from "@univerjs/docs-ui/locale/zh-CN";
import SheetsZhCN from "@univerjs/sheets/locale/zh-CN";
import SheetsUIZhCN from "@univerjs/sheets-ui/locale/zh-CN";
import { UniverInstanceType } from "@univerjs/core";
import { FUniver } from "@univerjs/facade";
import * as XLSX from "xlsx";

const workbookConfig = {
  id: "workbook",
  locale: "zhCN",
};

const App = () => {
  const univerAPI = useRef();
  const univer = useRef();
  const [excelData, setExcelData] = useState("");

  useEffect(() => {
    univer.current = new Univer({
      theme: defaultTheme,
      locale: LocaleType.ZH_CN,
      locales: {
        [LocaleType.ZH_CN]: Tools.deepMerge(
          SheetsZhCN,
          DocsUIZhCN,
          SheetsUIZhCN,
          UIZhCN,
          DesignZhCN
        ),
      },
    });
    univer.current.registerPlugin(UniverRenderEnginePlugin);
    univer.current.registerPlugin(UniverFormulaEnginePlugin);
    univer.current.registerPlugin(UniverUIPlugin, {
      container: "univer-sheet-container-id",
    });
    univer.current.registerPlugin(UniverDocsPlugin);
    univer.current.registerPlugin(UniverDocsUIPlugin);
    univer.current.registerPlugin(UniverSheetsPlugin);
    univer.current.registerPlugin(UniverSheetsUIPlugin);
    univer.current.registerPlugin(UniverSheetsFormulaPlugin);
    univer.current.createUnit(UniverInstanceType.UNIVER_SHEET, {});
    univerAPI.current = FUniver.newAPI(univer.current);
    return () => {
      univerAPI.current.disposeUnit(workbookConfig.id);
    };
  }, []);

  /** 获取表格数据 */
  const handleGetSheetData = () => {
    const data = univerAPI.current.getActiveWorkbook().save();
    console.log(
      "%c [ data ]-68",
      "font-size:13px; background:pink; color:#bf2c9f;",
      data
    );
    setExcelData(JSON.stringify(data));
  };

  /** 上传文件 */
  const handleChangeUploadExcel = async (fileData) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const data = e.target.result;
      const workbook = XLSX.read(data, { type: "binary" });
      const excelData = convertWorkbookToJson(workbook);
      console.log(
        "%c [ excelData ]-87",
        "font-size:13px; background:pink; color:#bf2c9f;",
        excelData
      );
      univerAPI.current.disposeUnit(workbookConfig.id);
      univer.current.createUnit(UniverInstanceType.UNIVER_SHEET, excelData);
    };
    reader.readAsBinaryString(fileData.file);
  };

  /** 将sheet数据转换为json */
  const convertWorkbookToJson = (workbook) => {
    const sheets = {};
    const sheetOrder = [];
    workbook.SheetNames.forEach((sheetName, sheetIndex) => {
      const worksheet = workbook.Sheets[sheetName];
      const jsonSheet = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
      const cellData = {};
      let maxColumnCount = 0;
      jsonSheet.forEach((row, rowIndex) => {
        row.forEach((cell, colIndex) => {
          if (cell !== null && cell !== undefined && cell !== "") {
            if (!cellData[rowIndex]) {
              cellData[rowIndex] = [];
            }
            cellData[rowIndex][colIndex] = { v: cell };
            if (colIndex + 1 > maxColumnCount) {
              maxColumnCount = colIndex + 1;
            }
          }
        });
      });
      const sheetId = `sheet_${sheetIndex}`;
      sheets[sheetId] = {
        id: sheetId,
        name: sheetName,
        rowCount: jsonSheet.length + 50,
        columnCount: maxColumnCount + 50,
        zoomRatio: 1,
        cellData: cellData,
        showGridlines: 1,
      };
      sheetOrder.push(sheetId);
    });
    return {
      ...workbookConfig,
      sheetOrder: sheetOrder,
      sheets: sheets,
    };
  };

  return (
    <div className="main-container">
      <div>
        <Upload
          accept=".xls,.xlsx"
          onChange={handleChangeUploadExcel}
          beforeUpload={() => false}
          showUploadList={false}
          multiple={false}
        >
          <Button type="primary" className="upload-btn">
            选择excel文件
          </Button>
        </Upload>
      </div>
      <div
        id="univer-sheet-container-id"
        className="univer-sheet-container"
        style={{ height: "500px" }}
      />
      <div>
        <Button type="primary" onClick={handleGetSheetData}>
          获取表格数据
        </Button>
      </div>
      表格数据:<div>{excelData}</div>
    </div>
  );
};
export default App;

源码在线demo:https://codesandbox.io/p/sandbox/univer-q87kqg?file=/src/Demo.jsx

### Univer 实现 Excel 文件的导入和导出功能 Univer 是一款基于 Web 的电子表格引擎,支持多种数据处理场景,包括 Excel 文件的导入和导出。以下是关于如何使用 Univer 实现这些功能的具体说明。 #### 1. 安装必要的依赖项 为了实现 Excel 文件的导入和导出功能,需要安装 `univer` 及其相关模块: ```bash npm install @univerjs/core @univerjs/sheets @universheet/excel-io ``` 上述命令会安装核心库以及与 Excel IO 相关的功能模块[^1]。 --- #### 2. 初始化 Univer 应用实例 创建一个基础的应用程序实例来加载和管理电子表格数据: ```javascript // 导入必要模块 import { Universe } from '@univerjs/core'; import { SheetsPlugin } from '@univerjs/sheets'; // 创建 Universe 实例并注册插件 const universe = new Universe(); universe.registerPlugin(SheetsPlugin); ``` 通过这段代码初始化了一个基本的 Univer 环境,并启用了电子表格插件以支持后续的数据操作[^2]。 --- #### 3. 配置 Excel IO 插件 为了让应用程序能够读取和写入 Excel 文件,需进一步配置 Excel IO 插件: ```javascript import { ExcelIOPlugin } from '@universheet/excel-io'; // 注册 Excel IO 插件 universe.registerPlugin(ExcelIOPlugin); // 获取当前工作簿对象 const workbookContext = universe.getWorkBookContext('defaultWorkbook'); if (!workbookContext) { throw new Error('无法获取默认的工作簿上下文'); } ``` 此部分代码完成了对 Excel IO 功能的支持,并准备好了用于存储数据的工作簿环境[^3]。 --- #### 4. 导入 Excel 数据 利用 Univer 提供的方法可以从本地文件或其他来源加载 Excel 数据到内存中: ```typescript async function importExcel(file: File): Promise<void> { const excelIoService = workbookContext.getCellMatrixController().getExcelIOService(); try { await excelIoService.importFromFile(file, (progress) => console.log(`Import progress: ${progress}%`)); console.log('Excel 文件成功导入'); } catch (error) { console.error('导入失败:', error); } } // 调用函数时传递用户上传的文件对象 ``` 该方法接收一个标准的 HTML5 `File` 对象作为参数,并将其解析为内部可使用的结构化数据形式[^4]。 --- #### 5. 导出 Excel 数据 当完成编辑或生成新的报表后,可以通过以下方式将数据保存回 Excel 文件: ```typescript function exportExcel(): void { const excelIoService = workbookContext.getCellMatrixController().getExcelIOService(); try { const blob = excelIoService.exportToFile({ fileName: 'output.xlsx', fileType: 'xlsx' }); saveAs(blob as Blob, 'output.xlsx'); // 使用 FileSaver.js 进行下载 console.log('Excel 文件成功导出'); } catch (error) { console.error('导出失败:', error); } } ``` 这里调用了 `exportToFile` 方法生成目标文件流,并借助第三方库(如 FileSaver.js)触发浏览器下载行为[^5]。 --- #### 6. 扩展功能 如果项目中有更复杂的需求,比如嵌入图片、自定义单元格样式等,则可以参考其他成熟的解决方案进行集成。例如,在 Vue 或 React 中结合 XLSX 和 ExcelJS 工具包可能是一个不错的选择[^6]。 --- ### 总结 以上展示了如何基于 Univer 构建一套完整的 Excel 文件导入/导出机制。它不仅提供了灵活的操作接口,还允许开发者轻松扩展更多高级特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值