kintone Excel预览插件

cnDevNet发表于:2020年06月01日 13:30:35更新于:2022年07月27日 10:26:46

开发者中心包含此范例模板(kintone Excel预览),请前往开发者中心下载学习。

Index

概要

这次为大家分享的是,如何用js写出Excel文件的预览。

他方便了pc用户和手机端用户可以无需下载,并且直接在线预览Excel文件。

因为Excel转html的显示用的是第三方开源库的代码,所以实现上有所限制。具体请参见 所用到开源的库 这些库的说明。

支持不支持
多sheet显示图片显示
合并后的单元格显示链接,文字样式等
手机画面优化

效果图

PC:

0015ed4c2338e02748a6246ec14c321


手机:

0015ed4c232e459910f436f2bcc0458

示例代码

所用到开源的库

js:

jQuery:https://js.cybozu.cn/jquery/3.4.1/jquery.min.js

sheetjs ( js-xlsx ):https://github.com/SheetJS/sheetjs

bootstrap: https://github.com/twbs/bootstrap

css:

https://github.com/FortAwesome/Font-Awesome

https://github.com/keaukraine/bootstrap4-fs-modal (mobile端)

代码

判断是否为Excel文件

    function checkXls(file) {
        let reg = /\.xl(s[xmb]|t[xm]|am|s)$/g;
        return reg.test(file);
    }

加载模态框,显示加载画面,添加预览图标

    function loadModal(fileInfo) {
        let previewElement;
        jQuery(".file-image-container-gaia").each(function (i, e) {
            let fileName = jQuery(e).children("a:eq(0)").text();
            if (fileName == fileInfo.name && jQuery(e).children("button").length == 0) {
                previewElement = jQuery(e);
                return false;
            }
        });
        if (!previewElement) return;
        let modalId = 'myModal' + fileInfo.fileKey;
        let tabId = 'myTab' + fileInfo.fileKey;
        let tabContentId = 'tab-content' + fileInfo.fileKey;
        let $button = $('<button type="button" class="btn btn-default" data-toggle="modal" data-target="#' + modalId + '"><span class="fa fa-search"></span></button>');
        let myModal =
            '<style type="text/css">td{word-break: keep-all;white-space:nowrap;}</style>' +
            '<div class="modal fade tab-pane active" id="' + modalId + '" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">' +
            '<div class="modal-dialog modal-xl" style="border-radius:5px" role="document">' +
            '<div class="modal-content">' +
            '<div class="modal-header">' +
            '<h5 class="modal-title">' + fileInfo.name + '</h5>' +
            '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
            '<span aria-hidden="true">&times;</span>' +
            '</button>' +
            '</div>' +
            '<ul class="nav nav-tabs" id=' + tabId + '>' +
            '</ul>' +
            '<div id=' + tabContentId + ' class="tab-content">' +
            '<div class="d-flex justify-content-center">' +
            '<div class="spinner-border" role="status">' +
            '<span class="sr-only">Loading...</span>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '<div class="modal-footer">' +
            '<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '</div>';
        previewElement.append($button);
        $('body').prepend(myModal);
        $('#' + modalId).on('shown.bs.modal', function (e) {
            loadRemoteFile(fileInfo);
        })
    }

下载文件并加载到模态框中

    function readWorkbookFromRemoteFile(url, callback) {
        let xhr = new XMLHttpRequest();
        xhr.open('get', url, true);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.responseType = 'arraybuffer';
        xhr.onload = function (e) {
            if (xhr.status == 200) {
                let data = new Uint8Array(xhr.response)
                let workbook = XLSX.read(data, { type: 'array' });
                if (callback) callback(workbook);
            }
        };
        xhr.send();
    }
    function readWorkbook(workbook, fileInfo) {
        let sheetNames = workbook.SheetNames;
        let navHtml = '';
        let tabHtml = '';
        let myTabId = 'myTab' + fileInfo.fileKey;
        let tabContentId = 'tab-content' + fileInfo.fileKey;
        for (let index = 0; index < sheetNames.length; index++) {
            let sheetName = sheetNames[index];
            let worksheet = workbook.Sheets[sheetName];
            let sheetHtml = XLSX.utils.sheet_to_html(worksheet);
            let tabid = "tab" + fileInfo.fileKey + "-" + index;
            let xlsid = "xlsid" + fileInfo.fileKey + "-" + index;
            let active = index == 0 ? "active" : '';
            navHtml += '<li class="nav-item"><a class="nav-link ' + active + '"  href="#"  data-target="#' + tabid + '" data-toggle="tab">' + sheetName + '</a></li>';
            tabHtml += '<div id="' + tabid + '" class="tab-pane ' + active + '" style="padding:10px;overflow:auto;height:600px" >' +
                '<div id="' + xlsid + '">' + sheetHtml + ' </div></div>';
        }
        jQuery("#" + myTabId).html(navHtml);
        jQuery("#" + tabContentId).html(tabHtml);
        jQuery("#" + tabContentId + ' table').addClass("table table-bordered table-hover");
    }
    function loadRemoteFile(fileInfo) {
        let fileUrl = '/k/v1/file.json?fileKey=' + fileInfo.fileKey;
        readWorkbookFromRemoteFile(fileUrl, function (workbook) {
            readWorkbook(workbook, fileInfo);
        });
    }

mobile优化

使用"bootstrap-fs-modal.min.css"库,在mobile上打开Excel预览图标,会全屏显示Excel内容,同时关闭按钮调整在最上端,符合用户使用习惯。

 function loadModal(fileInfo) {
        let previewElement;
        jQuery(".control-showlayout-file-gaia .control-value-gaia div").each(function (index, e) {
            let fileName = jQuery(e).find("a:eq(0)").text();
            if (fileName == fileInfo.name && jQuery(e).find("button").length == 0) {
                previewElement = jQuery(e);
                return false;
            }
        });
        if (!previewElement) return;
        let modalId = 'myModal' + fileInfo.fileKey;
        let tabId = 'myTab' + fileInfo.fileKey;
        let tabContentId = 'tab-content' + fileInfo.fileKey;
        let $button = $('<button type="button" class="btn btn-default" data-toggle="modal" data-target="#' + modalId + '"><span class="fa fa-search"></span></button>');
        let myModal =
            '<style type="text/css">td{word-break: keep-all;white-space:nowrap;}</style>' +
            '<div class="modal fade tab-pane active modal-fullscreen" id="' + modalId + '" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">' +
            '<div class="modal-dialog modal-dialog-scrollable" role="document">' +
            '<div class="modal-content">' +
            '<div class="modal-header">' +
            '<h5 class="modal-title">' + fileInfo.name + '</h5>' +
            '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
            '<span aria-hidden="true">&times;</span>' +
            '</button>' +
            '</div>' +
            '<div>'+
            '<ul class="nav nav-tabs" id=' + tabId + '>' +
            '</ul>' +
            '</div>' +
            '<div id=' + tabContentId + ' class="tab-content">' +
            '<div class="d-flex justify-content-center">' +
            '<div class="spinner-border" role="status">' +
            '<span class="sr-only">Loading...</span>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '</div>';
        previewElement.append($button);
        $('body').prepend(myModal);
        $('#' + modalId).on('shown.bs.modal', function (e) {
            loadRemoteFile(fileInfo);
        })
    }

和kintone的结合

绑定kintone事件

    kintone.events.on('app.record.detail.show', function (event) {
        let record = event.record;
        for (let index in record) {
            let field = record[index];
            if (field.type === "FILE") {
                let fieldValue = field.value;
                fieldValue.forEach(function (file) {
                    if (checkXls(file.name)) {
                        loadModal(file);
                    }
                })
            }
        }
    });

做成kintone插件

如果你还不了解插件开发,请先参考 kintone 插件开发流程

因为本范例没有用到插件的设置画面,所以插件的开发比较简单,只需要设置好manifest.json,然后打包即可

manifest.json

{
  "manifest_version": 1,
  "version": 1,
  "type": "APP",
  "homepage_url": { 
    "zh": "https://cybozudev.kf5.com/hc"
  },
  "desktop": {
    "js": [
      "https://js.cybozu.cn/jquery/3.4.1/jquery.min.js",
      "https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js",
      "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.1/xlsx.full.min.js",
      "js/excelPreview.js"
    ],
    "css": [
      "https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css",
      "https://js.cybozu.cn/font-awesome/v4.7.0/css/font-awesome.min.css"
    ]
  },
  "icon": "image/excelPreview.png",
  "name": {
    "en": "excelPreview",
    "ja": "excelPreview",
    "zh": "excelPreview"
  },
  "description": {
    "en": "Excel Preview",
    "ja": "Excel Preview",
    "zh": "Excel Preview"
  },
  "mobile": {
    "js": [
      "https://js.cybozu.cn/jquery/3.4.1/jquery.min.js",
      "https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/js/bootstrap.min.js",
      "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.1/xlsx.full.min.js",
      "js/excelPreviewMobile.js"
    ],
    "css": [
      "https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css",
      "https://js.cybozu.cn/font-awesome/v4.7.0/css/font-awesome.min.css",
      "css/bootstrap-fs-modal.min.css"
    ]
  }
}

使用

安装后,只有Excel的文件后面会有预览标识,其他文件不会出现预览图标。

代码下载

源码

注意事项

  • 本示例代码不保证其运行。

  • 我们不为本示例代码提供技术支持。