Xml to excel javascript

Время на прочтение
2 мин

Количество просмотров 58K

Введение

Всем привет! Сегодня я опишу довольно тривиальную, но нигде не освещенную тему экспорта из страницы данных в Excel. На мое удивление сам процесс не описан нигде в полной мере. Итак, приступим.

Все написано до нас

Подумал я и начал искать, нашел очень быстро SheetJS , но, боже мой, как там запущено все! Если с форматированием еще можно справиться, то стили — это головная боль.

Все написано до нас. Подход 2

В старом-старом SharePoint 2007 есть такая возможность экспортировать эксель файл, на удивление это работает до сих пор и хорошо поддается описанию.

Что нужно:

  • Современный браузер (проверьте в старых)
  • Отформатированная таблица
  • Colspan, rowspan, border — знание табличной верстки

var tableToExcel = (function() {
		var uri = 'data:application/vnd.ms-excel;base64,'
		, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--><meta http-equiv="content-type" content="text/plain; charset=UTF-8"/></head><body><table>{table}</table></body></html>'
		, base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
		, format = function(s, c) { 	    	 
			return s.replace(/{(w+)}/g, function(m, p) { return c[p]; }) 
		}
		, downloadURI = function(uri, name) {
		    var link = document.createElement("a");
		    link.download = name;
		    link.href = uri;
		    link.click();
		}

		return function(table, name, fileName) {
			if (!table.nodeType) table = document.getElementById(table)
				var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}
			var resuri = uri + base64(format(template, ctx))
			downloadURI(resuri, fileName);
		}
	})();  


    // params: element id, sheet name, file name
    tableToExcel('resultTable','Смета', 'Ремрайон_смета.xls');

Форматирование

Оформите саму сетку в таблице с помощью атрибутов colspan, rowspan, добавьте стили и после этого вызывайте генерацию файла.

В заключение

Могу ответить в комментах на ваши вопросы.

A simple node.js module for exporting data set to Excel xlsx file.

Setup configs object before passing it into the execute method. If generating multiple sheets, configs object can be an array of worksheet configuration. Or passing in a worksheet configuration to generate single worksheet xlsx file. Within a worksheet configuration uses name attribute to specify worksheet name. cols is an array for column definition. Column definition should have caption and type properties while width property is not required. The unit for width property is character. beforeCellWrite callback is optional. beforeCellWrite is invoked with row, cell data and option object (eOpt detail later) parameters. The return value from beforeCellWrite is what get written into the cell. Supported valid types are string, date, bool and number. rows is the data to be exported. It is an Array of Array (row). Each row should be the same length as cols. Styling is optional. However, if you want to style your spreadsheet, a valid excel styles xml file is needed. An easy way to get a styles xml file is to unzip an existing xlsx file which has the desired styles and copy out the styles.xml file. Use stylesXmlFile property of configuartion object to specify the relative path and file name of the xml file. Google for «spreadsheetml style» to learn more detail on styling spreadsheet. eOpt in beforeCellWrite callback contains rowNum for current row number. eOpt.styleIndex should be a valid zero based index from cellXfs tag of the selected styles xml file. eOpt.cellType is default to the type value specified in column definition. However, in some scenario you might want to change it for different format.

var express = require('express');
var nodeExcel = require('excel-export');
var app = express();

app.get('/Excel', function(req, res){
  	var conf ={};
	conf.stylesXmlFile = "styles.xml";
    conf.name = "mysheet";
  	conf.cols = [{
		caption:'string',
        type:'string',
        beforeCellWrite:function(row, cellData){
			 return cellData.toUpperCase();
		},
        width:28.7109375
	},{
		caption:'date',
		type:'date',
		beforeCellWrite:function(){
			var originDate = new Date(Date.UTC(1899,11,30));
			return function(row, cellData, eOpt){
          		if (eOpt.rowNum%2){
            		eOpt.styleIndex = 1;
          		}  
          		else{
            		eOpt.styleIndex = 2;
          		}
                if (cellData === null){
                  eOpt.cellType = 'string';
                  return 'N/A';
                } else
                  return (cellData - originDate) / (24 * 60 * 60 * 1000);
			} 
		}()
	},{
		caption:'bool',
		type:'bool'
	},{
		caption:'number',
		 type:'number'				
  	}];
  	conf.rows = [
 		['pi', new Date(Date.UTC(2013, 4, 1)), true, 3.14],
 		["e", new Date(2012, 4, 1), false, 2.7182],
        ["M&M<>'", new Date(Date.UTC(2013, 6, 9)), false, 1.61803],
        ["null date", null, true, 1.414]  
  	];
  	var result = nodeExcel.execute(conf);
  	res.setHeader('Content-Type', 'application/vnd.openxmlformats');
  	res.setHeader("Content-Disposition", "attachment; filename=" + "Report.xlsx");
  	res.end(result, 'binary');
});

app.listen(3000);
console.log('Listening on port 3000');

Answer by Jeremias Jaramillo

I’m trying to export XML data from a web page to a spreadsheet using javascript. So far I’ve just tried the very simple: ,How would I go about formatting the XML content to remove or replace the invalid characters to display properly to excel? The XML sheet is built from fields in a database, should I format it as it’s built or format it with javascript? I’m trying to find the simplest solution possible as I’m fairly new to web programming. Also, I’m using classic ASP/VBscript.,Managed to solve it by getting the HTML table output from the XML data then putting that into Excel using ActiveX.,Alternatively if you are using Response.Write to send the XML content you could use:-

I’m trying to export XML data from a web page to a spreadsheet using javascript. So far I’ve just tried the very simple:

Sub Export
    Response.ContentType = "application/vnd.ms-excel"
    <script>            
         var XML = document.getElementById("xmldata");              
         window.open(XML);
    </script>
End Sub

Answer by Royal Durham

I am given to understand that there are ways to generate Excel files from Classic ASP, by means of basically making an HTML table and calling it a spreadsheet. The output, however, doesn’t seem to be quite what I’m looking for — when opened in Excel, it looks like an HTML page with a table instead of a normal spreadsheet. So I’m not sure I want to go with that, though I’m open to being sold on the possibility.,What you might consider is something called SpreadsheetML, which is an xml schema that Excel will understand for defining a spreadsheet. This is different than the xml format used for the newer Office documents. Take a look here for an example:,Also, the accepted answer in that same question will cover some of your other options. It’s targeted for ASP.Net rather than classic ASP, but a lot of the material still applies.,Due to reasons, I’m working with a website that runs ASP Classic using JavaScript, which appears to have been very uncommon even back when ASP Classic was cutting-edge. I understand there are also means of generating Excel files in JavaScript, but they seem to be for more typical environments like a browser or Node.js; I think #include only works with other ASP files.

If you were using VBScript ASP then you would simply need to add the following lines, before your opening <table> tag

<%
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader "Content-Disposition", "attachment; filename=yourspreadsheetname.xls"
%>

Answer by Cory Valdez

Another possiblitly is to export the HTML tables as a CSV or TSV file, but you would need to setup the formatting in your code. This isn’t too difficult to accomplish.,As for .NET, I’ve always liked CarlosAG’s Excel XML Writer Library. It has a nice generator so you can setup your Excel file, save it as an XML spreadsheet and it generates the code to do all the formatting and everything. I know it’s not classic ASP, but I thought that I would throw it out there.,You can always just export the HTML table to an XLS document. Excel does a pretty good job understanding HTML tables.,When you open the file the data all appears in separate columns, but the spreadsheet is all white, no borders between the cells.

EDIT: Thus far, I have tried some of the suggestions, but it seems to fail. Ideally, I want the user to be able to click a link that will begin the download of a .xls file. This code:

<%@ Language=VBScript %>
<%  option explicit

Response.ContentType = "application/vnd.ms-excel"
Response.AppendHeader "content-disposition", " filename=excelTest.xls"
%>
<table>
    <tr>
        <th>Test Col 1</th>
        <th>Test Col 2</th>
        <th>Test Col 3</th>
        <th colspan="2">Test Col 4</th>
        <th>Test Col 6</th>
        <th>Test Col 7</th>
    </tr>
    <tr>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
    </tr>
</table>

Answer by Dayana Buck

Execute the following ASP code that converts XML spreadsheet file to Excel.,EasyXLS Excel library can be used to convert Excel files in Classic ASP. The library is a COM+ component that works without MS Excel installed.,Check if EasyXLS component is present in Component Services.,To download the trial version of EasyXLS Excel Library, press the below button:

<%@ Language=VBScript %>

<%
'=================================================================================
' Tutorial 41
'
' This tutorial shows how to convert XML spreadsheet to Excel in ASP classic. The
' XML Spreadsheet generated by Tutorial 32 is imported, some data is modified
' and after that is exported as Excel file.
'=================================================================================

response.write("Tutorial 41<br>")
response.write("----------<br>")

' Create an instance of the class used to import/export Excel files
Set workbook = Server.CreateObject("EasyXLS.ExcelDocument")

' Import XML Spreadsheet file
response.write("Reading file: C:SamplesTutorial32.xml<br>")
if (workbook.easy_LoadXMLSpreadsheetFile_2("C:SamplesTutorial32.xml")) then

    ' Get the table of data from the second sheet and add some data in cells (optional step)
    Set xlsTable = workbook.easy_getSheetAt(1).easy_getExcelTable()
    xlsTable.easy_getCell_2("A1").setValue("Data added by Tutorial41")

    for column=0 to 4
        xlsTable.easy_getCell(1, column).setValue("Data " & (column + 1))
    next

    ' Export Excel file
    response.write("Writing file: C:SamplesTutorial41 - convert XML spreadsheet to Excel.xlsx<br>")
    workbook.easy_WriteXLSXFile("C:SamplesTutorial41 - convert XML spreadsheet to Excel.xlsx")

    ' Confirm conversion of XML Spreadsheet to Excel
    if workbook.easy_getError() = "" then
        response.write("File successfully created.")
    else
        response.write("Error encountered: " + workbook.easy_getError())
    end if
else
    response.write("Error reading file C:SamplesTutorial32.xml")
    response.write(workbook.easy_getError())
end if

' Dispose memory
workbook.Dispose
%>


Introduction

This assumes basic familiarity with DataTables, its buttons extension, and the related ability to export table data to various file formats, including Excel.

I already wrote some overview notes here, but this is a large subject, and needs a bit more space.

Here, I will focus on reference material which is useful when you want to customize Excel exports.

More specifically I will only consider Office Open XML (.xlsx) files. Older .xls files (up to Excel 2003) use a different format and are not considered here.

Excel File Structure

The official Microsoft reference documentation for Excel file structures is here:

Excel (.xlsx) Extensions to the Office Open XML SpreadsheetML File Format

The underlying standards on which the above extensions are based can be found here:

ECMA-376 — Office Open XML file formats

In a nutshell, an Excel file is a zip file containing a series of sub-folders and XML documents.

Using Open Office nomenclature, the zip file is a “package” which contains “parts” (the XML files) and optionally other files such as graphics files.

We will look at a very simplified version of that structure, as used by DataTables:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
    "_rels": {
        ".rels": xml
    },
    "xl": {
        "_rels": {
            "workbook.xml.rels": xml
        },
        "workbook.xml": xml,
        "styles.xml": xml,
        "worksheets": {
            "sheet1.xml": xml
        }

    },
    "[Content_Types].xml": xml
}

DataTables builds a default Excel file from a series of XML strings hard-coded into the following JavaScript resource:

https://cdn.datatables.net/buttons/1.6.5/js/buttons.html5.js

Search for var excelStrings to see these for yourself. Here you will see, for example, the 68 predefined built-in cell styles which you can refer to when exporting DataTables data.

Content Types

The [Content_Types].xml file contains a list of the different parts in the package, together with each part’s type — for example:

1
2
PartName="/xl/workbook.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"

Relationships

The _rels.rels file contains a set of relationship IDs. These are then used to define the relationships between different parts in the package.

As well as the top-level .rels file, there can be others — such as the workbook.xml.rels file shown above, which can contain relationships to the other parts of the overall content, such as sheet1.xml, sharedStrings.xml, styles.xml, and so on.

An example is:

1
2
3
4
<Relationship
  Id="rId1"
  Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"
/>

Workbook

The workbook.xml file contains a list of worksheets:

1
2
3
4
5
6
7
<workbook>
    ...
    <sheets>
        <sheet name="Sheet1" sheetId="1" r:id="rId1"/>
    </sheets>
    ...
</workbook>

Here we can see the rId1 relationship ID being used.

Styles

The styles.xml file contains information relating to fonts, borders, fills, alignment, and so on. These can then be re-used in different locations.

An example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<styleSheet>
    ...
    <numFmts count="2">
        <numFmt numFmtId="43" formatCode="_(* #,##0.00_);_(* (#,##0.00);_(* &quot;-&quot;??_);_(@_)"/>
        <numFmt numFmtId="164" formatCode="#,##0.00_- [$$-45C]"/>
    </numFmts>
    ...
    <fonts count="1" x14ac:knownFonts="1">
        <font>
            <sz val="11"/>
            <color theme="1"/>
            <name val="Calibri"/>
            <family val="2"/>
            <scheme val="minor"/>
        </font>
    </fonts>
    ...
    <borders count="1">
        <border>
            <left/>
            <right/>
            <top/>
            <bottom/>
            <diagonal/>
        </border>
    </borders>
    ...
    <cellStyleXfs count="1">
        <xf numFmtId="0" fontId="0" fillId="0" borderId="0"/>
    </cellStyleXfs>
    ...
    <cellXfs count="2">
        <xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>
        <xf numFmtId="0" fontId="1" fillId="0" borderId="0" xfId="0" applyFont="1" applyAlignment="1">
            <alignment horizontal="center"/>
        </xf>
    </cellXfs>
    ...
    <cellStyles count="1">
        <cellStyle name="Normal" xfId="0" builtinId="0"/>
    </cellStyles>
  ...
</styleSheet>

Worksheets

The sheet1.xml file contains worksheet data:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<worksheet>
    ...
    <cols>
        <col min="1" max="1" width="18.85546875" customWidth="1"/>
        <col min="2" max="2" width="24.28515625" customWidth="1"/>
    </cols>
    <sheetData>
        <row r="1" spans="1:2">
            <c r="A1" s="1" t="s">
                <v>0</v>
            </c>
            <c r="B1" s="1" t="s">
                <v>1</v>
            </c>
        </row>
        <row r="2" spans="1:2">
            <c r="A2" t="s">
                <v>2</v>
            </c>
            <c r="B2" t="s">
                <v>3</v>
            </c>
        </row>
    </sheetData>
    ...
</worksheet>

Rows and Cells

In a row such as the following:

1
2
3
4
5
6
<row r="13">
  <c r="A13" s="12" t="s">
    <v>25</v>
  </c>
  ...
</row>

The meanings for each part are as follows:

Item Description
<row> a row
r="13" row 13
<c> cell tag
r="A13" cell reference A13
s="12" the cell’s formatting is at <xf> index 12 in the <cellXfs> formatting list
t="s" the t type attribute for the cell, where s means “shared strings”, where the text is stored.
<v="25"/> the string’s index is 25 — it’s the 26th string in the shared strings list.

List of t types:

Type Description
b boolean
d date
e error
inlineStr an inline string (i.e., not stored in the shared strings part, but directly in the cell)
n number, stored directly in the cell
s shared string (so stored in the shared strings part and not in the cell)
str a formula (a string representing the formula)

The following example shows a cell (B2) containing the number 400, stored in the cell itself:

1
2
3
<c r="B2" s="5" t="n">
    <v>400</v>
</c>

The above is just a small sample of the possible configuration options supported by Excel.

Documentation

Excel Options

The following page lists the main options which can be attached to an Excep export button.

https://datatables.net/reference/button/excel

Items of note are:

  • customize: function( xlsx ) { ... } — provides low-level access to the Excel file, where customizations can be made — typically by direct manipulation of the XML structures described in earlier sections of this post.
  • exportOptions — see the exportData section below for details.
  • filename and extension — for the Excel file.
  • header and footer — whether or not to include the table’s header and footer.
  • messageTop and messageBottom — additional line of data to be included in the spreadsheet.
  • sheetName — Excel sheet name.
  • title — added to the Excel sheet. See the exportInfo section below for details.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var table = $('#example').DataTable( {
  dom: 'Brftip',
  buttons: [
    {
      extend: 'excel',
      text: 'Save as Excel',
      filename: 'custom_name',
      extension: '.xlsx'
    }
  ]
} );

Here, options such as filename can also be functions:

1
2
3
filename: function() {
  return 'custom_name2';
}

Exported Data

The following page covers various ways to control what specific data is exported from the DataTable to Excel.

https://datatables.net/reference/api/buttons.exportData()

If the export options are provided as part of the DataTable button configuration, then you use the exportOptions: { ... } option referred to in the previous section.

If you use this as a standalone processor, then you use the exportData( { ... } ) function as follows:

1
2
3
4
5
6
7
var table = $('#myTable').DataTable();

var data = table.buttons.exportData( {
    modifier: {
        selected: true
    }
} );

Items of note are:

  • rows — a row selector.
  • columns — a column selector.
  • orthogonal — what orthogonal data to include.
  • stripHtml — strips HTML by default.
  • stripNewlines — stripts newlines by default.
  • format — various cell formatting functions — see below.

For the format option, you can provide various functions as follows:

1
2
3
4
5
format: {
  header: function ( data, columnIdx ) {
    return columnIdx +': '+ data;
  }
}

Items of note:

  • header (innerHTML, colIdx, node) — format the header data.
  • footer (innerHTML, colIdx, node) — format the footer data.
  • body (innerHTML, rowIdx, colIdx, node) — format the body data.
  • customizeData (data) — a final chance to customize the overall data. Mutate the data object which contains a header array, a footer array and a body 2D array. No return value is used.

Export Info

The following page covers options which may be common to multiple buttons for one table:

https://datatables.net/reference/api/buttons.exportInfo()

As such, the options available here overlap with some of those presented in the “Excel Options” section above — for example:

  • filename and extension — for the Excel file.
  • messageTop and messageBottom — additional line of data to be included in the spreadsheet.
  • title — added to the Excel sheet. By default, this will use the web page’s <title> value.

This is generally used outside of a button or with a custom button.

Low-Level Changes

Consider the following button option:

1
2
3
4
5
6
buttons: [
  customize: function( xlsx ) {
    var sheet = xlsx.xl.worksheets['sheet1.xml'];
    $( 'c[r=A1] t', sheet ).text( 'Custom text' );
  }
]

This accesses the underlying XML data for the Excel worksheet. It then uses jQuery to select the text content of cell A1. Finally it updates that content.

Some other examples:

Change row 1’s formatting:

1
$('row:first c', sheet).attr( 's', '42' );

NOTE: As of jQuery 3.4, the :first pseudo-class is deprecated. Remove it from your selectors and filter the results later using .first().

Change row 3’s formatting:

1
$('row[r=3] c', sheet).attr( 's', '25' );

Change column B’s formatting:

1
$('row c[r^='B']', sheet).attr( 's', '25' );

WARNING — if your spreadsheet has sufficient columns, you may find this also selects column BA, BB, and so on.

Change any row where the row number contains a 3 (3, 13, 23, 30, 31…):

1
$('row c[r*="3"]', sheet).attr( 's', '25' );

Get the last column in the sheet:

1
sheet.getElementsByTagName('col').length - 1

Here is an example which preserves very long numbers as text (and not, for example, as numbers in scientific notation):

https://stackoverflow.com/a/52047216/12567365

Here is an example which adds a new cell formatter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var table = $('#example').DataTable( {
  dom: 'Brftip',
  buttons: [
    customize: function( xlsx ) {
      addCustomNumberFormat(xlsx, '#,##0.0##');
    }
  ]
} );

function addCustomNumberFormat(xlsx, numberFormat) {
  // this adds a new custom number format to the Excel "styles" document:
  var numFmtsElement = xlsx.xl['styles.xml'].getElementsByTagName('numFmts')[0];
  // assume 6 custom number formats already exist, and next available ID is 176:
  var numFmtElement = '<numFmt numFmtId="176" formatCode="' + numberFormat + '"/>';
  $( numFmtsElement ).append( numFmtElement );
  $( numFmtsElement ).attr("count", "7"); // increment the count

  // now add a new "cellXfs" cell formatter, which uses our new number format (numFmt 176):
  var celXfsElement = xlsx.xl['styles.xml'].getElementsByTagName('cellXfs');
  var cellStyle = '<xf numFmtId="176" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"'
      + ' applyFont="1" applyFill="1" applyBorder="1"/>';
  // this will be the 8th "xf" element - and will therefore have an index of "7", when we use it later:
  $( celXfsElement ).append( cellStyle );
  $( celXfsElement ).attr("count", "69"); // increment the count
}

function formatTargetColumn(xlsx, col) {
  var sheet = xlsx.xl.worksheets['sheet1.xml'];
  // select all the cells whose addresses start with the letter prvoided
  // in 'col', and add a style (s) attribute for style number 68:
  $( 'row c[r^="' + col + '"]', sheet ).attr( 's', '68' );  
}

The following example shows the creation of additional sheets in the Excel file created from Datatables:

https://gist.github.com/northcoder-repo/05bde971c7879ea5ebc4907f323376fc

Custom Buttons

You can create completely customized buttons:

https://datatables.net/extensions/buttons/custom

https://datatables.net/reference/option/buttons.buttons.action

Consider this:

$.fn.DataTable.ext.buttons.excelHtml5.action.call(that, e, dt, node, config);

It uses the JavaScript call() method to call a function.

As used here, it allows us to provide a customized “please wait” pop-up modal (Swal is SweetAlert2):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
buttons: [
  {
    text: 'Excel',
    action: function(e, dt, node, config) {
      var that = this;
      Swal.fire('Data is being loaded...');
      setTimeout(function() {
        $.fn.DataTable.ext.buttons.excelHtml5.action.call(that, e, dt, node, config);
        Swal.close();
      }, 1000);
    }
  }
]

Like this post? Please share to your friends:
  • Xml text to excel
  • Xml templates for word
  • Xml template for word
  • Xml string to excel
  • Xml schema word 2010