2022-02-13 09:35:34 +00:00
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint mocha:true */
/* eslint-env mocha */
/*global process, document, require */
/*global ArrayBuffer, Uint8Array */
/ * : :
declare type EmptyFunc = ( ( ) => void ) | null ;
declare type DescribeIt = { ( desc : string , test : EmptyFunc ) : void ; skip ( desc : string , test : EmptyFunc ) : void ; } ;
declare var describe : DescribeIt ;
declare var it : DescribeIt ;
declare var before : ( test : EmptyFunc ) => void ;
declare var afterEach : ( test : EmptyFunc ) => void ;
declare var cptable : any ;
* /
import * as fs from 'fs' ;
import * as assert from 'assert' ;
import * as X from './xlsx.mjs' ;
X . set _fs ( fs ) ;
2022-05-17 01:26:22 +00:00
import * as cptable from './dist/cpexcel.full.mjs' ;
X . set _cptable ( cptable ) ;
import XLSX _ZAHL from './dist/xlsx.zahl.mjs' ;
2022-02-13 09:35:34 +00:00
var DIF _XL = true ;
var browser = typeof document !== 'undefined' ;
var Buffer _from = /*::(*/ function ( ) { } /*:: :any)*/ ;
if ( typeof Buffer !== 'undefined' ) {
var nbfs = ! Buffer . from ;
if ( ! nbfs ) try { Buffer . from ( "foo" , "utf8" ) ; } catch ( e ) { nbfs = true ; }
Buffer _from = nbfs ? function ( buf , enc ) { return ( enc ) ? new Buffer ( buf , enc ) : new Buffer ( buf ) ; } : Buffer . from . bind ( Buffer ) ;
// $FlowIgnore
if ( ! Buffer . alloc ) Buffer . alloc = function ( n ) { return new Buffer ( n ) ; } ;
}
var opts = ( { cellNF : true } /*:any*/ ) ;
var TYPE = browser ? "binary" : "buffer" ;
opts . type = TYPE ;
var fullex = [ ".xlsb" , /*".xlsm",*/ ".xlsx" /*, ".xlml", ".xls"*/ ] ;
var ofmt = [ "xlsb" , "xlsm" , "xlsx" , "ods" , "biff2" , "biff5" , "biff8" , "xlml" , "sylk" , "dif" , "dbf" , "eth" , "fods" , "csv" , "txt" , "html" ] ;
var ex = fullex . slice ( ) ; ex = ex . concat ( [ ".ods" , ".xls" , ".xml" , ".fods" ] ) ;
if ( typeof process != 'undefined' && ( ( process || { } ) . env ) ) {
opts . WTF = true ;
opts . cellStyles = true ;
if ( process . env . FMTS === "full" ) process . env . FMTS = ex . join ( ":" ) ;
if ( process . env . FMTS ) ex = process . env . FMTS . split ( ":" ) . map ( function ( x ) { return x [ 0 ] === "." ? x : "." + x ; } ) ;
}
var exp = ex . map ( function ( x ) { return x + ".pending" ; } ) ;
function test _file ( x ) { return ex . indexOf ( x . slice ( - 5 ) ) >= 0 || exp . indexOf ( x . slice ( - 13 ) ) >= 0 || ex . indexOf ( x . slice ( - 4 ) ) >= 0 || exp . indexOf ( x . slice ( - 12 ) ) >= 0 ; }
var files = [ ] , fileA = [ ] ;
if ( ! browser ) {
var _files = fs . existsSync ( 'tests.lst' ) ? fs . readFileSync ( 'tests.lst' , 'utf-8' ) . split ( "\n" ) . map ( function ( x ) { return x . trim ( ) ; } ) : fs . readdirSync ( 'test_files' ) ;
for ( var _filesi = 0 ; _filesi < _files . length ; ++ _filesi ) if ( test _file ( _files [ _filesi ] ) ) files . push ( _files [ _filesi ] ) ;
var _fileA = fs . existsSync ( 'tests/testA.lst' ) ? fs . readFileSync ( 'tests/testA.lst' , 'utf-8' ) . split ( "\n" ) . map ( function ( x ) { return x . trim ( ) ; } ) : [ ] ;
for ( var _fileAi = 0 ; _fileAi < _fileA . length ; ++ _fileAi ) if ( test _file ( _fileA [ _fileAi ] ) ) fileA . push ( _fileA [ _fileAi ] ) ;
}
2022-09-22 09:05:24 +00:00
var can _write _numbers = typeof Set !== "undefined" && typeof Array . prototype . findIndex == "function" && typeof Uint8Array !== "undefined" && typeof Uint8Array . prototype . indexOf == "function" ;
2022-02-13 09:35:34 +00:00
/* Excel enforces 31 character sheet limit, although technical file limit is 255 */
function fixsheetname ( x /*:string*/ ) /*:string*/ { return x . substr ( 0 , 31 ) ; }
function stripbom ( x /*:string*/ ) /*:string*/ { return x . replace ( /^\ufeff/ , "" ) ; }
function fixcsv ( x /*:string*/ ) /*:string*/ { return stripbom ( x ) . replace ( /\t/g , "," ) . replace ( /#{255}/g , "" ) . replace ( /"/g , "" ) . replace ( /[\n\r]+/g , "\n" ) . replace ( /\n*$/ , "" ) ; }
function fixjson ( x /*:string*/ ) /*:string*/ { return x . replace ( /[\r\n]+$/ , "" ) ; }
var dir = "./test_files/" ;
var dirwp = dir + "artifacts/wps/" , dirqp = dir + "artifacts/quattro/" ;
var paths = {
aadbf : dirwp + 'write.dbf' ,
aadif : dirwp + 'write.dif' ,
aaxls : dirwp + 'write.xls' ,
aaxlsx : dirwp + 'write.xlsx' ,
aaxml : dirwp + 'write.xml' ,
abcsv : dirqp + 'write_.csv' ,
abdif : dirqp + 'write_.dif' ,
abslk : dirqp + 'write_.slk' ,
abx57 : dirqp + 'write_57.xls' ,
abwb2 : dirqp + 'write_6.wb2' ,
abwb2b : dirqp + 'write_6b.wb2' ,
abwb3 : dirqp + 'write_8.wb3' ,
abqpw : dirqp + 'write_9.qpw' ,
abx97 : dirqp + 'write_97.xls' ,
abwks : dirqp + 'write_L1.wks' ,
abwk1 : dirqp + 'write_L2.wk1' ,
abwk3 : dirqp + 'write_L3.wk3' ,
abwk4 : dirqp + 'write_L45.wk4' ,
ab123 : dirqp + 'write_L9.123' ,
ab124 : dirqp + 'write_L97.123' ,
abwke2 : dirqp + 'write_Led.wke' ,
abwq1 : dirqp + 'write_qpdos.wq1' ,
abwb1 : dirqp + 'write_qpw.wb1' ,
afxls : dir + 'AutoFilter.xls' ,
afxml : dir + 'AutoFilter.xml' ,
afods : dir + 'AutoFilter.ods' ,
afxlsx : dir + 'AutoFilter.xlsx' ,
afxlsb : dir + 'AutoFilter.xlsb' ,
asxls : dir + 'author_snowman.xls' ,
asxls5 : dir + 'author_snowman.xls5' ,
asxml : dir + 'author_snowman.xml' ,
asods : dir + 'author_snowman.ods' ,
asxlsx : dir + 'author_snowman.xlsx' ,
asxlsb : dir + 'author_snowman.xlsb' ,
cpxls : dir + 'custom_properties.xls' ,
cpxml : dir + 'custom_properties.xls.xml' ,
cpxlsx : dir + 'custom_properties.xlsx' ,
cpxlsb : dir + 'custom_properties.xlsb' ,
cssxls : dir + 'cell_style_simple.xls' ,
cssxml : dir + 'cell_style_simple.xml' ,
cssxlsx : dir + 'cell_style_simple.xlsx' ,
cssxlsb : dir + 'cell_style_simple.xlsb' ,
cstxls : dir + 'comments_stress_test.xls' ,
cstxml : dir + 'comments_stress_test.xls.xml' ,
cstxlsx : dir + 'comments_stress_test.xlsx' ,
cstxlsb : dir + 'comments_stress_test.xlsb' ,
cstods : dir + 'comments_stress_test.ods' ,
cwxls : dir + 'column_width.xls' ,
cwxls5 : dir + 'column_width.biff5' ,
cwxml : dir + 'column_width.xml' ,
cwxlsx : dir + 'column_width.xlsx' ,
cwxlsb : dir + 'column_width.xlsb' ,
cwslk : dir + 'column_width.slk' ,
dnsxls : dir + 'defined_names_simple.xls' ,
dnsxml : dir + 'defined_names_simple.xml' ,
dnsxlsx : dir + 'defined_names_simple.xlsx' ,
dnsxlsb : dir + 'defined_names_simple.xlsb' ,
2022-05-17 01:26:22 +00:00
dnsslk : dir + 'defined_names_simple.slk' ,
2022-02-13 09:35:34 +00:00
dnuxls : dir + 'defined_names_unicode.xls' ,
dnuxml : dir + 'defined_names_unicode.xml' ,
dnuods : dir + 'defined_names_unicode.ods' ,
dnuxlsx : dir + 'defined_names_unicode.xlsx' ,
dnuxlsb : dir + 'defined_names_unicode.xlsb' ,
dtxls : dir + 'xlsx-stream-d-date-cell.xls' ,
dtxml : dir + 'xlsx-stream-d-date-cell.xls.xml' ,
dtxlsx : dir + 'xlsx-stream-d-date-cell.xlsx' ,
dtxlsb : dir + 'xlsx-stream-d-date-cell.xlsb' ,
2022-03-20 05:29:24 +00:00
dtfxlsx : dir + 'DataTypesFormats.xlsx' ,
2022-02-13 09:35:34 +00:00
fstxls : dir + 'formula_stress_test.xls' ,
fstxml : dir + 'formula_stress_test.xls.xml' ,
fstxlsx : dir + 'formula_stress_test.xlsx' ,
fstxlsb : dir + 'formula_stress_test.xlsb' ,
fstods : dir + 'formula_stress_test.ods' ,
hlxls : dir + 'hyperlink_stress_test_2011.xls' ,
hlxml : dir + 'hyperlink_stress_test_2011.xml' ,
hlxlsx : dir + 'hyperlink_stress_test_2011.xlsx' ,
hlxlsb : dir + 'hyperlink_stress_test_2011.xlsb' ,
ilxls : dir + 'internal_link.xls' ,
ilxls5 : dir + 'internal_link.biff5' ,
ilxml : dir + 'internal_link.xml' ,
ilxlsx : dir + 'internal_link.xlsx' ,
ilxlsb : dir + 'internal_link.xlsb' ,
ilods : dir + 'internal_link.ods' ,
lonxls : dir + 'LONumbers.xls' ,
lonxlsx : dir + 'LONumbers.xlsx' ,
2022-03-16 03:18:09 +00:00
m19xlsx : dir + 'metadata_2019.xlsx' ,
m19xlsb : dir + 'metadata_2019.xlsb' ,
2022-02-13 09:35:34 +00:00
mcxls : dir + 'merge_cells.xls' ,
mcxml : dir + 'merge_cells.xls.xml' ,
mcxlsx : dir + 'merge_cells.xlsx' ,
mcxlsb : dir + 'merge_cells.xlsb' ,
mcods : dir + 'merge_cells.ods' ,
nfxls : dir + 'number_format.xls' ,
nfxml : dir + 'number_format.xls.xml' ,
nfxlsx : dir + 'number_format.xlsm' ,
nfxlsb : dir + 'number_format.xlsb' ,
olxls : dir + 'outline.xls' ,
olxls5 : dir + 'outline.biff5' ,
olxlsx : dir + 'outline.xlsx' ,
olxlsb : dir + 'outline.xlsb' ,
olods : dir + 'outline.ods' ,
pmxls : dir + 'page_margins_2016.xls' ,
pmxls5 : dir + 'page_margins_2016_5.xls' ,
pmxml : dir + 'page_margins_2016.xml' ,
pmxlsx : dir + 'page_margins_2016.xlsx' ,
pmxlsb : dir + 'page_margins_2016.xlsb' ,
rhxls : dir + 'row_height.xls' ,
rhxls5 : dir + 'row_height.biff5' ,
rhxml : dir + 'row_height.xml' ,
rhxlsx : dir + 'row_height.xlsx' ,
rhxlsb : dir + 'row_height.xlsb' ,
rhslk : dir + 'row_height.slk' ,
svxls : dir + 'sheet_visibility.xls' ,
2022-05-22 23:51:41 +00:00
svxls5 : dir + 'sheet_visibility5.xls' ,
2022-02-13 09:35:34 +00:00
svxml : dir + 'sheet_visibility.xml' ,
svxlsx : dir + 'sheet_visibility.xlsx' ,
svxlsb : dir + 'sheet_visibility.xlsb' ,
2022-05-22 23:51:41 +00:00
svods : dir + 'sheet_visibility.ods' ,
2022-02-13 09:35:34 +00:00
swcxls : dir + 'apachepoi_SimpleWithComments.xls' ,
swcxml : dir + '2011/apachepoi_SimpleWithComments.xls.xml' ,
swcxlsx : dir + 'apachepoi_SimpleWithComments.xlsx' ,
swcxlsb : dir + '2013/apachepoi_SimpleWithComments.xlsx.xlsb'
} ;
function pathit ( p , ext ) { return ext . map ( function ( n ) { return paths [ p + n ] ; } ) ; }
var FSTPaths = pathit ( "fst" , [ "xlsx" , "xlsb" , "xls" , "xml" , "ods" ] ) ;
var CSTPaths = pathit ( "cst" , [ "xlsx" , "xlsb" , "xls" , "xml" , "ods" ] ) ;
var MCPaths = pathit ( "mc" , [ "xlsx" , "xlsb" , "xls" , "xml" , "ods" ] ) ;
var CSSPaths = pathit ( "css" , [ "xlsx" , "xlsb" , "xls" , "xml" ] ) ;
var NFPaths = pathit ( "nf" , [ "xlsx" , "xlsb" , "xls" , "xml" ] ) ;
var DTPaths = pathit ( "dt" , [ "xlsx" , "xlsb" , "xls" , "xml" ] ) ;
var HLPaths = pathit ( "hl" , [ "xlsx" , "xlsb" , "xls" , "xml" ] ) ;
var ILPaths = pathit ( "il" , [ "xlsx" , "xlsb" , "xls" , "xml" , "ods" , "xls5" ] ) ;
var OLPaths = pathit ( "ol" , [ "xlsx" , "xlsb" , "xls" , "ods" , "xls5" ] ) ;
var PMPaths = pathit ( "pm" , [ "xlsx" , "xlsb" , "xls" , "xml" , "xls5" ] ) ;
var SVPaths = pathit ( "sv" , [ "xlsx" , "xlsb" , "xls" , "xml" , "xls5" ] ) ;
var CWPaths = pathit ( "cw" , [ "xlsx" , "xlsb" , "xls" , "xml" , "xls5" , "slk" ] ) ;
var RHPaths = pathit ( "rh" , [ "xlsx" , "xlsb" , "xls" , "xml" , "xls5" , "slk" ] ) ;
var artifax = [
"cstods" , "cstxls" , "cstxlsb" , "cstxlsb" , "cstxml" , "aadbf" , "aadif" ,
"aaxls" , "aaxml" , "aaxlsx" , "ab123" , "ab124" , "abcsv" , "abdif" , "abqpw" ,
"abslk" , "abwb1" , "abwb2" , "abwb3" , "abwk1" , "abwk3" , "abwk4" , "abwks" ,
"abwq1" , "abx57" , "abx97" , "abwke2" , "abwb2b"
] . map ( function ( x ) { return paths [ x ] ; } ) ;
function parsetest ( x /*:string*/ , wb /*:Workbook*/ , full /*:boolean*/ , ext /*:?string*/ ) {
ext = ( ext ? " [" + ext + "]" : "" ) ;
if ( ! full && ext ) return ;
describe ( x + ext + ' should have all bits' , function ( ) {
var sname = dir + '2016/' + x . substr ( x . lastIndexOf ( '/' ) + 1 ) + '.sheetnames' ;
if ( ! fs . existsSync ( sname ) ) sname = dir + '2011/' + x . substr ( x . lastIndexOf ( '/' ) + 1 ) + '.sheetnames' ;
if ( ! fs . existsSync ( sname ) ) sname = dir + '2013/' + x . substr ( x . lastIndexOf ( '/' ) + 1 ) + '.sheetnames' ;
it ( 'should have all sheets' , function ( ) {
wb . SheetNames . forEach ( function ( y ) { assert . ok ( wb . Sheets [ y ] , 'bad sheet ' + y ) ; } ) ;
} ) ;
if ( fs . existsSync ( sname ) ) it ( 'should have the right sheet names' , function ( ) {
var file = fs . readFileSync ( sname , 'utf-8' ) . replace ( /\r/g , "" ) ;
var names = wb . SheetNames . map ( fixsheetname ) . join ( "\n" ) + "\n" ;
if ( file . length && ! x . match ( /artifacts/ ) ) assert . equal ( names , file ) ;
} ) ;
} ) ;
describe ( x + ext + ' should generate CSV' , function ( ) {
wb . SheetNames . forEach ( function ( ws , i ) {
it ( '#' + i + ' (' + ws + ')' , function ( ) {
X . utils . sheet _to _csv ( wb . Sheets [ ws ] ) ;
} ) ;
} ) ;
} ) ;
describe ( x + ext + ' should generate JSON' , function ( ) {
wb . SheetNames . forEach ( function ( ws , i ) {
it ( '#' + i + ' (' + ws + ')' , function ( ) {
X . utils . sheet _to _json ( wb . Sheets [ ws ] ) ;
} ) ;
} ) ;
} ) ;
describe ( x + ext + ' should generate formulae' , function ( ) {
wb . SheetNames . forEach ( function ( ws , i ) {
it ( '#' + i + ' (' + ws + ')' , function ( ) {
X . utils . sheet _to _formulae ( wb . Sheets [ ws ] ) ;
} ) ;
} ) ;
} ) ;
if ( ! full ) return ;
var getfile = function ( dir , x , i , type ) {
var name = ( dir + x + '.' + i + type ) ;
var root = "" ;
if ( x . substr ( - 5 ) === ".xlsb" ) {
root = x . slice ( 0 , - 5 ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsx.' + i + type ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsm.' + i + type ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xls.' + i + type ) ;
}
if ( x . substr ( - 4 ) === ".xls" ) {
root = x . slice ( 0 , - 4 ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsx.' + i + type ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsm.' + i + type ) ;
if ( ! fs . existsSync ( name ) ) name = ( dir + root + '.xlsb.' + i + type ) ;
}
return name ;
} ;
describe ( x + ext + ' should generate correct CSV output' , function ( ) {
wb . SheetNames . forEach ( function ( ws , i ) {
var name = getfile ( dir , x , i , ".csv" ) ;
if ( fs . existsSync ( name ) ) it ( '#' + i + ' (' + ws + ')' , function ( ) {
var file = fs . readFileSync ( name , 'utf-8' ) ;
var csv = X . utils . sheet _to _csv ( wb . Sheets [ ws ] ) ;
assert . equal ( fixcsv ( csv ) , fixcsv ( file ) , "CSV badness" ) ;
} ) ;
} ) ;
} ) ;
if ( typeof JSON !== 'undefined' ) describe ( x + ext + ' should generate correct JSON output' , function ( ) {
wb . SheetNames . forEach ( function ( ws , i ) {
var rawjson = getfile ( dir , x , i , ".rawjson" ) ;
if ( fs . existsSync ( rawjson ) ) it ( '#' + i + ' (' + ws + ')' , function ( ) {
var file = fs . readFileSync ( rawjson , 'utf-8' ) ;
var json = X . utils . sheet _to _json ( wb . Sheets [ ws ] , { raw : true } ) ;
assert . equal ( JSON . stringify ( json ) , fixjson ( file ) , "JSON badness" ) ;
} ) ;
var jsonf = getfile ( dir , x , i , ".json" ) ;
if ( fs . existsSync ( jsonf ) ) it ( '#' + i + ' (' + ws + ')' , function ( ) {
var file = fs . readFileSync ( jsonf , 'utf-8' ) ;
var json = X . utils . sheet _to _json ( wb . Sheets [ ws ] , { raw : false } ) ;
assert . equal ( JSON . stringify ( json ) , fixjson ( file ) , "JSON badness" ) ;
} ) ;
} ) ;
} ) ;
if ( fs . existsSync ( dir + '2011/' + x + '.xml' ) )
describe ( x + ext + '.xml from 2011' , function ( ) {
it ( 'should parse' , function ( ) {
/*var wb = */ X . readFile ( dir + '2011/' + x + '.xml' , opts ) ;
} ) ;
} ) ;
if ( fs . existsSync ( dir + '2013/' + x + '.xlsb' ) )
describe ( x + ext + '.xlsb from 2013' , function ( ) {
it ( 'should parse' , function ( ) {
/*var wb = */ X . readFile ( dir + '2013/' + x + '.xlsb' , opts ) ;
} ) ;
} ) ;
if ( fs . existsSync ( dir + x + '.xml' + ext ) )
describe ( x + '.xml' , function ( ) {
it ( 'should parse' , function ( ) {
/*var wb = */ X . readFile ( dir + x + '.xml' , opts ) ;
} ) ;
} ) ;
}
var wbtable = { } ;
2022-06-06 23:05:27 +00:00
if ( ! browser ) describe ( 'should parse test files' , function ( ) {
2022-02-13 09:35:34 +00:00
files . forEach ( function ( x ) {
if ( x . slice ( - 8 ) == ".pending" || ! fs . existsSync ( dir + x ) ) return ;
it ( x , function ( ) {
var wb = X . readFile ( dir + x , opts ) ;
wbtable [ dir + x ] = wb ;
parsetest ( x , wb , true ) ;
} ) ;
fullex . forEach ( function ( ext ) {
it ( x + ' [' + ext + ']' , function ( ) {
var wb = wbtable [ dir + x ] ;
if ( ! wb ) wb = X . readFile ( dir + x , opts ) ;
wb = X . read ( X . write ( wb , { type : "buffer" , bookType : ext . replace ( /\./ , "" ) } ) , { WTF : opts . WTF , cellNF : true } ) ;
parsetest ( x , wb , ext . replace ( /\./ , "" ) !== "xlsb" , ext ) ;
} ) ;
} ) ;
} ) ;
fileA . forEach ( function ( x ) {
if ( x . slice ( - 8 ) == ".pending" || ! fs . existsSync ( dir + x ) ) return ;
it ( x , function ( ) {
var wb = X . readFile ( dir + x , { WTF : opts . WTF , sheetRows : 10 } ) ;
parsetest ( x , wb , false ) ;
} ) ;
} ) ;
} ) ;
function get _cell ( ws /*:Worksheet*/ , addr /*:string*/ ) {
if ( ! Array . isArray ( ws ) ) return ws [ addr ] ;
var a = X . utils . decode _cell ( addr ) ;
return ( ws [ a . r ] || [ ] ) [ a . c ] ;
}
function each _cell ( ws , f ) {
if ( Array . isArray ( ws ) ) ws . forEach ( function ( row ) { if ( row ) row . forEach ( f ) ; } ) ;
else Object . keys ( ws ) . forEach ( function ( addr ) { if ( addr [ 0 ] === "!" || ! ws . hasOwnProperty ( addr ) ) return ; f ( ws [ addr ] ) ; } ) ;
}
function each _sheet ( wb , f ) { wb . SheetNames . forEach ( function ( n , i ) { f ( wb . Sheets [ n ] , i ) ; } ) ; }
/* comments_stress_test family */
function check _comments ( wb ) {
2022-06-06 23:05:27 +00:00
var ws0 = wb . Sheets [ "Sheet2" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws0 , "A1" ) . c [ 0 ] . a , 'Author' ) ;
assert . equal ( get _cell ( ws0 , "A1" ) . c [ 0 ] . t , 'Author:\nGod thinks this is good' ) ;
assert . equal ( get _cell ( ws0 , "C1" ) . c [ 0 ] . a , 'Author' ) ;
assert . equal ( get _cell ( ws0 , "C1" ) . c [ 0 ] . t , 'I really hope that xlsx decides not to use magic like rPr' ) ;
2022-06-06 23:05:27 +00:00
var ws3 = wb . Sheets [ "Sheet4" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws3 , "B1" ) . c [ 0 ] . a , 'Author' ) ;
assert . equal ( get _cell ( ws3 , "B1" ) . c [ 0 ] . t , 'The next comment is empty' ) ;
assert . equal ( get _cell ( ws3 , "B2" ) . c [ 0 ] . a , 'Author' ) ;
assert . equal ( get _cell ( ws3 , "B2" ) . c [ 0 ] . t , '' ) ;
}
describe ( 'parse options' , function ( ) {
var html _cell _types = [ 's' ] ;
describe ( 'cell' , function ( ) {
it ( 'XLSX should generate HTML by default' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths . cstxlsx ) , { type : TYPE } ) ;
2022-06-06 23:05:27 +00:00
var ws = wb . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
each _cell ( ws , function ( cell ) {
assert . ok ( html _cell _types . indexOf ( cell . t ) === - 1 || cell . h ) ;
} ) ;
} ) ;
it ( 'XLSX should not generate HTML when requested' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths . cstxlsx ) , { type : TYPE , cellHTML : false } ) ;
2022-06-06 23:05:27 +00:00
var ws = wb . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
each _cell ( ws , function ( cell ) {
assert . ok ( typeof cell . h === 'undefined' ) ;
} ) ;
} ) ;
it ( 'should generate formulae by default' , function ( ) {
FSTPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ;
var found = false ;
wb . SheetNames . forEach ( function ( s ) {
each _cell ( wb . Sheets [ s ] , function ( cell ) {
if ( typeof cell . f !== 'undefined' ) return ( found = true ) ;
} ) ;
} ) ;
assert . ok ( found ) ;
} ) ;
} ) ;
it ( 'should not generate formulae when requested' , function ( ) {
FSTPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , cellFormula : false } ) ;
wb . SheetNames . forEach ( function ( s ) {
each _cell ( wb . Sheets [ s ] , function ( cell ) {
assert . ok ( typeof cell . f === 'undefined' ) ;
} ) ;
} ) ;
} ) ;
} ) ;
it ( 'should generate formatted text by default' , function ( ) {
FSTPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ;
var found = false ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
each _cell ( ws , function ( cell ) {
if ( typeof cell . w !== 'undefined' ) return ( found = true ) ;
} ) ;
} ) ;
assert . ok ( found ) ;
} ) ;
} ) ;
it ( 'should not generate formatted text when requested' , function ( ) {
FSTPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , cellText : false } ) ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
each _cell ( ws , function ( cell ) {
assert . ok ( typeof cell . w === 'undefined' ) ;
} ) ;
} ) ;
} ) ;
} ) ;
it ( 'should not generate number formats by default' , function ( ) {
NFPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
each _cell ( ws , function ( cell ) {
assert . ok ( typeof cell . z === 'undefined' ) ;
} ) ;
} ) ;
} ) ;
} ) ;
it ( 'should generate number formats when requested' , function ( ) {
NFPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , cellNF : true } ) ;
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
each _cell ( ws , function ( cell ) {
assert . ok ( cell . t !== 'n' || typeof cell . z !== 'undefined' ) ;
} ) ;
} ) ;
} ) ;
} ) ;
it ( 'should not generate cell styles by default' , function ( ) {
CSSPaths . forEach ( function ( p ) {
2022-06-06 23:05:27 +00:00
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , WTF : true } ) ;
2022-02-13 09:35:34 +00:00
wb . SheetNames . forEach ( function ( s ) {
var ws = wb . Sheets [ s ] ;
each _cell ( ws , function ( cell ) {
assert . ok ( typeof cell . s === 'undefined' ) ;
} ) ;
} ) ;
} ) ;
} ) ;
it ( 'should generate cell styles when requested' , function ( ) {
/* TODO: XLS / XLML */
[ paths . cssxlsx /*, paths.cssxlsb, paths.cssxls, paths.cssxml*/ ] . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , cellStyles : true } ) ;
var found = false ;
each _sheet ( wb , function ( ws /*::, i*/ ) { /*:: void i; */ each _cell ( ws , function ( cell ) {
if ( typeof cell . s !== 'undefined' ) return ( found = true ) ;
} ) ; } ) ;
assert . ok ( found ) ;
} ) ;
} ) ;
it ( 'should not generate cell dates by default' , function ( ) {
DTPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ;
each _sheet ( wb , function ( ws /*::, i*/ ) { /*:: void i; */ each _cell ( ws , function ( cell ) {
assert . ok ( cell . t !== 'd' ) ;
} ) ; } ) ;
} ) ;
} ) ;
it ( 'should generate cell dates when requested' , function ( ) {
DTPaths . forEach ( function ( p ) {
2022-06-06 23:05:27 +00:00
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , cellDates : true , WTF : true } ) ;
2022-02-13 09:35:34 +00:00
var found = false ;
each _sheet ( wb , function ( ws /*::, i*/ ) { /*:: void i; */ each _cell ( ws , function ( cell ) {
if ( cell . t === 'd' ) return ( found = true ) ;
} ) ; } ) ;
assert . ok ( found ) ;
} ) ;
} ) ;
it ( 'should preserve `_xlfn.` only when requested' , function ( ) {
var wb = { SheetNames : [ "Sheet1" ] , Sheets : { Sheet1 : {
"!ref" : "A1:A1" ,
"A1" : { t : "n" , v : 2 , f : "_xlfn.IFS(2>3,1,3>2,2)" }
} } } ;
var str = X . write ( wb , { bookType : "xlsx" , type : "binary" } ) ;
var wb2 = X . read ( str , { type : "binary" } ) ;
/*jshint -W069 */
2022-06-06 23:05:27 +00:00
assert . equal ( wb2 . Sheets [ "Sheet1" ] [ "A1" ] . f , "IFS(2>3,1,3>2,2)" ) ;
2022-02-13 09:35:34 +00:00
var wb3 = X . read ( str , { type : "binary" , xlfn : true } ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( wb3 . Sheets [ "Sheet1" ] [ "A1" ] . f , "_xlfn.IFS(2>3,1,3>2,2)" ) ;
2022-02-13 09:35:34 +00:00
/*jshint +W069 */
} ) ;
} ) ;
describe ( 'sheet' , function ( ) {
it ( 'should not generate sheet stubs by default' , function ( ) {
MCPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ;
2022-06-06 23:05:27 +00:00
assert . throws ( function ( ) { return get _cell ( wb . Sheets [ "Merge" ] , "A2" ) . v ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
it ( 'should generate sheet stubs when requested' , function ( ) {
MCPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , sheetStubs : true } ) ;
2022-06-06 23:05:27 +00:00
assert . ok ( get _cell ( wb . Sheets [ "Merge" ] , "A2" ) . t == 'z' ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
it ( 'should handle stub cells' , function ( ) {
MCPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , sheetStubs : true } ) ;
2022-06-06 23:05:27 +00:00
X . utils . sheet _to _csv ( wb . Sheets [ "Merge" ] ) ;
X . utils . sheet _to _json ( wb . Sheets [ "Merge" ] ) ;
X . utils . sheet _to _formulae ( wb . Sheets [ "Merge" ] ) ;
2022-02-13 09:35:34 +00:00
ofmt . forEach ( function ( f ) { if ( f != "dbf" ) X . write ( wb , { type : TYPE , bookType : f } ) ; } ) ;
} ) ;
} ) ;
function checkcells ( wb , A46 , B26 , C16 , D2 ) {
[ [ "A46" , A46 ] , [ "B26" , B26 ] , [ "C16" , C16 ] , [ "D2" , D2 ] ] . forEach ( function ( r ) {
2022-06-06 23:05:27 +00:00
assert . ok ( ( typeof get _cell ( wb . Sheets [ "Text" ] , r [ 0 ] ) !== 'undefined' ) == r [ 1 ] ) ;
2022-02-13 09:35:34 +00:00
} ) ;
}
it ( 'should read all cells by default' , function ( ) { FSTPaths . forEach ( function ( p ) {
checkcells ( X . read ( fs . readFileSync ( p ) , { type : TYPE } ) , true , true , true , true ) ;
} ) ; } ) ;
it ( 'sheetRows n=30' , function ( ) { FSTPaths . forEach ( function ( p ) {
checkcells ( X . read ( fs . readFileSync ( p ) , { type : TYPE , sheetRows : 30 } ) , false , true , true , true ) ;
} ) ; } ) ;
it ( 'sheetRows n=20' , function ( ) { FSTPaths . forEach ( function ( p ) {
checkcells ( X . read ( fs . readFileSync ( p ) , { type : TYPE , sheetRows : 20 } ) , false , false , true , true ) ;
} ) ; } ) ;
it ( 'sheetRows n=10' , function ( ) { FSTPaths . forEach ( function ( p ) {
checkcells ( X . read ( fs . readFileSync ( p ) , { type : TYPE , sheetRows : 10 } ) , false , false , false , true ) ;
} ) ; } ) ;
it ( 'sheetRows n=1' , function ( ) { ofmt . forEach ( function ( fmt ) {
[ TYPE , "base64" , "binary" , "array" ] . forEach ( function ( ot ) {
var data = [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ] ;
var ws = X . utils . aoa _to _sheet ( data ) ;
assert . ok ( ws [ '!ref' ] === "A1:B3" ) ;
var wb = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb , ws , "Sheet1" ) ;
2022-06-06 23:05:27 +00:00
var bs = X . write ( wb , { bookType : fmt , type : ot , WTF : true } ) ;
2022-02-13 09:35:34 +00:00
2022-06-06 23:05:27 +00:00
var wb0 = X . read ( bs , { type : ot , WTF : true } ) ;
var ws0 = wb0 . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( ws0 [ '!ref' ] , "A1:B3" ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( ws0 , "A1" ) . v , fmt == "dbf" ? "1" : 1 ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws0 , "B2" ) . v , 4 ) ;
assert . equal ( get _cell ( ws0 , "A3" ) . v , 5 ) ;
var wb1 = X . read ( bs , { type : ot , sheetRows : 1 } ) ;
2022-06-06 23:05:27 +00:00
var ws1 = wb1 . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( ws1 [ '!ref' ] , "A1:B1" ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( ws1 , "A1" ) . v , fmt == "dbf" ? "1" : 1 ) ;
2022-02-13 09:35:34 +00:00
assert . ok ( ! get _cell ( ws1 , "B2" ) ) ;
assert . ok ( ! get _cell ( ws1 , "A3" ) ) ;
if ( ws1 [ '!fullref' ] ) assert . equal ( ws1 [ '!fullref' ] , "A1:B3" ) ;
var wb2 = X . read ( bs , { type : ot , sheetRows : 2 } ) ;
2022-06-06 23:05:27 +00:00
var ws2 = wb2 . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( ws2 [ '!ref' ] , "A1:B2" ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( ws2 , "A1" ) . v , fmt == "dbf" ? "1" : 1 ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws2 , "B2" ) . v , 4 ) ;
assert . ok ( ! get _cell ( ws2 , "A3" ) ) ;
if ( ws2 [ '!fullref' ] ) assert . equal ( ws2 [ '!fullref' ] , "A1:B3" ) ;
var wb3 = X . read ( bs , { type : ot , sheetRows : 3 } ) ;
2022-06-06 23:05:27 +00:00
var ws3 = wb3 . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( ws3 [ '!ref' ] , "A1:B3" ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( ws3 , "A1" ) . v , fmt == "dbf" ? "1" : 1 ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws3 , "B2" ) . v , 4 ) ;
assert . equal ( get _cell ( ws3 , "A3" ) . v , 5 ) ;
if ( ws3 [ '!fullref' ] ) assert . equal ( ws3 [ '!fullref' ] , "A1:B3" ) ;
} ) ; } ) ; } ) ;
} ) ;
describe ( 'book' , function ( ) {
it ( 'bookSheets should not generate sheets' , function ( ) {
MCPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , bookSheets : true } ) ;
assert . ok ( typeof wb . Sheets === 'undefined' ) ;
} ) ;
} ) ;
it ( 'bookProps should not generate sheets' , function ( ) {
NFPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , bookProps : true } ) ;
assert . ok ( typeof wb . Sheets === 'undefined' ) ;
} ) ;
} ) ;
it ( 'bookProps && bookSheets should not generate sheets' , function ( ) {
PMPaths . forEach ( function ( p ) {
if ( ! fs . existsSync ( p ) ) return ;
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , bookProps : true , bookSheets : true } ) ;
assert . ok ( typeof wb . Sheets === 'undefined' ) ;
} ) ;
} ) ;
var FSTXL = [
[ paths . fstxlsx , true ] ,
[ paths . fstxlsb , true ] ,
[ paths . fstxls , false ]
] ;
it ( 'should not generate deps by default' , function ( ) {
FSTPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ;
assert . ok ( typeof wb . Deps === 'undefined' || ! ( wb . Deps && wb . Deps . length > 0 ) ) ;
} ) ;
} ) ;
it ( 'bookDeps should generate deps (XLSX/XLSB)' , function ( ) {
FSTXL . forEach ( function ( p ) {
if ( ! p [ 1 ] ) return ;
var wb = X . read ( fs . readFileSync ( p [ 0 ] ) , { type : TYPE , bookDeps : true } ) ;
assert . ok ( typeof wb . Deps !== 'undefined' && wb . Deps . length > 0 ) ;
} ) ;
} ) ;
var ckf = function ( wb , fields , exists ) { fields . forEach ( function ( f ) { assert . ok ( ( typeof wb [ f ] !== 'undefined' ) == exists ) ; } ) ; } ;
it ( 'should not generate book files by default' , function ( ) { FSTXL . forEach ( function ( r ) {
var wb = X . read ( fs . readFileSync ( r [ 0 ] ) , { type : TYPE } ) ;
ckf ( wb , r [ 1 ] ? [ 'files' , 'keys' ] : [ 'cfb' ] , false ) ;
} ) ; } ) ;
it ( 'bookFiles should generate book files' , function ( ) { FSTXL . forEach ( function ( r ) {
var wb = X . read ( fs . readFileSync ( r [ 0 ] ) , { type : TYPE , bookFiles : true } ) ;
ckf ( wb , r [ 1 ] ? [ 'files' , 'keys' ] : [ 'cfb' ] , true ) ;
} ) ; } ) ;
var NFVBA = [ "nfxlsx" , "nfxlsb" , "nfxls" ] . map ( function ( n ) { return paths [ n ] ; } ) ;
it ( 'should not generate VBA by default' , function ( ) { NFPaths . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ; assert . ok ( typeof wb . vbaraw === 'undefined' ) ;
} ) ; } ) ;
it ( 'bookVBA should generate vbaraw' , function ( ) { NFVBA . forEach ( function ( p ) {
var wb = X . read ( fs . readFileSync ( p ) , { type : TYPE , bookVBA : true } ) ;
assert . ok ( wb . vbaraw ) ;
var cfb = X . CFB . read ( wb . vbaraw , { type : 'array' } ) ;
assert . ok ( X . CFB . find ( cfb , '/VBA/ThisWorkbook' ) ) ;
} ) ; } ) ;
} ) ;
} ) ;
describe ( 'input formats' , function ( ) {
it ( 'should read binary strings' , function ( ) { artifax . forEach ( function ( p ) {
X . read ( fs . readFileSync ( p , 'binary' ) , { type : 'binary' } ) ;
} ) ; } ) ;
it ( 'should read base64 strings' , function ( ) { artifax . forEach ( function ( p ) {
X . read ( fs . readFileSync ( p , 'base64' ) , { type : 'base64' } ) ;
} ) ; } ) ;
2022-08-08 23:21:46 +00:00
it ( 'handles base64 within data URI scheme (gh-2762)' , function ( ) {
var data = 'TmFtZXMNCkhhZmV6DQpTYW0NCg==' ;
var wb0 = X . read ( data , { type : 'base64' } ) ; // raw base64 string
var wb1 = X . read ( 'data:;base64,' + data , { type : 'base64' } ) ; // data URI, no media type
var wb2 = X . read ( 'data:text/csv;base64,' + data , { type : 'base64' } ) ; // data URI, CSV type
var wb3 = X . read ( 'data:application/vnd.ms-excel;base64,' + data , { type : 'base64' } ) ; // data URI, Excel
[ wb0 , wb1 , wb2 , wb3 ] . forEach ( function ( wb ) {
var ws = wb . Sheets . Sheet1 ;
assert . equal ( ws [ "!ref" ] , "A1:A3" ) ;
assert . equal ( get _cell ( ws , "A1" ) . v , "Names" ) ;
assert . equal ( get _cell ( ws , "A2" ) . v , "Hafez" ) ;
assert . equal ( get _cell ( ws , "A3" ) . v , "Sam" ) ;
} ) ;
} ) ;
2022-06-06 23:05:27 +00:00
if ( typeof Uint8Array !== 'undefined' ) it ( 'should read array' , function ( ) { artifax . forEach ( function ( p ) {
2022-02-13 09:35:34 +00:00
X . read ( fs . readFileSync ( p , 'binary' ) . split ( "" ) . map ( function ( x ) { return x . charCodeAt ( 0 ) ; } ) , { type : 'array' } ) ;
} ) ; } ) ;
( ( browser || typeof Buffer === 'undefined' ) ? it . skip : it ) ( 'should read Buffers' , function ( ) { artifax . forEach ( function ( p ) {
X . read ( fs . readFileSync ( p ) , { type : 'buffer' } ) ;
} ) ; } ) ;
2022-06-06 23:05:27 +00:00
if ( typeof Uint8Array !== 'undefined' ) it ( 'should read ArrayBuffer / Uint8Array' , function ( ) { artifax . forEach ( function ( p ) {
2022-02-13 09:35:34 +00:00
var payload = fs . readFileSync ( p , browser ? 'buffer' : null ) ;
var ab = new ArrayBuffer ( payload . length ) , vu = new Uint8Array ( ab ) ;
for ( var i = 0 ; i < payload . length ; ++ i ) vu [ i ] = payload [ i ] ;
X . read ( ab , { type : 'array' } ) ;
X . read ( vu , { type : 'array' } ) ;
} ) ; } ) ;
it ( 'should throw if format is unknown' , function ( ) { artifax . forEach ( function ( p ) {
assert . throws ( function ( ) { X . read ( fs . readFileSync ( p ) , { type : 'dafuq' } ) ; } ) ;
} ) ; } ) ;
var T = browser ? 'base64' : 'buffer' ;
it ( 'should default to "' + T + '" type' , function ( ) { artifax . forEach ( function ( p ) {
X . read ( fs . readFileSync . apply ( fs , browser ? [ p , 'base64' ] : [ p ] ) ) ;
} ) ; } ) ;
if ( ! browser ) it ( 'should read files' , function ( ) { artifax . forEach ( function ( p ) { X . readFile ( p ) ; } ) ; } ) ;
} ) ;
describe ( 'output formats' , function ( ) {
var fmts = [
/* fmt unicode str */
[ "xlsx" , true , false ] ,
[ "xlsb" , true , false ] ,
[ "xls" , true , false ] ,
[ "xlml" , true , true ] ,
[ "ods" , true , false ] ,
[ "fods" , true , true ] ,
[ "csv" , true , true ] ,
[ "txt" , true , true ] ,
2022-07-07 06:30:44 +00:00
[ "rtf" , false , true ] ,
2022-02-13 09:35:34 +00:00
[ "sylk" , false , true ] ,
[ "eth" , false , true ] ,
[ "html" , true , true ] ,
[ "dif" , false , true ] ,
[ "dbf" , false , false ] ,
[ "prn" , false , true ]
] ;
function RT ( T ) {
fmts . forEach ( function ( fmt ) {
var wb = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 'R' , "\u2603" ] , [ "\u0BEE" , 2 ] ] ) , "Sheet1" ) ;
2022-06-06 23:05:27 +00:00
if ( T == 'string' && ! fmt [ 2 ] ) return assert . throws ( function ( ) { X . write ( wb , { type : T , bookType : fmt [ 0 ] , WTF : true } ) ; } ) ;
var out = X . write ( wb , { type : T , bookType : fmt [ 0 ] , WTF : true } ) ;
var nwb = X . read ( out , { type : T , PRN : fmt [ 0 ] == 'prn' , WTF : true } ) ;
2022-02-13 09:35:34 +00:00
var nws = nwb . Sheets [ nwb . SheetNames [ 0 ] ] ;
assert . equal ( get _cell ( nws , "B2" ) . v , 2 ) ;
assert . equal ( get _cell ( nws , "A1" ) . v , "R" ) ;
if ( fmt [ 1 ] ) assert . equal ( get _cell ( nws , "A2" ) . v , "\u0BEE" ) ;
if ( fmt [ 1 ] ) assert . equal ( get _cell ( nws , "B1" ) . v , "\u2603" ) ;
} ) ;
}
it ( 'should write binary strings' , function ( ) { RT ( 'binary' ) ; } ) ;
it ( 'should write base64 strings' , function ( ) { RT ( 'base64' ) ; } ) ;
it ( 'should write JS strings' , function ( ) { RT ( 'string' ) ; } ) ;
if ( typeof ArrayBuffer !== 'undefined' && ( typeof process == 'undefined' || ! process . version . match ( /v0.12/ ) ) ) it ( 'should write array buffers' , function ( ) { RT ( 'array' ) ; } ) ;
if ( ! browser ) it ( 'should write buffers' , function ( ) { RT ( 'buffer' ) ; } ) ;
it ( 'should throw if format is unknown' , function ( ) { assert . throws ( function ( ) { RT ( 'dafuq' ) ; } ) ; } ) ;
} ) ;
function eqarr ( a , b ) {
assert . equal ( a . length , b . length ) ;
a . forEach ( function ( x , i ) { assert . equal ( x , b [ i ] ) ; } ) ;
}
describe ( 'API' , function ( ) {
it ( 'book_append_sheet' , function ( ) {
var wb = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 1 , 2 , 3 ] , [ 4 ] , [ 5 ] ] ) , "A" ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 1 , 2 , 3 ] , [ 4 ] , [ 5 ] ] ) ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 1 , 2 , 3 ] , [ 4 ] , [ 5 ] ] ) ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 1 , 2 , 3 ] , [ 4 ] , [ 5 ] ] ) , "B" ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 1 , 2 , 3 ] , [ 4 ] , [ 5 ] ] ) ) ;
eqarr ( wb . SheetNames , [ "A" , "Sheet1" , "Sheet2" , "B" , "Sheet3" ] ) ;
} ) ;
it ( 'sheet_add_json' , function ( ) {
var ws = X . utils . json _to _sheet ( [ { A : "S" , B : "h" , C : "e" , D : "e" , E : "t" , F : "J" , G : "S" } ] , { header : [ "A" , "B" , "C" , "D" , "E" , "F" , "G" ] , skipHeader : true } ) ;
X . utils . sheet _add _json ( ws , [ { A : 1 , B : 2 } , { A : 2 , B : 3 } , { A : 3 , B : 4 } ] , { skipHeader : true , origin : "A2" } ) ;
X . utils . sheet _add _json ( ws , [ { A : 5 , B : 6 , C : 7 } , { A : 6 , B : 7 , C : 8 } , { A : 7 , B : 8 , C : 9 } ] , { skipHeader : true , origin : { r : 1 , c : 4 } , header : [ "A" , "B" , "C" ] } ) ;
X . utils . sheet _add _json ( ws , [ { A : 4 , B : 5 , C : 6 , D : 7 , E : 8 , F : 9 , G : 0 } ] , { header : [ "A" , "B" , "C" , "D" , "E" , "F" , "G" ] , skipHeader : true , origin : - 1 } ) ;
assert . equal ( X . utils . sheet _to _csv ( ws ) . trim ( ) , "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0" ) ;
} ) ;
it ( 'sheet_add_aoa' , function ( ) {
var ws = X . utils . aoa _to _sheet ( [ "SheetJS" . split ( "" ) ] ) ;
X . utils . sheet _add _aoa ( ws , [ [ 1 , 2 ] , [ 2 , 3 ] , [ 3 , 4 ] ] , { origin : "A2" } ) ;
X . utils . sheet _add _aoa ( ws , [ [ 5 , 6 , 7 ] , [ 6 , 7 , 8 ] , [ 7 , 8 , 9 ] ] , { origin : { r : 1 , c : 4 } } ) ;
X . utils . sheet _add _aoa ( ws , [ [ 4 , 5 , 6 , 7 , 8 , 9 , 0 ] ] , { origin : - 1 } ) ;
assert . equal ( X . utils . sheet _to _csv ( ws ) . trim ( ) , "S,h,e,e,t,J,S\n1,2,,,5,6,7\n2,3,,,6,7,8\n3,4,,,7,8,9\n4,5,6,7,8,9,0" ) ;
} ) ;
it ( 'sheet_add_aoa support object cell' , function ( ) {
var data = X . utils . aoa _to _sheet ( [
[ 'url' , 'name' , 'id' ] ,
[ { l : { Target : 'https://123.com' } , v : 'url' , t : 's' } , 'tom' , 'xxx' ]
] ) ;
if ( assert . deepEqual ) assert . deepEqual ( data . A2 , { l : { Target : 'https://123.com' } , v : 'url' , t : 's' } ) ;
} ) ;
it ( 'decode_range' , function ( ) {
var _c = "ABC" , _r = "123" , _C = "DEF" , _R = "456" ;
var r = X . utils . decode _range ( _c + _r + ":" + _C + _R ) ;
assert . ok ( r . s != r . e ) ;
assert . equal ( r . s . c , X . utils . decode _col ( _c ) ) ; assert . equal ( r . s . r , X . utils . decode _row ( _r ) ) ;
assert . equal ( r . e . c , X . utils . decode _col ( _C ) ) ; assert . equal ( r . e . r , X . utils . decode _row ( _R ) ) ;
r = X . utils . decode _range ( _c + _r ) ;
assert . ok ( r . s != r . e ) ;
assert . equal ( r . s . c , X . utils . decode _col ( _c ) ) ; assert . equal ( r . s . r , X . utils . decode _row ( _r ) ) ;
assert . equal ( r . e . c , X . utils . decode _col ( _c ) ) ; assert . equal ( r . e . r , X . utils . decode _row ( _r ) ) ;
} ) ;
} ) ;
function coreprop ( props ) {
assert . equal ( props . Title , 'Example with properties' ) ;
assert . equal ( props . Subject , 'Test it before you code it' ) ;
assert . equal ( props . Author , 'Pony Foo' ) ;
assert . equal ( props . Manager , 'Despicable Drew' ) ;
assert . equal ( props . Company , 'Vector Inc' ) ;
assert . equal ( props . Category , 'Quirky' ) ;
assert . equal ( props . Keywords , 'example humor' ) ;
assert . equal ( props . Comments , 'some comments' ) ;
assert . equal ( props . LastAuthor , 'Hugues' ) ;
}
function custprop ( props ) {
assert . equal ( props [ 'I am a boolean' ] , true ) ;
assert . equal ( props [ 'Date completed' ] . toISOString ( ) , '1967-03-09T16:30:00.000Z' ) ;
assert . equal ( props . Status , 2 ) ;
assert . equal ( props . Counter , - 3.14 ) ;
}
function cmparr ( x ) { for ( var i = 1 ; i < x . length ; ++ i ) assert . deepEqual ( x [ 0 ] , x [ i ] ) ; }
function deepcmp ( x , y , k , m , c ) {
var s = k . indexOf ( "." ) ;
m = ( m || "" ) + "|" + ( s > - 1 ? k . substr ( 0 , s ) : k ) ;
if ( s < 0 ) return assert [ c < 0 ? 'notEqual' : 'equal' ] ( x [ k ] , y [ k ] , m ) ;
return deepcmp ( x [ k . substr ( 0 , s ) ] , y [ k . substr ( 0 , s ) ] , k . substr ( s + 1 ) , m , c ) ;
}
var styexc = [
'A2|H10|bgColor.rgb' ,
'F6|H1|patternType'
] ;
var stykeys = [
"patternType" ,
"fgColor.rgb" ,
"bgColor.rgb"
] ;
function diffsty ( ws , r1 , r2 ) {
var c1 = get _cell ( ws , r1 ) . s , c2 = get _cell ( ws , r2 ) . s ;
stykeys . forEach ( function ( m ) {
var c = - 1 ;
if ( styexc . indexOf ( r1 + "|" + r2 + "|" + m ) > - 1 ) c = 1 ;
else if ( styexc . indexOf ( r2 + "|" + r1 + "|" + m ) > - 1 ) c = 1 ;
deepcmp ( c1 , c2 , m , r1 + "," + r2 , c ) ;
} ) ;
}
function hlink1 ( ws ) { [
[ "A1" , "http://www.sheetjs.com" ] ,
[ "A2" , "http://oss.sheetjs.com" ] ,
[ "A3" , "http://oss.sheetjs.com#foo" ] ,
[ "A4" , "mailto:dev@sheetjs.com" ] ,
[ "A5" , "mailto:dev@sheetjs.com?subject=hyperlink" ] ,
[ "A6" , "../../sheetjs/Documents/Test.xlsx" ] ,
[ "A7" , "http://sheetjs.com" , "foo bar baz" ]
] . forEach ( function ( r ) {
assert . equal ( get _cell ( ws , r [ 0 ] ) . l . Target , r [ 1 ] ) ;
if ( r [ 2 ] ) assert . equal ( get _cell ( ws , r [ 0 ] ) . l . Tooltip , r [ 2 ] ) ;
} ) ; }
function hlink2 ( ws ) { [
[ "A1" , "#Sheet2!A1" ] ,
[ "A2" , "#WBScope" ] ,
[ "A3" , "#Sheet1!WSScope1" , "#Sheet1!C7:E8" ] ,
[ "A5" , "#Sheet1!A5" ]
] . forEach ( function ( r ) {
if ( r [ 2 ] && get _cell ( ws , r [ 0 ] ) . l . Target == r [ 2 ] ) return ;
assert . equal ( get _cell ( ws , r [ 0 ] ) . l . Target , r [ 1 ] ) ;
} ) ; }
function check _margin ( margins , exp ) {
[ "left" , "right" , "top" , "bottom" , "header" , "footer" ] . forEach ( function ( m , i ) {
assert . equal ( margins [ m ] , exp [ i ] ) ;
} ) ;
}
describe ( 'parse features' , function ( ) {
describe ( 'sheet visibility' , function ( ) {
var wbs = [ ] ;
var bef = ( function ( ) {
wbs = SVPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ; } ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( 'should detect visible sheets' , function ( ) {
if ( ! wbs . length ) bef ( ) ;
wbs . forEach ( function ( wb ) {
assert . ok ( ! wb . Workbook . Sheets [ 0 ] . Hidden ) ;
} ) ;
} ) ;
it ( 'should detect all hidden sheets' , function ( ) {
wbs . forEach ( function ( wb ) {
assert . ok ( wb . Workbook . Sheets [ 1 ] . Hidden ) ;
assert . ok ( wb . Workbook . Sheets [ 2 ] . Hidden ) ;
} ) ;
} ) ;
it ( 'should distinguish very hidden sheets' , function ( ) {
wbs . forEach ( function ( wb ) {
assert . equal ( wb . Workbook . Sheets [ 1 ] . Hidden , 1 ) ;
assert . equal ( wb . Workbook . Sheets [ 2 ] . Hidden , 2 ) ;
} ) ;
} ) ;
} ) ;
describe ( 'comments' , function ( ) {
if ( fs . existsSync ( paths . swcxlsx ) ) it ( 'should have comment as part of cell properties' , function ( ) {
var sheet = 'Sheet1' ;
var wb1 = X . read ( fs . readFileSync ( paths . swcxlsx ) , { type : TYPE } ) ;
var wb2 = X . read ( fs . readFileSync ( paths . swcxlsb ) , { type : TYPE } ) ;
var wb3 = X . read ( fs . readFileSync ( paths . swcxls ) , { type : TYPE } ) ;
var wb4 = X . read ( fs . readFileSync ( paths . swcxml ) , { type : TYPE } ) ;
[ wb1 , wb2 , wb3 , wb4 ] . map ( function ( wb ) { return wb . Sheets [ sheet ] ; } ) . forEach ( function ( ws , i ) {
assert . equal ( get _cell ( ws , "B1" ) . c . length , 1 , "must have 1 comment" ) ;
assert . equal ( get _cell ( ws , "B1" ) . c [ 0 ] . a , "Yegor Kozlov" , "must have the same author" ) ;
assert . equal ( get _cell ( ws , "B1" ) . c [ 0 ] . t , "Yegor Kozlov:\nfirst cell" , "must have the concatenated texts" ) ;
if ( i > 0 ) return ;
assert . equal ( get _cell ( ws , "B1" ) . c [ 0 ] . r , '<r><rPr><b/><sz val="8"/><color indexed="81"/><rFont val="Tahoma"/></rPr><t>Yegor Kozlov:</t></r><r><rPr><sz val="8"/><color indexed="81"/><rFont val="Tahoma"/></rPr><t xml:space="preserve">\r\nfirst cell</t></r>' , "must have the rich text representation" ) ;
assert . equal ( get _cell ( ws , "B1" ) . c [ 0 ] . h , '<span style="font-size:8pt;"><b>Yegor Kozlov:</b></span><span style="font-size:8pt;"><br/>first cell</span>' , "must have the html representation" ) ;
} ) ;
} ) ;
[
[ 'xlsx' , paths . cstxlsx ] ,
[ 'xlsb' , paths . cstxlsb ] ,
[ 'xls' , paths . cstxls ] ,
[ 'xlml' , paths . cstxml ] ,
[ 'ods' , paths . cstods ]
] . forEach ( function ( m ) { it ( m [ 0 ] + ' stress test' , function ( ) {
var wb = X . read ( fs . readFileSync ( m [ 1 ] ) , { type : TYPE } ) ;
check _comments ( wb ) ;
2022-06-06 23:05:27 +00:00
var ws0 = wb . Sheets [ "Sheet2" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws0 , "A1" ) . c [ 0 ] . a , 'Author' ) ;
assert . equal ( get _cell ( ws0 , "A1" ) . c [ 0 ] . t , 'Author:\nGod thinks this is good' ) ;
assert . equal ( get _cell ( ws0 , "C1" ) . c [ 0 ] . a , 'Author' ) ;
assert . equal ( get _cell ( ws0 , "C1" ) . c [ 0 ] . t , 'I really hope that xlsx decides not to use magic like rPr' ) ;
} ) ; } ) ;
} ) ;
describe ( 'should parse core properties and custom properties' , function ( ) {
var wbs = [ ] ;
var bef = ( function ( ) {
wbs = [
2022-06-06 23:05:27 +00:00
X . read ( fs . readFileSync ( paths . cpxlsx ) , { type : TYPE , WTF : true } ) ,
X . read ( fs . readFileSync ( paths . cpxlsb ) , { type : TYPE , WTF : true } ) ,
X . read ( fs . readFileSync ( paths . cpxls ) , { type : TYPE , WTF : true } ) ,
X . read ( fs . readFileSync ( paths . cpxml ) , { type : TYPE , WTF : true } )
2022-02-13 09:35:34 +00:00
] ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
[ 'XLSX' , 'XLSB' , 'XLS' , 'XML' ] . forEach ( function ( x , i ) {
it ( x + ' should parse core properties' , function ( ) { coreprop ( wbs [ i ] . Props ) ; } ) ;
it ( x + ' should parse custom properties' , function ( ) { custprop ( wbs [ i ] . Custprops ) ; } ) ;
} ) ;
[
[ "asxls" , "BIFF8" , "\u2603" ] ,
[ "asxls5" , "BIFF5" , "_" ] ,
[ "asxml" , "XLML" , "\u2603" ] ,
[ "asods" , "ODS" , "God" ] ,
[ "asxlsx" , "XLSX" , "\u2603" ] ,
[ "asxlsb" , "XLSB" , "\u2603" ]
] . forEach ( function ( x ) {
( fs . existsSync ( paths [ x [ 0 ] ] ) ? it : it . skip ) ( x [ 1 ] + ' should read ' + ( x [ 2 ] == "\u2603" ? 'unicode ' : "" ) + 'author' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths [ x [ 0 ] ] ) , { type : TYPE } ) ;
assert . equal ( wb . Props . Author , x [ 2 ] ) ;
} ) ; } ) ;
var BASE = "இராமா" ;
/* TODO: ODS, XLS */
[ "xlsx" , "xlsb" , "xlml" /*, "ods", "xls" */ ] . forEach ( function ( n ) {
it ( n + ' should round-trip unicode category' , function ( ) {
var wb = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ "a" ] ] ) , "Sheet1" ) ;
if ( ! wb . Props ) wb . Props = { } ;
wb . Props . Category = BASE ;
var wb2 = X . read ( X . write ( wb , { bookType : n , type : TYPE } ) , { type : TYPE } ) ;
assert . equal ( wb2 . Props . Category , BASE ) ;
} ) ; } ) ;
} ) ;
describe ( 'sheetRows' , function ( ) {
it ( 'should use original range if not set' , function ( ) {
var opts = { type : TYPE } ;
FSTPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , opts ) ; } ) . forEach ( function ( wb ) {
2022-06-06 23:05:27 +00:00
assert . equal ( wb . Sheets [ "Text" ] [ "!ref" ] , "A1:F49" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
it ( 'should adjust range if set' , function ( ) {
var opts = { type : TYPE , sheetRows : 10 } ;
var wbs = FSTPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , opts ) ; } ) ;
/* TODO: XLS, XML, ODS */
wbs . slice ( 0 , 2 ) . forEach ( function ( wb ) {
2022-06-06 23:05:27 +00:00
assert . equal ( wb . Sheets [ "Text" ] [ "!fullref" ] , "A1:F49" ) ;
assert . equal ( wb . Sheets [ "Text" ] [ "!ref" ] , "A1:F10" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
it ( 'should not generate comment cells' , function ( ) {
var opts = { type : TYPE , sheetRows : 10 } ;
var wbs = CSTPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , opts ) ; } ) ;
/* TODO: XLS, XML, ODS */
wbs . slice ( 0 , 2 ) . forEach ( function ( wb ) {
2022-06-06 23:05:27 +00:00
assert . equal ( wb . Sheets [ "Sheet7" ] [ "!fullref" ] , "A1:N34" ) ;
assert . equal ( wb . Sheets [ "Sheet7" ] [ "!ref" ] , "A1" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
} ) ;
describe ( 'column properties' , function ( ) {
var wbs = [ ] , wbs _no _slk = [ ] ;
var bef = ( function ( ) {
wbs = CWPaths . map ( function ( n ) { return X . read ( fs . readFileSync ( n ) , { type : TYPE , cellStyles : true } ) ; } ) ;
wbs _no _slk = wbs . slice ( 0 , 5 ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( 'should have "!cols"' , function ( ) {
2022-06-06 23:05:27 +00:00
wbs . forEach ( function ( wb ) { assert . ok ( wb . Sheets [ "Sheet1" ] [ '!cols' ] ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
it ( 'should have correct widths' , function ( ) {
/* SYLK rounds wch so skip non-integral */
2022-06-06 23:05:27 +00:00
wbs _no _slk . map ( function ( x ) { return x . Sheets [ "Sheet1" ] [ '!cols' ] ; } ) . forEach ( function ( x ) {
2022-02-13 09:35:34 +00:00
assert . equal ( x [ 1 ] . width , 0.1640625 ) ;
assert . equal ( x [ 2 ] . width , 16.6640625 ) ;
assert . equal ( x [ 3 ] . width , 1.6640625 ) ;
} ) ;
2022-06-06 23:05:27 +00:00
wbs . map ( function ( x ) { return x . Sheets [ "Sheet1" ] [ '!cols' ] ; } ) . forEach ( function ( x ) {
2022-02-13 09:35:34 +00:00
assert . equal ( x [ 4 ] . width , 4.83203125 ) ;
assert . equal ( x [ 5 ] . width , 8.83203125 ) ;
assert . equal ( x [ 6 ] . width , 12.83203125 ) ;
assert . equal ( x [ 7 ] . width , 16.83203125 ) ;
} ) ;
} ) ;
it ( 'should have correct pixels' , function ( ) {
/* SYLK rounds wch so skip non-integral */
2022-06-06 23:05:27 +00:00
wbs _no _slk . map ( function ( x ) { return x . Sheets [ "Sheet1" ] [ '!cols' ] ; } ) . forEach ( function ( x ) {
2022-02-13 09:35:34 +00:00
assert . equal ( x [ 1 ] . wpx , 1 ) ;
assert . equal ( x [ 2 ] . wpx , 100 ) ;
assert . equal ( x [ 3 ] . wpx , 10 ) ;
} ) ;
2022-06-06 23:05:27 +00:00
wbs . map ( function ( x ) { return x . Sheets [ "Sheet1" ] [ '!cols' ] ; } ) . forEach ( function ( x ) {
2022-02-13 09:35:34 +00:00
assert . equal ( x [ 4 ] . wpx , 29 ) ;
assert . equal ( x [ 5 ] . wpx , 53 ) ;
assert . equal ( x [ 6 ] . wpx , 77 ) ;
assert . equal ( x [ 7 ] . wpx , 101 ) ;
} ) ;
} ) ;
} ) ;
describe ( 'row properties' , function ( ) {
var wbs = [ ] , ols = [ ] ;
var ol = fs . existsSync ( paths . olxls ) ;
var bef = ( function ( ) {
wbs = RHPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE , cellStyles : true } ) ; } ) ;
/* */
if ( ! ol ) return ;
ols = OLPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE , cellStyles : true } ) ; } ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( 'should have "!rows"' , function ( ) {
2022-06-06 23:05:27 +00:00
wbs . forEach ( function ( wb ) { assert . ok ( wb . Sheets [ "Sheet1" ] [ '!rows' ] ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
it ( 'should have correct points' , function ( ) {
2022-06-06 23:05:27 +00:00
wbs . map ( function ( x ) { return x . Sheets [ "Sheet1" ] [ '!rows' ] ; } ) . forEach ( function ( x ) {
2022-02-13 09:35:34 +00:00
assert . equal ( x [ 1 ] . hpt , 1 ) ;
assert . equal ( x [ 2 ] . hpt , 10 ) ;
assert . equal ( x [ 3 ] . hpt , 100 ) ;
} ) ;
} ) ;
it ( 'should have correct pixels' , function ( ) {
2022-06-06 23:05:27 +00:00
wbs . map ( function ( x ) { return x . Sheets [ "Sheet1" ] [ '!rows' ] ; } ) . forEach ( function ( x ) {
2022-02-13 09:35:34 +00:00
/* note: at 96 PPI hpt == hpx */
assert . equal ( x [ 1 ] . hpx , 1 ) ;
assert . equal ( x [ 2 ] . hpx , 10 ) ;
assert . equal ( x [ 3 ] . hpx , 100 ) ;
} ) ;
} ) ;
2022-06-06 23:05:27 +00:00
it ( 'should have correct outline levels' , function ( ) {
ols . map ( function ( x ) { return x . Sheets [ "Sheet1" ] ; } ) . forEach ( function ( ws ) {
2022-02-13 09:35:34 +00:00
var rows = ws [ '!rows' ] ;
for ( var i = 0 ; i < 29 ; ++ i ) {
var cell = get _cell ( ws , "A" + X . utils . encode _row ( i ) ) ;
var lvl = ( rows [ i ] || { } ) . level || 0 ;
if ( ! cell || cell . t == 's' ) assert . equal ( lvl , 0 ) ;
else if ( cell . t == 'n' ) {
if ( cell . v === 0 ) assert . equal ( lvl , 0 ) ;
else assert . equal ( lvl , cell . v ) ;
}
}
assert . equal ( rows [ 29 ] . level , 7 ) ;
} ) ;
} ) ;
} ) ;
describe ( 'merge cells' , function ( ) {
var wbs = [ ] ;
var bef = ( function ( ) {
wbs = MCPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE } ) ; } ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( 'should have !merges' , function ( ) {
wbs . forEach ( function ( wb ) {
2022-06-06 23:05:27 +00:00
assert . ok ( wb . Sheets [ "Merge" ] [ '!merges' ] ) ;
2022-02-13 09:35:34 +00:00
} ) ;
2022-06-06 23:05:27 +00:00
var m = wbs . map ( function ( x ) { return x . Sheets [ "Merge" ] [ '!merges' ] . map ( function ( y ) { return X . utils . encode _range ( y ) ; } ) ; } ) ;
2022-02-13 09:35:34 +00:00
m . slice ( 1 ) . forEach ( function ( x ) {
assert . deepEqual ( m [ 0 ] . sort ( ) , x . sort ( ) ) ;
} ) ;
} ) ;
} ) ;
describe ( 'should find hyperlinks' , function ( ) {
var wb1 , wb2 ;
var bef = ( function ( ) {
2022-06-06 23:05:27 +00:00
wb1 = HLPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE , WTF : true } ) ; } ) ;
wb2 = ILPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE , WTF : true } ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
[ 'xlsx' , 'xlsb' , 'xls' , 'xml' ] . forEach ( function ( x , i ) {
2022-06-06 23:05:27 +00:00
it ( x + " external" , function ( ) { hlink1 ( wb1 [ i ] . Sheets [ "Sheet1" ] ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
[ 'xlsx' , 'xlsb' , 'xls' , 'xml' , 'ods' ] . forEach ( function ( x , i ) {
2022-06-06 23:05:27 +00:00
it ( x + " internal" , function ( ) { hlink2 ( wb2 [ i ] . Sheets [ "Sheet1" ] ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
describe ( 'should parse cells with date type (XLSX/XLSM)' , function ( ) {
it ( 'Must have read the date' , function ( ) {
var wb , ws ;
var sheetName = 'Sheet1' ;
wb = X . read ( fs . readFileSync ( paths . dtxlsx ) , { type : TYPE } ) ;
ws = wb . Sheets [ sheetName ] ;
var sheet = X . utils . sheet _to _json ( ws , { raw : false } ) ;
assert . equal ( sheet [ 3 ] [ 'てすと' ] , '2/14/14' ) ;
} ) ;
it ( 'cellDates should not affect formatted text' , function ( ) {
var sheetName = 'Sheet1' ;
var ws1 = X . read ( fs . readFileSync ( paths . dtxlsx ) , { type : TYPE } ) . Sheets [ sheetName ] ;
var ws2 = X . read ( fs . readFileSync ( paths . dtxlsb ) , { type : TYPE } ) . Sheets [ sheetName ] ;
assert . equal ( X . utils . sheet _to _csv ( ws1 ) , X . utils . sheet _to _csv ( ws2 ) ) ;
} ) ;
} ) ;
describe ( 'cellDates' , function ( ) {
var fmts = [
/* desc path sheet cell formatted */
[ 'XLSX' , paths . dtxlsx , 'Sheet1' , 'B5' , '2/14/14' ] ,
[ 'XLSB' , paths . dtxlsb , 'Sheet1' , 'B5' , '2/14/14' ] ,
[ 'XLS' , paths . dtxls , 'Sheet1' , 'B5' , '2/14/14' ] ,
[ 'XLML' , paths . dtxml , 'Sheet1' , 'B5' , '2/14/14' ] ,
[ 'XLSM' , paths . nfxlsx , 'Implied' , 'B13' , '18-Oct-33' ]
] ;
it ( 'should not generate date cells by default' , function ( ) { fmts . forEach ( function ( f ) {
var wb , ws ;
wb = X . read ( fs . readFileSync ( f [ 1 ] ) , { type : TYPE } ) ;
ws = wb . Sheets [ f [ 2 ] ] ;
assert . equal ( get _cell ( ws , f [ 3 ] ) . w , f [ 4 ] ) ;
assert . equal ( get _cell ( ws , f [ 3 ] ) . t , 'n' ) ;
} ) ; } ) ;
it ( 'should generate date cells if cellDates is true' , function ( ) { fmts . forEach ( function ( f ) {
var wb , ws ;
wb = X . read ( fs . readFileSync ( f [ 1 ] ) , { type : TYPE , cellDates : true } ) ;
ws = wb . Sheets [ f [ 2 ] ] ;
assert . equal ( get _cell ( ws , f [ 3 ] ) . w , f [ 4 ] ) ;
assert . equal ( get _cell ( ws , f [ 3 ] ) . t , 'd' ) ;
} ) ; } ) ;
} ) ;
describe ( 'defined names' , function ( ) { [
/* desc path cmnt */
[ 'xlsx' , paths . dnsxlsx , true ] ,
[ 'xlsb' , paths . dnsxlsb , true ] ,
[ 'xls' , paths . dnsxls , true ] ,
2022-05-17 01:26:22 +00:00
[ 'xlml' , paths . dnsxml , false ] ,
[ 'slk' , paths . dnsslk , false ]
2022-02-13 09:35:34 +00:00
] . forEach ( function ( m ) { it ( m [ 0 ] , function ( ) {
var wb = X . read ( fs . readFileSync ( m [ 1 ] ) , { type : TYPE } ) ;
var names = wb . Workbook . Names ;
2022-05-17 01:26:22 +00:00
if ( m [ 0 ] != 'slk' ) {
2022-02-13 09:35:34 +00:00
for ( var i = 0 ; i < names . length ; ++ i ) if ( names [ i ] . Name == "SheetJS" ) break ;
assert . ok ( i < names . length , "Missing name" ) ;
assert . equal ( names [ i ] . Sheet , null ) ;
assert . equal ( names [ i ] . Ref , "Sheet1!$A$1" ) ;
if ( m [ 2 ] ) assert . equal ( names [ i ] . Comment , "defined names just suck excel formulae are bad MS should feel bad" ) ;
2022-05-17 01:26:22 +00:00
}
2022-02-13 09:35:34 +00:00
for ( i = 0 ; i < names . length ; ++ i ) if ( names [ i ] . Name == "SHEETjs" ) break ;
assert . ok ( i < names . length , "Missing name" ) ;
assert . equal ( names [ i ] . Sheet , 0 ) ;
assert . equal ( names [ i ] . Ref , "Sheet1!$A$2" ) ;
} ) ; } ) ; } ) ;
describe ( 'defined names unicode' , function ( ) { [
2022-05-25 01:45:55 +00:00
/* desc path RT */
[ 'xlsx' , paths . dnuxlsx , true ] ,
[ 'xlsb' , paths . dnuxlsb , true ] ,
[ 'ods' , paths . dnuods , true ] ,
[ 'xls' , paths . dnuxls , false ] ,
[ 'xlml' , paths . dnuxml , false ]
2022-02-13 09:35:34 +00:00
] . forEach ( function ( m ) { it ( m [ 0 ] , function ( ) {
var wb = X . read ( fs . readFileSync ( m [ 1 ] ) , { type : TYPE } ) ;
2022-05-25 01:45:55 +00:00
var wb2 = X . read ( X . write ( wb , { type : TYPE , bookType : m [ 0 ] } ) , { type : TYPE } ) ;
2022-02-13 09:35:34 +00:00
[
"NoContainsJapanese" ,
"\u65E5\u672C\u8a9e\u306e\u307f" ,
"sheet\u65e5\u672c\u8a9e" ,
"\u65e5\u672c\u8a9esheet" ,
"sheet\u65e5\u672c\u8a9esheet"
] . forEach ( function ( n , i ) { assert . equal ( wb . SheetNames [ i ] , n ) ; } ) ;
[
[ "name\u65e5\u672c\u8a9e" , "sheet\u65e5\u672c\u8a9e!$A$1" ] ,
[ "name\u65e5\u672c\u8a9ename" , "sheet\u65e5\u672c\u8a9esheet!$B$2" ] ,
[ "NoContainsJapaneseName" , "\u65e5\u672c\u8a9e\u306e\u307f!$A$1" ] ,
[ "sheet\u65e5\u672c\u8a9e" , "sheet\u65e5\u672c\u8a9e!$A$1" ] ,
[ "\u65e5\u672c\u8a9e" , "NoContainsJapanese!$A$1" ] ,
[ "\u65e5\u672c\u8a9ename" , "\u65e5\u672c\u8a9esheet!$I$2" ]
2022-05-25 01:45:55 +00:00
] . forEach ( function ( n ) { ( m [ 2 ] ? [ wb , wb2 ] : [ wb ] ) . forEach ( function ( wb ) {
2022-02-13 09:35:34 +00:00
var DN = null ;
var arr = wb . Workbook . Names ;
for ( var j = 0 ; j < arr . length ; ++ j ) if ( arr [ j ] . Name == n [ 0 ] ) DN = arr [ j ] ;
assert . ok ( DN ) ;
// $FlowIgnore
assert . equal ( DN . Ref , n [ 1 ] ) ;
2022-05-25 01:45:55 +00:00
} ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ; } ) ; } ) ;
describe ( 'workbook codename unicode' , function ( ) {
var ws , wb ;
var bef = ( function ( ) {
wb = X . utils . book _new ( ) ;
ws = X . utils . aoa _to _sheet ( [ [ 1 ] ] ) ;
X . utils . book _append _sheet ( wb , ws , "Sheet1" ) ;
wb . Workbook = { WBProps : { CodeName : "本工作簿" } } ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
[ 'xlsx' , 'xlsb' ] . forEach ( function ( m ) { it ( m , function ( ) {
var bstr = X . write ( wb , { type : "binary" , bookType : m } ) ;
var nwb = X . read ( bstr , { type : "binary" } ) ;
assert . equal ( nwb . Workbook . WBProps . CodeName , wb . Workbook . WBProps . CodeName ) ;
} ) ; } ) ;
} ) ;
describe ( 'auto filter' , function ( ) { [
[ 'xlsx' , paths . afxlsx ] ,
[ 'xlsb' , paths . afxlsb ] ,
[ 'xls' , paths . afxls ] ,
[ 'xlml' , paths . afxml ] ,
[ 'ods' , paths . afods ]
] . forEach ( function ( m ) { it ( m [ 0 ] , function ( ) {
var wb = X . read ( fs . readFileSync ( m [ 1 ] ) , { type : TYPE } ) ;
assert . ok ( ! wb . Sheets [ wb . SheetNames [ 0 ] ] [ '!autofilter' ] ) ;
for ( var i = 1 ; i < wb . SheetNames . length ; ++ i ) {
assert . ok ( wb . Sheets [ wb . SheetNames [ i ] ] [ '!autofilter' ] ) ;
assert . equal ( wb . Sheets [ wb . SheetNames [ i ] ] [ '!autofilter' ] . ref , "A1:E22" ) ;
}
} ) ; } ) ; } ) ;
describe ( 'HTML' , function ( ) {
var ws , wb ;
var bef = ( function ( ) {
ws = X . utils . aoa _to _sheet ( [
[ "a" , "b" , "c" ] ,
[ "&" , "<" , ">" , "\n" ]
] ) ;
wb = { SheetNames : [ "Sheet1" ] , Sheets : { Sheet1 : ws } } ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
[ 'xlsx' ] . forEach ( function ( m ) { it ( m , function ( ) {
var wb2 = X . read ( X . write ( wb , { bookType : m , type : TYPE } ) , { type : TYPE , cellHTML : true } ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( wb2 . Sheets [ "Sheet1" ] , "A2" ) . h , "&" ) ;
assert . equal ( get _cell ( wb2 . Sheets [ "Sheet1" ] , "B2" ) . h , "<" ) ;
assert . equal ( get _cell ( wb2 . Sheets [ "Sheet1" ] , "C2" ) . h , ">" ) ;
var h = get _cell ( wb2 . Sheets [ "Sheet1" ] , "D2" ) . h ;
2022-02-13 09:35:34 +00:00
assert . ok ( h == "
" || h == "<br/>" ) ;
} ) ; } ) ;
} ) ;
describe ( 'page margins' , function ( ) {
var wbs = [ ] ;
var bef = ( function ( ) {
if ( ! fs . existsSync ( paths . pmxls ) ) return ;
2022-06-06 23:05:27 +00:00
wbs = PMPaths . map ( function ( p ) { return X . read ( fs . readFileSync ( p ) , { type : TYPE , WTF : true } ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
[
/* Sheet Name Margins: left right top bottom head foot */
[ "Normal" , [ 0.70 , 0.70 , 0.75 , 0.75 , 0.30 , 0.30 ] ] ,
[ "Wide" , [ 1.00 , 1.00 , 1.00 , 1.00 , 0.50 , 0.50 ] ] ,
[ "Narrow" , [ 0.25 , 0.25 , 0.75 , 0.75 , 0.30 , 0.30 ] ] ,
[ "Custom 1 Inch Centered" , [ 1.00 , 1.00 , 1.00 , 1.00 , 0.30 , 0.30 ] ] ,
[ "1 Inch HF" , [ 0.70 , 0.70 , 0.75 , 0.75 , 1.00 , 1.00 ] ]
] . forEach ( function ( t ) { it ( 'should parse ' + t [ 0 ] + ' margin' , function ( ) { wbs . forEach ( function ( wb ) {
check _margin ( wb . Sheets [ t [ 0 ] ] [ "!margins" ] , t [ 1 ] ) ;
} ) ; } ) ; } ) ;
} ) ;
describe ( 'should correctly handle styles' , function ( ) {
var wsxls , wsxlsx , rn , rn2 ;
var bef = ( function ( ) {
2022-06-06 23:05:27 +00:00
wsxls = X . read ( fs . readFileSync ( paths . cssxls ) , { type : TYPE , cellStyles : true , WTF : true } ) . Sheets [ "Sheet1" ] ;
wsxlsx = X . read ( fs . readFileSync ( paths . cssxlsx ) , { type : TYPE , cellStyles : true , WTF : true } ) . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
rn = function ( range ) {
var r = X . utils . decode _range ( range ) ;
var out = [ ] ;
for ( var R = r . s . r ; R <= r . e . r ; ++ R ) for ( var C = r . s . c ; C <= r . e . c ; ++ C )
out . push ( X . utils . encode _cell ( { c : C , r : R } ) ) ;
return out ;
} ;
rn2 = function ( r ) { return [ ] . concat . apply ( [ ] , r . split ( "," ) . map ( rn ) ) ; } ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
var ranges = [
'A1:D1,F1:G1' , 'A2:D2,F2:G2' , /* rows */
'A3:A10' , 'B3:B10' , 'E1:E10' , 'F6:F8' , /* cols */
'H1:J4' , 'H10' /* blocks */
] ;
/*eslint-disable */
var exp /*:Array<any>*/ = [
{ patternType : 'darkHorizontal' ,
fgColor : { theme : 9 , raw _rgb : 'F79646' } ,
bgColor : { theme : 5 , raw _rgb : 'C0504D' } } ,
{ patternType : 'darkUp' ,
fgColor : { theme : 3 , raw _rgb : '1F497D' } ,
bgColor : { theme : 7 , raw _rgb : '8064A2' } } ,
{ patternType : 'darkGray' ,
fgColor : { theme : 3 , raw _rgb : '1F497D' } ,
bgColor : { theme : 1 , raw _rgb : '000000' } } ,
{ patternType : 'lightGray' ,
fgColor : { theme : 6 , raw _rgb : '9BBB59' } ,
bgColor : { theme : 2 , raw _rgb : 'EEECE1' } } ,
{ patternType : 'lightDown' ,
fgColor : { theme : 4 , raw _rgb : '4F81BD' } ,
bgColor : { theme : 7 , raw _rgb : '8064A2' } } ,
{ patternType : 'lightGrid' ,
fgColor : { theme : 6 , raw _rgb : '9BBB59' } ,
bgColor : { theme : 9 , raw _rgb : 'F79646' } } ,
{ patternType : 'lightGrid' ,
fgColor : { theme : 4 , raw _rgb : '4F81BD' } ,
bgColor : { theme : 2 , raw _rgb : 'EEECE1' } } ,
{ patternType : 'lightVertical' ,
fgColor : { theme : 3 , raw _rgb : '1F497D' } ,
bgColor : { theme : 7 , raw _rgb : '8064A2' } }
] ;
/*eslint-enable */
ranges . forEach ( function ( rng ) {
it ( 'XLS | ' + rng , function ( ) { cmparr ( rn2 ( rng ) . map ( function ( x ) { return get _cell ( wsxls , x ) . s ; } ) ) ; } ) ;
it ( 'XLSX | ' + rng , function ( ) { cmparr ( rn2 ( rng ) . map ( function ( x ) { return get _cell ( wsxlsx , x ) . s ; } ) ) ; } ) ;
} ) ;
it ( 'different styles' , function ( ) {
for ( var i = 0 ; i != ranges . length - 1 ; ++ i ) {
for ( var j = i + 1 ; j != ranges . length ; ++ j ) {
diffsty ( wsxlsx , rn2 ( ranges [ i ] ) [ 0 ] , rn2 ( ranges [ j ] ) [ 0 ] ) ;
/* TODO: XLS */
//diffsty(wsxls, rn2(ranges[i])[0], rn2(ranges[j])[0]);
}
}
} ) ;
it ( 'correct styles' , function ( ) {
//var stylesxls = ranges.map(function(r) { return rn2(r)[0]; }).map(function(r) { return get_cell(wsxls,r).s; });
var stylesxlsx = ranges . map ( function ( r ) { return rn2 ( r ) [ 0 ] ; } ) . map ( function ( r ) { return get _cell ( wsxlsx , r ) . s ; } ) ;
exp . forEach ( function ( e , i ) {
[
"fgColor.theme" , "fgColor.raw_rgb" ,
"bgColor.theme" , "bgColor.raw_rgb" ,
"patternType"
] . forEach ( function ( k ) {
deepcmp ( e , stylesxlsx [ i ] , k , i + ":" + k , 0 ) ;
/* TODO: XLS */
//deepcmp(e, stylesxls[i], k, i + ":" + k, 0);
} ) ;
} ) ;
} ) ;
} ) ;
2022-03-20 05:29:24 +00:00
describe ( 'data types formats' , function ( ) { [
2022-08-08 23:21:46 +00:00
[ 'xlsx' , paths . dtfxlsx ]
2022-03-20 05:29:24 +00:00
] . forEach ( function ( m ) { it ( m [ 0 ] , function ( ) {
var wb = X . read ( fs . readFileSync ( m [ 1 ] ) , { type : TYPE , cellDates : true } ) ;
var ws = wb . Sheets [ wb . SheetNames [ 0 ] ] ;
var data = X . utils . sheet _to _json ( ws , { header : 1 , raw : true , rawNumbers : false } ) ;
assert . ok ( data [ 0 ] [ 1 ] instanceof Date ) ;
assert . ok ( data [ 1 ] [ 1 ] instanceof Date ) ;
assert . equal ( data [ 2 ] [ 1 ] , '$123.00' ) ;
assert . equal ( data [ 3 ] [ 1 ] , '98.76%' ) ;
assert . equal ( data [ 4 ] [ 1 ] , '456.00' ) ;
assert . equal ( data [ 5 ] [ 1 ] , '7,890' ) ;
} ) ; } ) ; } ) ;
2022-06-06 23:05:27 +00:00
it ( 'date system' , function ( ) { [
"biff5" , "ods" , "slk" , "xls" , "xlsb" , "xlsx" , "xml"
] . forEach ( function ( ext ) {
// TODO: verify actual date values
var wb0 = X . read ( fs . readFileSync ( "./test_files/1904/1900." + ext ) , { type : TYPE , cellNF : true } ) ;
assert . ok ( ! wb0 . Workbook || ! wb0 . Workbook . WBProps || ! wb0 . Workbook . WBProps . date1904 ) ;
assert . equal ( X . utils . sheet _to _csv ( wb0 . Sheets [ wb0 . SheetNames [ 0 ] ] ) , [
"1,1900-01-01,1900-01-01,1900-01-01" ,
"11,1900-01-11,1900-01-11,1900-01-11" ,
"111,1900-04-20,1900-04-20,1900-04-20" ,
"1111,1903-01-15,1903-01-15,1903-01-15" ,
"11111,1930-06-02,1930-06-02,1930-06-02"
] . join ( "\n" ) ) ;
var wb4 = X . read ( fs . readFileSync ( "./test_files/1904/1904." + ext ) , { type : TYPE , cellNF : true } ) ;
assert . ok ( wb4 . Workbook . WBProps . date1904 ) ;
assert . equal ( X . utils . sheet _to _csv ( wb4 . Sheets [ wb4 . SheetNames [ 0 ] ] ) , [
"1,1904-01-02,1904-01-02,1904-01-02" ,
"11,1904-01-12,1904-01-12,1904-01-12" ,
"111,1904-04-21,1904-04-21,1904-04-21" ,
"1111,1907-01-16,1907-01-16,1907-01-16" ,
"11111,1934-06-03,1934-06-03,1934-06-03"
] . join ( "\n" ) ) ;
2022-07-08 22:31:08 +00:00
} ) ; } ) ;
it ( 'bookType metadata' , function ( ) {
[
// TODO: keep in sync with BookType, support other formats
"xlsx" /*, "xlsm" */ , "xlsb" /* xls / xla / biff# */ , "xlml" , "ods" , "fods" /*, "csv", "txt", */ , "sylk" , "html" , "dif" , "rtf" /*, "prn", "eth"*/ , "dbf" , "numbers"
] . forEach ( function ( r ) {
2022-09-22 09:05:24 +00:00
if ( r == "numbers" && ! can _write _numbers ) return ;
2022-07-08 22:31:08 +00:00
var ws = X . utils . aoa _to _sheet ( [ [ "a" , "b" , "c" ] , [ 1 , 2 , 3 ] ] ) ;
var wb = X . utils . book _new ( ) ; X . utils . book _append _sheet ( wb , ws , "Sheet1" ) ;
var data = X . write ( wb , { type : TYPE , bookType : r , WTF : true , numbers : XLSX _ZAHL } ) ;
assert . equal ( X . read ( data , { type : TYPE , WTF : true } ) . bookType , r ) ;
2022-06-06 23:05:27 +00:00
} ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
describe ( 'write features' , function ( ) {
describe ( 'props' , function ( ) {
describe ( 'core' , function ( ) {
var baseprops = {
Category : "Newspaper" ,
ContentStatus : "Published" ,
Keywords : "☃" ,
LastAuthor : "Perry White" ,
LastPrinted : "1978-12-15" ,
RevNumber : 6969 ,
AppVersion : 69 ,
Author : "Lois Lane" ,
Comments : "Needs work" ,
Identifier : "1d" ,
Language : "English" ,
Subject : "Superman" ,
Title : "Man of Steel"
} ;
2022-06-06 23:05:27 +00:00
var ws ;
2022-02-13 09:35:34 +00:00
var bef = ( function ( ) {
ws = X . utils . aoa _to _sheet ( [ [ "a" , "b" , "c" ] , [ 1 , 2 , 3 ] ] ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
[ 'xlml' , 'xlsx' , 'xlsb' ] . forEach ( function ( w ) { it ( w , function ( ) {
var wb = {
Props : { } ,
SheetNames : [ "Sheet1" ] ,
Sheets : { Sheet1 : ws }
} ;
Object . keys ( baseprops ) . forEach ( function ( k ) { wb . Props [ k ] = baseprops [ k ] ; } ) ;
var wb2 = X . read ( X . write ( wb , { bookType : w , type : TYPE } ) , { type : TYPE } ) ;
Object . keys ( baseprops ) . forEach ( function ( k ) { assert . equal ( baseprops [ k ] , wb2 . Props [ k ] ) ; } ) ;
var wb3 = X . read ( X . write ( wb2 , { bookType : w , type : TYPE , Props : { Author : "SheetJS" } } ) , { type : TYPE } ) ;
assert . equal ( "SheetJS" , wb3 . Props . Author ) ;
} ) ; } ) ;
} ) ;
} ) ;
describe ( 'HTML' , function ( ) {
it ( 'should use `h` value when present' , function ( ) {
var sheet = X . utils . aoa _to _sheet ( [ [ "abc" ] ] ) ;
get _cell ( sheet , "A1" ) . h = "<b>abc</b>" ;
var wb = { SheetNames : [ "Sheet1" ] , Sheets : { Sheet1 : sheet } } ;
var str = X . write ( wb , { bookType : "html" , type : "binary" } ) ;
assert . ok ( str . indexOf ( "<b>abc</b>" ) > 0 ) ;
} ) ;
} ) ;
describe ( 'sheet range limits' , function ( ) { [
[ "biff2" , "IV16384" ] ,
[ "biff5" , "IV16384" ] ,
[ "biff8" , "IV65536" ] ,
[ "xlsx" , "XFD1048576" ] ,
[ "xlsb" , "XFD1048576" ]
] . forEach ( function ( r ) { it ( r [ 0 ] , function ( ) {
var C = X . utils . decode _cell ( r [ 1 ] ) ;
2022-06-06 23:05:27 +00:00
var wopts = { bookType : r [ 0 ] , type : 'binary' , WTF : true } ;
2022-02-13 09:35:34 +00:00
var wb = { SheetNames : [ "Sheet1" ] , Sheets : { Sheet1 : { } } } ;
2022-06-06 23:05:27 +00:00
wb . Sheets [ "Sheet1" ] [ '!ref' ] = "A1:" + X . utils . encode _cell ( { r : 0 , c : C . c } ) ;
2022-02-13 09:35:34 +00:00
X . write ( wb , wopts ) ;
2022-06-06 23:05:27 +00:00
wb . Sheets [ "Sheet1" ] [ '!ref' ] = "A" + X . utils . encode _row ( C . r - 5 ) + ":" + X . utils . encode _cell ( { r : C . r , c : 0 } ) ;
2022-02-13 09:35:34 +00:00
X . write ( wb , wopts ) ;
2022-06-06 23:05:27 +00:00
wb . Sheets [ "Sheet1" ] [ '!ref' ] = "A1:" + X . utils . encode _cell ( { r : 0 , c : C . c + 1 } ) ;
2022-02-13 09:35:34 +00:00
assert . throws ( function ( ) { X . write ( wb , wopts ) ; } ) ;
2022-06-06 23:05:27 +00:00
wb . Sheets [ "Sheet1" ] [ '!ref' ] = "A" + X . utils . encode _row ( C . r - 5 ) + ":" + X . utils . encode _cell ( { r : C . r + 1 , c : 0 } ) ;
2022-02-13 09:35:34 +00:00
assert . throws ( function ( ) { X . write ( wb , wopts ) ; } ) ;
} ) ; } ) ; } ) ;
it ( 'single worksheet formats' , function ( ) {
var wb = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 1 , 2 ] , [ 3 , 4 ] ] ) , "Sheet1" ) ;
X . utils . book _append _sheet ( wb , X . utils . aoa _to _sheet ( [ [ 5 , 6 ] , [ 7 , 8 ] ] ) , "Sheet2" ) ;
2022-03-09 01:44:10 +00:00
assert . equal ( X . write ( wb , { type : "string" , bookType : "csv" , sheet : "Sheet1" } ) , "1,2\n3,4" ) ;
assert . equal ( X . write ( wb , { type : "string" , bookType : "csv" , sheet : "Sheet2" } ) , "5,6\n7,8" ) ;
2022-02-13 09:35:34 +00:00
assert . throws ( function ( ) { X . write ( wb , { type : "string" , bookType : "csv" , sheet : "Sheet3" } ) ; } ) ;
} ) ;
2022-05-30 08:40:51 +00:00
it ( 'should create/update autofilter defined name on write' , function ( ) { [
"xlsx" , "xlsb" , /* "xls", */ "xlml" /*, "ods" */
] . forEach ( function ( fmt ) {
var wb = X . utils . book _new ( ) ;
var ws = X . utils . aoa _to _sheet ( [ [ "A" , "B" , "C" ] , [ 1 , 2 , 3 ] ] ) ;
ws [ "!autofilter" ] = { ref : ws [ "!ref" ] } ;
X . utils . book _append _sheet ( wb , ws , "Sheet1" ) ;
var wb2 = X . read ( X . write ( wb , { bookType : fmt , type : TYPE } ) , { type : TYPE } ) ;
var Name = void 0 ;
( ( wb2 . Workbook || { } ) . Names || [ ] ) . forEach ( function ( dn ) { if ( dn . Name == "_xlnm._FilterDatabase" && dn . Sheet == 0 ) Name = dn ; } ) ;
assert . ok ( ! ! Name , "Could not find _xlnm._FilterDatabases name WR" ) ;
assert . equal ( Name . Ref , "Sheet1!$A$1:$C$2" ) ;
2022-06-06 23:05:27 +00:00
X . utils . sheet _add _aoa ( wb2 . Sheets [ "Sheet1" ] , [ [ 4 , 5 , 6 ] ] , { origin : - 1 } ) ;
wb2 . Sheets [ "Sheet1" ] [ "!autofilter" ] . ref = wb2 . Sheets [ "Sheet1" ] [ "!ref" ] ;
2022-05-30 08:40:51 +00:00
var wb3 = X . read ( X . write ( wb2 , { bookType : fmt , type : TYPE } ) , { type : TYPE } ) ;
Name = void 0 ;
( ( wb3 . Workbook || { } ) . Names || [ ] ) . forEach ( function ( dn ) { if ( dn . Name == "_xlnm._FilterDatabase" && dn . Sheet == 0 ) Name = dn ; } ) ;
assert . ok ( ! ! Name , "Could not find _xlnm._FilterDatabases name WRWR" ) ;
assert . equal ( Name . Ref , "Sheet1!$A$1:$C$3" ) ;
assert . equal ( wb2 . Workbook . Names . length , wb3 . Workbook . Names . length ) ;
} ) ; } ) ;
2023-06-23 09:48:47 +00:00
it ( 'should handle non-string values for "s" cells' , function ( ) { [
"xlsx" , "xlsb" , "xls" , "biff5" , "biff2" , "xlml" , "numbers" , "ods" , "fods" , "wk3" , "csv" , "txt" , "sylk" , "html" , "dif" , "dbf" , "wk1" , "rtf" , "prn"
] . forEach ( function ( fmt ) {
if ( fmt == "numbers" && ! can _write _numbers ) return ;
var ws = X . utils . aoa _to _sheet ( [
[ "String" , "123" ] ,
[ "Number" , 123 ] ,
[ "Boolean" , true ] ,
[ "Date" , new Date ( ) ] ,
] , { cellDates : true } ) ;
ws [ "B2" ] . t = ws [ "B3" ] . t = ws [ "B4" ] . t = "s"
var wb = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb , ws , "Sheet1" ) ;
X . write ( wb , { type : TYPE , bookType : fmt , bookSST : false , numbers : XLSX _ZAHL } ) ;
X . write ( wb , { type : TYPE , bookType : fmt , bookSST : true , numbers : XLSX _ZAHL } ) ;
} ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
function seq ( end /*:number*/ , start /*:?number*/ ) /*:Array<number>*/ {
var s = start || 0 ;
var o = new Array ( end - s ) ;
for ( var i = 0 ; i != o . length ; ++ i ) o [ i ] = s + i ;
return o ;
}
2023-06-23 09:48:47 +00:00
var dnthresh = /*#__PURE__*/ Date . UTC ( 1899 , 11 , 30 , 0 , 0 , 0 ) ; // -2209161600000
var dnthresh1 = /*#__PURE__*/ Date . UTC ( 1899 , 11 , 31 , 0 , 0 , 0 ) ; // -2209075200000
var dnthresh2 = /*#__PURE__*/ Date . UTC ( 1904 , 0 , 1 , 0 , 0 , 0 ) ; // -2209075200000
2022-02-13 09:35:34 +00:00
function datenum ( v /*:Date*/ , date1904 /*:?boolean*/ ) /*:number*/ {
2023-06-23 09:48:47 +00:00
var epoch = /*#__PURE__*/ v . getTime ( ) ;
var res = ( epoch - dnthresh ) / ( 24 * 60 * 60 * 1000 ) ;
if ( date1904 ) return res - 1462 ;
return res < 60 ? res - 1 : res ;
2022-02-13 09:35:34 +00:00
}
2023-06-23 09:48:47 +00:00
/* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/ ; // HH:MM[:SS[.UUU]]
var pdre2 = /^(\d+)-(\d+)-(\d+)$/ ; // YYYY-mm-dd
var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/ ; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]] sans "Z"
/* parses a date string as a UTC date */
function parseDate ( str /*:string*/ , date1904 /*:boolean*/ ) /*:Date*/ {
2022-02-13 09:35:34 +00:00
if ( str instanceof Date ) return str ;
2023-06-23 09:48:47 +00:00
var m = str . match ( pdre1 ) ;
if ( m ) return new Date ( ( date1904 ? dnthresh2 : dnthresh1 ) + ( ( parseInt ( m [ 1 ] , 10 ) * 60 + parseInt ( m [ 2 ] , 10 ) ) * 60 + ( m [ 3 ] ? parseInt ( m [ 3 ] . slice ( 1 ) , 10 ) : 0 ) ) * 1000 + ( m [ 4 ] ? parseInt ( ( m [ 4 ] + "000" ) . slice ( 1 , 4 ) , 10 ) : 0 ) ) ;
m = str . match ( pdre2 ) ;
if ( m ) return new Date ( Date . UTC ( + m [ 1 ] , + m [ 2 ] - 1 , + m [ 3 ] , 0 , 0 , 0 , 0 ) ) ;
m = str . match ( pdre3 ) ;
if ( m ) return new Date ( Date . UTC ( + m [ 1 ] , + m [ 2 ] - 1 , + m [ 3 ] , + m [ 4 ] , + m [ 5 ] , ( ( m [ 6 ] && parseInt ( m [ 6 ] . slice ( 1 ) , 10 ) ) || 0 ) , ( ( m [ 7 ] && parseInt ( m [ 7 ] . slice ( 1 ) , 10 ) ) || 0 ) ) ) ;
var d = new Date ( str ) ;
return d ;
2022-02-13 09:35:34 +00:00
}
var fixdate = browser ? parseDate ( "2014-02-19T14:30:00.000Z" ) : new Date ( "2014-02-19T14:30Z" ) ;
describe ( 'roundtrip features' , function ( ) {
describe ( 'should preserve core properties' , function ( ) { [
[ 'xls' , paths . cpxls ] ,
[ 'xlml' , paths . cpxml ] ,
[ 'xlsx' , paths . cpxlsx ] ,
[ 'xlsb' , paths . cpxlsb ]
] . forEach ( function ( w ) {
it ( w [ 0 ] , function ( ) {
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE } ) ;
coreprop ( wb1 . Props ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : TYPE } ) , { type : TYPE } ) ;
coreprop ( wb2 . Props ) ;
} ) ;
} ) ; } ) ;
describe ( 'should preserve custom properties' , function ( ) { [
[ 'xls' , paths . cpxls ] ,
[ 'xlml' , paths . cpxml ] ,
[ 'xlsx' , paths . cpxlsx ] ,
[ 'xlsb' , paths . cpxlsb ]
] . forEach ( function ( w ) {
it ( w [ 0 ] , function ( ) {
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE } ) ;
custprop ( wb1 . Custprops ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : TYPE } ) , { type : TYPE } ) ;
custprop ( wb2 . Custprops ) ;
} ) ;
} ) ; } ) ;
describe ( 'should preserve merge cells' , function ( ) {
2022-05-17 01:26:22 +00:00
[ "xlsx" , "xlsb" , "xlml" , "ods" , "biff8" , "numbers" ] . forEach ( function ( f ) { it ( f , function ( ) {
2022-09-22 09:05:24 +00:00
if ( f == "numbers" && ! can _write _numbers ) return ;
2022-02-13 09:35:34 +00:00
var wb1 = X . read ( fs . readFileSync ( paths . mcxlsx ) , { type : TYPE } ) ;
2022-05-17 01:26:22 +00:00
var wb2 = X . read ( X . write ( wb1 , { bookType : f , type : 'binary' , numbers : XLSX _ZAHL } ) , { type : 'binary' } ) ;
2022-06-06 23:05:27 +00:00
var m1 = wb1 . Sheets [ "Merge" ] [ '!merges' ] . map ( X . utils . encode _range ) ;
var m2 = wb2 . Sheets [ "Merge" ] [ '!merges' ] . map ( X . utils . encode _range ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( m1 . length , m2 . length ) ;
for ( var i = 0 ; i < m1 . length ; ++ i ) assert . ok ( m1 . indexOf ( m2 [ i ] ) > - 1 ) ;
} ) ; } ) ;
} ) ;
describe ( 'should preserve dates' , function ( ) {
seq ( 16 ) . forEach ( function ( n ) {
var d = ( n & 1 ) ? 'd' : 'n' , dk = d === 'd' ;
var c = ( n & 2 ) ? 'd' : 'n' , dj = c === 'd' ;
var b = ( n & 4 ) ? 'd' : 'n' , di = b === 'd' ;
var a = ( n & 8 ) ? 'd' : 'n' , dh = a === 'd' ;
var f , sheet , addr ;
if ( dh ) { f = paths . dtxlsx ; sheet = 'Sheet1' ; addr = 'B5' ; }
else { f = paths . nfxlsx ; sheet = '2011' ; addr = 'J36' ; }
it ( '[' + a + '] -> (' + b + ') -> [' + c + '] -> (' + d + ')' , function ( ) {
var wb1 = X . read ( fs . readFileSync ( f ) , { type : TYPE , cellNF : true , cellDates : di , WTF : opts . WTF } ) ;
var _f = X . write ( wb1 , { type : 'binary' , cellDates : dj , WTF : opts . WTF } ) ;
var wb2 = X . read ( _f , { type : 'binary' , cellDates : dk , WTF : opts . WTF } ) ;
var m = [ wb1 , wb2 ] . map ( function ( x ) { return get _cell ( x . Sheets [ sheet ] , addr ) ; } ) ;
assert . equal ( m [ 0 ] . w , m [ 1 ] . w ) ;
assert . equal ( m [ 0 ] . t , b ) ;
assert . equal ( m [ 1 ] . t , d ) ;
if ( m [ 0 ] . t === 'n' && m [ 1 ] . t === 'n' ) assert . equal ( m [ 0 ] . v , m [ 1 ] . v ) ;
else if ( m [ 0 ] . t === 'd' && m [ 1 ] . t === 'd' ) assert . equal ( m [ 0 ] . v . toString ( ) , m [ 1 ] . v . toString ( ) ) ;
else if ( m [ 1 ] . t === 'n' ) assert . ok ( Math . abs ( datenum ( browser ? parseDate ( m [ 0 ] . v ) : new Date ( m [ 0 ] . v ) ) - m [ 1 ] . v ) < 0.01 ) ;
} ) ;
} ) ;
} ) ;
2022-06-06 23:05:27 +00:00
describe ( 'should preserve formulae' , function ( ) { var ff = [
2022-02-13 09:35:34 +00:00
[ 'xlml' , paths . fstxml ] ,
[ 'xlsx' , paths . fstxlsx ] ,
[ 'ods' , paths . fstods ]
2022-06-06 23:05:27 +00:00
] ; ff . forEach ( function ( w ) { it ( w [ 0 ] , function ( ) {
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE , cellFormula : true , WTF : true } ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : TYPE } ) , { cellFormula : true , type : TYPE , WTF : true } ) ;
2022-02-13 09:35:34 +00:00
wb1 . SheetNames . forEach ( function ( n ) {
assert . equal (
X . utils . sheet _to _formulae ( wb1 . Sheets [ n ] ) . sort ( ) . join ( "\n" ) ,
X . utils . sheet _to _formulae ( wb2 . Sheets [ n ] ) . sort ( ) . join ( "\n" )
) ;
} ) ;
} ) ; } ) ; } ) ;
2022-03-16 03:18:09 +00:00
describe ( 'should preserve dynamic array formulae' , function ( ) { [
[ 'xlsx' , paths . m19xlsx ]
] . forEach ( function ( w ) { it ( w [ 0 ] , function ( ) {
2022-06-06 23:05:27 +00:00
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { xlfn : true , type : TYPE , cellFormula : true , WTF : true } ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : TYPE } ) , { cellFormula : true , xlfn : true , type : TYPE , WTF : true } ) ;
assert . equal ( ! ! get _cell ( wb2 . Sheets [ "Sheet1" ] , "B3" ) . D , true ) ;
assert . equal ( ! ! get _cell ( wb2 . Sheets [ "Sheet1" ] , "B13" ) . D , true ) ;
assert . equal ( ! ! get _cell ( wb2 . Sheets [ "Sheet1" ] , "C13" ) . D , true ) ;
get _cell ( wb2 . Sheets [ "Sheet1" ] , "B3" ) . D = false ;
var wb3 = X . read ( X . write ( wb2 , { bookType : w [ 0 ] , type : TYPE } ) , { cellFormula : true , xlfn : true , type : TYPE , WTF : true } ) ;
assert . equal ( ! ! get _cell ( wb3 . Sheets [ "Sheet1" ] , "B3" ) . D , false ) ;
assert . equal ( ! ! get _cell ( wb3 . Sheets [ "Sheet1" ] , "B13" ) . D , true ) ;
assert . equal ( ! ! get _cell ( wb3 . Sheets [ "Sheet1" ] , "C13" ) . D , true ) ;
2022-03-16 03:18:09 +00:00
} ) ; } ) ; } ) ;
2022-02-13 09:35:34 +00:00
describe ( 'should preserve hyperlink' , function ( ) { [
[ 'xlml' , paths . hlxml , true ] ,
[ 'xls' , paths . hlxls , true ] ,
[ 'xlsx' , paths . hlxlsx , true ] ,
[ 'xlsb' , paths . hlxlsb , true ] ,
[ 'xlml' , paths . ilxml , false ] ,
[ 'xls' , paths . ilxls , false ] ,
[ 'xlsx' , paths . ilxlsx , false ] ,
[ 'xlsb' , paths . ilxlsb , false ] ,
[ 'ods' , paths . ilods , false ]
] . forEach ( function ( w ) { it ( w [ 0 ] + " " + ( w [ 2 ] ? "ex" : "in" ) + "ternal" , function ( ) {
var wb = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE , WTF : opts . WTF } ) ;
2022-06-06 23:05:27 +00:00
var hlink = ( w [ 2 ] ? hlink1 : hlink2 ) ; hlink ( wb . Sheets [ "Sheet1" ] ) ;
2022-02-13 09:35:34 +00:00
wb = X . read ( X . write ( wb , { bookType : w [ 0 ] , type : TYPE , WTF : opts . WTF } ) , { type : TYPE , WTF : opts . WTF } ) ;
2022-06-06 23:05:27 +00:00
hlink ( wb . Sheets [ "Sheet1" ] ) ;
2022-02-13 09:35:34 +00:00
} ) ; } ) ; } ) ;
2022-06-06 23:05:27 +00:00
describe ( 'should preserve page margins' , function ( ) { [
2022-02-13 09:35:34 +00:00
[ 'xlml' , paths . pmxml ] ,
[ 'xlsx' , paths . pmxlsx ] ,
[ 'xlsb' , paths . pmxlsb ]
] . forEach ( function ( w ) { it ( w [ 0 ] , function ( ) {
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE } ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : "binary" } ) , { type : "binary" } ) ;
[
/* Sheet Name Margins: left right top bottom head foot */
[ "Normal" , [ 0.70 , 0.70 , 0.75 , 0.75 , 0.30 , 0.30 ] ] ,
[ "Wide" , [ 1.00 , 1.00 , 1.00 , 1.00 , 0.50 , 0.50 ] ] ,
[ "Narrow" , [ 0.25 , 0.25 , 0.75 , 0.75 , 0.30 , 0.30 ] ] ,
[ "Custom 1 Inch Centered" , [ 1.00 , 1.00 , 1.00 , 1.00 , 0.30 , 0.30 ] ] ,
[ "1 Inch HF" , [ 0.70 , 0.70 , 0.75 , 0.75 , 1.00 , 1.00 ] ]
] . forEach ( function ( t ) {
check _margin ( wb2 . Sheets [ t [ 0 ] ] [ "!margins" ] , t [ 1 ] ) ;
} ) ;
} ) ; } ) ; } ) ;
describe ( 'should preserve sheet visibility' , function ( ) { [
[ 'xlml' , paths . svxml ] ,
[ 'xlsx' , paths . svxlsx ] ,
2022-05-22 23:51:41 +00:00
[ 'xlsb' , paths . svxlsb ] ,
[ 'xls' , paths . svxls ] ,
[ 'biff5' , paths . svxls5 ]
// ['ods', paths.svods]
2022-02-13 09:35:34 +00:00
] . forEach ( function ( w ) {
it ( w [ 0 ] , function ( ) {
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE } ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : TYPE } ) , { type : TYPE } ) ;
var wbs1 = wb1 . Workbook . Sheets ;
var wbs2 = wb2 . Workbook . Sheets ;
assert . equal ( wbs1 . length , wbs2 . length ) ;
for ( var i = 0 ; i < wbs1 . length ; ++ i ) {
assert . equal ( wbs1 [ i ] . name , wbs2 [ i ] . name ) ;
assert . equal ( wbs1 [ i ] . Hidden , wbs2 [ i ] . Hidden ) ;
}
} ) ;
} ) ;
} ) ;
describe ( 'should preserve column properties' , function ( ) { [
/*'xlml',*/ /*'biff2', 'biff8', */ 'xlsx' , 'xlsb' , 'slk'
] . forEach ( function ( w ) { it ( w , function ( ) {
var ws1 = X . utils . aoa _to _sheet ( [ [ "hpx12" , "hpt24" , "hpx48" , "hidden" ] ] ) ;
ws1 [ '!cols' ] = [ { wch : 9 } , { wpx : 100 } , { width : 80 } , { hidden : true } ] ;
var wb1 = { SheetNames : [ "Sheet1" ] , Sheets : { Sheet1 : ws1 } } ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w , type : TYPE } ) , { type : TYPE , cellStyles : true } ) ;
2022-06-06 23:05:27 +00:00
var ws2 = wb2 . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( ws2 [ '!cols' ] [ 3 ] . hidden , true ) ;
assert . equal ( ws2 [ '!cols' ] [ 0 ] . wch , 9 ) ;
if ( w == 'slk' ) return ;
assert . equal ( ws2 [ '!cols' ] [ 1 ] . wpx , 100 ) ;
/* xlml stores integral pixels -> approximate width */
if ( w == 'xlml' ) assert . equal ( Math . round ( ws2 [ '!cols' ] [ 2 ] . width ) , 80 ) ;
else assert . equal ( ws2 [ '!cols' ] [ 2 ] . width , 80 ) ;
} ) ; } ) ;
} ) ;
/* TODO: ODS and BIFF5/8 */
describe ( 'should preserve row properties' , function ( ) { [
'xlml' , /*'biff2', 'biff8', */ 'xlsx' , 'xlsb' , 'slk'
] . forEach ( function ( w ) { it ( w , function ( ) {
var ws1 = X . utils . aoa _to _sheet ( [ [ "hpx12" ] , [ "hpt24" ] , [ "hpx48" ] , [ "hidden" ] ] ) ;
ws1 [ '!rows' ] = [ { hpx : 12 } , { hpt : 24 } , { hpx : 48 } , { hidden : true } ] ;
for ( var i = 0 ; i <= 7 ; ++ i ) ws1 [ '!rows' ] . push ( { level : i } ) ;
var wb1 = { SheetNames : [ "Sheet1" ] , Sheets : { Sheet1 : ws1 } } ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w , type : TYPE , cellStyles : true } ) , { type : TYPE , cellStyles : true } ) ;
2022-06-06 23:05:27 +00:00
var ws2 = wb2 . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( ws2 [ '!rows' ] [ 0 ] . hpx , 12 ) ;
assert . equal ( ws2 [ '!rows' ] [ 1 ] . hpt , 24 ) ;
assert . equal ( ws2 [ '!rows' ] [ 2 ] . hpx , 48 ) ;
assert . equal ( ws2 [ '!rows' ] [ 3 ] . hidden , true ) ;
if ( w == 'xlsb' || w == 'xlsx' ) for ( i = 0 ; i <= 7 ; ++ i ) assert . equal ( ( ws2 [ '!rows' ] [ 4 + i ] || { } ) . level || 0 , i ) ;
} ) ; } ) ;
} ) ;
/* TODO: ODS and XLS */
describe ( 'should preserve cell comments' , function ( ) { [
[ 'xlsx' , paths . cstxlsx ] ,
[ 'xlsb' , paths . cstxlsb ] ,
2022-05-30 08:40:51 +00:00
//['xls', paths.cstxls],
2022-02-13 09:35:34 +00:00
[ 'xlml' , paths . cstxml ]
//['ods', paths.cstods]
] . forEach ( function ( w ) {
it ( w [ 0 ] , function ( ) {
var wb1 = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE } ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : w [ 0 ] , type : TYPE } ) , { type : TYPE } ) ;
check _comments ( wb1 ) ;
check _comments ( wb2 ) ;
} ) ;
} ) ;
} ) ;
it ( 'should preserve JS objects' , function ( ) {
var data /*:Array<any>*/ = [
{ a : 1 } ,
{ b : 2 , c : 3 } ,
{ b : "a" , d : "b" } ,
{ a : true , c : false } ,
{ c : fixdate }
] ;
var o = X . utils . sheet _to _json ( X . utils . json _to _sheet ( data , { cellDates : true } ) ) ;
data . forEach ( function ( row , i ) {
2023-06-23 09:48:47 +00:00
Object . keys ( row ) . forEach ( function ( k ) { assert . equal ( row [ k ] . valueOf ( ) , o [ i ] [ k ] . valueOf ( ) ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
2022-05-30 08:40:51 +00:00
it ( 'should preserve autofilter settings' , function ( ) { [
[ 'xlsx' , paths . afxlsx ] ,
[ 'xlsb' , paths . afxlsb ] ,
// TODO:
//['xls', paths.afxls],
[ 'xlml' , paths . afxml ]
//['ods', paths.afods]
] . forEach ( function ( w ) {
var wb = X . read ( fs . readFileSync ( w [ 1 ] ) , { type : TYPE } ) ;
var wb2 = X . read ( X . write ( wb , { bookType : w [ 0 ] , type : TYPE } ) , { type : TYPE } ) ;
assert . ok ( ! wb2 . Sheets [ wb2 . SheetNames [ 0 ] ] [ '!autofilter' ] ) ;
for ( var i = 1 ; i < wb2 . SheetNames . length ; ++ i ) {
assert . ok ( wb2 . Sheets [ wb2 . SheetNames [ i ] ] [ '!autofilter' ] ) ;
assert . equal ( wb2 . Sheets [ wb2 . SheetNames [ i ] ] [ '!autofilter' ] . ref , "A1:E22" ) ;
}
} ) ; } ) ;
2022-06-06 23:05:27 +00:00
2022-07-05 06:52:55 +00:00
it ( 'should preserve date system' , function ( ) { [
"biff5" , "ods" , "slk" , "xls" , "xlsb" , "xlsx" , "xml"
] . forEach ( function ( ext ) {
// TODO: check actual date codes and actual date values
var wb0 = X . read ( fs . readFileSync ( "./test_files/1904/1900." + ext ) , { type : TYPE } ) ;
assert . ok ( ! wb0 . Workbook || ! wb0 . Workbook . WBProps || ! wb0 . Workbook . WBProps . date1904 ) ;
var wb1 = X . read ( X . write ( wb0 , { type : TYPE , bookType : ext } ) , { type : TYPE } ) ;
assert . ok ( ! wb1 . Workbook || ! wb1 . Workbook . WBProps || ! wb1 . Workbook . WBProps . date1904 ) ;
var wb2 = X . utils . book _new ( ) ; X . utils . book _append _sheet ( wb2 , X . utils . aoa _to _sheet ( [ [ 1 ] ] ) , "Sheet1" ) ;
wb2 . Workbook = { WBProps : { date1904 : false } } ;
assert . ok ( ! wb2 . Workbook || ! wb2 . Workbook . WBProps || ! wb2 . Workbook . WBProps . date1904 ) ;
var wb3 = X . read ( X . write ( wb2 , { type : TYPE , bookType : ext } ) , { type : TYPE } ) ;
assert . ok ( ! wb3 . Workbook || ! wb3 . Workbook . WBProps || ! wb3 . Workbook . WBProps . date1904 ) ;
var wb4 = X . read ( fs . readFileSync ( "./test_files/1904/1904." + ext ) , { type : TYPE } ) ;
assert . ok ( wb4 . Workbook . WBProps . date1904 ) ;
var wb5 = X . read ( X . write ( wb4 , { type : TYPE , bookType : ext } ) , { type : TYPE } ) ;
assert . ok ( wb5 . Workbook . WBProps . date1904 ) ; // xlsb, xml
var wb6 = X . utils . book _new ( ) ; X . utils . book _append _sheet ( wb6 , X . utils . aoa _to _sheet ( [ [ 1 ] ] ) , "Sheet1" ) ;
wb6 . Workbook = { WBProps : { date1904 : true } } ;
assert . ok ( wb6 . Workbook . WBProps . date1904 ) ;
var wb7 = X . read ( X . write ( wb6 , { type : TYPE , bookType : ext } ) , { type : TYPE } ) ;
assert . ok ( wb7 . Workbook . WBProps . date1904 ) ;
} ) ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
//function password_file(x){return x.match(/^password.*\.xls$/); }
var password _files = [
//"password_2002_40_972000.xls",
"password_2002_40_xor.xls"
] ;
describe ( 'invalid files' , function ( ) {
describe ( 'parse' , function ( ) { [
2022-05-17 01:26:22 +00:00
[ 'KEY files' , 'numbers/Untitled.key' ] ,
[ 'PAGES files' , 'numbers/Untitled.pages' ] ,
2022-02-13 09:35:34 +00:00
[ 'password' , 'apachepoi_password.xls' ] ,
[ 'passwords' , 'apachepoi_xor-encryption-abc.xls' ] ,
[ 'DOC files' , 'word_doc.doc' ]
] . forEach ( function ( w ) { it ( 'should fail on ' + w [ 0 ] , function ( ) {
assert . throws ( function ( ) { X . read ( fs . readFileSync ( dir + w [ 1 ] , 'binary' ) , { type : 'binary' } ) ; } ) ;
assert . throws ( function ( ) { X . read ( fs . readFileSync ( dir + w [ 1 ] , 'base64' ) , { type : 'base64' } ) ; } ) ;
} ) ; } ) ; } ) ;
describe ( 'write' , function ( ) {
it ( 'should pass -> XLSX' , function ( ) { FSTPaths . forEach ( function ( p ) {
X . write ( X . read ( fs . readFileSync ( p ) , { type : TYPE } ) , { type : TYPE } ) ;
} ) ; } ) ;
it ( 'should pass if a sheet is missing' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths . fstxlsx ) , { type : TYPE } ) ; delete wb . Sheets [ wb . SheetNames [ 0 ] ] ;
X . read ( X . write ( wb , { type : 'binary' } ) , { type : 'binary' } ) ;
} ) ;
[ 'Props' , 'Custprops' , 'SSF' ] . forEach ( function ( t ) { it ( 'should pass if ' + t + ' is missing' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths . fstxlsx ) , { type : TYPE } ) ;
assert . doesNotThrow ( function ( ) { delete wb [ t ] ; X . write ( wb , { type : 'binary' } ) ; } ) ;
} ) ; } ) ;
[ 'SheetNames' , 'Sheets' ] . forEach ( function ( t ) { it ( 'should fail if ' + t + ' is missing' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths . fstxlsx ) , { type : TYPE } ) ;
assert . throws ( function ( ) { delete wb [ t ] ; X . write ( wb , { type : 'binary' } ) ; } ) ;
} ) ; } ) ;
it ( 'should fail if SheetNames has duplicate entries' , function ( ) {
var wb = X . read ( fs . readFileSync ( paths . fstxlsx ) , { type : TYPE } ) ;
wb . SheetNames . push ( wb . SheetNames [ 0 ] ) ;
assert . throws ( function ( ) { X . write ( wb , { type : 'binary' } ) ; } ) ;
} ) ;
2023-06-23 09:48:47 +00:00
it ( 'should fail if sheet name is not valid' , function ( ) {
var names = [
"" , // cannot be blank
"abcdefghijklmnopqrstuvwxyz1234567890" , // cannot exceed 31 chars
"'sheetjs" , "sheetjs'" , // cannot start or end with apostrophe
"History" , // cannot be History
"Sheet:JS" , "Sheet]JS" , "Sheet[JS" , "Sheet*JS" , // bad characters
"Sheet?JS" , "Sheet\\JS" , "Sheet\/JS"
] ;
names . forEach ( function ( n ) { assert . throws ( function ( ) {
var wb = { SheetNames : [ n ] , Sheets : { } } ;
wb . Sheets [ n ] = X . utils . aoa _to _sheet ( [ [ "SheetJS" ] ] ) ;
X . write ( wb , { type : "binary" , bookType : "xlsx" } ) ;
} ) ; } ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
describe ( 'json output' , function ( ) {
function seeker ( json , keys , val ) {
if ( typeof keys == "string" ) keys = keys . split ( "" ) ;
for ( var i = 0 ; i != json . length ; ++ i ) {
for ( var j = 0 ; j != keys . length ; ++ j ) {
if ( json [ i ] [ keys [ j ] ] === val ) throw new Error ( "found " + val + " in row " + i + " key " + keys [ j ] ) ;
}
}
}
var data , ws ;
var bef = ( function ( ) {
data = [
[ 1 , 2 , 3 ] ,
[ true , false , null , "sheetjs" ] ,
[ "foo" , "bar" , fixdate , "0.3" ] ,
[ "baz" , undefined , "qux" ]
] ;
ws = X . utils . aoa _to _sheet ( data ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( 'should use first-row headers and full sheet by default' , function ( ) {
2022-05-17 01:26:22 +00:00
var json = X . utils . sheet _to _json ( ws , { raw : false } ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( json . length , data . length - 1 ) ;
assert . equal ( json [ 0 ] [ 1 ] , "TRUE" ) ;
assert . equal ( json [ 1 ] [ 2 ] , "bar" ) ;
assert . equal ( json [ 2 ] [ 3 ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 1 , 2 , 3 ] , "baz" ) ; } ) ;
} ) ;
it ( 'should create array of arrays if header == 1' , function ( ) {
2022-05-17 01:26:22 +00:00
var json = X . utils . sheet _to _json ( ws , { header : 1 , raw : false } ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] [ 0 ] , "TRUE" ) ;
assert . equal ( json [ 2 ] [ 1 ] , "bar" ) ;
assert . equal ( json [ 3 ] [ 2 ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "baz" ) ; } ) ;
} ) ;
it ( 'should use column names if header == "A"' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : 'A' , raw : false } ) ;
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] . A , "TRUE" ) ;
assert . equal ( json [ 2 ] . B , "bar" ) ;
assert . equal ( json [ 3 ] . C , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , "ABC" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ABCD" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ABC" , "baz" ) ; } ) ;
} ) ;
it ( 'should use column labels if specified' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : [ "O" , "D" , "I" , "N" ] , raw : 0 } ) ;
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] . O , "TRUE" ) ;
assert . equal ( json [ 2 ] . D , "bar" ) ;
assert . equal ( json [ 3 ] . I , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , "ODI" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ODIN" , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , "ODIN" , "baz" ) ; } ) ;
} ) ;
[ [ "string" , "A2:D4" ] , [ "numeric" , 1 ] , [ "object" , { s : { r : 1 , c : 0 } , e : { r : 3 , c : 3 } } ] ] . forEach ( function ( w ) {
it ( 'should accept custom ' + w [ 0 ] + ' range' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { header : 1 , range : w [ 1 ] } ) ;
assert . equal ( json . length , 3 ) ;
assert . equal ( json [ 0 ] [ 0 ] , true ) ;
assert . equal ( json [ 1 ] [ 1 ] , "bar" ) ;
assert . equal ( json [ 2 ] [ 2 ] , "qux" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 0 , 1 , 2 ] , "baz" ) ; } ) ;
} ) ;
} ) ;
it ( 'should use defval if requested' , function ( ) {
var json = X . utils . sheet _to _json ( ws , { defval : 'jimjin' } ) ;
assert . equal ( json . length , data . length - 1 ) ;
assert . equal ( json [ 0 ] [ 1 ] , true ) ;
assert . equal ( json [ 1 ] [ 2 ] , "bar" ) ;
assert . equal ( json [ 2 ] [ 3 ] , "qux" ) ;
assert . equal ( json [ 2 ] [ 2 ] , "jimjin" ) ;
assert . equal ( json [ 0 ] [ 3 ] , "jimjin" ) ;
assert . doesNotThrow ( function ( ) { seeker ( json , [ 1 , 2 , 3 ] , "sheetjs" ) ; } ) ;
assert . throws ( function ( ) { seeker ( json , [ 1 , 2 , 3 ] , "baz" ) ; } ) ;
X . utils . sheet _to _json ( ws , { raw : true } ) ;
X . utils . sheet _to _json ( ws , { raw : true , defval : 'jimjin' } ) ;
} ) ;
2022-03-12 00:24:23 +00:00
it ( 'should handle skipHidden for rows if requested' , function ( ) {
var ws2 = X . utils . aoa _to _sheet ( data ) , json = X . utils . sheet _to _json ( ws2 ) ;
assert . equal ( json [ 0 ] [ "1" ] , true ) ;
assert . equal ( json [ 2 ] [ "3" ] , "qux" ) ;
2022-05-17 01:26:22 +00:00
ws2 [ "!rows" ] = [ null , { hidden : true } , null , null ] ; json = X . utils . sheet _to _json ( ws2 , { skipHidden : true } ) ;
2022-03-12 00:24:23 +00:00
assert . equal ( json [ 0 ] [ "1" ] , "foo" ) ;
assert . equal ( json [ 1 ] [ "3" ] , "qux" ) ;
} ) ;
it ( 'should handle skipHidden for columns if requested' , function ( ) {
var ws2 = X . utils . aoa _to _sheet ( data ) , json = X . utils . sheet _to _json ( ws2 ) ;
assert . equal ( json [ 1 ] [ "2" ] , "bar" ) ;
assert . equal ( json [ 2 ] [ "3" ] , "qux" ) ;
ws2 [ "!cols" ] = [ ] ; ws2 [ "!cols" ] [ 1 ] = { hidden : true } ; json = X . utils . sheet _to _json ( ws2 , { skipHidden : true } ) ;
assert . equal ( json [ 1 ] [ "2" ] , void 0 ) ;
assert . equal ( json [ 2 ] [ "3" ] , "qux" ) ;
} ) ;
it ( 'should handle skipHidden when first row is hidden' , function ( ) {
var ws2 = X . utils . aoa _to _sheet ( data ) , json = X . utils . sheet _to _json ( ws2 ) ;
assert . equal ( json [ 0 ] [ "1" ] , true ) ;
assert . equal ( json [ 2 ] [ "3" ] , "qux" ) ;
ws2 [ "!rows" ] = [ { hidden : true } ] ; json = X . utils . sheet _to _json ( ws2 , { skipHidden : true } ) ;
assert . equal ( json [ 1 ] [ "1" ] , "foo" ) ;
assert . equal ( json [ 2 ] [ "3" ] , "qux" ) ;
} ) ;
2022-02-13 09:35:34 +00:00
it ( 'should disambiguate headers' , function ( ) {
var _data = [ [ "S" , "h" , "e" , "e" , "t" , "J" , "S" ] , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] , [ 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ] ;
var _ws = X . utils . aoa _to _sheet ( _data ) ;
var json = X . utils . sheet _to _json ( _ws ) ;
for ( var i = 0 ; i < json . length ; ++ i ) {
assert . equal ( json [ i ] . S , 1 + i ) ;
assert . equal ( json [ i ] . h , 2 + i ) ;
assert . equal ( json [ i ] . e , 3 + i ) ;
assert . equal ( json [ i ] . e _1 , 4 + i ) ;
assert . equal ( json [ i ] . t , 5 + i ) ;
assert . equal ( json [ i ] . J , 6 + i ) ;
assert . equal ( json [ i ] . S _1 , 7 + i ) ;
}
} ) ;
2022-03-09 01:44:10 +00:00
it ( 'should handle collisions in disambiguation' , function ( ) {
var _data = [ [ "a_1" , "a" , "a" ] , [ 1 , 2 , 3 ] ] ;
var _ws = X . utils . aoa _to _sheet ( _data ) ;
var json = X . utils . sheet _to _json ( _ws ) ;
assert . equal ( json [ 0 ] . a , 2 ) ;
assert . equal ( json [ 0 ] . a _1 , 1 ) ;
assert . equal ( json [ 0 ] . a _2 , 3 ) ;
} ) ;
2022-02-13 09:35:34 +00:00
it ( 'should handle raw data if requested' , function ( ) {
var _ws = X . utils . aoa _to _sheet ( data , { cellDates : true } ) ;
var json = X . utils . sheet _to _json ( _ws , { header : 1 , raw : true } ) ;
assert . equal ( json . length , data . length ) ;
assert . equal ( json [ 1 ] [ 0 ] , true ) ;
assert . equal ( json [ 1 ] [ 2 ] , null ) ;
assert . equal ( json [ 2 ] [ 1 ] , "bar" ) ;
assert . equal ( json [ 2 ] [ 2 ] . getTime ( ) , fixdate . getTime ( ) ) ;
assert . equal ( json [ 3 ] [ 2 ] , "qux" ) ;
} ) ;
it ( 'should include __rowNum__' , function ( ) {
var _data = [ [ "S" , "h" , "e" , "e" , "t" , "J" , "S" ] , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] , [ ] , [ 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ] ;
var _ws = X . utils . aoa _to _sheet ( _data ) ;
var json = X . utils . sheet _to _json ( _ws ) ;
assert . equal ( json [ 0 ] . _ _rowNum _ _ , 1 ) ;
assert . equal ( json [ 1 ] . _ _rowNum _ _ , 3 ) ;
} ) ;
it ( 'should handle blankrows' , function ( ) {
var _data = [ [ "S" , "h" , "e" , "e" , "t" , "J" , "S" ] , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] , [ ] , [ 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ] ;
var _ws = X . utils . aoa _to _sheet ( _data ) ;
var json1 = X . utils . sheet _to _json ( _ws ) ;
assert . equal ( json1 . length , 2 ) ; // = 2 non-empty records
var json2 = X . utils . sheet _to _json ( _ws , { header : 1 } ) ;
assert . equal ( json2 . length , 4 ) ; // = 4 sheet rows
var json3 = X . utils . sheet _to _json ( _ws , { blankrows : true } ) ;
assert . equal ( json3 . length , 3 ) ; // = 2 records + 1 blank row
var json4 = X . utils . sheet _to _json ( _ws , { blankrows : true , header : 1 } ) ;
assert . equal ( json4 . length , 4 ) ; // = 4 sheet rows
var json5 = X . utils . sheet _to _json ( _ws , { blankrows : false } ) ;
assert . equal ( json5 . length , 2 ) ; // = 2 records
var json6 = X . utils . sheet _to _json ( _ws , { blankrows : false , header : 1 } ) ;
assert . equal ( json6 . length , 3 ) ; // = 4 sheet rows - 1 blank row
} ) ;
it ( 'should have an index that starts with zero when selecting range' , function ( ) {
var _data = [ [ "S" , "h" , "e" , "e" , "t" , "J" , "S" ] , [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ] , [ 7 , 6 , 5 , 4 , 3 , 2 , 1 ] , [ 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ] ;
var _ws = X . utils . aoa _to _sheet ( _data ) ;
var json1 = X . utils . sheet _to _json ( _ws , { header : 1 , raw : true , range : "B1:F3" } ) ;
assert . equal ( json1 [ 0 ] [ 3 ] , "t" ) ;
assert . equal ( json1 [ 1 ] [ 0 ] , 2 ) ;
assert . equal ( json1 [ 2 ] [ 1 ] , 5 ) ;
assert . equal ( json1 [ 2 ] [ 3 ] , 3 ) ;
} ) ;
it ( 'should preserve values when column header is missing' , function ( ) {
/*jshint elision:true */
var _data = [ [ , "a" , "b" , , "c" ] , [ 1 , 2 , 3 , , 5 ] , [ , 3 , 4 , 5 , 6 ] ] ; // eslint-disable-line no-sparse-arrays
/*jshint elision:false */
var _ws = X . utils . aoa _to _sheet ( _data ) ;
var json1 = X . utils . sheet _to _json ( _ws , { raw : true } ) ;
assert . equal ( json1 [ 0 ] . _ _EMPTY , 1 ) ;
assert . equal ( json1 [ 1 ] . _ _EMPTY _1 , 5 ) ;
} ) ;
it ( 'should ignore errors and support default values' , function ( ) {
var ws = {
A1 : { t : 's' , v : "Field" } , B1 : { t : 's' , v : "Text" } ,
A2 : { t : 'e' , v : 0x2A , w : "#N/A" } , B2 : { t : 's' , v : "#N/A" } ,
A3 : { t : 'e' , v : 0x0F } , B3 : { t : 's' , v : "#VALUE!" } ,
A4 : { t : 'e' , w : "#NAME?" } , B4 : { t : 's' , v : "#NAME?" } ,
"!ref" : "A1:B4" } ;
seq ( 8 ) . forEach ( function ( n ) {
var opts = { } ;
if ( n & 1 ) opts . header = 1 ;
2022-06-06 23:05:27 +00:00
if ( n & 2 ) opts . raw = true ;
2022-02-13 09:35:34 +00:00
if ( n & 4 ) opts . defval = null ;
var J = X . utils . sheet _to _json ( ws , opts ) ;
for ( var i = 0 ; i < 3 ; ++ i ) {
var k = ( ( n & 1 ) ? J [ i + 1 ] [ 0 ] : J [ i ] . Field ) ;
assert . ok ( ( n & 4 ) ? ( k === null ) : ( k !== null ) ) ;
}
} ) ;
} ) ;
} ) ;
var codes = [ [ "あ 1" , "\u00E3\u0081\u0082 1" ] ] ;
2022-06-06 23:05:27 +00:00
var plaintext _val = ( [
2022-02-13 09:35:34 +00:00
[ "A1" , 'n' , - 0.08 , "-0.08" ] ,
[ "B1" , 'n' , 4001 , "4,001" ] ,
[ "C1" , 's' , "あ 1" , "あ 1" ] ,
[ "A2" , 'n' , 41.08 , "$41.08" ] ,
[ "B2" , 'n' , 0.11 , "11%" ] ,
[ "C3" , 'b' , true , "TRUE" ] ,
[ "D3" , 'b' , false , "FALSE" ] ,
[ "B3" , 's' , " " , " " ] ,
[ "A3" ]
2022-06-06 23:05:27 +00:00
] ) ;
2022-02-13 09:35:34 +00:00
function plaintext _test ( wb , raw ) {
var sheet = wb . Sheets [ wb . SheetNames [ 0 ] ] ;
plaintext _val . forEach ( function ( x ) {
var cell = get _cell ( sheet , x [ 0 ] ) ;
2022-06-06 23:05:27 +00:00
var tcval = x [ 2 + ( ! ! raw ? 1 : 0 ) ] ;
2022-02-13 09:35:34 +00:00
var type = raw ? 's' : x [ 1 ] ;
if ( x . length == 1 ) { if ( cell ) { assert . equal ( cell . t , 'z' ) ; assert . ok ( ! cell . v ) ; } return ; }
assert . equal ( cell . v , tcval ) ; assert . equal ( cell . t , type ) ;
} ) ;
}
function make _html _str ( idx ) { return [ "<table>" ,
"<tr><td>-0.08</td><td>4,001</td><td>" , codes [ 0 ] [ idx ] , "</td></tr>" ,
"<tr><td>$41.08</td><td>11%</td></tr>" ,
"<tr><td></td><td> \n </td><td>TRUE</td><td>FALSE</td></tr>" ,
"</table>" ] . join ( "" ) ; }
function make _csv _str ( idx ) { return [ ( idx == 1 ? '\u00EF\u00BB\u00BF' : "" ) +
'-0.08,"4,001",' + codes [ 0 ] [ idx ] + '' ,
'$41.08,11%' ,
', ,TRUE,FALSE'
] . join ( "\n" ) ; }
var html _bstr = make _html _str ( 1 ) , html _str = make _html _str ( 0 ) ;
var csv _bstr = make _csv _str ( 1 ) , csv _str = make _csv _str ( 0 ) ;
describe ( 'CSV' , function ( ) {
describe ( 'input' , function ( ) {
var b = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n" ;
it ( 'should generate date numbers by default' , function ( ) {
var opts = { type : "binary" } ;
2022-06-06 23:05:27 +00:00
var cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . w , '2/19/14' ) ;
assert . equal ( cell . t , 'n' ) ;
assert . ok ( typeof cell . v == "number" ) ;
} ) ;
it ( 'should generate dates when requested' , function ( ) {
var opts = { type : "binary" , cellDates : true } ;
2022-06-06 23:05:27 +00:00
var cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . w , '2/19/14' ) ;
assert . equal ( cell . t , 'd' ) ;
assert . ok ( cell . v instanceof Date || typeof cell . v == "string" ) ;
} ) ;
it ( 'should use US date code 14 by default' , function ( ) {
var opts = ( { type : "binary" } /*:any*/ ) ;
2022-06-06 23:05:27 +00:00
var cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . w , '2/19/14' ) ;
opts . cellDates = true ;
2022-06-06 23:05:27 +00:00
cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . w , '2/19/14' ) ;
} ) ;
it ( 'should honor dateNF override' , function ( ) {
2023-06-23 09:48:47 +00:00
var opts = ( { type : "binary" , dateNF : "YYYY-MM-DD" , cellNF : true } /*:any*/ ) ;
var cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
/* NOTE: IE interprets 2-digit years as 19xx */
assert . ok ( cell . w == '2014-02-19' || cell . w == '1914-02-19' || cell . w == "2/19/14" ) ;
assert . equal ( cell . z , "YYYY-MM-DD" ) ;
opts . cellDates = true ; opts . dateNF = "YY-MM-DD" ;
cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
assert . ok ( cell . w == '14-02-19' || cell . w == "2/19/14" ) ;
var opts = ( { type : "binary" , dateNF : "YYYY-MM-DD" , UTC : true } /*:any*/ ) ;
2022-06-06 23:05:27 +00:00
var cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
/* NOTE: IE interprets 2-digit years as 19xx */
assert . ok ( cell . w == '2014-02-19' || cell . w == '1914-02-19' ) ;
opts . cellDates = true ; opts . dateNF = "YY-MM-DD" ;
2022-06-06 23:05:27 +00:00
cell = get _cell ( X . read ( b , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . w , '14-02-19' ) ;
} ) ;
it ( 'should interpret dateNF' , function ( ) {
var bb = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/3/14,0.3\n,,,\nbaz,,qux,\n" ;
var opts = { type : "binary" , cellDates : true , dateNF : 'm/d/yy' } ;
2022-06-06 23:05:27 +00:00
var cell = get _cell ( X . read ( bb , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . v . getMonth ( ) , 1 ) ;
assert . equal ( cell . w , "2/3/14" ) ;
2023-06-23 09:48:47 +00:00
opts . dateNF = 'd/m/yy' ;
2022-06-06 23:05:27 +00:00
cell = get _cell ( X . read ( bb , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
2022-02-13 09:35:34 +00:00
assert . equal ( cell . v . getMonth ( ) , 2 ) ;
assert . equal ( cell . w , "2/3/14" ) ;
2023-06-23 09:48:47 +00:00
opts = { type : "binary" , cellDates : true , dateNF : 'm/d/yy' , UTC : true } ;
cell = get _cell ( X . read ( bb , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
assert . equal ( cell . v . getUTCMonth ( ) , 1 ) ;
assert . equal ( cell . w , "2/3/14" ) ;
opts . dateNF = 'd/m/yy' ;
cell = get _cell ( X . read ( bb , opts ) . Sheets [ "Sheet1" ] , "C3" ) ;
assert . equal ( cell . v . getUTCMonth ( ) , 2 ) ;
assert . equal ( cell . w , "2/3/14" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
it ( 'should interpret values by default' , function ( ) { plaintext _test ( X . read ( csv _bstr , { type : "binary" } ) , false ) ; } ) ;
it ( 'should generate strings if raw option is passed' , function ( ) { plaintext _test ( X . read ( csv _str , { type : "string" , raw : true } ) , true ) ; } ) ;
it ( 'should handle formulae' , function ( ) {
var bb = '=,=1+1,="100"' ;
2022-06-06 23:05:27 +00:00
var sheet = X . read ( bb , { type : "binary" } ) . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( sheet , "A1" ) . t , 's' ) ;
assert . equal ( get _cell ( sheet , "A1" ) . v , '=' ) ;
assert . equal ( get _cell ( sheet , "B1" ) . f , '1+1' ) ;
assert . equal ( get _cell ( sheet , "C1" ) . t , 's' ) ;
assert . equal ( get _cell ( sheet , "C1" ) . v , '100' ) ;
} ) ;
it ( 'should interpret CRLF newlines' , function ( ) {
var wb = X . read ( "sep=&\r\n1&2&3\r\n4&5&6" , { type : "string" } ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( wb . Sheets [ "Sheet1" ] [ "!ref" ] , "A1:C2" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
if ( ! browser || typeof cptable !== 'undefined' ) it ( 'should honor codepage for binary strings' , function ( ) {
var data = "abc,def\nghi,j\xD3l" ;
[ [ 1251 , 'У ' ] , [ 1252 , 'Ó' ] , [ 1253 , 'Σ' ] , [ 1254 , 'Ó' ] , [ 1255 , '׃ ' ] , [ 1256 , 'س' ] , [ 10000 , '”' ] ] . forEach ( function ( m ) {
2022-06-06 23:05:27 +00:00
var ws = X . read ( data , { type : "binary" , codepage : m [ 0 ] } ) . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
assert . equal ( get _cell ( ws , "B2" ) . v , "j" + m [ 1 ] + "l" ) ;
} ) ;
} ) ;
2022-08-07 02:50:58 +00:00
it ( 'should parse date-less meridien time values' , function ( ) {
var aoa = [
[ "3a" , "3 a" , "3 a-1" ] ,
[ "3b" , "3 b" , "3 b-1" ] ,
2022-08-08 23:21:46 +00:00
[ "3p" , "3 P" , "3 p-1" ]
2022-09-09 20:59:22 +00:00
] ;
2023-06-23 09:48:47 +00:00
var ws = X . read ( aoa . map ( function ( row ) { return row . join ( "," ) ; } ) . join ( "\n" ) , { type : "string" , cellDates : true , UTC : false } ) . Sheets . Sheet1 ;
2022-08-07 02:50:58 +00:00
for ( var R = 0 ; R < 3 ; ++ R ) {
assert . equal ( get _cell ( ws , "A" + ( R + 1 ) ) . v , aoa [ R ] [ 0 ] ) ;
assert . equal ( get _cell ( ws , "C" + ( R + 1 ) ) . v , aoa [ R ] [ 2 ] ) ;
}
assert . equal ( get _cell ( ws , "B2" ) . v , "3 b" ) ;
2022-09-09 20:59:22 +00:00
var B1 = get _cell ( ws , "B1" ) ; assert . equal ( B1 . t , "d" ) ; assert . equal ( B1 . v . getHours ( ) , 3 ) ;
2022-08-07 02:50:58 +00:00
var B3 = get _cell ( ws , "B3" ) ; assert . equal ( B3 . t , "d" ) ; assert . equal ( B3 . v . getHours ( ) , 15 ) ;
2023-06-23 09:48:47 +00:00
ws = X . read ( aoa . map ( function ( row ) { return row . join ( "," ) ; } ) . join ( "\n" ) , { type : "string" , cellDates : false , UTC : false } ) . Sheets . Sheet1 ;
for ( var R = 0 ; R < 3 ; ++ R ) {
assert . equal ( get _cell ( ws , "A" + ( R + 1 ) ) . v , aoa [ R ] [ 0 ] ) ;
assert . equal ( get _cell ( ws , "C" + ( R + 1 ) ) . v , aoa [ R ] [ 2 ] ) ;
}
assert . equal ( get _cell ( ws , "B2" ) . v , "3 b" ) ;
ws = X . read ( aoa . map ( function ( row ) { return row . join ( "," ) ; } ) . join ( "\n" ) , { type : "string" , cellDates : true , UTC : true } ) . Sheets . Sheet1 ;
for ( var R = 0 ; R < 3 ; ++ R ) {
assert . equal ( get _cell ( ws , "A" + ( R + 1 ) ) . v , aoa [ R ] [ 0 ] ) ;
assert . equal ( get _cell ( ws , "C" + ( R + 1 ) ) . v , aoa [ R ] [ 2 ] ) ;
}
assert . equal ( get _cell ( ws , "B2" ) . v , "3 b" ) ;
B1 = get _cell ( ws , "B1" ) ; assert . equal ( B1 . t , "d" ) ; assert . equal ( B1 . v . getUTCHours ( ) , 3 ) ;
B3 = get _cell ( ws , "B3" ) ; assert . equal ( B3 . t , "d" ) ; assert . equal ( B3 . v . getUTCHours ( ) , 15 ) ;
ws = X . read ( aoa . map ( function ( row ) { return row . join ( "," ) ; } ) . join ( "\n" ) , { type : "string" , cellDates : false , UTC : true } ) . Sheets . Sheet1 ;
for ( var R = 0 ; R < 3 ; ++ R ) {
assert . equal ( get _cell ( ws , "A" + ( R + 1 ) ) . v , aoa [ R ] [ 0 ] ) ;
assert . equal ( get _cell ( ws , "C" + ( R + 1 ) ) . v , aoa [ R ] [ 2 ] ) ;
}
assert . equal ( get _cell ( ws , "B2" ) . v , "3 b" ) ;
B1 = get _cell ( ws , "B1" ) ; assert . equal ( B1 . t , "n" ) ; assert . equal ( B1 . v * 24 , 3 ) ;
B3 = get _cell ( ws , "B3" ) ; assert . equal ( B3 . t , "n" ) ; assert . equal ( B3 . v * 24 , 15 ) ;
ws = X . read ( aoa . map ( function ( row ) { return row . join ( "," ) ; } ) . join ( "\n" ) , { type : "string" , cellDates : true } ) . Sheets . Sheet1 ;
for ( var R = 0 ; R < 3 ; ++ R ) {
assert . equal ( get _cell ( ws , "A" + ( R + 1 ) ) . v , aoa [ R ] [ 0 ] ) ;
assert . equal ( get _cell ( ws , "C" + ( R + 1 ) ) . v , aoa [ R ] [ 2 ] ) ;
}
assert . equal ( get _cell ( ws , "B2" ) . v , "3 b" ) ;
B1 = get _cell ( ws , "B1" ) ; assert . equal ( B1 . t , "d" ) ; assert . equal ( B1 . v . getUTCHours ( ) , 3 ) ;
B3 = get _cell ( ws , "B3" ) ; assert . equal ( B3 . t , "d" ) ; assert . equal ( B3 . v . getUTCHours ( ) , 15 ) ;
2022-08-07 02:50:58 +00:00
ws = X . read ( aoa . map ( function ( row ) { return row . join ( "," ) ; } ) . join ( "\n" ) , { type : "string" , cellDates : false } ) . Sheets . Sheet1 ;
for ( var R = 0 ; R < 3 ; ++ R ) {
assert . equal ( get _cell ( ws , "A" + ( R + 1 ) ) . v , aoa [ R ] [ 0 ] ) ;
assert . equal ( get _cell ( ws , "C" + ( R + 1 ) ) . v , aoa [ R ] [ 2 ] ) ;
}
assert . equal ( get _cell ( ws , "B2" ) . v , "3 b" ) ;
2023-06-23 09:48:47 +00:00
B1 = get _cell ( ws , "B1" ) ; assert . equal ( B1 . t , "n" ) ; assert . equal ( B1 . v * 24 , 3 ) ;
B3 = get _cell ( ws , "B3" ) ; assert . equal ( B3 . t , "n" ) ; assert . equal ( B3 . v * 24 , 15 ) ;
2022-08-07 02:50:58 +00:00
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
describe ( 'output' , function ( ) {
var data , ws ;
var bef = ( function ( ) {
data = [
[ 1 , 2 , 3 , null ] ,
[ true , false , null , "sheetjs" ] ,
[ "foo" , "bar" , fixdate , "0.3" ] ,
[ null , null , null ] ,
[ "baz" , undefined , "qux" ]
] ;
ws = X . utils . aoa _to _sheet ( data ) ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( 'should generate csv' , function ( ) {
2022-03-09 01:44:10 +00:00
var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux," ;
2022-02-13 09:35:34 +00:00
assert . equal ( baseline , X . utils . sheet _to _csv ( ws ) ) ;
} ) ;
it ( 'should handle FS' , function ( ) {
assert . equal ( X . utils . sheet _to _csv ( ws , { FS : "|" } ) . replace ( /[|]/g , "," ) , X . utils . sheet _to _csv ( ws ) ) ;
assert . equal ( X . utils . sheet _to _csv ( ws , { FS : ";" } ) . replace ( /[;]/g , "," ) , X . utils . sheet _to _csv ( ws ) ) ;
} ) ;
it ( 'should handle RS' , function ( ) {
assert . equal ( X . utils . sheet _to _csv ( ws , { RS : "|" } ) . replace ( /[|]/g , "\n" ) , X . utils . sheet _to _csv ( ws ) ) ;
assert . equal ( X . utils . sheet _to _csv ( ws , { RS : ";" } ) . replace ( /[;]/g , "\n" ) , X . utils . sheet _to _csv ( ws ) ) ;
} ) ;
it ( 'should handle dateNF' , function ( ) {
2022-03-09 01:44:10 +00:00
var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,20140219,0.3\n,,,\nbaz,,qux," ;
2022-02-13 09:35:34 +00:00
var _ws = X . utils . aoa _to _sheet ( data , { cellDates : true } ) ;
delete get _cell ( _ws , "C3" ) . w ;
delete get _cell ( _ws , "C3" ) . z ;
assert . equal ( baseline , X . utils . sheet _to _csv ( _ws , { dateNF : "YYYYMMDD" } ) ) ;
} ) ;
it ( 'should handle strip' , function ( ) {
2022-03-09 01:44:10 +00:00
var baseline = "1,2,3\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n\nbaz,,qux" ;
2022-02-13 09:35:34 +00:00
assert . equal ( baseline , X . utils . sheet _to _csv ( ws , { strip : true } ) ) ;
} ) ;
it ( 'should handle blankrows' , function ( ) {
2022-03-09 01:44:10 +00:00
var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\nbaz,,qux," ;
2022-02-13 09:35:34 +00:00
assert . equal ( baseline , X . utils . sheet _to _csv ( ws , { blankrows : false } ) ) ;
} ) ;
it ( 'should handle various line endings' , function ( ) {
var data = [ "1,a" , "2,b" , "3,c" ] ;
[ "\r" , "\n" , "\r\n" ] . forEach ( function ( RS ) {
var wb = X . read ( data . join ( RS ) , { type : 'binary' } ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( wb . Sheets [ "Sheet1" ] , "A1" ) . v , 1 ) ;
assert . equal ( get _cell ( wb . Sheets [ "Sheet1" ] , "B3" ) . v , "c" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] [ '!ref' ] , "A1:B3" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
it ( 'should handle skipHidden for rows if requested' , function ( ) {
2022-03-09 01:44:10 +00:00
var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux," ;
2022-02-13 09:35:34 +00:00
delete ws [ "!rows" ] ;
assert . equal ( X . utils . sheet _to _csv ( ws ) , baseline ) ;
assert . equal ( X . utils . sheet _to _csv ( ws , { skipHidden : true } ) , baseline ) ;
ws [ "!rows" ] = [ null , { hidden : true } , null , null ] ;
assert . equal ( X . utils . sheet _to _csv ( ws ) , baseline ) ;
2022-03-09 01:44:10 +00:00
assert . equal ( X . utils . sheet _to _csv ( ws , { skipHidden : true } ) , "1,2,3,\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux," ) ;
2022-02-13 09:35:34 +00:00
delete ws [ "!rows" ] ;
} ) ;
it ( 'should handle skipHidden for columns if requested' , function ( ) {
2022-03-09 01:44:10 +00:00
var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux," ;
2022-02-13 09:35:34 +00:00
delete ws [ "!cols" ] ;
assert . equal ( X . utils . sheet _to _csv ( ws ) , baseline ) ;
assert . equal ( X . utils . sheet _to _csv ( ws , { skipHidden : true } ) , baseline ) ;
ws [ "!cols" ] = [ null , { hidden : true } , null , null ] ;
assert . equal ( X . utils . sheet _to _csv ( ws ) , baseline ) ;
2022-03-09 01:44:10 +00:00
assert . equal ( X . utils . sheet _to _csv ( ws , { skipHidden : true } ) , "1,3,\nTRUE,,sheetjs\nfoo,2/19/14,0.3\n,,\nbaz,qux," ) ;
2022-02-13 09:35:34 +00:00
ws [ "!cols" ] = [ { hidden : true } , null , null , null ] ;
2022-03-09 01:44:10 +00:00
assert . equal ( X . utils . sheet _to _csv ( ws , { skipHidden : true } ) , "2,3,\nFALSE,,sheetjs\nbar,2/19/14,0.3\n,,\n,qux," ) ;
2022-02-13 09:35:34 +00:00
delete ws [ "!cols" ] ;
} ) ;
2022-03-09 01:44:10 +00:00
it ( 'should properly handle blankrows and strip options' , function ( ) {
var _ws = X . utils . aoa _to _sheet ( [ [ "" ] , [ ] , [ "" , "" ] ] ) ;
assert . equal ( X . utils . sheet _to _csv ( _ws , { } ) , ",\n,\n," ) ;
assert . equal ( X . utils . sheet _to _csv ( _ws , { strip : true } ) , "\n\n" ) ;
assert . equal ( X . utils . sheet _to _csv ( _ws , { blankrows : false } ) , ",\n," ) ;
assert . equal ( X . utils . sheet _to _csv ( _ws , { blankrows : false , strip : true } ) , "" ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
describe ( 'sylk' , function ( ) {
var cpavail = true ;
var bef = ( function ( ) {
if ( typeof cptable == 'undefined' ) cpavail = false ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
describe ( 'input' , function ( ) {
it ( 'codepage' , cpavail ? function ( ) {
var str = "ID;PWXL;N;E\r\nC;X1;Y1;K\"a – b\"\r\nE" , A1 = "a – b" ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( X . read ( str , { type : "string" } ) . Sheets [ "Sheet1" ] , "A1" ) . v , A1 ) ;
assert . equal ( get _cell ( X . read ( str . replace ( /– / , "\x96" ) , { type : "binary" , codepage : 1252 } ) . Sheets [ "Sheet1" ] , "A1" ) . v , A1 ) ;
2022-02-13 09:35:34 +00:00
if ( typeof Buffer !== 'undefined' && ! browser ) {
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( X . read ( Buffer _from ( str ) , { type : "buffer" , codepage : 65001 } ) . Sheets [ "Sheet1" ] , "A1" ) . v , A1 ) ;
assert . equal ( get _cell ( X . read ( Buffer _from ( str . replace ( /– / , "\x96" ) , "binary" ) , { type : "buffer" , codepage : 1252 } ) . Sheets [ "Sheet1" ] , "A1" ) . v , A1 ) ;
2022-02-13 09:35:34 +00:00
}
} : null ) ;
} ) ;
2022-05-17 01:26:22 +00:00
describe ( 'date system' , function ( ) {
function make _slk ( d1904 ) { return "ID;PSheetJS\nP;Pd\\/m\\/yy\nP;Pd\\/m\\/yyyy\n" + ( d1904 != null ? "O;D;V" + d1904 : "" ) + "\nF;P0;FG0G;X1;Y1\nC;K1\nE" ; }
it ( 'should default to 1900' , function ( ) {
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( X . read ( make _slk ( ) , { type : "binary" } ) . Sheets [ "Sheet1" ] , "A1" ) . v , 1 ) ;
assert . ok ( get _cell ( X . read ( make _slk ( ) , { type : "binary" , cellDates : true } ) . Sheets [ "Sheet1" ] , "A1" ) . v . getFullYear ( ) < 1902 ) ;
assert . equal ( get _cell ( X . read ( make _slk ( 5 ) , { type : "binary" } ) . Sheets [ "Sheet1" ] , "A1" ) . v , 1 ) ;
assert . ok ( get _cell ( X . read ( make _slk ( 5 ) , { type : "binary" , cellDates : true } ) . Sheets [ "Sheet1" ] , "A1" ) . v . getFullYear ( ) < 1902 ) ;
2022-05-17 01:26:22 +00:00
} ) ;
it ( 'should use 1904 when specified' , function ( ) {
2022-06-06 23:05:27 +00:00
assert . ok ( get _cell ( X . read ( make _slk ( 1 ) , { type : "binary" , cellDates : true } ) . Sheets [ "Sheet1" ] , "A1" ) . v . getFullYear ( ) > 1902 ) ;
assert . ok ( get _cell ( X . read ( make _slk ( 4 ) , { type : "binary" , cellDates : true } ) . Sheets [ "Sheet1" ] , "A1" ) . v . getFullYear ( ) > 1902 ) ;
2022-05-17 01:26:22 +00:00
} ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
2022-06-06 23:05:27 +00:00
if ( typeof Uint8Array !== "undefined" )
describe ( 'numbers' , function ( ) {
2022-02-13 09:35:34 +00:00
it ( 'should parse files from Numbers 6.x' , function ( ) {
2022-06-06 23:05:27 +00:00
var wb = X . read ( fs . readFileSync ( dir + 'numbers/types_61.numbers' ) , { type : TYPE , WTF : true } ) ;
2022-02-13 09:35:34 +00:00
var ws = wb . Sheets [ "Sheet 1" ] ;
assert . equal ( get _cell ( ws , "A1" ) . v , "Sheet" ) ;
assert . equal ( get _cell ( ws , "B1" ) . v , "JS" ) ;
assert . equal ( get _cell ( ws , "B2" ) . v , 123 ) ;
assert . equal ( get _cell ( ws , "B11" ) . v , true ) ;
assert . equal ( get _cell ( ws , "B13" ) . v , 50 ) ;
} ) ;
2022-09-22 09:05:24 +00:00
if ( can _write _numbers ) it ( 'should cap cols at 1000 (ALL)' , function ( ) {
2022-04-11 04:11:47 +00:00
var aoa = [ [ 1 ] , [ ] , [ ] ] ; aoa [ 1 ] [ 999 ] = 2 ; aoa [ 2 ] [ 1000 ] = 3 ;
var ws1 = X . utils . aoa _to _sheet ( aoa ) ;
var wb1 = X . utils . book _new ( ) ; X . utils . book _append _sheet ( wb1 , ws1 , "Sheet1" ) ;
var wb2 = X . read ( X . write ( wb1 , { bookType : "numbers" , type : 'binary' , numbers : XLSX _ZAHL } ) , { type : 'binary' } ) ;
2022-06-06 23:05:27 +00:00
var ws2 = wb2 . Sheets [ "Sheet1" ] ;
2022-04-11 04:11:47 +00:00
assert . equal ( ws2 [ "!ref" ] , "A1:ALL3" ) ;
assert . equal ( get _cell ( ws2 , "A1" ) . v , 1 ) ;
assert . equal ( get _cell ( ws2 , "ALL2" ) . v , 2 ) ;
} ) ;
2022-07-05 06:52:55 +00:00
it ( 'should support icloud.com files' , function ( ) {
var wb = X . read ( fs . readFileSync ( dir + 'Attendance.numbers' ) , { type : TYPE , WTF : true } ) ;
var ws = wb . Sheets [ "Attendance" ] ;
assert . equal ( get _cell ( ws , "A1" ) . v , "Date" ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
2022-06-06 23:05:27 +00:00
describe ( 'dbf' , function ( ) {
2022-02-13 09:35:34 +00:00
var wbs /*:Array<any>*/ = ( [
[ 'd11' , dir + 'dbf/d11.dbf' ] ,
[ 'vfp3' , dir + 'dbf/vfp3.dbf' ]
] /*:any*/ ) ;
2023-06-23 09:48:47 +00:00
var wbsfalse = ( [ ] ) ;
var wbstrue = ( [ ] ) ;
2022-02-13 09:35:34 +00:00
var bef = ( function ( ) {
2023-06-23 09:48:47 +00:00
wbsfalse = wbs . map ( function ( x ) { return [ x [ 0 ] , X . read ( fs . readFileSync ( x [ 1 ] ) , { type : TYPE , cellDates : false } ) ] ; } ) ;
wbstrue = wbs . map ( function ( x ) { return [ x [ 0 ] , X . read ( fs . readFileSync ( x [ 1 ] ) , { type : TYPE , cellDates : true } ) ] ; } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
it ( wbs [ 1 ] [ 0 ] , function ( ) {
2023-06-23 09:48:47 +00:00
var wsfalse = wbsfalse [ 1 ] [ 1 ] . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
[
2023-06-23 09:48:47 +00:00
[ "A1" , "v" , "CHAR10" ] , [ "A2" , "v" , "test1" ] , [ "B2" , "v" , 123.45 ] , [ "C2" , "v" , 12.345 ] , [ "D2" , "v" , 1234.1 ] ,
[ "E2" , "v" , 6260 ] , [ "E2" , "w" , "19170219" ] ,
[ "F2" , "v" , 6260 ] , [ "F2" , "w" , "19170219" ] ,
[ "G2" , "v" , 1231.4 ] , [ "H2" , "v" , 123234 ] , [ "I2" , "v" , true ] , [ "L2" , "v" , "SheetJS" ]
] . forEach ( function ( r ) {
assert . equal ( get _cell ( wsfalse , r [ 0 ] ) [ r [ 1 ] ] , r [ 2 ] ) ;
} ) ;
var wstrue = wbstrue [ 1 ] [ 1 ] . Sheets [ "Sheet1" ] ;
[
[ "E2" , "v" , Date . UTC ( 1917 , 1 , 19 , 0 , 0 , 0 , 0 ) ] , [ "E2" , "w" , "19170219" ] ,
[ "F2" , "v" , Date . UTC ( 1917 , 1 , 19 , 0 , 0 , 0 , 0 ) ] , [ "F2" , "w" , "19170219" ] ,
] . forEach ( function ( r ) {
assert . equal ( get _cell ( wstrue , r [ 0 ] ) [ r [ 1 ] ] . valueOf ( ) , r [ 2 ] . valueOf ( ) ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
2022-09-09 20:59:22 +00:00
if ( ! browser || typeof cptable !== 'undefined' ) it ( "Ś╫êëτ⌡ś and Š╫ěéτ⌡š" , function ( ) {
[ [ 620 , "Ś╫êëτ⌡ś" ] , [ 895 , "Š╫ěéτ⌡š" ] ] . forEach ( function ( r ) {
var book = X . utils . book _new ( ) ;
var sheet = X . utils . aoa _to _sheet ( [ [ "ASCII" , "encoded" ] , [ "Test" , r [ 1 ] ] ] ) ;
X . utils . book _append _sheet ( book , sheet , "sheet1" ) ;
var data = X . write ( book , { type : TYPE , bookType : "dbf" , codepage : r [ 0 ] } ) ;
var wb = X . read ( data , { type : TYPE } ) ;
assert . equal ( wb . Sheets . Sheet1 . B2 . v , r [ 1 ] ) ;
} ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
import { JSDOM } from 'jsdom' ;
var domtest = true ;
var inserted _dom _elements = [ ] ;
function get _dom _element ( html ) {
if ( browser ) {
var domelt = document . createElement ( 'div' ) ;
domelt . innerHTML = html ;
if ( document . body ) document . body . appendChild ( domelt ) ;
inserted _dom _elements . push ( domelt ) ;
return domelt . children [ 0 ] ;
}
if ( ! JSDOM ) throw new Error ( "Browser test fail" ) ;
return new JSDOM ( html ) . window . document . body . children [ 0 ] ;
}
describe ( 'HTML' , function ( ) {
afterEach ( function ( ) {
// Remove the DOM elements inserted to the page by get_dom_element
inserted _dom _elements . forEach ( function ( element ) {
if ( element . parentNode ) element . parentNode . removeChild ( element ) ;
} ) ;
inserted _dom _elements = [ ] ;
} ) ;
describe ( 'input string' , function ( ) {
it ( 'should interpret values by default' , function ( ) { plaintext _test ( X . read ( html _bstr , { type : "binary" } ) , false ) ; } ) ;
it ( 'should generate strings if raw option is passed' , function ( ) { plaintext _test ( X . read ( html _bstr , { type : "binary" , raw : true } ) , true ) ; } ) ;
it ( 'should handle "string" type' , function ( ) { plaintext _test ( X . read ( html _str , { type : "string" } ) , false ) ; } ) ;
it ( 'should handle newlines correctly' , function ( ) {
var table = "<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>" ;
var wb = X . read ( table , { type : "string" } ) ;
2022-06-06 23:05:27 +00:00
assert . equal ( get _cell ( wb . Sheets [ "Sheet1" ] , "A1" ) . v , "foo\nbar" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
it ( 'should generate multi-sheet workbooks' , function ( ) {
var table = "" ;
for ( var i = 0 ; i < 4 ; ++ i ) table += "<table><tr><td>" + X . utils . encode _col ( i ) + "</td><td>" + i + "</td></tr></table>" ;
table += table ; table += table ;
var wb = X . read ( table , { type : "string" } ) ;
assert . equal ( wb . SheetNames . length , 16 ) ;
assert . equal ( wb . SheetNames [ 1 ] , "Sheet2" ) ;
for ( var j = 0 ; j < 4 ; ++ j ) {
assert . equal ( get _cell ( wb . Sheets [ "Sheet" + ( j + 1 ) ] , "A1" ) . v , X . utils . encode _col ( j ) ) ;
assert . equal ( get _cell ( wb . Sheets [ "Sheet" + ( j + 1 ) ] , "B1" ) . v , j ) ;
}
} ) ;
} ) ;
2022-06-06 23:05:27 +00:00
if ( domtest ) describe ( 'input DOM' , function ( ) {
2022-02-13 09:35:34 +00:00
it ( 'should interpret values by default' , function ( ) { plaintext _test ( X . utils . table _to _book ( get _dom _element ( html _str ) ) , false ) ; } ) ;
it ( 'should generate strings if raw option is passed' , function ( ) { plaintext _test ( X . utils . table _to _book ( get _dom _element ( html _str ) , { raw : true } ) , true ) ; } ) ;
it ( 'should handle newlines correctly' , function ( ) {
var table = get _dom _element ( "<table><tr><td>foo<br/>bar</td><td>baz</td></tr></table>" ) ;
var ws = X . utils . table _to _sheet ( table ) ;
assert . equal ( get _cell ( ws , "A1" ) . v , "foo\nbar" ) ;
} ) ;
it ( 'should trim whitespace' , function ( ) {
if ( get _dom _element ( "foo <br> bar" ) . innerHTML != "foo <br> bar" ) return ;
var table = get _dom _element ( "<table><tr><td> foo <br/> bar </td><td> baz qux </td></tr></table>" ) ;
var ws = X . utils . table _to _sheet ( table ) ;
assert . equal ( get _cell ( ws , "A1" ) . v . replace ( /\n/g , "|" ) , "foo | bar" ) ;
assert . equal ( get _cell ( ws , "B1" ) . v , "baz qux" ) ;
} ) ;
} ) ;
if ( domtest ) it ( 'should handle entities' , function ( ) {
var html = "<table><tr><td>A&B</td><td>A·B</td></tr></table>" ;
var ws = X . utils . table _to _sheet ( get _dom _element ( html ) ) ;
assert . equal ( get _cell ( ws , "A1" ) . v , "A&B" ) ;
assert . equal ( get _cell ( ws , "B1" ) . v , "A·B" ) ;
} ) ;
if ( domtest ) it ( 'should honor sheetRows' , function ( ) {
var html = X . utils . sheet _to _html ( X . utils . aoa _to _sheet ( [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ] ) ) ;
// $FlowIgnore
html = /<body[^>]*>([\s\S]*)<\/body>/i . exec ( html ) [ 1 ] ;
var ws = X . utils . table _to _sheet ( get _dom _element ( html ) ) ;
assert . equal ( ws [ '!ref' ] , "A1:B3" ) ;
ws = X . utils . table _to _sheet ( get _dom _element ( html ) , { sheetRows : 1 } ) ;
assert . equal ( ws [ '!ref' ] , "A1:B1" ) ;
assert . equal ( ws [ '!fullref' ] , "A1:B3" ) ;
ws = X . utils . table _to _sheet ( get _dom _element ( html ) , { sheetRows : 2 } ) ;
assert . equal ( ws [ '!ref' ] , "A1:B2" ) ;
assert . equal ( ws [ '!fullref' ] , "A1:B3" ) ;
} ) ;
if ( domtest ) it ( 'should hide hidden rows' , function ( ) {
var html = "<table><tr style='display: none;'><td>Foo</td></tr><tr><td style='display: none;'>Bar</td></tr><tr class='hidden'><td>Baz</td></tr></table><style>.hidden {display: none}</style>" ;
var ws = X . utils . table _to _sheet ( get _dom _element ( html ) ) ;
var expected _rows = [ ] ;
expected _rows [ 0 ] = expected _rows [ 2 ] = { hidden : true } ;
assert . equal ( ws [ '!ref' ] , "A1:A3" ) ;
try {
assert . deepEqual ( ws [ '!rows' ] , expected _rows ) ;
} catch ( e ) {
expected _rows [ 1 ] = { } ;
assert . deepEqual ( ws [ '!rows' ] , expected _rows ) ;
}
assert . equal ( get _cell ( ws , "A1" ) . v , "Foo" ) ;
assert . equal ( get _cell ( ws , "A2" ) . v , "Bar" ) ;
assert . equal ( get _cell ( ws , "A3" ) . v , "Baz" ) ;
} ) ;
if ( domtest ) it ( 'should ignore hidden rows and cells when the `display` option is on' , function ( ) {
var html = "<table><tr style='display: none;'><td>1</td><td>2</td><td>3</td></tr><tr><td class='hidden'>Foo</td><td>Bar</td><td style='display: none;'>Baz</td></tr></table><style>.hidden {display: none}</style>" ;
var ws = X . utils . table _to _sheet ( get _dom _element ( html ) , { display : true } ) ;
assert . equal ( ws [ '!ref' ] , "A1" ) ;
assert . ok ( ws . hasOwnProperty ( '!rows' ) == false || ! ws [ "!rows" ] [ 0 ] || ! ws [ "!rows" ] [ 0 ] . hidden ) ;
assert . equal ( get _cell ( ws , "A1" ) . v , "Bar" ) ;
} ) ;
describe ( 'type override' , function ( ) {
function chk ( ws ) {
assert . equal ( get _cell ( ws , "A1" ) . t , "s" ) ;
assert . equal ( get _cell ( ws , "A1" ) . v , "1234567890" ) ;
assert . equal ( get _cell ( ws , "B1" ) . t , "n" ) ;
assert . equal ( get _cell ( ws , "B1" ) . v , 1234567890 ) ;
}
var html = "<table><tr><td t=\"s\">1234567890</td><td>1234567890</td></tr></table>" ;
it ( 'HTML string' , function ( ) {
2022-06-06 23:05:27 +00:00
var ws = X . read ( html , { type : 'string' } ) . Sheets [ "Sheet1" ] ; chk ( ws ) ;
chk ( X . read ( X . utils . sheet _to _html ( ws ) , { type : 'string' } ) . Sheets [ "Sheet1" ] ) ;
2022-02-13 09:35:34 +00:00
} ) ;
if ( domtest ) it ( 'DOM' , function ( ) { chk ( X . utils . table _to _sheet ( get _dom _element ( html ) ) ) ; } ) ;
} ) ;
describe ( 'TH/THEAD/TBODY/TFOOT elements' , function ( ) {
var html = "<table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody><tfoot><tr><th>4</th><th>6</th></tr></tfoot></table>" ;
it ( 'HTML string' , function ( ) {
2022-06-06 23:05:27 +00:00
var ws = X . read ( html , { type : 'string' } ) . Sheets [ "Sheet1" ] ;
2022-03-09 01:44:10 +00:00
assert . equal ( X . utils . sheet _to _csv ( ws ) , "A,B\n1,2\n3,4\n4,6" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
if ( domtest ) it ( 'DOM' , function ( ) {
var ws = X . utils . table _to _sheet ( get _dom _element ( html ) ) ;
2022-03-09 01:44:10 +00:00
assert . equal ( X . utils . sheet _to _csv ( ws ) , "A,B\n1,2\n3,4\n4,6" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
} ) ;
2022-03-10 05:31:13 +00:00
describe ( 'empty cell containing html element should increment cell index' , function ( ) {
var html = "<table><tr><td>abc</td><td><b> </b></td><td>def</td></tr></table>" ;
var expectedCellCount = 3 ;
it ( 'HTML string' , function ( ) {
2022-06-06 23:05:27 +00:00
var ws = X . read ( html , { type : 'string' } ) . Sheets [ "Sheet1" ] ;
var range = X . utils . decode _range ( ws [ '!ref' ] || "A1" ) ;
2022-03-10 05:31:13 +00:00
assert . equal ( range . e . c , expectedCellCount - 1 ) ;
} ) ;
if ( domtest ) it ( 'DOM' , function ( ) {
var ws = X . utils . table _to _sheet ( get _dom _element ( html ) ) ;
2022-06-06 23:05:27 +00:00
var range = X . utils . decode _range ( ws [ '!ref' ] || "A1" ) ;
2022-03-10 05:31:13 +00:00
assert . equal ( range . e . c , expectedCellCount - 1 ) ;
} ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
describe ( 'js -> file -> js' , function ( ) {
var wb , BIN = "binary" ;
var bef = ( function ( ) {
var ws = X . utils . aoa _to _sheet ( [
[ "number" , "bool" , "string" , "date" ] ,
[ 1 , true , "sheet" ] ,
[ 2 , false , "dot" ] ,
[ 6.9 , false , "JS" , fixdate ] ,
[ 72.62 , true , "0.3" ]
] ) ;
wb = { SheetNames : [ 'Sheet1' ] , Sheets : { Sheet1 : ws } } ;
} ) ;
if ( typeof before != 'undefined' ) before ( bef ) ;
else it ( 'before' , bef ) ;
function eqcell ( wb1 , wb2 , s , a ) {
assert . equal ( get _cell ( wb1 . Sheets [ s ] , a ) . v , get _cell ( wb2 . Sheets [ s ] , a ) . v ) ;
assert . equal ( get _cell ( wb1 . Sheets [ s ] , a ) . t , get _cell ( wb2 . Sheets [ s ] , a ) . t ) ;
}
ofmt . forEach ( function ( f ) {
it ( f , function ( ) {
var newwb = X . read ( X . write ( wb , { type : BIN , bookType : f } ) , { type : BIN } ) ;
var cb = function ( cell ) { eqcell ( wb , newwb , 'Sheet1' , cell ) ; } ;
[ 'A2' , 'A3' ] . forEach ( cb ) ; /* int */
[ 'A4' , 'A5' ] . forEach ( cb ) ; /* double */
[ 'B2' , 'B3' ] . forEach ( cb ) ; /* bool */
[ 'C2' , 'C3' ] . forEach ( cb ) ; /* string */
if ( ! DIF _XL ) cb ( 'D4' ) ; /* date */
if ( f != 'csv' && f != 'txt' ) eqcell ( wb , newwb , 'Sheet1' , 'C5' ) ;
} ) ;
} ) ;
it ( 'should roundtrip DIF strings' , function ( ) {
var wb1 = X . read ( X . write ( wb , { type : BIN , bookType : 'dif' } ) , { type : BIN } ) ;
var wb2 = X . read ( X . write ( wb1 , { type : BIN , bookType : 'dif' } ) , { type : BIN } ) ;
eqcell ( wb , wb1 , 'Sheet1' , 'C5' ) ;
eqcell ( wb , wb2 , 'Sheet1' , 'C5' ) ;
} ) ;
} ) ;
2022-07-07 06:30:44 +00:00
describe ( 'rtf' , function ( ) {
it ( 'roundtrip should be idempotent' , function ( ) {
var ws = X . utils . aoa _to _sheet ( [
[ 1 , 2 , 3 ] ,
[ true , false , null , "sheetjs" ] ,
[ "foo" , "bar" , fixdate , "0.3" ] ,
[ "baz" , null , "q\"ux" ]
] ) ;
var wb1 = X . utils . book _new ( ) ;
X . utils . book _append _sheet ( wb1 , ws , "Sheet1" ) ;
var rtf1 = X . write ( wb1 , { bookType : "rtf" , type : "string" } ) ;
var wb2 = X . read ( rtf1 , { type : "string" } ) ;
var rtf2 = X . write ( wb2 , { bookType : "rtf" , type : "string" } ) ;
assert . equal ( rtf1 , rtf2 ) ;
} ) ;
} ) ;
2022-02-13 09:35:34 +00:00
describe ( 'corner cases' , function ( ) {
it ( 'output functions' , function ( ) {
var ws = X . utils . aoa _to _sheet ( [
[ 1 , 2 , 3 ] ,
[ true , false , null , "sheetjs" ] ,
[ "foo" , "bar" , fixdate , "0.3" ] ,
[ "baz" , null , "q\"ux" ]
] ) ;
get _cell ( ws , "A1" ) . f = "" ; get _cell ( ws , "A1" ) . w = "" ;
delete get _cell ( ws , "C3" ) . w ; delete get _cell ( ws , "C3" ) . z ; get _cell ( ws , "C3" ) . XF = { ifmt : 14 } ;
get _cell ( ws , "A4" ) . t = "e" ;
X . utils . sheet _to _formulae ( ws ) ;
X . utils . sheet _to _csv ( ws ) ;
X . utils . sheet _to _json ( ws ) ;
ws [ '!cols' ] = [ { wch : 6 } , { wch : 7 } , { wch : 10 } , { wch : 20 } ] ;
var wb = { SheetNames : [ 'sheetjs' ] , Sheets : { sheetjs : ws } } ;
X . write ( wb , { type : "binary" , bookType : 'xlsx' } ) ;
X . write ( wb , { type : TYPE , bookType : 'xlsm' } ) ;
X . write ( wb , { type : "base64" , bookType : 'xlsb' } ) ;
X . write ( wb , { type : "binary" , bookType : 'ods' } ) ;
X . write ( wb , { type : "binary" , bookType : 'biff2' } ) ;
X . write ( wb , { type : "binary" , bookType : 'biff5' } ) ;
X . write ( wb , { type : "binary" , bookType : 'biff8' } ) ;
get _cell ( ws , "A2" ) . t = "f" ;
assert . throws ( function ( ) { X . utils . sheet _to _json ( ws ) ; } ) ;
} ) ;
it ( 'SSF' , function ( ) {
X . SSF . format ( "General" , "dafuq" ) ;
assert . throws ( function ( ) { return X . SSF . format ( "General" , { sheet : "js" } ) ; } ) ;
X . SSF . format ( "b e ddd hh AM/PM" , 41722.4097222222 ) ;
X . SSF . format ( "b ddd hh m" , 41722.4097222222 ) ;
[ "hhh" , "hhh A/P" , "hhmmm" , "sss" , "[hhh]" , "G eneral" ] . forEach ( function ( f ) {
assert . throws ( function ( ) { return X . SSF . format ( f , 12345.6789 ) ; } ) ;
} ) ;
[ "[m]" , "[s]" ] . forEach ( function ( f ) {
assert . doesNotThrow ( function ( ) { return X . SSF . format ( f , 12345.6789 ) ; } ) ;
} ) ;
} ) ;
if ( typeof JSON !== 'undefined' ) it ( 'SSF oddities' , function ( ) {
// $FlowIgnore
var ssfdata = JSON . parse ( fs . readFileSync ( './misc/ssf.json' , 'utf8' ) ) ;
var cb = function ( d , j ) { return function ( ) { return X . SSF . format ( d [ 0 ] , d [ j ] [ 0 ] ) ; } ; } ;
ssfdata . forEach ( function ( d ) {
for ( var j = 1 ; j < d . length ; ++ j ) {
if ( d [ j ] . length == 2 ) {
var expected = d [ j ] [ 1 ] , actual = X . SSF . format ( d [ 0 ] , d [ j ] [ 0 ] , { } ) ;
assert . equal ( actual , expected ) ;
} else if ( d [ j ] [ 2 ] !== "#" ) assert . throws ( cb ( d , j ) ) ;
}
} ) ;
} ) ;
it ( 'codepage' , function ( ) {
X . read ( fs . readFileSync ( dir + "biff5/number_format_greek.xls" ) , { type : TYPE } ) ;
} ) ;
it ( 'large binary files' , function ( ) {
var data = [ [ "Row Number" ] ] ;
for ( var j = 0 ; j < 19 ; ++ j ) data [ 0 ] . push ( "Column " + j + 1 ) ;
for ( var i = 0 ; i < 499 ; ++ i ) {
var o = [ "Row " + i ] ;
for ( j = 0 ; j < 19 ; ++ j ) o . push ( i + j ) ;
data . push ( o ) ;
}
var ws = X . utils . aoa _to _sheet ( data ) ;
var wb = { Sheets : { Sheet1 : ws } , SheetNames : [ "Sheet1" ] } ;
var type = "binary" ;
[ "xlsb" , "biff8" , "biff5" , "biff2" ] . forEach ( function ( btype ) {
void X . read ( X . write ( wb , { bookType : btype , type : type } ) , { type : type } ) ;
} ) ;
} ) ;
if ( fs . existsSync ( dir + 'wtf_path.xlsx' ) ) it ( 'OPC oddities' , function ( ) {
2022-06-06 23:05:27 +00:00
X . read ( fs . readFileSync ( dir + 'wtf_path.xlsx' ) , { WTF : true , type : TYPE } ) ;
X . read ( fs . readFileSync ( dir + 'wtf_path.xlsb' ) , { WTF : true , type : TYPE } ) ;
2022-02-13 09:35:34 +00:00
} ) ;
it ( "should quote unicode sheet names in formulae" , function ( ) {
2022-06-06 23:05:27 +00:00
var wb = X . read ( fs . readFileSync ( dir + "cross-sheet_formula_names.xlsb" ) , { WTF : true , type : TYPE } ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A1 . f , "'a-b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A2 . f , "'a#b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A3 . f , "'a^b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A4 . f , "'a%b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A5 . f , "'a\u066ab'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A6 . f , "'☃️'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A7 . f , "'\ud83c\udf63'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A8 . f , "'a!!b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A9 . f , "'a$b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A10 . f , "'a!b'!A1" ) ;
assert . equal ( wb . Sheets [ "Sheet1" ] . A11 . f , "'a b'!A1" ) ;
2022-02-13 09:35:34 +00:00
} ) ;
it . skip ( 'should parse CSV date values with preceding space' , function ( ) {
function check _ws ( ws , dNF ) {
//var d = X.SSF.parse_date_code(ws.B1.v);
assert . equal ( ws . B1 . w , dNF ? '2018-03-24' : "3/23/18" ) ;
//assert.equal(d.d, 24);
//assert.equal(d.m, 3);
//assert.equal(d.y, 2018);
}
[ true , false ] . forEach ( function ( cD ) {
[ void 0 , 'yyyy-mm-dd' ] . forEach ( function ( dNF ) {
var ws1 = X . read (
'7,2018-03-24' ,
{ cellDates : cD , dateNF : dNF , type : 'string' }
2022-06-06 23:05:27 +00:00
) . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
check _ws ( ws1 , dNF ) ;
var ws2 = X . read (
'7, 2018-03-24' ,
{ cellDates : cD , dateNF : dNF , type : 'string' }
2022-06-06 23:05:27 +00:00
) . Sheets [ "Sheet1" ] ;
2022-02-13 09:35:34 +00:00
check _ws ( ws2 , dNF ) ;
} ) ;
} ) ;
} ) ;
2022-05-17 01:26:22 +00:00
it ( 'should handle \\r and \\n' , function ( ) {
var base = "./test_files/crlf/" ;
[
"CRLFR9.123" ,
"CRLFR9.WK1" ,
"CRLFR9.WK3" ,
"CRLFR9.WK4" ,
"CRLFR9.XLS" ,
"CRLFR9_4.XLS" ,
"CRLFR9_5.XLS" ,
"CRLFX5_2.XLS" ,
"CRLFX5_3.XLS" ,
"CRLFX5_4.XLS" ,
"CRLFX5_5.XLS" ,
"crlf.csv" ,
"crlf.fods" ,
"crlf.htm" ,
"crlf.numbers" ,
"crlf.ods" ,
"crlf.rtf" ,
"crlf.slk" ,
"crlf.xls" ,
"crlf.xlsb" ,
"crlf.xlsx" ,
"crlf.xml" ,
"crlf5.xls" ,
"crlfq9.qpw" ,
"crlfq9.wb1" ,
"crlfq9.wb2" ,
"crlfq9.wb3" ,
"crlfq9.wk1" ,
"crlfq9.wk3" ,
"crlfq9.wk4" ,
"crlfq9.wks" ,
"crlfq9.wq1" ,
"crlfw4_2.wks" ,
"crlfw4_3.wks" ,
"crlfw4_4.wks"
] . map ( function ( path ) { return base + path ; } ) . forEach ( function ( w ) {
var wb = X . read ( fs . readFileSync ( w ) , { type : TYPE } ) ;
var ws = wb . Sheets [ wb . SheetNames [ 0 ] ] ;
var B1 = get _cell ( ws , "B1" ) , B2 = get _cell ( ws , "B2" ) ;
var lio = w . match ( /\.[^\.]*$/ ) . index , stem = w . slice ( 0 , lio ) . toLowerCase ( ) , ext = w . slice ( lio + 1 ) . toLowerCase ( ) ;
switch ( ext ) {
case 'fm3' : break ;
case '123' :
assert . equal ( B1 . v , "abc\ndef" ) ;
// TODO: parse formula // assert.equal(B1.v, "abc\r\ndef");
break ;
case 'qpw' :
case 'wb1' :
case 'wb2' :
case 'wb3' :
case 'wk1' :
case 'wk3' :
case 'wk4' :
case 'wq1' :
assert . ok ( B1 . v == "abcdef" || B1 . v == "abc\ndef" ) ;
// TODO: formula -> string values
if ( B2 && B2 . t != "e" && B2 . v != "" ) assert . ok ( B2 . v == "abcdef" || B2 . v == "abc\r\ndef" ) ;
break ;
case 'wks' :
if ( stem . match ( /w4/ ) ) {
assert . equal ( B1 . v , "abc\ndef" ) ;
assert . ok ( ! B2 || B2 . t == "z" ) ; // Works4 did not support CODE / CHAR
} else if ( stem . match ( /q9/ ) ) {
assert . equal ( B1 . v , "abcdef" ) ;
assert . equal ( B2 . v , "abc\r\ndef" ) ;
} else {
assert . equal ( B1 . v , "abc\ndef" ) ;
assert . equal ( B2 . v , "abc\r\ndef" ) ;
}
break ;
case 'xls' :
if ( stem . match ( /CRLFR9/i ) ) {
assert . equal ( B1 . v , "abc\r\ndef" ) ;
} else {
assert . equal ( B1 . v , "abc\ndef" ) ;
}
assert . equal ( B2 . v , "abc\r\ndef" ) ;
break ;
case 'rtf' :
case 'htm' :
assert . equal ( B1 . v , "abc\ndef" ) ;
assert . equal ( B2 . v , "abc\n\ndef" ) ;
break ;
case 'xlsx' :
case 'xlsb' :
case 'xml' :
case 'slk' :
case 'csv' :
assert . equal ( B1 . v , "abc\ndef" ) ;
assert . equal ( B2 . v , "abc\r\ndef" ) ;
break ;
case 'fods' :
case 'ods' :
assert . equal ( B1 . v , "abc\nDef" ) ;
assert . equal ( B2 . v , "abc\r\ndef" ) ;
break ;
case 'numbers' :
assert . equal ( B1 . v , "abc\ndef" ) ;
// TODO: B2 should be a formula error
break ;
default : throw ext ;
}
} ) ;
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
describe ( 'encryption' , function ( ) {
password _files . forEach ( function ( x ) {
describe ( x , function ( ) {
it ( 'should throw with no password' , function ( ) { assert . throws ( function ( ) { X . read ( fs . readFileSync ( dir + x ) , { type : TYPE } ) ; } ) ; } ) ;
it ( 'should throw with wrong password' , function ( ) {
try {
X . read ( fs . readFileSync ( dir + x ) , { type : TYPE , password : 'Password' , WTF : opts . WTF } ) ;
throw new Error ( "incorrect password was accepted" ) ;
} catch ( e ) {
if ( e . message != "Password is incorrect" ) throw e ;
}
} ) ;
it ( 'should recognize correct password' , function ( ) {
try {
X . read ( fs . readFileSync ( dir + x ) , { type : TYPE , password : 'password' , WTF : opts . WTF } ) ;
} catch ( e ) {
if ( e . message == "Password is incorrect" ) throw e ;
}
} ) ;
2022-06-06 23:05:27 +00:00
if ( false ) it ( 'should decrypt file' , function ( ) {
2022-02-13 09:35:34 +00:00
/*var wb = */ X . read ( fs . readFileSync ( dir + x ) , { type : TYPE , password : 'password' , WTF : opts . WTF } ) ;
} ) ;
} ) ;
} ) ;
} ) ;
if ( ! browser || typeof cptable !== 'undefined' )
describe ( 'multiformat tests' , function ( ) {
var mfopts = opts ;
var mft = fs . readFileSync ( 'multiformat.lst' , 'utf-8' ) . replace ( /\r/g , "" ) . split ( "\n" ) . map ( function ( x ) { return x . trim ( ) ; } ) ;
var csv = true , formulae = false ;
mft . forEach ( function ( x ) {
if ( x . charAt ( 0 ) != "#" ) describe ( 'MFT ' + x , function ( ) {
var f = [ ] , r = x . split ( /\s+/ ) ;
if ( r . length < 3 ) return ;
if ( ! fs . existsSync ( dir + r [ 0 ] + r [ 1 ] ) ) return ;
it ( 'should parse all' , function ( ) {
for ( var j = 1 ; j < r . length ; ++ j ) f [ j - 1 ] = X . read ( fs . readFileSync ( dir + r [ 0 ] + r [ j ] ) , mfopts ) ;
} ) ;
it ( 'should have the same sheetnames' , function ( ) {
cmparr ( f . map ( function ( x ) { return x . SheetNames ; } ) ) ;
} ) ;
it ( 'should have the same ranges' , function ( ) {
f [ 0 ] . SheetNames . forEach ( function ( s ) {
var ss = f . map ( function ( x ) { return x . Sheets [ s ] ; } ) ;
cmparr ( ss . map ( function ( s ) { return s [ '!ref' ] ; } ) ) ;
} ) ;
} ) ;
it ( 'should have the same merges' , function ( ) {
f [ 0 ] . SheetNames . forEach ( function ( s ) {
var ss = f . map ( function ( x ) { return x . Sheets [ s ] ; } ) ;
cmparr ( ss . map ( function ( s ) { return ( s [ '!merges' ] || [ ] ) . map ( function ( y ) { return X . utils . encode _range ( y ) ; } ) . sort ( ) ; } ) ) ;
} ) ;
} ) ;
2022-06-06 23:05:27 +00:00
if ( csv ) it ( 'should have the same CSV' , function ( ) {
2022-02-13 09:35:34 +00:00
cmparr ( f . map ( function ( x ) { return x . SheetNames ; } ) ) ;
f [ 0 ] . SheetNames . forEach ( function ( name ) {
cmparr ( f . map ( function ( x ) { return X . utils . sheet _to _csv ( x . Sheets [ name ] ) ; } ) ) ;
} ) ;
2022-06-06 23:05:27 +00:00
} ) ;
if ( formulae ) it ( 'should have the same formulae' , function ( ) {
2022-02-13 09:35:34 +00:00
cmparr ( f . map ( function ( x ) { return x . SheetNames ; } ) ) ;
f [ 0 ] . SheetNames . forEach ( function ( name ) {
cmparr ( f . map ( function ( x ) { return X . utils . sheet _to _formulae ( x . Sheets [ name ] ) . sort ( ) ; } ) ) ;
} ) ;
2022-06-06 23:05:27 +00:00
} ) ;
2022-02-13 09:35:34 +00:00
} ) ;
else x . split ( /\s+/ ) . forEach ( function ( w ) { switch ( w ) {
case "no-csv" : csv = false ; break ;
case "yes-csv" : csv = true ; break ;
case "no-formula" : formulae = false ; break ;
case "yes-formula" : formulae = true ; break ;
} } ) ;
} ) ; } ) ;