国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

徹底理解使用JavaScript 將Json數(shù)據(jù)導(dǎo)出CSV文件

hyuan / 3196人閱讀

摘要:前言將數(shù)據(jù)報表導(dǎo)出,是數(shù)據(jù)報告展示常用的附帶功能。今天我們主要講的是直接通過前端將數(shù)據(jù)導(dǎo)出的格式的文件。但其實真正的答案應(yīng)該是把相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成和。若是超過瀏覽器自身限制的最大長度,會導(dǎo)致下載失敗。

前言

將數(shù)據(jù)報表導(dǎo)出,是web數(shù)據(jù)報告展示常用的附帶功能。通常這種功能都是用后端開發(fā)人員編寫的。今天我們主要講的是直接通過前端js將數(shù)據(jù)導(dǎo)出Excel的CSV格式的文件。

原理

首先在本地用Excel新建一個test.csv的文件 ===> 隨便填寫一些數(shù)據(jù),保存并用Safari瀏覽打開該文件 ===> 打開瀏覽器的開發(fā)者工具,執(zhí)行JSON.stringify(document.body.innerText);,我們得到結(jié)果如下圖:

從圖中,可以看出:

CSV文件格式單元格之間是通過,隔開的

CSV文件格式里,換行是通過 實現(xiàn)的

從上面兩條結(jié)論,我們只有把相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成, 就可以了。但其實真正的答案應(yīng)該是把相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成,
為什么會這樣?且讓我一一道來:
我們在編輯Excel文件時,當(dāng)編輯完成當(dāng)前單元格時,想要編輯下一行緊挨著的單元格,按一下Enter鍵就可以。而Enter鍵在js字符串中是用 表示的。那是不是吧 替換成 就可以了呢?
其實不可以,因為涉及到操作系統(tǒng)的問題:

在Windows系統(tǒng)中,標(biāo)準(zhǔn)模式采用的是 匹配Enter

在mac系統(tǒng)中,用 匹配Enter

在Linux系統(tǒng)中,用 匹配Enter

所以,最最最最終終終的結(jié)論是:

將相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成, ,即:名稱,熟練 張三,2

由于單元格之間使用,隔開,所以不支持單元格的合并行、合并列,其實這句話有點多余,CSV格式的文件本身就不支持單元格的合并列和行

實現(xiàn)方式

在編寫代碼之前,我們先來看一下具體數(shù)據(jù)和樣式。假如當(dāng)前的JSON數(shù)據(jù)是這樣的

[
    {name: "張三", amont: "323433.56", proportion: 33.4},
    {name: "李四", amont: "545234.43", proportion: 55.45}
]

數(shù)據(jù)報告展示樣式如下:

姓名 金額 占比
張三 323,433.56 33.40%
李四 545,234.43 55.45%

那如何使得導(dǎo)出的數(shù)據(jù)與展示的保持一致呢?
答案是:

把要展示的表頭文字也進(jìn)行處理

遍歷取對應(yīng)的key值

設(shè)置formatter回調(diào)處理的當(dāng)前值的函數(shù)

由此我們得到如下代碼:

var JSonToCSV = {
  /*
   * obj是一個對象,其中包含有:
   * ## data 是導(dǎo)出的具體數(shù)據(jù)
   * ## fileName 是導(dǎo)出時保存的文件名稱 是string格式
   * ## showLabel 表示是否顯示表頭 默認(rèn)顯示 是布爾格式
   * ## columns 是表頭對象,且title和key必須一一對應(yīng),包含有
        title:[], // 表頭展示的文字
        key:[], // 獲取數(shù)據(jù)的Key
        formatter: function() // 自定義設(shè)置當(dāng)前數(shù)據(jù)的 傳入(key, value)
   */
  setDataConver: function(obj) {
    var data = obj["data"],
        ShowLabel = typeof obj["showLabel"] === "undefined" ? true : obj["showLabel"],
        fileName = (obj["fileName"] || "UserExport") + ".csv",
        columns = obj["columns"] || {
            title: [],
            key: [],
            formatter: undefined
        };
    var ShowLabel = typeof ShowLabel === "undefined" ? true : ShowLabel;
    var row = "", CSV = "", key;
    // 如果要現(xiàn)實表頭文字
    if (ShowLabel) {
        // 如果有傳入自定義的表頭文字
        if (columns.title.length) {
            columns.title.map(function(n) {
                row += n + ",";
            });
        } else {
            // 如果沒有,就直接取數(shù)據(jù)第一條的對象的屬性
            for (key in data[0]) row += key + ",";
        }
        row = row.slice(0, -1); // 刪除最后一個,號,即a,b, => a,b
        CSV += row + "
"; // 添加換行符號
    }
    // 具體的數(shù)據(jù)處理
    data.map(function(n) {
        row = "";
        // 如果存在自定義key值
        if (columns.key.length) {
            columns.key.map(function(m) {
                row += """ + (typeof columns.formatter === "function" ? columns.formatter(m, n[m]) || n[m] : n[m]) + "",";
            });
        } else {
            for (key in n) {
                row += """ + (typeof columns.formatter === "function" ? columns.formatter(key, n[key]) || n[key] : n[key]) + "",";
            }
        }
        row.slice(0, row.length - 1); // 刪除最后一個,
        CSV += row + "
"; // 添加換行符號
    });
    if(!CSV) return;
    this.SaveAs(fileName, CSV);
  },
  SaveAs: function(fileName, csvData) {
    // console.log(fileName, csvData);
  }
};

然后我們分別測試了如下數(shù)據(jù):

JSonToCSV.setDataConver({
  data: [
    {name: "張三", amont: "323433.56", proportion: 33.4},
    {name: "李四", amont: "545234.43", proportion: 55.45}
  ],
  fileName: "test",
  columns: {
    title: ["姓名", "金額", "占比"],
    key: ["name", "amont", "proportion"],
    formatter: function(n, v) {
      if(n === "amont" && !isNaN(Number(v))) {
        v = v + "";
        v = v.split(".");
        v[0] = v[0].replace(/(d)(?=(?:d{3})+$)/g, "$1,"); // 千分位的設(shè)置
         return v.join(".");
      }
      if(n === "proportion") return v + "%";
    }
  }
});

到此,數(shù)據(jù)轉(zhuǎn)換完畢

下載方式

由于瀏覽器之間的差異,尤其是IE,所以不同的瀏覽器下載的方式也不一樣,如Chrome和Firefox都支持a標(biāo)簽設(shè)置download屬性和href值,然后調(diào)用aclick方法即可下載,IE既不支持adownload屬性也不允許調(diào)用aclick方法。代碼如下:

var a = document.querySelector("a");
a.click(); // 在這里 IE是拒絕執(zhí)行的,會提示權(quán)限問題

那么對于支持a的download屬性的,直接設(shè)置download屬性值和href值,具體代碼如下:

Chrome、Firefox等瀏覽器的的下載方式
SaveAs: function(fileName, csvData) {
    var bw = this.browser();
    if(!bw["edge"] ||  !bw["ie"]) {
      var alink = document.createElement("a");
      alink.id = "linkDwnldLink";
      alink.href = this.getDownloadUrl(csvData);
      document.body.appendChild(alink);
      var linkDom = document.getElementById("linkDwnldLink");
      linkDom.setAttribute("download", fileName);
      linkDom.click();
      document.body.removeChild(linkDom);
    }
  },
  getDownloadUrl: function(csvData) {
    var _utf = "uFEFF"; // 為了使Excel以utf-8的編碼模式,同時也是解決中文亂碼的問題
    return "data:attachment/csv;charset=utf-8," + _utf + encodeURIComponent(csvData);
  },
  browser: function() {
    var Sys = {};
    var ua = navigator.userAgent.toLowerCase();
    var s;
    (s = ua.indexOf("edge") !== - 1 ? Sys.edge = "edge" : ua.match(/rv:([d.]+)) like gecko/)) ? Sys.ie = s[1]:
        (s = ua.match(/msie ([d.]+)/)) ? Sys.ie = s[1] :
        (s = ua.match(/firefox/([d.]+)/)) ? Sys.firefox = s[1] :
        (s = ua.match(/chrome/([d.]+)/)) ? Sys.chrome = s[1] :
        (s = ua.match(/opera.([d.]+)/)) ? Sys.opera = s[1] :
        (s = ua.match(/version/([d.]+).*safari/)) ? Sys.safari = s[1] : 0;
    return Sys;
  }

雖然看起來是可以了,但還是有問題。什么問題呢?
就是當(dāng)數(shù)據(jù)量大的時候,比如幾千條甚至幾萬條,在數(shù)據(jù)轉(zhuǎn)換的時候,href的數(shù)值自然也就長了。若是超過瀏覽器自身限制的最大長度,會導(dǎo)致下載失敗。具體每個瀏覽器之前URL最大長度限制如下(HTTP協(xié)議并沒有限制URL的長度):

瀏覽器 最大長度(字符數(shù)) 備注
IE 2083 如果超過這個數(shù)字,提交按鈕沒有任何反應(yīng)
Firefox 65,536 -
Chrome 8,182 -
Safari 80,000 -
Opera 190,000 -

所以我們這里借助 Blob(Blob傳送門)來將轉(zhuǎn)換好的數(shù)據(jù)進(jìn)行處理,代碼如下:

getDownloadUrl: function(csvData) {
    var _utf = "uFEFF"; // 為了使Excel以utf-8的編碼模式,同時也是解決中文亂碼的問題
    if (window.Blob && window.URL && window.URL.createObjectURL) {
        var csvData = new Blob([_utf + csvData], {
            type: "text/csv"
        });
        return URL.createObjectURL(csvData);
    }
    // return "data:attachment/csv;charset=utf-8," + _utf + encodeURIComponent(csvData);
  }

我們在查看href值為:blob:http://127.0.0.1:3000/9715ca8a-bb9a-4b0c-8546-9bd13e8f0b69
這樣不管幾萬條還是幾十萬條數(shù)據(jù)都可以下載的
這里涉及到的知識點:encodeURIComponent、URL.createObjectURL
到這里,Chrome、Firefox等瀏覽器解決了。

IE10~Edge瀏覽的下載方式

IE10~Edge等瀏覽器調(diào)用windows.navigator.msSaveBlob實現(xiàn)保存文件,msSaveBlob是IE10~Edge的私有方法。
所以SaveAs代碼改寫如下:

SaveAs: function(fileName, csvData) {
    var bw = this.browser();
    if(!bw["edge"] || !bw["ie"]) {
      var alink = document.createElement("a");
      alink.id = "linkDwnldLink";
      alink.href = this.getDownloadUrl(csvData);
      document.body.appendChild(alink);
      var linkDom = document.getElementById("linkDwnldLink");
      linkDom.setAttribute("download", fileName);
      linkDom.click();
      document.body.removeChild(linkDom);
    }
    else if(bw["ie"] >= 10 || bw["edge"] == "edge") {
      var _utf = "uFEFF";
      var _csvData = new Blob([_utf + csvData], {
          type: "text/csv"
      });
      navigator.msSaveBlob(_csvData, fileName);
    }
  }
IE9下載方式

IE9使用execCommand方法來保存csv文件,SaveAs改寫如下:

SaveAs: function(fileName, csvData) {
    var bw = this.browser();
    if(!bw["edge"] || !bw["ie"]) {
      var alink = document.createElement("a");
      alink.id = "linkDwnldLink";
      alink.href = this.getDownloadUrl(csvData);
      document.body.appendChild(alink);
      var linkDom = document.getElementById("linkDwnldLink");
      linkDom.setAttribute("download", fileName);
      linkDom.click();
      document.body.removeChild(linkDom);
    }
    else if(bw["ie"] >= 10 || bw["edge"] == "edge") {
      var _utf = "uFEFF";
      var _csvData = new Blob([_utf + csvData], {
          type: "text/csv"
      });
      navigator.msSaveBlob(_csvData, fileName);
    }
    else {
      var oWin = window.top.open("about:blank", "_blank");
      oWin.document.write("sep=,
" + csvData);
      oWin.document.close();
      oWin.document.execCommand("SaveAs", true, fileName);
      oWin.close();
    }
  }

所以最終代碼整體如下(也可以訪問我的GitHub下載最新的js文件):

var JSonToCSV = {
  /*
   * obj是一個對象,其中包含有:
   * ## data 是導(dǎo)出的具體數(shù)據(jù)
   * ## fileName 是導(dǎo)出時保存的文件名稱 是string格式
   * ## showLabel 表示是否顯示表頭 默認(rèn)顯示 是布爾格式
   * ## columns 是表頭對象,且title和key必須一一對應(yīng),包含有
        title:[], // 表頭展示的文字
        key:[], // 獲取數(shù)據(jù)的Key
        formatter: function() // 自定義設(shè)置當(dāng)前數(shù)據(jù)的 傳入(key, value)
   */
  setDataConver: function(obj) {
    var bw = this.browser();
    if(bw["ie"] < 9) return; // IE9以下的
    var data = obj["data"],
        ShowLabel = typeof obj["showLabel"] === "undefined" ? true : obj["showLabel"],
        fileName = (obj["fileName"] || "UserExport") + ".csv",
        columns = obj["columns"] || {
            title: [],
            key: [],
            formatter: undefined
        };
    var ShowLabel = typeof ShowLabel === "undefined" ? true : ShowLabel;
    var row = "", CSV = "", key;
    // 如果要現(xiàn)實表頭文字
    if (ShowLabel) {
        // 如果有傳入自定義的表頭文字
        if (columns.title.length) {
            columns.title.map(function(n) {
                row += n + ",";
            });
        } else {
            // 如果沒有,就直接取數(shù)據(jù)第一條的對象的屬性
            for (key in data[0]) row += key + ",";
        }
        row = row.slice(0, -1); // 刪除最后一個,號,即a,b, => a,b
        CSV += row + "
"; // 添加換行符號
    }
    // 具體的數(shù)據(jù)處理
    data.map(function(n) {
        row = "";
        // 如果存在自定義key值
        if (columns.key.length) {
            columns.key.map(function(m) {
                row += """ + (typeof columns.formatter === "function" ? columns.formatter(m, n[m]) || n[m] : n[m]) + "",";
            });
        } else {
            for (key in n) {
                row += """ + (typeof columns.formatter === "function" ? columns.formatter(key, n[key]) || n[key] : n[key]) + "",";
            }
        }
        row.slice(0, row.length - 1); // 刪除最后一個,
        CSV += row + "
"; // 添加換行符號
    });
    if(!CSV) return;
    this.SaveAs(fileName, CSV);
  },
  SaveAs: function(fileName, csvData) {
    var bw = this.browser();
    if(!bw["edge"] || !bw["ie"]) {
      var alink = document.createElement("a");
      alink.id = "linkDwnldLink";
      alink.href = this.getDownloadUrl(csvData);
      document.body.appendChild(alink);
      var linkDom = document.getElementById("linkDwnldLink");
      linkDom.setAttribute("download", fileName);
      linkDom.click();
      document.body.removeChild(linkDom);
    }
    else if(bw["ie"] >= 10 || bw["edge"] == "edge") {
      var _utf = "uFEFF";
      var _csvData = new Blob([_utf + csvData], {
          type: "text/csv"
      });
      navigator.msSaveBlob(_csvData, fileName);
    }
    else {
      var oWin = window.top.open("about:blank", "_blank");
      oWin.document.write("sep=,
" + csvData);
      oWin.document.close();
      oWin.document.execCommand("SaveAs", true, fileName);
      oWin.close();
    }
  },
  getDownloadUrl: function(csvData) {
    var _utf = "uFEFF"; // 為了使Excel以utf-8的編碼模式,同時也是解決中文亂碼的問題
    if (window.Blob && window.URL && window.URL.createObjectURL) {
        var csvData = new Blob([_utf + csvData], {
            type: "text/csv"
        });
        return URL.createObjectURL(csvData);
    }
    // return "data:attachment/csv;charset=utf-8," + _utf + encodeURIComponent(csvData);
  },
  browser: function() {
    var Sys = {};
    var ua = navigator.userAgent.toLowerCase();
    var s;
    (s = ua.indexOf("edge") !== - 1 ? Sys.edge = "edge" : ua.match(/rv:([d.]+)) like gecko/)) ? Sys.ie = s[1]:
        (s = ua.match(/msie ([d.]+)/)) ? Sys.ie = s[1] :
        (s = ua.match(/firefox/([d.]+)/)) ? Sys.firefox = s[1] :
        (s = ua.match(/chrome/([d.]+)/)) ? Sys.chrome = s[1] :
        (s = ua.match(/opera.([d.]+)/)) ? Sys.opera = s[1] :
        (s = ua.match(/version/([d.]+).*safari/)) ? Sys.safari = s[1] : 0;
    return Sys;
  }
};
// 測試
JSonToCSV.setDataConver({
  data: [
    {name: "張三", amont: "323433.56", proportion: 33.4},
    {name: "李四", amont: "545234.43", proportion: 55.45}
  ],
  fileName: "test",
  columns: {
    title: ["姓名", "金額", "占比"],
    key: ["name", "amont", "proportion"],
    formatter: function(n, v) {
      if(n === "amont" && !isNaN(Number(v))) {
        v = v + "";
        v = v.split(".");
        v[0] = v[0].replace(/(d)(?=(?:d{3})+$)/g, "$1,");
         return v.join(".");
      }
      if(n === "proportion") return v + "%";
    }
  }
});

也可以訪問我的GitHub下載最新的js文件

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/88758.html

相關(guān)文章

  • 徹底理解使用JavaScript Json數(shù)據(jù)導(dǎo)出CSV文件

    摘要:前言將數(shù)據(jù)報表導(dǎo)出,是數(shù)據(jù)報告展示常用的附帶功能。今天我們主要講的是直接通過前端將數(shù)據(jù)導(dǎo)出的格式的文件。但其實真正的答案應(yīng)該是把相應(yīng)的數(shù)據(jù)轉(zhuǎn)換成和。若是超過瀏覽器自身限制的最大長度,會導(dǎo)致下載失敗。 前言 將數(shù)據(jù)報表導(dǎo)出,是web數(shù)據(jù)報告展示常用的附帶功能。通常這種功能都是用后端開發(fā)人員編寫的。今天我們主要講的是直接通過前端js將數(shù)據(jù)導(dǎo)出Excel的CSV格式的文件。 原理 首先在本地...

    jsliang 評論0 收藏0
  • 如何 JSON, Text, XML, CSV 數(shù)據(jù)文件導(dǎo)入 MySQL

    摘要:舉個例子,要處理的文件或者文件是以作為分隔符的,每行有這么三個數(shù)據(jù)域,那么首先我們需要在數(shù)據(jù)庫中創(chuàng)建這個表創(chuàng)建成功以后就可以導(dǎo)入了。 文/freenik 將外部數(shù)據(jù)導(dǎo)入(import)數(shù)據(jù)庫是在數(shù)據(jù)庫應(yīng)用中一個很常見的需求。其實這就是在數(shù)據(jù)的管理和操作中的ETL (Extract, transform, load)的L (Load)部分,也就是說,將特定結(jié)構(gòu)(structure)或者格...

    崔曉明 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<