forked from sheetjs/sheetjs
		
	
		
			
	
	
		
			218 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			218 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|  | ### Generating JSON and JS Data
 | ||
|  | 
 | ||
|  | JSON and JS data tend to represent single worksheets. The utility functions in | ||
|  | this section work with single worksheets. | ||
|  | 
 | ||
|  | The ["Common Spreadsheet Format"](#common-spreadsheet-format) section describes | ||
|  | the object structure in more detail.  `workbook.SheetNames` is an ordered list | ||
|  | of the worksheet names.  `workbook.Sheets` is an object whose keys are sheet | ||
|  | names and whose values are worksheet objects. | ||
|  | 
 | ||
|  | The "first worksheet" is stored at `workbook.Sheets[workbook.SheetNames[0]]`. | ||
|  | 
 | ||
|  | **API** | ||
|  | 
 | ||
|  | _Create an array of JS objects from a worksheet_ | ||
|  | 
 | ||
|  | ```js | ||
|  | var jsa = XLSX.utils.sheet_to_json(worksheet, opts); | ||
|  | ``` | ||
|  | 
 | ||
|  | _Create an array of arrays of JS values from a worksheet_ | ||
|  | 
 | ||
|  | ```js | ||
|  | var aoa = XLSX.utils.sheet_to_json(worksheet, {...opts, header: 1}); | ||
|  | ``` | ||
|  | 
 | ||
|  | The `sheet_to_json` utility function walks a workbook in row-major order, | ||
|  | generating an array of objects.  The second `opts` argument controls a number of | ||
|  | export decisions including the type of values (JS values or formatted text). The | ||
|  | ["JSON"](#json) section describes the argument in more detail. | ||
|  | 
 | ||
|  | By default, `sheet_to_json` scans the first row and uses the values as headers. | ||
|  | With the `header: 1` option, the function exports an array of arrays of values. | ||
|  | 
 | ||
|  | **Examples** | ||
|  | 
 | ||
|  | [`x-spreadsheet`](https://github.com/myliang/x-spreadsheet) is an interactive | ||
|  | data grid for previewing and modifying structured data in the web browser.  The | ||
|  | [`xspreadsheet` demo](/demos/xspreadsheet) includes a sample script with the | ||
|  | `stox` function for converting from a workbook to x-spreadsheet data object. | ||
|  | <https://oss.sheetjs.com/sheetjs/x-spreadsheet> is a live demo. | ||
|  | 
 | ||
|  | <details> | ||
|  |   <summary><b>Populating a database (SQL or no-SQL)</b> (click to show)</summary> | ||
|  | 
 | ||
|  | The [`database` demo](/demos/database/) includes examples of working with | ||
|  | databases and query results. | ||
|  | 
 | ||
|  | </details> | ||
|  | 
 | ||
|  | <details> | ||
|  |   <summary><b>Numerical Computations with TensorFlow.js</b> (click to show)</summary> | ||
|  | 
 | ||
|  | [`@tensorflow/tfjs`](@tensorflow/tfjs) and other libraries expect data in simple | ||
|  | arrays, well-suited for worksheets where each column is a data vector.  That is | ||
|  | the transpose of how most people use spreadsheets, where each row is a vector. | ||
|  | 
 | ||
|  | A single `Array#map` can pull individual named rows from `sheet_to_json` export: | ||
|  | 
 | ||
|  | ```js | ||
|  | const XLSX = require("xlsx"); | ||
|  | const tf = require('@tensorflow/tfjs'); | ||
|  | 
 | ||
|  | const key = "age"; // this is the field we want to pull | ||
|  | const ages = XLSX.utils.sheet_to_json(worksheet).map(r => r[key]); | ||
|  | const tf_data = tf.tensor1d(ages); | ||
|  | ``` | ||
|  | 
 | ||
|  | All fields can be processed at once using a transpose of the 2D tensor generated | ||
|  | with the `sheet_to_json` export with `header: 1`. The first row, if it contains | ||
|  | header labels, should be removed with a slice: | ||
|  | 
 | ||
|  | ```js | ||
|  | const XLSX = require("xlsx"); | ||
|  | const tf = require('@tensorflow/tfjs'); | ||
|  | 
 | ||
|  | /* array of arrays of the data starting on the second row */ | ||
|  | const aoa = XLSX.utils.sheet_to_json(worksheet, {header: 1}).slice(1); | ||
|  | /* dataset in the "correct orientation" */ | ||
|  | const tf_dataset = tf.tensor2d(aoa).transpose(); | ||
|  | /* pull out each dataset with a slice */ | ||
|  | const tf_field0 = tf_dataset.slice([0,0], [1,tensor.shape[1]]).flatten(); | ||
|  | const tf_field1 = tf_dataset.slice([1,0], [1,tensor.shape[1]]).flatten(); | ||
|  | ``` | ||
|  | 
 | ||
|  | The [`array` demo](demos/array/) shows a complete example. | ||
|  | 
 | ||
|  | </details> | ||
|  | 
 | ||
|  | 
 | ||
|  | ### Generating HTML Tables
 | ||
|  | 
 | ||
|  | **API** | ||
|  | 
 | ||
|  | _Generate HTML Table from Worksheet_ | ||
|  | 
 | ||
|  | ```js | ||
|  | var html = XLSX.utils.sheet_to_html(worksheet); | ||
|  | ``` | ||
|  | 
 | ||
|  | The `sheet_to_html` utility function generates HTML code based on the worksheet | ||
|  | data.  Each cell in the worksheet is mapped to a `<TD>` element.  Merged cells | ||
|  | in the worksheet are serialized by setting `colspan` and `rowspan` attributes. | ||
|  | 
 | ||
|  | **Examples** | ||
|  | 
 | ||
|  | The `sheet_to_html` utility function generates HTML code that can be added to | ||
|  | any DOM element by setting the `innerHTML`: | ||
|  | 
 | ||
|  | ```js | ||
|  | var container = document.getElementById("tavolo"); | ||
|  | container.innerHTML = XLSX.utils.sheet_to_html(worksheet); | ||
|  | ``` | ||
|  | 
 | ||
|  | Combining with `fetch`, constructing a site from a workbook is straightforward: | ||
|  | 
 | ||
|  | <details> | ||
|  |   <summary><b>Vanilla JS + HTML fetch workbook and generate table previews</b> (click to show)</summary> | ||
|  | 
 | ||
|  | ```html | ||
|  | <body> | ||
|  |   <style>TABLE { border-collapse: collapse; } TD { border: 1px solid; }</style> | ||
|  |   <div id="tavolo"></div> | ||
|  |   <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script> | ||
|  |   <script type="text/javascript"> | ||
|  | (async() => { | ||
|  |   /* fetch and parse workbook -- see the fetch example for details */ | ||
|  |   const workbook = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer()); | ||
|  | 
 | ||
|  |   let output = []; | ||
|  |   /* loop through the worksheet names in order */ | ||
|  |   workbook.SheetNames.forEach(name => { | ||
|  | 
 | ||
|  |     /* generate HTML from the corresponding worksheets */ | ||
|  |     const worksheet = workbook.Sheets[name]; | ||
|  |     const html = XLSX.utils.sheet_to_html(worksheet); | ||
|  | 
 | ||
|  |     /* add a header with the title name followed by the table */ | ||
|  |     output.push(`<H3>${name}</H3>${html}`); | ||
|  |   }); | ||
|  |   /* write to the DOM at the end */ | ||
|  |   tavolo.innerHTML = output.join("\n"); | ||
|  | })(); | ||
|  |   </script> | ||
|  | </body> | ||
|  | ``` | ||
|  | 
 | ||
|  | </details> | ||
|  | 
 | ||
|  | <details> | ||
|  |   <summary><b>React fetch workbook and generate HTML table previews</b> (click to show)</summary> | ||
|  | 
 | ||
|  | It is generally recommended to use a React-friendly workflow, but it is possible | ||
|  | to generate HTML and use it in React with `dangerouslySetInnerHTML`: | ||
|  | 
 | ||
|  | ```jsx | ||
|  | function Tabeller(props) { | ||
|  |   /* the workbook object is the state */ | ||
|  |   const [workbook, setWorkbook] = React.useState(XLSX.utils.book_new()); | ||
|  | 
 | ||
|  |   /* fetch and update the workbook with an effect */ | ||
|  |   React.useEffect(() => { (async() => { | ||
|  |     /* fetch and parse workbook -- see the fetch example for details */ | ||
|  |     const wb = XLSX.read(await (await fetch("sheetjs.xlsx")).arrayBuffer()); | ||
|  |     setWorkbook(wb); | ||
|  |   })(); }); | ||
|  | 
 | ||
|  |   return workbook.SheetNames.map(name => (<> | ||
|  |     <h3>name</h3> | ||
|  |     <div dangerouslySetInnerHTML={{ | ||
|  |       /* this __html mantra is needed to set the inner HTML */ | ||
|  |       __html: XLSX.utils.sheet_to_html(workbook.Sheets[name]) | ||
|  |     }} /> | ||
|  |   </>)); | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | The [`react` demo](demos/react) includes more React examples. | ||
|  | 
 | ||
|  | </details> | ||
|  | 
 | ||
|  | <details> | ||
|  |   <summary><b>VueJS fetch workbook and generate HTML table previews</b> (click to show)</summary> | ||
|  | 
 | ||
|  | It is generally recommended to use a VueJS-friendly workflow, but it is possible | ||
|  | to generate HTML and use it in VueJS with the `v-html` directive: | ||
|  | 
 | ||
|  | ```jsx | ||
|  | import { read, utils } from 'xlsx'; | ||
|  | import { reactive } from 'vue'; | ||
|  | 
 | ||
|  | const S5SComponent = { | ||
|  |   mounted() { (async() => { | ||
|  |     /* fetch and parse workbook -- see the fetch example for details */ | ||
|  |     const workbook = read(await (await fetch("sheetjs.xlsx")).arrayBuffer()); | ||
|  |     /* loop through the worksheet names in order */ | ||
|  |     workbook.SheetNames.forEach(name => { | ||
|  |       /* generate HTML from the corresponding worksheets */ | ||
|  |       const html = utils.sheet_to_html(workbook.Sheets[name]); | ||
|  |       /* add to state */ | ||
|  |       this.wb.wb.push({ name, html }); | ||
|  |     }); | ||
|  |   })(); }, | ||
|  |   /* this state mantra is required for array updates to work */ | ||
|  |   setup() { return { wb: reactive({ wb: [] }) }; }, | ||
|  |   template: ` | ||
|  |   <div v-for="ws in wb.wb" :key="ws.name"> | ||
|  |     <h3>{{ ws.name }}</h3> | ||
|  |     <div v-html="ws.html"></div> | ||
|  |   </div>` | ||
|  | }; | ||
|  | ``` | ||
|  | 
 | ||
|  | The [`vuejs` demo](demos/vue) includes more React examples. | ||
|  | 
 | ||
|  | </details> | ||
|  | 
 |