Greasy Fork

Greasy Fork is available in English.

浮动上传按钮(支持Excel解析和JSON导出,并附带帮助函数)

在任意网站添加一个可移动的上传按钮,支持上传并解析Excel文件,以及将JSON数据保存为Excel文件,并提供帮助函数

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         浮动上传按钮(支持Excel解析和JSON导出,并附带帮助函数)
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  在任意网站添加一个可移动的上传按钮,支持上传并解析Excel文件,以及将JSON数据保存为Excel文件,并提供帮助函数
// @author       你的名字
// @match        *://*/*
// @license      MIT
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// ==/UserScript==

(function() {
    'use strict';

    // 创建上传按钮
    const uploadButton = document.createElement('div');
    uploadButton.style.width = '50px';
    uploadButton.style.height = '50px';
    uploadButton.style.backgroundColor = '#FF5722';
    uploadButton.style.position = 'fixed';
    uploadButton.style.right = '20px';
    uploadButton.style.top = '50%';
    uploadButton.style.transform = 'translateY(-50%)';
    uploadButton.style.cursor = 'move';
    uploadButton.style.zIndex = '10000';
    uploadButton.style.display = 'flex';
    uploadButton.style.justifyContent = 'center';
    uploadButton.style.alignItems = 'center';
    uploadButton.style.borderRadius = '8px';
    uploadButton.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
    uploadButton.title = '点击上传Excel文件';

    // 添加上传图标或文字
    uploadButton.innerHTML = '📁';

    document.body.appendChild(uploadButton);

    // 创建隐藏的文件输入
    const fileInput = document.createElement('input');
    fileInput.type = 'file';
    fileInput.accept = '.xlsx, .xls';
    fileInput.style.display = 'none';
    document.body.appendChild(fileInput);

    // 点击按钮触发文件选择
    uploadButton.addEventListener('click', function(e) {
        // 阻止拖动时触发点击事件
        if (e.target === uploadButton) {
            fileInput.click();
        }
    });

    // 文件选择后处理
    fileInput.addEventListener('change', function() {
        const files = fileInput.files;
        if (files.length > 0) {
            const file = files[0];
            const fileName = file.name;
            const fileExtension = fileName.split('.').pop().toLowerCase();
            const allowedExtensions = ['xlsx', 'xls'];

            if (!allowedExtensions.includes(fileExtension)) {
                console.warn('上传的文件不是Excel文件。');
                // 可选:显示提示信息
                // alert('请上传Excel文件(.xlsx 或 .xls)。');
                return;
            }

            const reader = new FileReader();
            reader.onload = function(e) {
                try {
                    const data = new Uint8Array(e.target.result);
                    const workbook = XLSX.read(data, {type: 'array'});

                    const jsonData = {};

                    workbook.SheetNames.forEach(function(sheetName) {
                        const roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {header:1});
                        if(roa.length) jsonData[sheetName] = roa;
                    });

                    console.log('解析后的Excel JSON数据:', jsonData);
                } catch (error) {
                    console.error('解析Excel文件时出错:', error);
                }
            };

            reader.onerror = function(error) {
                console.error('读取文件时出错:', error);
            };

            reader.readAsArrayBuffer(file);
        }
        // 清除选择
        fileInput.value = '';
    });

    // 实现拖动功能
    let isDragging = false;
    let offsetX, offsetY;

    uploadButton.addEventListener('mousedown', function(e) {
        isDragging = true;
        const rect = uploadButton.getBoundingClientRect();
        offsetX = e.clientX - rect.left;
        offsetY = e.clientY - rect.top;
        document.body.style.userSelect = 'none'; // 禁止文本选择
    });

    document.addEventListener('mousemove', function(e) {
        if (isDragging) {
            let newX = e.clientX - offsetX;
            let newY = e.clientY - offsetY;

            // 限制在视口内
            const maxX = window.innerWidth - uploadButton.offsetWidth;
            const maxY = window.innerHeight - uploadButton.offsetHeight;

            newX = Math.max(0, Math.min(newX, maxX));
            newY = Math.max(0, Math.min(newY, maxY));

            uploadButton.style.left = `${newX}px`;
            uploadButton.style.top = `${newY}px`;
            uploadButton.style.right = 'auto';
            uploadButton.style.transform = 'none';
        }
    });

    document.addEventListener('mouseup', function() {
        if (isDragging) {
            isDragging = false;
            document.body.style.userSelect = 'auto'; // 恢复文本选择
        }
    });

    // 全局函数:将JSON保存为Excel文件
    window.jsonToExcel = function(jsonData) {
        if (typeof jsonData !== 'object' || jsonData === null) {
            console.error('传入的参数必须是一个有效的JSON对象。');
            return;
        }

        const filename = prompt('请输入要保存的Excel文件名(不需要扩展名):', 'data');
        if (!filename) {
            console.warn('未输入文件名,操作取消。');
            return;
        }

        const workbook = XLSX.utils.book_new();

        try {
            for (const sheetName in jsonData) {
                if (Object.prototype.hasOwnProperty.call(jsonData, sheetName)) {
                    const sheetData = jsonData[sheetName];
                    let worksheet;

                    // 判断sheetData是数组的数组还是数组的对象
                    if (Array.isArray(sheetData) && sheetData.length > 0 && Array.isArray(sheetData[0])) {
                        // 数组的数组
                        worksheet = XLSX.utils.aoa_to_sheet(sheetData);
                    } else if (Array.isArray(sheetData) && sheetData.length > 0 && typeof sheetData[0] === 'object') {
                        // 数组的对象
                        worksheet = XLSX.utils.json_to_sheet(sheetData);
                    } else {
                        console.warn(`工作表 "${sheetName}" 的数据格式不支持。`);
                        continue;
                    }

                    XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
                }
            }

            const wbout = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});

            const blob = new Blob([wbout], {type: 'application/octet-stream'});

            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = `${filename}.xlsx`;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);

            console.log(`Excel文件 "${filename}.xlsx" 已生成并下载。`);
        } catch (error) {
            console.error('将JSON保存为Excel时出错:', error);
        }
    };

    // 全局函数:帮助函数,展示使用示例
    window.help = function() {
        console.log('%c=== 浮动上传按钮脚本使用帮助 ===', 'color: green; font-weight: bold;');

        console.group('上传Excel文件并查看JSON输出');
        console.log('1. 点击页面右侧中间的 📁 按钮,选择一个Excel文件(.xlsx 或 .xls)。');
        console.log('2. 上传成功后,解析后的JSON数据会输出到控制台。');
        console.log('   示例输出:');
        console.log('%c解析后的Excel JSON数据:', 'color: blue; font-weight: bold;');
        console.log({
            "Sheet1": [
                ["姓名", "年龄", "城市"],
                ["张三", 28, "北京"],
                ["李四", 34, "上海"],
                ["王五", 23, "广州"]
            ],
            "Sheet2": [
                { "产品": "手机", "价格": 5000 },
                { "产品": "电脑", "价格": 8000 },
                { "产品": "平板", "价格": 3000 }
            ]
        });
        console.groupEnd();

        console.group('将JSON对象保存为Excel文件');
        console.log('1. 在控制台中定义一个JSON对象,结构如下:');
        console.log(`const myData = {
    "Sheet1": [
        ["姓名", "年龄", "城市"],
        ["张三", 28, "北京"],
        ["李四", 34, "上海"],
        ["王五", 23, "广州"]
    ],
    "Sheet2": [
        { "产品": "手机", "价格": 5000 },
        { "产品": "电脑", "价格": 8000 },
        { "产品": "平板", "价格": 3000 }
    ]
};`);
        console.log('2. 调用保存函数:');
        console.log('jsonToExcel(myData);');
        console.log('3. 会弹出提示框,输入文件名(不需要扩展名),例如 "我的数据"。');
        console.log('4. 浏览器将自动下载 "我的数据.xlsx" 文件,包含两个工作表 "Sheet1" 和 "Sheet2"。');
        console.groupEnd();

        console.log('%c=== 结束帮助 ===', 'color: green; font-weight: bold;');
    };

})();