1.效果

2.实现代码
首先要加载Handsontable,在示例中我是cdn的方式引入的,vue的话需要下载插件
      let hot = null;
      var exportPlugin = null;
      function showHandsontable(param) {
        const container = document.getElementById("hot-container");
        // 如果已有实例,先销毁
        if (hot) {
          hot.destroy();
        }
        hot = new Handsontable(container, {
          data: [], // 初始为空
          colHeaders: true, // 动态列头
          rowHeaders: true, // 动态行头
          width: "100%",
          height: 800,
          licenseKey: "non-commercial-and-evaluation", // 免费版许可证
          contextMenu: true, // 启用右键菜单
          manualColumnResize: true, // 允许调整列宽
          manualRowResize: true, // 允许调整行高
          filters: true, // 启用筛选
          dropdownMenu: true, // 启用下拉菜单
          columnSorting: true, // 启用列排序
          stretchH: "all", // 列宽自适应
          afterChange: function (changes, source) {
            if (source === "edit") {
              console.log("数据已修改:", changes);
            }
          },
        });
      }
      showHandsontable();
点击后开始加载数据,注意colHeaders,rowHeaders,是行和列的名称,是数组格式
updateSettings:更新表格数据和表头
loadData:重新加载数据

      document
        .getElementById("load-data")
        .addEventListener("click", async function () {
          try {
            const response = await mockApiCall();
            console.log(response, "这时候弄-");
            // 更新表格数据和表头
            hot.updateSettings({
              colHeaders: response.headers.columns,
              rowHeaders: response.headers.rows,
            });
            hot.loadData(response.data);
            exportPlugin = hot.getPlugin("exportFile");
            console.log("数据加载成功");
          } catch (error) {
            console.error("加载数据失败:", error);
          }3.下载表格
主要用到downloadFile和hot.getPlugin("exportFile")下载格式为csv,目前在Handsontable官网没有看到可以下载xlsx格式的,可能需要xlsx插件
   button.addEventListener("click", () => {
        //下载表格的数据
        exportPlugin.downloadFile("csv", {
          bom: false,
          columnDelimiter: ",",
          columnHeaders: true,//显示表头
          exportHiddenColumns: true,
          exportHiddenRows: true,
          fileExtension: "csv",
          filename: "Handsontable-CSV-file_[YYYY]-[MM]-[DD]",
          mimeType: "text/csv",
          rowDelimiter: "\r\n",
          rowHeaders: true,
        });
        //改为下载报表接口数据
      });4.完整代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>动态表格示例 - Handsontable</title>
    <!-- <script src="./handsontable.full.min.js"></script>
    <link rel="stylesheet" href="./handsontable.full.min.css" /> -->
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/15.0.0/handsontable.full.min.js"
      integrity="sha512-3Os2SFklHFmIWzqQsBOmpA9fYBiar8ASBI4hqgeUKttdJ6lDWli7W+JmXyN8exab8NOpiYT441s6hfqX6Tx+WA=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    ></script>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/15.0.0/handsontable.full.min.css"
      integrity="sha512-reELraG6l/OUbRy0EnDh2RxkanfohOkWJX7afyUG1aGHv49SA9uqrAcJOMhyCNW6kcwbnhePc6JKcdUsQxmjvw=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 20px;
      }
      #hot-container {
        margin-top: 20px;
      }
      .controls {
        margin-bottom: 10px;
      }
      button {
        padding: 8px 12px;
        margin-right: 10px;
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <h1>动态表格示例</h1>
    <div class="controls">
      <button id="load-data">加载数据</button>
      <button id="export-file">下载表格</button>
    </div>
    <div id="hot-container"></div>
    <!-- <script src="app.js"></script> -->
    <script type="text/javascript">
      let hot = null;
      var exportPlugin = null;
      function showHandsontable(param) {
        const container = document.getElementById("hot-container");
        // 如果已有实例,先销毁
        if (hot) {
          hot.destroy();
        }
        hot = new Handsontable(container, {
          data: [], // 初始为空
          colHeaders: true, // 动态列头
          rowHeaders: true, // 动态行头
          width: "100%",
          height: 800,
          licenseKey: "non-commercial-and-evaluation", // 免费版许可证
          contextMenu: true, // 启用右键菜单
          manualColumnResize: true, // 允许调整列宽
          manualRowResize: true, // 允许调整行高
          filters: true, // 启用筛选
          dropdownMenu: true, // 启用下拉菜单
          columnSorting: true, // 启用列排序
          stretchH: "all", // 列宽自适应
          afterChange: function (changes, source) {
            if (source === "edit") {
              console.log("数据已修改:", changes);
            }
          },
        });
      }
      showHandsontable();
      // 加载数据按钮事件
      document
        .getElementById("load-data")
        .addEventListener("click", async function () {
          try {
            const response = await mockApiCall();
            console.log(response, "这时候弄-");
            // 更新表格数据和表头
            hot.updateSettings({
              colHeaders: response.headers.columns,
              rowHeaders: response.headers.rows,
            });
            hot.loadData(response.data);
            exportPlugin = hot.getPlugin("exportFile");
            console.log("数据加载成功");
          } catch (error) {
            console.error("加载数据失败:", error);
          }
        });
      function mockApiCall() {
        return new Promise((resolve) => {
          // 模拟网络延迟
          setTimeout(() => {
            const mockData = {
              headers: {
                columns: ["ID", "姓名", "年龄", "部门", "薪资"],
                rows: Array.from({ length: 15 }, (_, i) => `员工${i + 1}`),
              },
              data: Array.from({ length: 15 }, (_, i) => [
                i + 1000,
                `员工${i + 1}`,
                Math.floor(Math.random() * 20) + 20,
                ["研发部", "市场部", "人事部", "财务部"][
                  Math.floor(Math.random() * 4)
                ],
                (Math.random() * 10000 + 5000).toFixed(2),
              ]),
            };
            resolve(mockData);
          }, 500);
        });
      }
      const button = document.querySelector("#export-file");
      button.addEventListener("click", () => {
        //下载表格的数据
        exportPlugin.downloadFile("csv", {
          bom: false,
          columnDelimiter: ",",
          columnHeaders: false,
          exportHiddenColumns: true,
          exportHiddenRows: true,
          fileExtension: "csv",
          filename: "Handsontable-CSV-file_[YYYY]-[MM]-[DD]",
          mimeType: "text/csv",
          rowDelimiter: "\r\n",
          rowHeaders: true,
        });
        //改为下载报表接口数据
      });
    </script>
  </body>
</html>
文章到此结束,希望对你有所帮助~



















