forked from sheetjs/sheetjs
		
	ssf format NaN and Infinity values
This commit is contained in:
		
							parent
							
								
									87a695747e
								
							
						
					
					
						commit
						947a5178bd
					
				| @ -4,8 +4,8 @@ The SheetJS Libraries should be free and clear to use in your projects.  In | ||||
| order to maintain that, every contributor must be vigilant. | ||||
| 
 | ||||
| There have been many projects in the past that have been very lax regarding | ||||
| licensing, and we are of the opinion that those are ticking timebombs and that | ||||
| no commercial product should depend on them. | ||||
| licensing. We are of the opinion that those are ticking timebombs and that no | ||||
| commercial product should depend on them. | ||||
| 
 | ||||
| 
 | ||||
| # Required Reading | ||||
| @ -30,10 +30,9 @@ inbox is self-hosted. | ||||
| 
 | ||||
| # Opening Pull Requests | ||||
| 
 | ||||
| Before opening a pull request, [squash all commits into  | ||||
| one](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). If the pull  | ||||
| request addresses documentation or demos, add `[ci skip]` in the body or title  | ||||
| of your commit message to skip Travis checks. | ||||
| [Squash commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) | ||||
| before opening a pull request, If the pull request addresses documentation or | ||||
| demos, add `[ci skip]` in the body or title of the commit message to skip tests. | ||||
| 
 | ||||
| # Pre-Contribution Checklist | ||||
| 
 | ||||
| @ -57,8 +56,8 @@ issue.  If it is a particularly high-priority issue, please drop an email to | ||||
| Keep these in mind as you work: | ||||
| 
 | ||||
| - Your contributions are your original work.  Take note of any resources you | ||||
|   consult in the process (and be extra careful not to use unlicensed code on | ||||
|   the internet. | ||||
|   consult in the process. Be extra careful not to use unlicensed code on the | ||||
|   Internet or code generated by a large language model or other AI tool. | ||||
| 
 | ||||
| - You are working on your own time.  Unless they explicitly grant permission, | ||||
|   your employer may be the ultimate owner of your IP | ||||
|  | ||||
| @ -940,6 +940,8 @@ function choose_fmt(f/*:string*/, v/*:any*/) { | ||||
| 	if(l<4 && lat>-1) --l; | ||||
| 	if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|"); | ||||
| 	if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"]; | ||||
| 	/* NOTE: most spreadsheet software do not support NaN or infinities */ | ||||
| 	if(typeof v === "number" && !isFinite(v)) v = 0; | ||||
| 	switch(fmt.length) { | ||||
| 		case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break; | ||||
| 		case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break; | ||||
| @ -976,6 +978,8 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) { | ||||
| 	if(SSF_isgeneral(f[1])) return SSF_general(v, o); | ||||
| 	if(v === true) v = "TRUE"; else if(v === false) v = "FALSE"; | ||||
| 	else if(v === "" || v == null) return ""; | ||||
| 	else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!"; | ||||
| 	else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!"; | ||||
| 	return eval_fmt(f[1], v, o, f[0]); | ||||
| } | ||||
| function SSF_load(fmt/*:string*/, idx/*:?number*/)/*:number*/ { | ||||
|  | ||||
| @ -145,7 +145,6 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh | ||||
| 		if(!data[R]) continue; | ||||
| 		if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays"); | ||||
| 		var __R = _R + R, __Rstr = "" + (__R + 1); | ||||
| 		//console.log("!!", R, _R, __R);
 | ||||
| 		if(dense) { | ||||
| 			if(!ws["!data"][__R]) ws["!data"][__R] = []; | ||||
| 			row = ws["!data"][__R]; | ||||
| @ -168,7 +167,11 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh | ||||
| 					else if(!o.sheetStubs) continue; | ||||
| 					else cell.t = 'z'; | ||||
| 				} | ||||
| 				else if(typeof cell.v === 'number') cell.t = 'n'; | ||||
| 				else if(typeof cell.v === 'number') { | ||||
| 					if(isFinite(cell.v)) cell.t = 'n'; | ||||
| 					else if(isNaN(cell.v)) { cell.t = 'e'; cell.v = 0x0F; /* #VALUE! */ } | ||||
| 					else { cell.t = 'e'; cell.v = 0x07; /*# DIV/0 */ } | ||||
| 				} | ||||
| 				else if(typeof cell.v === 'boolean') cell.t = 'b'; | ||||
| 				else if(cell.v instanceof Date) { | ||||
| 					cell.z = o.dateNF || table_fmt[14]; | ||||
| @ -192,4 +195,3 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh | ||||
| 	return ws; | ||||
| } | ||||
| function aoa_to_sheet(data/*:AOA*/, opts/*:?any*/)/*:Worksheet*/ { return sheet_add_aoa(null, data, opts); } | ||||
| 
 | ||||
|  | ||||
| @ -5,6 +5,6 @@ function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t | ||||
| function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);} | ||||
| function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;} | ||||
| function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;} | ||||
| var p2_32 = Math.pow(2,32); | ||||
| var p2_32 = /*#__PURE__*/Math.pow(2,32); | ||||
| function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); } | ||||
| function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; } | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| function init_table(t/*:any*/) { | ||||
| 	if(!t) t = {}; | ||||
| 	t[0]=  'General'; | ||||
| 	t[1]=  '0'; | ||||
| 	t[2]=  '0.00'; | ||||
| @ -28,6 +29,7 @@ function init_table(t/*:any*/) { | ||||
| 	t[48]= '##0.0E+0'; | ||||
| 	t[49]= '@'; | ||||
| 	t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "'; | ||||
| 	return t; | ||||
| } | ||||
| 
 | ||||
| var table_fmt = {}; | ||||
|  | ||||
| @ -39,7 +39,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s | ||||
| 	return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length); | ||||
| } | ||||
| var dec1 = /^#*0*\.([0#]+)/; | ||||
| var closeparen = /\).*[0#]/; | ||||
| var closeparen = /\)[^)]*[0#]/; | ||||
| var phone = /\(###\) ###\\?-####/; | ||||
| function hashq(str/*:string*/)/*:string*/ { | ||||
| 	var o = "", cc; | ||||
|  | ||||
| @ -4,6 +4,8 @@ function choose_fmt(f/*:string*/, v/*:any*/) { | ||||
| 	if(l<4 && lat>-1) --l; | ||||
| 	if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|"); | ||||
| 	if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"]; | ||||
| 	/* NOTE: most spreadsheet software do not support NaN or infinities */ | ||||
| 	if(typeof v === "number" && !isFinite(v)) v = 0; | ||||
| 	switch(fmt.length) { | ||||
| 		case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break; | ||||
| 		case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break; | ||||
| @ -40,5 +42,7 @@ function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) { | ||||
| 	if(isgeneral(f[1])) return general_fmt(v, o); | ||||
| 	if(v === true) v = "TRUE"; else if(v === false) v = "FALSE"; | ||||
| 	else if(v === "" || v == null) return ""; | ||||
| 	else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!"; | ||||
| 	else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!"; | ||||
| 	return eval_fmt(f[1], v, o, f[0]); | ||||
| } | ||||
|  | ||||
| @ -20,7 +20,7 @@ | ||||
| 		"dtslint": "^0.1.2", | ||||
| 		"mocha": "~2.5.3", | ||||
| 		"typescript": "2.2.0", | ||||
| 		"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz" | ||||
| 		"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz" | ||||
| 	}, | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
|  | ||||
| @ -12,7 +12,7 @@ function pad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v;return t.length>=d?t | ||||
| function rpad_(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);} | ||||
| function pad0r1(v/*:any*/,d/*:number*/)/*:string*/{var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;} | ||||
| function pad0r2(v/*:any*/,d/*:number*/)/*:string*/{var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;} | ||||
| var p2_32 = Math.pow(2,32); | ||||
| var p2_32 = /*#__PURE__*/Math.pow(2,32); | ||||
| function pad0r(v/*:any*/,d/*:number*/)/*:string*/{if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); } | ||||
| function isgeneral(s/*:string*/, i/*:?number*/)/*:boolean*/ { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; } | ||||
| /*:: | ||||
| @ -42,6 +42,7 @@ var months/*:Array<Array<string> >*/ = [ | ||||
| 	['D', 'Dec', 'December'] | ||||
| ]; | ||||
| function init_table(t/*:any*/) { | ||||
| 	if(!t) t = {}; | ||||
| 	t[0]=  'General'; | ||||
| 	t[1]=  '0'; | ||||
| 	t[2]=  '0.00'; | ||||
| @ -71,6 +72,7 @@ function init_table(t/*:any*/) { | ||||
| 	t[48]= '##0.0E+0'; | ||||
| 	t[49]= '@'; | ||||
| 	t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "'; | ||||
| 	return t; | ||||
| } | ||||
| 
 | ||||
| var table_fmt = {}; | ||||
| @ -417,7 +419,7 @@ function write_num_f2(r/*:Array<string>*/, aval/*:number*/, sign/*:string*/)/*:s | ||||
| 	return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length); | ||||
| } | ||||
| var dec1 = /^#*0*\.([0#]+)/; | ||||
| var closeparen = /\).*[0#]/; | ||||
| var closeparen = /\)[^)]*[0#]/; | ||||
| var phone = /\(###\) ###\\?-####/; | ||||
| function hashq(str/*:string*/)/*:string*/ { | ||||
| 	var o = "", cc; | ||||
| @ -951,6 +953,8 @@ function choose_fmt(f/*:string*/, v/*:any*/) { | ||||
| 	if(l<4 && lat>-1) --l; | ||||
| 	if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|"); | ||||
| 	if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"]; | ||||
| 	/* NOTE: most spreadsheet software do not support NaN or infinities */ | ||||
| 	if(typeof v === "number" && !isFinite(v)) v = 0; | ||||
| 	switch(fmt.length) { | ||||
| 		case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break; | ||||
| 		case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break; | ||||
| @ -987,6 +991,8 @@ function format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) { | ||||
| 	if(isgeneral(f[1])) return general_fmt(v, o); | ||||
| 	if(v === true) v = "TRUE"; else if(v === false) v = "FALSE"; | ||||
| 	else if(v === "" || v == null) return ""; | ||||
| 	else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!"; | ||||
| 	else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!"; | ||||
| 	return eval_fmt(f[1], v, o, f[0]); | ||||
| } | ||||
| function load_entry(fmt/*:string*/, idx/*:?number*/)/*:number*/ { | ||||
|  | ||||
| @ -38,6 +38,7 @@ var months = [ | ||||
| 	['D', 'Dec', 'December'] | ||||
| ]; | ||||
| function init_table(t) { | ||||
| 	if(!t) t = {}; | ||||
| 	t[0]=  'General'; | ||||
| 	t[1]=  '0'; | ||||
| 	t[2]=  '0.00'; | ||||
| @ -67,6 +68,7 @@ function init_table(t) { | ||||
| 	t[48]= '##0.0E+0'; | ||||
| 	t[49]= '@'; | ||||
| 	t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "'; | ||||
| 	return t; | ||||
| } | ||||
| 
 | ||||
| var table_fmt = {}; | ||||
| @ -412,7 +414,7 @@ function write_num_f2(r, aval, sign) { | ||||
| 	return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length); | ||||
| } | ||||
| var dec1 = /^#*0*\.([0#]+)/; | ||||
| var closeparen = /\).*[0#]/; | ||||
| var closeparen = /\)[^)]*[0#]/; | ||||
| var phone = /\(###\) ###\\?-####/; | ||||
| function hashq(str) { | ||||
| 	var o = "", cc; | ||||
| @ -943,6 +945,8 @@ function choose_fmt(f, v) { | ||||
| 	if(l<4 && lat>-1) --l; | ||||
| 	if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|"); | ||||
| 	if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"]; | ||||
| 	/* NOTE: most spreadsheet software do not support NaN or infinities */ | ||||
| 	if(typeof v === "number" && !isFinite(v)) v = 0; | ||||
| 	switch(fmt.length) { | ||||
| 		case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break; | ||||
| 		case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break; | ||||
| @ -979,6 +983,8 @@ function format(fmt,v,o) { | ||||
| 	if(isgeneral(f[1])) return general_fmt(v, o); | ||||
| 	if(v === true) v = "TRUE"; else if(v === false) v = "FALSE"; | ||||
| 	else if(v === "" || v == null) return ""; | ||||
| 	else if(isNaN(v) && f[1].indexOf("0") > -1) return "#VALUE!"; | ||||
| 	else if(!isFinite(v) && f[1].indexOf("0") > -1) return "#DIV/0!"; | ||||
| 	return eval_fmt(f[1], v, o, f[0]); | ||||
| } | ||||
| function load_entry(fmt, idx) { | ||||
|  | ||||
| @ -19,4 +19,12 @@ describe('oddities', function() { | ||||
|     var chk = function(fmt){ return function(){ SSF.format(fmt,0); }; }; | ||||
|     bad.forEach(function(fmt){assert.throws(chk(fmt));}); | ||||
|   }); | ||||
|   it('should handle NaN values and infinities', function() { | ||||
|     assert.equal(SSF.format('#,##0.0; (#,##0.0); "-"', NaN), " -"); | ||||
|     assert.equal(SSF.format('#,##0.0; (#,##0.0); "-"', Infinity), " -"); | ||||
|     assert.equal(SSF.format('#,##0.0; (#,##0.0); "-"', -Infinity), " -"); | ||||
|     assert.equal(SSF.format('0.00', NaN), "#VALUE!"); | ||||
|     assert.equal(SSF.format('0.00', Infinity), "#DIV/0!"); | ||||
|     assert.equal(SSF.format('0.00', -Infinity), "#DIV/0!"); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
							
								
								
									
										8
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -24,12 +24,12 @@ export function readFile(filename: string, opts?: ParsingOptions): WorkBook; | ||||
| /** Attempts to parse data */ | ||||
| export function read(data: any, opts?: ParsingOptions): WorkBook; | ||||
| /** Attempts to write or download workbook data to file */ | ||||
| export function writeFile(data: WorkBook, filename: string, opts?: WritingOptions): any; | ||||
| export function writeFile(data: WorkBook, filename: string, opts?: WritingOptions): void; | ||||
| /** Attempts to write or download workbook data to XLSX file */ | ||||
| export function writeFileXLSX(data: WorkBook, filename: string, opts?: WritingOptions): any; | ||||
| export function writeFileXLSX(data: WorkBook, filename: string, opts?: WritingOptions): void; | ||||
| /** Attempts to write or download workbook data to file asynchronously */ | ||||
| type CBFunc = () => void; | ||||
| export function writeFileAsync(filename: string, data: WorkBook, opts: WritingOptions | CBFunc, cb?: CBFunc): any; | ||||
| export function writeFileAsync(filename: string, data: WorkBook, opts: WritingOptions | CBFunc, cb?: CBFunc): void; | ||||
| /** Attempts to write the workbook data */ | ||||
| export function write(data: WorkBook, opts: WritingOptions): any; | ||||
| /** Attempts to write the workbook data as XLSX */ | ||||
| @ -277,7 +277,7 @@ export interface WritingOptions extends CommonOptions { | ||||
|      */ | ||||
|     compression?: boolean; | ||||
| 
 | ||||
|     /** Overwride theme XML when exporting to XLSX/XLSM/XLSB */ | ||||
|     /** Override theme XML when exporting to XLSX/XLSM/XLSB */ | ||||
|     themeXLSX?: string; | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user