原生js导入表格并导出

179 阅读1分钟

遇到一个小需求,把火星坐标系转换为wgs84坐标系,给的是一个表格,要求转换完以后导出一个表格,导出导入利用了一个插件xlsx.full.min.js直接npm下载就行

文件导入

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>导入文件并处理格式</title>
    <script src="./xlsx.full.min.js"></script>
</head>

<body>
    <div class="demofile"> <input type="file" onchange="importf(this)" /></div>

    <button>跳转到导出</button>
    <div id="demo"></div>
    <script>
        var rABS = false; //是否将文件读取为二进制字符串
        function importf(obj) {//导入
            if (!obj.files) { return; }
            var f = obj.files[0];
            {
                var reader = new FileReader();
                var name = f.name;
                reader.onload = function (e) {
                    var data = e.target.result;
                    var wb;
                    if (rABS) {
                        wb = XLSX.read(data, { type: 'binary' });
                    } else {
                        var arr = fixdata(data);
                        wb = XLSX.read(btoa(arr), { type: 'base64' });
                    }
                    document.getElementById("demo").innerHTML = JSON.stringify(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]));
                    localStorage.setItem("datas", JSON.stringify(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])));
                };
                if (rABS) reader.readAsBinaryString(f);
                else reader.readAsArrayBuffer(f);
            }
            setTimeout(() => {
                window.location.reload()
            }, 2000);
        }
        function fixdata(data) {
            var o = "", l = 0, w = 10240;
            for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)));
            o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));
            return o;
        }
        var lon = 0;
        var lat = 0;
        var jsono = JSON.parse(localStorage.getItem("datas"));
        var qq = jsono.map(item => {
            var pi = 3.14159265358979324;
            function transformLat(x, y) {
                var ret =
                    -100.0 +
                    2.0 * x +
                    3.0 * y +
                    0.2 * y * y +
                    0.1 * x * y +
                    0.2 * Math.sqrt(Math.abs(x));
                ret +=
                    ((20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0) /
                    3.0;
                ret +=
                    ((20.0 * Math.sin(y * pi) + 40.0 * Math.sin((y / 3.0) * pi)) * 2.0) / 3.0;
                ret +=
                    ((160.0 * Math.sin((y / 12.0) * pi) + 320 * Math.sin((y * pi) / 30.0)) *
                        2.0) /
                    3.0;
                return ret;
            }
            function transformLon(x, y) {
                var ret =
                    300.0 +
                    x +
                    2.0 * y +
                    0.1 * x * x +
                    0.1 * x * y +
                    0.1 * Math.sqrt(Math.abs(x));
                ret +=
                    ((20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0) /
                    3.0;
                ret +=
                    ((20.0 * Math.sin(x * pi) + 40.0 * Math.sin((x / 3.0) * pi)) * 2.0) / 3.0;
                ret +=
                    ((150.0 * Math.sin((x / 12.0) * pi) + 300.0 * Math.sin((x / 30.0) * pi)) *
                        2.0) /
                    3.0;
                return ret;
            }
            function delta(lat, lon) {
                let a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
                let ee = 0.00669342162296594323; //  ee: 椭球的偏心率。
                let dLat = transformLat(lon - 105.0, lat - 35.0);
                let dLon = transformLon(lon - 105.0, lat - 35.0);
                let radLat = (lat / 180.0) * pi;
                let magic = Math.sin(radLat);
                magic = 1 - ee * magic * magic;
                let sqrtMagic = Math.sqrt(magic);
                dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * pi);
                dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * pi);
                return {
                    lat: dLat,
                    lon: dLon,
                };
            }
            function transformGCJ2WGS(item) {
            //这里的lat,与lon是我表格里面固定的俩列的表头,要处理就是他俩
                const gcjLat = item.lat;
                const gcjLon = item.lon;
                let d = delta(gcjLat, gcjLon);
                lat = gcjLat - d.lat
                lon = gcjLon - d.lon
                return {
                    lat: gcjLat - d.lat,
                    lng: gcjLon - d.lon,
                };
            }
            // console.log(transformGCJ2WGS(item));
            // console.log(lat, lon);
            item.lat = transformGCJ2WGS(item).lat.toFixed(8);
            item.lon = transformGCJ2WGS(item).lng.toFixed(8);
            return item;
        });
        // console.log(qq);
        // localStorage.setItem("datass", qq);
        document.querySelector('button').addEventListener('click', function (e) {
            localStorage.setItem('d', JSON.stringify(qq));
            window.location.reload()
            window.location.href = './导出文件.html';
            localStorage.removeItem('datas')

        });
        localStorage.removeItem('d')

    </script>
</body>

</html>

文件导出

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>导出文件</title>
    <script src="./xlsx.full.min.js"></script>
    <style>
        .daochu {
            height: 50px;
            width: 80px;
        }

        div {
            display: flex;
            justify-content: space-between;
        }
    </style>
</head>

<body>
    <div>
        <button class="daochu" onclick="downloadExl(jsono)">导出</button>
        <button class="back">返回到导入</button>
    </div>

    <!--
            以下a标签不需要内容
        -->
    <a href="" download="导出的文件.xlsx" id="hf"></a>
    <script>
        var jsono = JSON.parse(localStorage.getItem('d'));
        var jsonolength = jsono.length;
        var tmpDown; //导出的二进制对象
        function downloadExl(json, type) {
            var tmpdata = json[0];
            if (json.length <= jsonolength) {
                json.unshift({});
            }
            var keyMap = []; //获取keys
            //keyMap =Object.keys(json[0]);
            for (var k in tmpdata) {
                keyMap.push(k);
                json[0][k] = k;
            }
            var tmpdata = [];//用来保存转换好的json 
            json.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
                v: v[k],
                position: (j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
            }))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
                v: v.v
            });
            var outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
            var tmpWB = {
                SheetNames: ['mySheet'], //保存的表标题
                Sheets: {
                    'mySheet': Object.assign({},
                        tmpdata, //内容
                        {
                            '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //设置填充区域
                        })
                }
            };
            tmpDown = new Blob([s2ab(XLSX.write(tmpWB,
                { bookType: (type == undefined ? 'xlsx' : type), bookSST: false, type: 'binary' }//这里的数据是用来定义导出的格式类型
            ))], {
                type: ""
            }); //创建二进制对象写入转换好的字节流
            var href = URL.createObjectURL(tmpDown); //创建对象超链接
            document.getElementById("hf").href = href; //绑定a标签
            document.getElementById("hf").click(); //模拟点击实现下载
            setTimeout(function () { //延时释放
                URL.revokeObjectURL(tmpDown); //用URL.revokeObjectURL()来释放这个object URL
            }, 100);
        }

        function s2ab(s) { //字符串转字符流
            var buf = new ArrayBuffer(s.length);
            var view = new Uint8Array(buf);
            for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
            return buf;
        }
        // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
        function getCharCol(n) {
            let temCol = '',
                s = '',
                m = 0
            while (n > 0) {
                m = n % 26 + 1
                s = String.fromCharCode(m + 64) + s
                n = (n - m) / 26
            }
            return s
        }
        document.querySelector('.back').addEventListener('click', function () {
            window.location.href = './导入文件.html';
        })
    </script>
</body>

</html>