Js excel to blob

I have a similar question to this question(Javascript: Exporting large text/csv file crashes Google Chrome):

I am trying to save the data created by excelbuilder.js‘s EB.createFile() function. If I put the file data as the href attribute value of a link, it works. However, when data is big, it crashes Chrome browser. Code are like this:

//generate a temp <a /> tag
var link = document.createElement("a");
link.href = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' + encodeURIComponent(data);
link.style = "visibility:hidden";
link.download = fileName;

document.body.appendChild(link);
link.click();
document.body.removeChild(link);

My code to create the data using excelbuilder.js is like follows:

var artistWorkbook = EB.createWorkbook();
var albumList = artistWorkbook.createWorksheet({name: 'Album List'});

albumList.setData(originalData); 

artistWorkbook.addWorksheet(albumList);

var data = EB.createFile(artistWorkbook);

As suggested by the answer of the similar question (Javascript: Exporting large text/csv file crashes Google Chrome), a blob needs to be created.

My problem is, what is saved in the file isn’t a valid Excel file that can be opened by Excel. The code that I use to save the blob is like this:

var blob = new Blob(
    [data],
    {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,"}
);

// Programatically create a link and click it:
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = fileName;
a.click();

If I replace the [data] in the above code with [Base64.decode(data)], the contents in the file saved looks more like the expected excel data, but still cannot be opened by Excel.

The answer above is correct. Please be sure that you have a string data in base64 in the data variable without any prefix or stuff like that just raw data.

Here’s what I did on the server side (asp.net mvc core):

string path = Path.Combine(folder, fileName);
Byte[] bytes = System.IO.File.ReadAllBytes(path);
string base64 = Convert.ToBase64String(bytes);

On the client side, I did the following code:

const xhr = new XMLHttpRequest();

xhr.open("GET", url);
xhr.setRequestHeader("Content-Type", "text/plain");

xhr.onload = () => {
    var bin = atob(xhr.response);
    var ab = s2ab(bin); // from example above
    var blob = new Blob([ab], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' });

    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = 'demo.xlsx';

    document.body.appendChild(link);

    link.click();

    document.body.removeChild(link);
};

xhr.send();

And it works perfectly for me.

I’ve found a solution worked for me:

const handleDownload = async () => {
   const req = await axios({
     method: "get",
     url: `/companies/${company.id}/data`,
     responseType: "blob",
   });
   var blob = new Blob([req.data], {
     type: req.headers["content-type"],
   });
   const link = document.createElement("a");
   link.href = window.URL.createObjectURL(blob);
   link.download = `report_${new Date().getTime()}.xlsx`;
   link.click();
 };

I just point a responseType: «blob»

I had the same problem as you. It turns out you need to convert the Excel data file to an ArrayBuffer.

var blob = new Blob([s2ab(atob(data))], {
    type: ''
});

href = URL.createObjectURL(blob);

The s2ab (string to array buffer) method (which I got from https://github.com/SheetJS/js-xlsx/blob/master/README.md) is:

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;
}

This works as of: v0.14.0 of https://github.com/SheetJS/js-xlsx

/* generate array buffer */
var wbout = XLSX.write(wb, {type:"array", bookType:'xlsx'});
/* create data URL */
var url = URL.createObjectURL(new Blob([wbout], {type: 'application/octet-stream'}));
/* trigger download with chrome API */
chrome.downloads.download({ url: url, filename: "testsheet.xlsx", saveAs: true });

Preface

Recently, the company needs to export several statistical tables to excel. Because the company’s existing export excel function is front-end and back-end export, it is troublesome, so I want to find a pure front-end export tool, and finally found js-xlsx, which is highly rated, but the Chinese documents were not found, Baidu did not find a more comprehensive one.Tutorial, so I stepped on a lot of pits, I record them for future use.

Environmental Science

Since my business only uses exporting the contents of a table tag to excel, I only write how to export the contents of a table element to excel.It can also be exported through json, which seems simpler.

install

GitHub address
npm installation

npm install xlsx

After installation, there is a file named xlsx.full.min.js under the dist folder, which was introduced into the project

First example

Code first

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <table id="table1" border="1" cellspacing="0" cellpadding="0" >
        <thead>
            <tr>
                <td>Sequence Number</td>
                <td>Full name</td>
                <td>Age</td>
                <td>Interest</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>Zhang San</td>
                <td>18</td>
                <td>Play games</td>
            </tr>
            <tr>
                <td>2</td>
                <td>Li Si</td>
                <td>88</td>
                <td>Watch movie</td>
            </tr>
            <tr>
                <td>3</td>
                <td>King Five</td>
                <td>81</td>
                <td>Sleep</td>
            </tr>
        </tbody>
    </table>

    <button id="btn" onclick="btn_export()">export</button>
</body>
<script src="js/xlsx.full.min.js"></script>
<script src="js/export.js"></script>
<script>
    function btn_export() {
        var table1 = document.querySelector("#table1");
        var sheet = XLSX.utils.table_to_sheet(table1);//Convert a table object to a sheet object
        openDownloadDialog(sheet2blob(sheet),'download.xlsx');
    }
</script>
</html>

Running effect

Export results:


As you may notice, I’ve introduced an export.js file here. There are only two methods in this export.js file: openDownload Dialog (sheet2blob,’download.xlsx’), which is used in the code above.
This is the code for export.js:

// Turn a sheet into a blob object for the final excel file and download it using the URL.createObjectURL
function sheet2blob(sheet, sheetName) {
    sheetName = sheetName || 'sheet1';
    var workbook = {
        SheetNames: [sheetName],
        Sheets: {}
    };
    workbook.Sheets[sheetName] = sheet; // Generate excel configuration items

    var wopts = {
        bookType: 'xlsx', // File type to generate
        bookSST: false, // Whether to generate Shared String Table or not, the official explanation is that the build speed will decrease if turned on, but there is better compatibility on lower version IOS devices
        type: 'binary'
    };
    var wbout = XLSX.write(workbook, wopts);
    var blob = new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    }); // String to ArrayBuffer
    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;
    }
    return blob;
}

function openDownloadDialog(url, saveName) {
    if (typeof url == 'object' && url instanceof Blob) {
        url = URL.createObjectURL(url); // Create a blob address
    }
    var aLink = document.createElement('a');
    aLink.href = url;
    aLink.download = saveName || ''; // HTML5 new property, specify save file name, may not suffix, note that file:///mode will not take effect
    var event;
    if (window.MouseEvent) event = new MouseEvent('click');
    else {
        event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    }
    aLink.dispatchEvent(event);
}

PS: These two methods are online. Original Address .The author writes very well and finds clues here as well.

If your table tag contains operations to merge cells, XLSX.utils.table_to_sheet(*) can also be read, and the results you print can also be displayed, image:


As you can see, the tables in excel have also been merged.
But in reality, if the customer feels that the line is not centered, he will talk to you about not centering anything, so we’ll solve the problem of not centering the text now.

Set Style (Center, Text Size Color, Background Color…)

PS: This is the place where I walk the most holes…

There’s no looping around here. If you set the style, the xlsx.full.min.js above won’t work.
xlsx-style must be installed

Install xlsx-style

It looks like only npm is installed, github I can’t find an address

npm install xlsx-style

Similarly, there is an xlsx.full.min.js in the dist folder under the installation directory, huh?Same name?How to use it?Okay, I can’t get started, so I’ll just have to put my scalp on it. Note that I put the JS file for xlsx-style below:

There is also the btn_export() method to change, adding a style.
Specific cell style instructions can be found in this article xlsx-style cell style reference table

function btn_export() {
        var table1 = document.querySelector("#table1");
        var sheet = XLSX.utils.table_to_sheet(table1);
        //This is the code to modify the format
        sheet["A5"].s = { 
            font: { sz: 13, bold: true, },
            alignment: { 
                horizontal: "center", vertical: "center", wrap_text: true 
            } 
        };
        openDownloadDialog(sheet2blob(sheet),'download.xlsx');
    }

After changing, click Run, otherwise, the error is reported:

What’s the reason, because the variables exposed by both js files are called’XLSX’, but there is no XLSX.utils method in the xlsx-style js file, and the xlsx-style js file was introduced later, it overwrites the previous XLSX, so the error is reported.
There are many methods available in XLSX.utils, but they cannot be invoked in this way:

You might want to swap two js files, but the result is that xlsx exposed variables override xlsx-style exposed variables.You still can’t change your style.

Be careful

If your export function is to import json format or other formats without using XLSX.utils, you only need to use xlsx-style’s js. The following can be ignored. The following is how to make xlsx work with xlsx-style’s js.

Not using XLSX.utils

Since these two JS are encrypted content, it is impossible to interpret them and find anything useful on them.Fortunately, xlsx.extendscript.js was found in the xlsx dist folder. Look at this file as a tool class. Since I used the table_to_sheet method above, I searched over xlsx.extendscript and found this method. Next, delete the JS reference of xlsx and introduce xlsx.extendscript:

Function.As a result, you should have guessed that the style hasn’t changed.For what reason, the variables exposed by xlsx.extendscript.js are still’XLSX’, and the variables below cover the variables above.

Be careful!!!

If you use webpack, babel, etc. in your project, you can import directly without changing the variable name

Fortunately, this xlsx.extendscript.js is not a compressed version. You can modify the content by changing the exposed variable to’XLSX2′.This way we only use xlsx.extendscript.js when using the utils tool and xlsx-style as the JS for the rest, so that’s fine.
Don’t forget to change XSLX.utils.table_to_sheet() to XLSX2.utils.table_to_sheet() once you’ve modified it.
(It is not recommended to modify the source code, because the work requires that you do not modify the source code before it can be used)

function btn_export() {
        var table1 = document.querySelector("#table1");
        var sheet = XLSX2.utils.table_to_sheet(table1);
        sheet["A5"].s = {
            font: {
                sz: 13,
                bold: true,
                color: {
                    rgb: "FFFFAA00"
                }
            },
            alignment: {
                horizontal: "center",
                vertical: "center",
                wrap_text: true
            }
        };
        openDownloadDialog(sheet2blob(sheet), 'download.xlsx');
    }

Function:

You can see that the styling changes you made have taken effect.
Customer demand is increasing: I want the first few lines to be empty and print the company name on them.
Looking at the xlsx.extendscript.js source, it is found that table_to_sheet, or parse_dom_table, does not have a parameter set for the starting row. The code for parse_dom_table is given below:

function parse_dom_table(table, _opts) {
    var opts = _opts || {};
    if(DENSE != null) opts.dense = DENSE;
    var ws = opts.dense ? ([]) : ({});
    var rows = table.getElementsByTagName('tr');
    var sheetRows = opts.sheetRows || 10000000;
    var range = {s:{r:0,c:0},e:{r:0,c:0}};
    var merges = [], midx = 0;
    var rowinfo = [];
    var _R = 0, R = 0, _C, C, RS, CS;
    for(; _R < rows.length && R < sheetRows; ++_R) {
        var row = rows[_R];
        if (is_dom_element_hidden(row)) {
            if (opts.display) continue;
            rowinfo[R] = {hidden: true};
        }
        var elts = (row.children);
        for(_C = C = 0; _C < elts.length; ++_C) {
            var elt = elts[_C];
            if (opts.display && is_dom_element_hidden(elt)) continue;
            var v = htmldecode(elt.innerHTML);
            for(midx = 0; midx < merges.length; ++midx) {
                var m = merges[midx];
                if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
            }
            /* TODO: figure out how to extract nonstandard mso- style */
            CS = +elt.getAttribute("colspan") || 1;
            if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
            var o = {t:'s', v:v};
            var _t = elt.getAttribute("t") || "";
            if(v != null) {
                if(v.length == 0) o.t = _t || 'z';
                else if(opts.raw || v.trim().length == 0 || _t == "s"){}
                else if(v === 'TRUE') o = {t:'b', v:true};
                else if(v === 'FALSE') o = {t:'b', v:false};
                else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
                else if(!isNaN(fuzzydate(v).getDate())) {
                    o = ({t:'d', v:parseDate(v)});
                    if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
                    o.z = opts.dateNF || SSF._table[14];
                }
            }
            if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
            else ws[encode_cell({c:C, r:R})] = o;
            if(range.e.c < C) range.e.c = C;
            C += CS;
        }
        ++R;
    }
    if(merges.length) ws['!merges'] = merges;
    if(rowinfo.length) ws['!rows'] = rowinfo;
    range.e.r = R - 1;
    ws['!ref'] = encode_range(range);
    if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1,range)); // We can count the real number of rows to parse but we don't to improve the performance
    return ws;
}

Add one yourself
As you can see, the R variable inside is the key to controlling the starting line. Okay, let’s make some changes:

var _R = 0, R = _opts.rowIndex || 0, _C, C, RS, CS;

Here we add an attribute, rowIndex, to _opts, which is passed in when the table_to_sheet method is called.Here is the changed code:

function btn_export() {
        var table1 = document.querySelector("#table1");
        var opt = {
            rowIndex: 4
        }; //Start empty 4 lines
        var sheet = XLSX2.utils.table_to_sheet(table1, opt);
        sheet["A1"] = {
            t: "s",
            v: 'Sanlu Group Ltd.'
        }; //Assign values to A1 cells
        sheet["A1"].s = {
            font: {
                name: 'Song Style',
                sz: 24,
                bold: true,
                underline: true,
                color: {
                    rgb: "FFFFAA00"
                }
            },
            alignment: { horizontal: "center", vertical: "center", wrap_text: true },
            fill: {
                bgColor: { rgb: 'ffff00' }
            }
        };
        //['!merges'] This property is designed for cell merging 
        sheet["!merges"].push({//If not null push is null = assign
            //Merge cell index starts at 0
            s: { //s Start
                c: 0, //Beginning column
                r: 0 //Start Line
            },
            e: { //e End
                c: 3, //End Column
                r: 2 //End line
            }
        });
        sheet["A9"].s = { //style
            font: {
                sz: 13,
                bold: true,
                color: {
                    rgb: "FFFFAA00"
                }
            },
            alignment: {
                horizontal: "center",
                vertical: "center",
                wrap_text: true
            }
        };
        openDownloadDialog(sheet2blob(sheet), 'download.xlsx');
    }

Run result:

You can see that the changes you made have taken effect.

Customers have new requirements, to add 2 fields, ID number and mobile phone number.
Isn’t that easy? Add two fields.2 minutes, export:

???
How did the ID number become a scientific method of counting and what the ghost was (later it was found that the percentage would be converted directly to 0-1 decimals for you, but statistics can’t be done)
What’s going on? Or a masterpiece of parse_dom_table!
Note this line:

else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};

This means that as long as the value read from the text of td is followed by a number (regardless of your string type), a fuzzynum(v) will be given to you to convert to a numbertype.
Make the following changes, the result is:

function parse_dom_table(table, _opts) {
    var opts = _opts || {};
    if(DENSE != null) opts.dense = DENSE;
    var ws = opts.dense ? ([]) : ({});
    var rows = table.getElementsByTagName('tr');
    var sheetRows = opts.sheetRows || 10000000;
    var range = {s:{r:0,c:0},e:{r:0,c:0}};
    var merges = [], midx = 0;
    var rowinfo = [];
    var _R = 0, R = _opts.rowIndex || 0, _C, C, RS, CS;
    for(; _R < rows.length && R < sheetRows; ++_R) {
        var row = rows[_R];
        if (is_dom_element_hidden(row)) {
            if (opts.display) continue;
            rowinfo[R] = {hidden: true};
        }
        var elts = (row.children);
        for(_C = C = 0; _C < elts.length; ++_C) {
            var elt = elts[_C];
            if (opts.display && is_dom_element_hidden(elt)) continue;
            var v = htmldecode(elt.innerHTML);
            for(midx = 0; midx < merges.length; ++midx) {
                var m = merges[midx];
                if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
            }
            /* TODO: figure out how to extract nonstandard mso- style */
            CS = +elt.getAttribute("colspan") || 1;
            if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
            var o = {t:'s', v:v};
            var _t = elt.getAttribute("t") || "";
            if(v != null) {
                if(v.length == 0) o.t = _t || 'z';
                else if(opts.raw || v.trim().length == 0 || _t == "s"){}
                else if(v === 'TRUE') o = {t:'b', v:true};
                else if(v === 'FALSE') o = {t:'b', v:false};
        //else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
        else if(!isNaN(fuzzynum(v))) o = {t:'s', v:v};//number type is not automatically formatted
                else if(!isNaN(fuzzydate(v).getDate())) {
                    o = ({t:'d', v:parseDate(v)});
                    if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
                    o.z = opts.dateNF || SSF._table[14];
                }
            }
            if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
            else ws[encode_cell({c:C, r:R})] = o;
            if(range.e.c < C) range.e.c = C;
            C += CS;
        }
        ++R;
    }
    if(merges.length) ws['!merges'] = merges;
    if(rowinfo.length) ws['!rows'] = rowinfo;
    range.e.r = R - 1;
    ws['!ref'] = encode_range(range);
    if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1,range)); // We can count the real number of rows to parse but we don't to improve the performance
    return ws;
}

Comment out the converted statement, rewrite the line of code, and if it is of type number, leave it unchanged as to what value it should be or what value it should be.
Now rerun, the result is:
You can see that the numbers are displayed properly.But this cell doesn’t seem to expand automatically, it’s always so big, and xlsx-style also provides a way to control the width of the cell:

sheet["!cols"] = [{
            wpx: 70
        }, {
            wpx: 70
        }, {
            wpx: 70
        }, {
            wpx: 70
        }, {
            wpx: 150
        }, {
            wpx: 120
        }]; //Cell Column Width

Note that setting cell column widths starts with the first row
Result:

Full front-end code:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <table id="table1" border="1" cellspacing="0" cellpadding="0">
        <thead>
            <tr>
                <td>Sequence Number</td>
                <td>Full name</td>
                <td>Age</td>
                <td>Interest</td>
                <td>ID number</td>
                <td>Cell-phone number</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>Zhang San</td>
                <td>18</td>
                <td>Play games</td>
                <td>320322184087562589</td>
                <td>1374569821</td>
            </tr>
            <tr>
                <td>2</td>
                <td>Li Si</td>
                <td>88</td>
                <td>Watch movie</td>
                <td>420322184087562589</td>
                <td>2374569821</td>
            </tr>
            <tr>
                <td>3</td>
                <td>King Five</td>
                <td>81</td>
                <td>Sleep</td>
                <td>520322184087562589</td>
                <td>3374569821</td>
            </tr>
            <tr>
                <td colspan="4">This is a merged cell</td>
            </tr>
        </tbody>
    </table>

    <button id="btn" onclick="btn_export()">export</button>
</body>
<script src="js/xlsx.extendscript.js"></script>
<script src="js/xlsx-style/xlsx.full.min.js"></script>

<script src="js/export.js"></script>
<script>
    function btn_export() {
        var table1 = document.querySelector("#table1");
        var opt = {
            rowIndex: 4
        }; //Start empty 4 lines
        var sheet = XLSX2.utils.table_to_sheet(table1, opt);
        sheet["A1"] = {
            t: "s",
            v: 'Sanlu Group Ltd.'
        }; //Assign values to A1 cells
        sheet["A1"].s = {
            font: {
                name: 'Song Style',
                sz: 24,
                bold: true,
                underline: true,
                color: {
                    rgb: "FFFFAA00"
                }
            },
            alignment: {
                horizontal: "center",
                vertical: "center",
                wrap_text: true
            },
            fill: {
                bgColor: {
                    rgb: 'ffff00'
                }
            }
        };
        //['!merges'] This property is designed for cell merging 
        sheet["!merges"].push({ //If not null push is null = assign
            //Merge cell index starts at 0
            s: { //s Start
                c: 0, //Beginning column
                r: 0 //Start Line
            },
            e: { //e End
                c: 3, //End Column
                r: 2 //End line
            }
        });
        sheet["A9"].s = { //style
            font: {
                sz: 13,
                bold: true,
                color: {
                    rgb: "FFFFAA00"
                }
            },
            alignment: {
                horizontal: "center",
                vertical: "center",
                wrap_text: true
            }
        };

        sheet["!cols"] = [{
            wpx: 70
        }, {
            wpx: 70
        }, {
            wpx: 70
        }, {
            wpx: 70
        }, {
            wpx: 150
        }, {
            wpx: 120
        }]; //Cell Column Width

        openDownloadDialog(sheet2blob(sheet), 'download.xlsx');
    }
</script>

</html>

demo source

github address Full Instance

summary

  1. Source modification is not recommended in exceptional circumstances
  2. Since the code was modified after all, this approach can only be targeted to a smaller audience
  3. I’ve heard that the toll version is full of features. I suggest you buy the toll version if you need it, but the address can’t be found.
  4. You can modify the xlsx source code to suit your own needs.However, this is more difficult to maintain, so it is up to you to choose between them.
  5. I have just listed the functions I need in my actual work. xlsx has so many functions that I can think over more when I have time.

js-xlsx введение

кSheetJSПроизведеноjs-xlsxЭто очень удобная библиотека инструментов, которой для чтения и экспорта в Excel нужен только чистый JS. Она имеет мощные функции, поддерживает множество форматов и поддерживаетxlsxlsxods(Собственный формат файлов таблицы OpenOffice) и более десятка форматов. Вся эта статья основана наxlsxВозьмем, к примеру, формат.

  • Официальный гитхаб:https://github.com/SheetJS/js-xlsx
  • Онлайн-демонстрационный адрес поддерживающей демонстрации для этой статьи:http://demo.haoji.me/2017/02/08-js-xlsx/
  • Эта статья впервые была опубликована у меня синхронноличный блогсБлог сад。

1.1. Совместимость

Совместимость следующая:

1.2. Как пользоваться

distВ каталоге много JS-файлов, обычно используйтеxlsx.core.min.jsдовольно,xlsx.full.min.jsОн содержит все функциональные модули.

непосредственныйscriptЭтикетка может быть введена:

<script type="text/javascript" src="./js/xlsx.core.min.js"></script>

Читать в Excel

Чтение в Excel происходит в основном черезXLSX.read(data, {type: type});Способ достижения, ответьте на звонокWorkBookОсновные значения типа следующие:

  • base64: Читать в режиме base64;
  • binary: Формат BinaryString (n-й байт — это data.charCodeAt (n))
  • string: Строка в кодировке UTF8;
  • buffer: nodejs Buffer;
  • array: Uint8Array, 8-битный беззнаковый массив;
  • file: Путь к файлу (поддерживается только в nodejs);

2.1. Получить объект книги

2.1.1. Чтение локальных файлов

Непосредственно по коду:

// читаем локальный файл Excel
function readWorkbookFromLocalFile(file, callback) {
    var reader = new FileReader();
    reader.onload = function(e) {
        var data = e.target.result;
        var workbook = XLSX.read(data, {type: 'binary'});
        if(callback) callback(workbook);
    };
    reader.readAsBinaryString(file);
}

2.1.2. Чтение сетевых файлов

// Чтобы прочитать файл Excel из Интернета, URL-адрес должен находиться в том же домене, иначе будет сообщено об ошибке
function readWorkbookFromRemoteFile(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('get', url, true);
    xhr.responseType = 'arraybuffer';
    xhr.onload = function(e) {
        if(xhr.status == 200) {
            var data = new Uint8Array(xhr.response)
            var workbook = XLSX.read(data, {type: 'array'});
            if(callback) callback(workbook);
        }
    };
    xhr.send();
}

2.2. Подробная рабочая тетрадь

2.2.1. Workbook Object

workbookЧто в нем, распечатаем и посмотрим:

можно увидеть,SheetNamesВ нем сохраняются все названия листов, а затемSheetsКонкретное содержимое каждого листа сохраняется (мы называем этоSheet Object). КаждыйsheetЧерез что-то вродеA1Такое значение ключа сохраняет содержимое каждой ячейки, и мы называем его объектом ячейки (Cell Object):

2.2.2. Sheet Object

КаждыйSheet ObjectПредставляет форму, если она не!Те, что в начале, указывают на обычныеcell, В противном случае это означает какое-то особое значение, а именно:

  • sheet['!ref']: Указывает диапазон всех ячеек, например, от A1 до F8, он записывается какA1:F8
  • sheet[!merges]: Хранить некоторую информацию о слиянии ячеек, это массив, каждый массив состоит изsсeСоставьте композицию объекта,sЗначит старт,eОзначает конец,rПредставляет строку,cПредставляет столбец;
  • и многое другое;

Что касается слияния ячеек, в принципе не проблема понять следующую картину:

Результаты приведены ниже:

2.2.3. Объект Cell

Каждая ячейка — это объект (Cell Object),ЕстьtvrhwИ другие поля (см.Здесь):

  • t: указывает тип содержимого,sПредставляет тип строки,nПредставляет числовой тип,bПредставляет логический тип,dПредставляет тип даты и т. Д.
  • v: представляет исходное значение;
  • f: представляет формулу, напримерB2+B3
  • h: HTML-контент
  • w: форматированный контент
  • r: богатый текстовый контентrich text
  • и многое другое

2.2.4. Читать книгу

Обычный метод:

// читаем файл Excel
function outputWorkbook(workbook) {
         var sheetNames = workbook.SheetNames; // набор имен рабочих листов
    sheetNames.forEach(name => {
                 var worksheet = workbook.Sheets [name]; // Указанный рабочий лист можно получить только по имени рабочего листа
        for(var key in worksheet) {
                         // v - исходное значение прочитанной ячейки
            console.log(key, key[0] === '!' ? worksheet[key] : worksheet[key].v);
        }
    });
}

в соответствии с!refОпределите сферу применения Excel, а затем в соответствии с!mergesУбедитесь, что ячейки объединены (если есть), и, наконец, выведите всю таблицу, что вызывает затруднения. К счастью, сам плагин уже написал инструментXLSX.utilsДля непосредственного использования, без нашего собственного обхода, выходные данные инструмента в основном включают следующее:

Некоторые из них обычно не используются, наиболее часто используются:

  • XLSX.utils.sheet_to_csv: Создать формат CSV
  • XLSX.utils.sheet_to_txt: Создать текстовый формат
  • XLSX.utils.sheet_to_html: Создать формат HTML
  • XLSX.utils.sheet_to_json: Выходной формат JSON

Чаще всего используютсяsheet_to_csvили жеsheet_to_html, Формат, объединение ячеек и другая информация будут игнорироваться при преобразовании в CSV, поэтому сложные таблицы могут быть неприменимы. Если вы конвертируете в html, ячейки будут объединены, но результат будет<html></html>Код вместо<table></table>, Это неудобно, когда вам нужно внести некоторые изменения в форму, поэтому вам все равно придется использовать соответствующие инструменты в зависимости от ситуации.

Вот простой пример вывода результатов путем преобразования в CSV, вы можете щелкнуть здесь, чтобы просмотретьДЕМО онлайн:

function readWorkbook(workbook)
{
         var sheetNames = workbook.SheetNames; // набор имен рабочих листов
         var worksheet = workbook.Sheets [sheetNames [0]]; // здесь мы читаем только первый лист
    var csv = XLSX.utils.sheet_to_csv(worksheet);
    document.getElementById('result').innerHTML = csv2table(csv);
}

 // Преобразование csv в простую таблицу, игнорирование слияния ячеек, добавление индекса, аналогичного excel, в первой строке и первом столбце
function csv2table(csv)
{
    var html = '<table>';
    var rows = csv.split('n');
         rows.pop (); // последняя строка бесполезна
    rows.forEach(function(row, idx) {
        var columns = row.split(',');
                 columns.unshift (idx + 1); // добавляем индекс строки
                 if (idx == 0) {// добавляем индекс столбца
            html += '<tr>';
            for(var i=0; i<columns.length; i++) {
                html += '<th>' + (i==0?'':String.fromCharCode(65+i-1)) + '</th>';
            }
            html += '</tr>';
        }
        html += '<tr>';
        columns.forEach(function(column) {
            html += '<td>'+column+'</td>';
        });
        html += '</tr>';
    });
    html += '</table>';
    return html;
}

Экспорт в Excel

Существует два типа экспорта: один основан на существующей модификации Excel, другой — нового поколения, первый относительно прост, здесь мы сосредоточимся на втором.

3.1. Создайте собственный рукописный код

Экспорт файла Excel, в основном, как его создатьsheet, Здесь мы пишем простой пример csv для Excel:

// csv в объект листа
function csv2sheet(csv) {
         var sheet = {}; // лист, который будет сгенерирован
    csv = csv.split('n');
    csv.forEach(function(row, i) {
        row = row.split(',');
        if(i == 0) sheet['!ref'] = 'A1:'+String.fromCharCode(65+row.length-1)+(csv.length-1);
        row.forEach(function(col, j) {
            sheet[String.fromCharCode(65+j)+(i+1)] = {v: col};
        });
    });
    return sheet;
}

 // Преобразование листа в объект blob окончательного файла Excel, а затем использование URL.createObjectURL для загрузки
function sheet2blob(sheet, sheetName) {
    sheetName = sheetName || 'sheet1';
    var workbook = {
        SheetNames: [sheetName],
        Sheets: {}
    };
    workbook.Sheets[sheetName] = sheet;
         // Создание элементов конфигурации для Excel
    var wopts = {
                 bookType: 'xlsx', // тип создаваемого файла
                 bookSST: false, // Следует ли генерировать общую таблицу строк, официальное объяснение состоит в том, что если она включена, скорость генерации уменьшится, но есть лучшая совместимость с устройствами IOS более низкой версии
        type: 'binary'
    };
    var wbout = XLSX.write(workbook, wopts);
    var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});
         // Строка в ArrayBuffer
    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;
    }
    return blob;
}

Получите объект blob выше, и вы можете загрузить его напрямую, см. Мой предыдущийJS всплывает диалоговое окно загрузкиИнкапсулирован внутриopenDownloadDialogметод:

/**
   * Общий метод открытия диалогового окна загрузки не тестировался на совместимость
   * @param url-адрес загрузки, это также может быть объект blob, обязательно
   * @param saveName имя файла сохранения, необязательно
 */
function openDownloadDialog(url, saveName)
{
    if(typeof url == 'object' && url instanceof Blob)
    {
                 url = URL.createObjectURL (url); // Создание адреса большого двоичного объекта
    }
    var aLink = document.createElement('a');
    aLink.href = url;
         aLink.download = saveName || ''; // новый атрибут HTML5, укажите имя файла сохранения, суффикс не требуется, обратите внимание, что он не вступит в силу в режиме file: ///
    var event;
    if(window.MouseEvent) event = new MouseEvent('click');
    else
    {
        event = document.createEvent('MouseEvents');
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    }
    aLink.dispatchEvent(event);
}

Таким образом, окончательная загрузка выглядит следующим образом:

// Передаем csv, и после выполнения появится окно загрузки
function exportExcel(csv) {
    var sheet = csv2sheet(csv);
    var blob = sheet2blob(sheet);
         openDownloadDialog (blob, 'Export.xlsx');
}

3.2. Используйте официальные инструменты для создания

На самом деле, нам не нужно писать ни один из вышеперечисленных кодов. Чиновник предоставил нам готовые инструменты, в основном в том числе:

  • aoa_to_sheet: Этот класс инструментов является наиболее мощным и практичным.Преобразование двумерного массива в лист автоматически обработает числовые, строковые, логические, даты и другие типы данных;
  • table_to_sheet: Поставить одинtable domНепосредственно преобразованный в лист, он будет автоматически распознанcolspanсrowspanИ преобразовать его в соответствующую ячейку и объединить;
  • json_to_sheet: Преобразовать массив объектов в лист;

aoa_to_sheetПример:

var aoa = [
         ["Имя", "Пол", "Возраст", "Время регистрации"],
         ['Zhang San', 'Male', 18 лет, новое свидание ()],
         [' ', ' ', 22, новая дата ()]
];
var sheet = XLSX.utils.aoa_to_sheet(aoa);
 openDownloadDialog (sheet2blob (лист), 'Export.xlsx');

table_to_sheetЕще проще, прямоXLSX.utils.table_to_sheet($('table')[0])Может

3.3. Решение проблемы слияния ячеек

Вообще говоря, интерфейсное поколениеexcelВместоcsvОсновная цель — решить проблему, заключающуюся в том, что csv не может выполнить слияние ячеек. В противном случае было бы неплохо напрямую экспортировать файл csv. Зачем вводить несколько сотен килобайт плагинов.

Предположим, мы хотим сгенерировать файл Excel в следующем формате, гдеA1-C1Чтобы объединить ячейки:

код показан ниже:

var aoa = [
         ['Основная информация', null, null, 'Другая информация'], // Особое внимание следует уделить резервированию 2 нулевых значений за объединенным местом
         ["Имя", "Пол", "Возраст", "Время регистрации"],
         ['Zhang San', 'Male', 18 лет, новое свидание ()],
         [' ', ' ', 22, новая дата ()]
];
var sheet = XLSX.utils.aoa_to_sheet(aoa);
sheet['!merges'] = [
         // Устанавливаем слияние ячеек A1-C1
    {s: {r: 0, c: 0}, e: {r: 0, c: 2}}
];
 openDownloadDialog (sheet2blob (sheet), 'Слияние ячеек example.xlsx');

Стоит обратить внимание на использование объединенных ячеек.nullЗарезервируйте место, иначе следующий контент (в этом примере четвертый столбецДополнительная информация) Будет перезаписан.

3.4. Пользовательский стиль

Обычная версия не поддерживает определение шрифтов, цветов, цветов фона и т. Д., Вы можете использовать ее, если вам нужна эта функция.профессиональная версия, Вроде заряжено, потому что официальный сайт не видел адреса загрузки.

Персональный сайт:https://haoji.me
github:https://github.com/sxei
Сад блогов:http://www.cnblogs.com/liuxianan
авторское право © 2012-2018 одноклассник Xiaominggrapecity.com.cn/spreadjs/excel-online/content/index.html

Welcome to a tutorial on how to create an Excel file in Javascript. Yes, you read that right. We are referring to “browser Javascript”, and not the server-side NodeJS. The dark days have passed and it is actually possible to generate Excel files using client-side Javascript – Read on for the examples!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

TLDR – QUICK SLIDES

Create Excel File In Javascript

Fullscreen Mode – Click Here

TABLE OF CONTENTS

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

SCREENSHOT

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

All right, let us now get into the examples of generating an Excel file in Javascript.

EXAMPLE 1) GENERATE EXCEL FILE & FORCE DOWNLOAD

1A) THE HTML

1-create-excel.html

<!-- (A) LOAD SHEETJS FROM CDN -->
<!-- https://sheetjs.com/ -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
 
<!-- (B) CLICK TO GENERATE DEMO EXCEL -->
<button id="demo">Download Demo Excel</button>

<!-- (C) JAVASCRIPT -->
document.getElementById("demo").onclick = () => { ... };

Yep, that is pretty much everything we need to drive the example.

  1. Load SheetJS from CDNJS, this library is required to create the Excel file. Will leave a link in the extras section below to their full documentation.
  2. A demo button to start generating the Excel file.
  3. Generate the Excel file when the button is clicked.

1B) DUMMY DATA

1-create-excel.html

// (C1) DUMMY DATA
var data = [
  ["Joa Doe", "joa@doe.com"],
  ["Job Doe", "job@doe.com"],
  ["Joe Doe", "joe@doe.com"],
  ["Jon Doe", "jon@doe.com"],
  ["Joy Doe", "joy@doe.com"]
];

For the Javascript, we will first start by defining a nested array of dummy data. Don’t think it needs a lot of explanation, this will get “converted” into rows and columns in the Excel file.

1C) CREATE A NEW EXCEL OBJECT

1-create-excel.html

// (C2) CREATE NEW EXCEL "FILE"
var workbook = XLSX.utils.book_new(),
    worksheet = XLSX.utils.aoa_to_sheet(data);
workbook.SheetNames.push("First");
workbook.Sheets["First"] = worksheet;

This should be pretty self-explanatory for the folks who already know Excel well, but for the sake of those who are new:

  • A “workbook” is simply “the entire Excel file”.
  • A “worksheet” is a table within a workbook.
  • A workbook can contain multiple worksheets.

So what this section is doing:

  • workbook = XLSX.utils.book_new() Creates a new Excel workbook.
  • worksheet = XLSX.utils.aoa_to_sheet(data) Creates a new worksheet, using the dummy data array above.
  • workbook.SheetNames.push("First") and workbook.Sheets["First"] = worksheet Attach the worksheet to the workbook.

1D) FORCE DOWNLOAD

1-create-excel.html

// (C3) "FORCE DOWNLOAD" XLSX FILE
XLSX.writeFile(workbook, "demo.xlsx");

Horray, we now have an Excel object. All that’s left is to “force download” the Excel file, and allow the user to save it.

EXAMPLE 2) GENERATE EXCEL FILE & UPLOAD TO SERVER

2A) UPLOAD GENERATED EXCEL FILE

2a-upload-excel.html

// (C3) TO BLOB
var xlsblob = new Blob(
  [new Uint8Array(XLSX.write(workbook, { bookType: "xlsx", type: "array" }))],
  {type:"application/octet-stream"}
);
 
// (C4) FORM DATA
var data = new FormData();
data.append("xls", xlsblob, "demo.xlsx");
 
// (C5) UPLOAD TO SERVER
fetch("2b-upload.php", { method: "POST", body: data })
.then(res => res.text())
.then(txt => console.log(txt));

This is an alternative if you want to upload the generated Excel file to the server instead.

  • (C3) Instead of “forcing a download”, we turn the workbook into a blob (binary object).
  • (C4) Attach the Excel blob as form data.
  • (C5) Send the Excel blob to the server… Otherwise also known as “file upload”.

2B) SAVE THE UPLOADED EXCEL FILE

2b-upload.php

<?php
echo move_uploaded_file(
  $_FILES["xls"]["tmp_name"],
  __DIR__ . DIRECTORY_SEPARATOR . $_FILES["xls"]["name"]
) ? "OK" : "ERROR" ;

On the server side, we simply save the uploaded Excel file like a “normal file upload”. This is a simple “save uploaded file” snippet in PHP.

EFFICIENCY & PERFORMANCE

Just a quick note that we are holding an entire Excel file in the memory with this example… This will work great for small to medium Excel files, but the massive ones are going to run into performance issues and memory limits. You may want to implement some sort of restrictions on the maximum amount of data, or look at server-side alternatives with streaming.

COMPATIBILITY CHECKS

  • Arrow Functions – CanIUse
  • Array Buffer – CanIUse
  • Uint8Array – Can I Use

This example will work on all modern “Grade A” browsers.

LINKS & REFERENCES

  • SheetJS Documentation
  • Export From MySQL Database To Excel In NodeJS – Code Boxx

INFOGRAPHICS CHEAT SHEET

Create Excel File In Javascript (Click To Enlarge)

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Понравилась статья? Поделить с друзьями:
  • Jquery данные в excel
  • Jquery выгрузка в excel
  • Jquery datatables export excel
  • Jqgrid export to excel
  • Jpg перевести в word формат онлайн бесплатно