forked from sheetjs/sheetjs
		
	x-spreadsheet demo merges and formulae [ci skip]
Co-authored-by: SheetJS <dev@sheetjs.com>
This commit is contained in:
		
							parent
							
								
									e110fe8952
								
							
						
					
					
						commit
						5c02c819f6
					
				| @ -35,56 +35,21 @@ var grid = x_spreadsheet(document.getElementById("gridctr")); | ||||
| The following function converts data from SheetJS to x-spreadsheet: | ||||
| 
 | ||||
| ```js | ||||
| function stox(wb) { | ||||
|   var out = []; | ||||
|   wb.SheetNames.forEach(function(name) { | ||||
|     var o = {name:name, rows:{}}; | ||||
|     var ws = wb.Sheets[name]; | ||||
|     var aoa = XLSX.utils.sheet_to_json(ws, {raw: false, header:1}); | ||||
|     aoa.forEach(function(r, i) { | ||||
|       var cells = {}; | ||||
|       r.forEach(function(c, j) { cells[j] = ({ text: c }); }); | ||||
|       o.rows[i] = { cells: cells }; | ||||
|     }) | ||||
|     out.push(o); | ||||
|   }); | ||||
|   return out; | ||||
| } | ||||
| 
 | ||||
| /* load data */ | ||||
| grid.loadData(stox(workbook_object)); | ||||
| ``` | ||||
| 
 | ||||
| `stox` is defined in [xlsxspread.js](./xlsxspread.js) | ||||
| 
 | ||||
| ## Editing | ||||
| 
 | ||||
| `x-spreadsheet` handles the entire edit cycle.  No intervention is necessary. | ||||
| `x-spreadsheet` handles the entire edit cycle. No intervention is necessary. | ||||
| 
 | ||||
| ## Saving Data | ||||
| 
 | ||||
| `grid.getData()` returns an object that can be converted back to a worksheet: | ||||
| 
 | ||||
| ```js | ||||
| function xtos(sdata) { | ||||
|   var out = XLSX.utils.book_new(); | ||||
|   sdata.forEach(function(xws) { | ||||
|     var aoa = [[]]; | ||||
|     var rowobj = xws.rows; | ||||
|     for(var ri = 0; ri < rowobj.len; ++ri) { | ||||
|       var row = rowobj[ri]; | ||||
|       if(!row) continue; | ||||
|       aoa[ri] = []; | ||||
|       Object.keys(row.cells).forEach(function(k) { | ||||
|         var idx = +k; | ||||
|         if(isNaN(idx)) return; | ||||
|         aoa[ri][idx] = row.cells[k].text; | ||||
|       }); | ||||
|     } | ||||
|     var ws = XLSX.utils.aoa_to_sheet(aoa); | ||||
|     XLSX.utils.book_append_sheet(out, ws, xws.name); | ||||
|   }); | ||||
|   return out; | ||||
| } | ||||
| 
 | ||||
| /* build workbook from the grid data */ | ||||
| var new_wb = xtos(xspr.getData()); | ||||
| 
 | ||||
| @ -92,6 +57,8 @@ var new_wb = xtos(xspr.getData()); | ||||
| XLSX.writeFile(new_wb, "SheetJS.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| `stox` is defined in [xlsxspread.js](./xlsxspread.js) | ||||
| 
 | ||||
| ## Additional Features | ||||
| 
 | ||||
| This demo barely scratches the surface.  The underlying grid component includes | ||||
|  | ||||
| @ -1,37 +1,141 @@ | ||||
| /*! xlsxspread.js (C) SheetJS LLC -- https://sheetjs.com/ */ | ||||
| /* eslint-env browser */ | ||||
| /*global XLSX */ | ||||
| /*exported stox, xtos */ | ||||
| 
 | ||||
| /** | ||||
|  * Converts data from SheetJS to x-spreadsheet | ||||
|  * | ||||
|  * @param  {Object} wb SheetJS workbook object | ||||
|  * | ||||
|  * @returns {Object[]} An x-spreadsheet data | ||||
|  */ | ||||
| function stox(wb) { | ||||
| 	var out = []; | ||||
| 	wb.SheetNames.forEach(function(name) { | ||||
| 		var o = {name:name, rows:{}}; | ||||
| 		var ws = wb.Sheets[name]; | ||||
| 		var aoa = XLSX.utils.sheet_to_json(ws, {raw: false, header:1}); | ||||
| 		aoa.forEach(function(r, i) { | ||||
| 			var cells = {}; | ||||
| 			r.forEach(function(c, j) { cells[j] = ({ text: c }); }); | ||||
| 			o.rows[i] = { cells: cells }; | ||||
| 		}) | ||||
| 		out.push(o); | ||||
| 	}); | ||||
| 	return out; | ||||
|   var out = []; | ||||
|   wb.SheetNames.forEach(function (name) { | ||||
|     var o = { name: name, rows: {} }; | ||||
|     var ws = wb.Sheets[name]; | ||||
|     var range = XLSX.utils.decode_range(ws['!ref']); | ||||
|     // sheet_to_json will lost empty row and col at begin as default
 | ||||
|     range.s = { r: 0, c: 0 }; | ||||
|     var aoa = XLSX.utils.sheet_to_json(ws, { | ||||
|       raw: false, | ||||
|       header: 1, | ||||
|       range: range | ||||
|     }); | ||||
| 
 | ||||
|     aoa.forEach(function (r, i) { | ||||
|       var cells = {}; | ||||
|       r.forEach(function (c, j) { | ||||
|         cells[j] = { text: c }; | ||||
| 
 | ||||
|         var cellRef = XLSX.utils.encode_cell({ r: i, c: j }); | ||||
| 
 | ||||
|         if ( ws[cellRef] != null && ws[cellRef].f != null) { | ||||
|           cells[j].text = "=" + ws[cellRef].f; | ||||
|         } | ||||
|       }); | ||||
|       o.rows[i] = { cells: cells }; | ||||
|     }); | ||||
| 
 | ||||
|     o.merges = []; | ||||
|     (ws["!merges"]||[]).forEach(function (merge, i) { | ||||
|       //Needed to support merged cells with empty content
 | ||||
|       if (o.rows[merge.s.r] == null) { | ||||
|         o.rows[merge.s.r] = { cells: {} }; | ||||
|       } | ||||
|       if (o.rows[merge.s.r].cells[merge.s.c] == null) { | ||||
|         o.rows[merge.s.r].cells[merge.s.c] = {}; | ||||
|       } | ||||
| 
 | ||||
|       o.rows[merge.s.r].cells[merge.s.c].merge = [ | ||||
|         merge.e.r - merge.s.r, | ||||
|         merge.e.c - merge.s.c | ||||
|       ]; | ||||
| 
 | ||||
|       o.merges[i] = XLSX.utils.encode_range(merge); | ||||
|     }); | ||||
| 
 | ||||
|     out.push(o); | ||||
|   }); | ||||
| 
 | ||||
|   return out; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Converts data from x-spreadsheet to SheetJS | ||||
|  * | ||||
|  * @param  {Object[]} sdata An x-spreadsheet data object | ||||
|  * | ||||
|  * @returns {Object} A SheetJS workbook object | ||||
|  */ | ||||
| function xtos(sdata) { | ||||
| 	var out = XLSX.utils.book_new(); | ||||
| 	sdata.forEach(function(xws) { | ||||
| 		var aoa = [[]]; | ||||
| 		var rowobj = xws.rows; | ||||
| 		for(var ri = 0; ri < rowobj.len; ++ri) { | ||||
| 			var row = rowobj[ri]; | ||||
| 			if(!row) continue; | ||||
| 			aoa[ri] = []; | ||||
| 			Object.keys(row.cells).forEach(function(k) { | ||||
| 				var idx = +k; | ||||
| 				if(isNaN(idx)) return; | ||||
| 				aoa[ri][idx] = row.cells[k].text; | ||||
| 			}); | ||||
| 		} | ||||
| 		var ws = XLSX.utils.aoa_to_sheet(aoa); | ||||
| 		XLSX.utils.book_append_sheet(out, ws, xws.name); | ||||
| 	}); | ||||
| 	return out; | ||||
| } | ||||
|   var out = XLSX.utils.book_new(); | ||||
|   sdata.forEach(function (xws) { | ||||
|     var ws = {}; | ||||
|     var rowobj = xws.rows; | ||||
|     for (var ri = 0; ri < rowobj.len; ++ri) { | ||||
|       var row = rowobj[ri]; | ||||
|       if (!row) continue; | ||||
| 
 | ||||
|       var minCoord, maxCoord; | ||||
|       Object.keys(row.cells).forEach(function (k) { | ||||
|         var idx = +k; | ||||
|         if (isNaN(idx)) return; | ||||
| 
 | ||||
|         var lastRef = XLSX.utils.encode_cell({ r: ri, c: idx }); | ||||
|         if (minCoord == null) { | ||||
|           minCoord = { r: ri, c: idx }; | ||||
|         } else { | ||||
|           if (ri < minCoord.r) minCoord.r = ri; | ||||
|           if (idx < minCoord.c) minCoord.c = idx; | ||||
|         } | ||||
|         if (maxCoord == undefined) { | ||||
|           maxCoord = { r: ri, c: idx }; | ||||
|         } else { | ||||
|           if (ri > maxCoord.r) maxCoord.r = ri; | ||||
|           if (idx > maxCoord.c) maxCoord.c = idx; | ||||
|         } | ||||
| 
 | ||||
|         var cellText = row.cells[k].text, type = "s"; | ||||
|         if (!cellText) { | ||||
|           cellText = ""; | ||||
|           type = "z"; | ||||
|         } else if (!isNaN(parseFloat(cellText))) { | ||||
|           cellText = parseFloat(cellText); | ||||
|           type = "n"; | ||||
|         } else if (cellText.toLowerCase() === "true" || cellText.toLowerCase() === "false") { | ||||
|           cellText = Boolean(cellText); | ||||
|           type = "b"; | ||||
|         } | ||||
| 
 | ||||
|         ws[lastRef] = { v: cellText, t: type }; | ||||
| 
 | ||||
|         if (type == "s" && cellText[0] == "=") { | ||||
|           ws[lastRef].f = cellText.slice(1); | ||||
|         } | ||||
| 
 | ||||
|         if (row.cells[k].merge != null) { | ||||
|           if (ws["!merges"] == null) ws["!merges"] = []; | ||||
| 
 | ||||
|           ws["!merges"].push({ | ||||
|             s: { r: ri, c: idx }, | ||||
|             e: { | ||||
|               r: ri + row.cells[k].merge[0], | ||||
|               c: idx + row.cells[k].merge[1] | ||||
|             } | ||||
|           }); | ||||
|         } | ||||
|       }); | ||||
| 
 | ||||
|       ws["!ref"] = XLSX.utils.encode_range({ | ||||
|         s: { r: minCoord.r, c: minCoord.c }, | ||||
|         e: { r: maxCoord.r, c: maxCoord.c } | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     XLSX.utils.book_append_sheet(out, ws, xws.name); | ||||
|   }); | ||||
| 
 | ||||
|   return out; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user