Spreadsheet-Read-0.84/0000755000031300001440000000000014016160366015265 5ustar00merijnusers00000000000000Spreadsheet-Read-0.84/files/0000755000031300001440000000000014016160366016367 5ustar00merijnusers00000000000000Spreadsheet-Read-0.84/files/test_x.csv0000644000031300001440000000005010313232324020373 0ustar00merijnusers00000000000000A1=B1==D1 A2=_B2_== A3==C3=D3 A4=B4=C4= Spreadsheet-Read-0.84/files/merged.xls0000644000031300001440000003400012474071332020357 0ustar00merijnusers00000000000000ࡱ;  Root Entry  \pCalc Ba==@ 8X@"1& DejaVu Sans1Arial1Arial1Arial GENERAL                + ) , *   8 ` $Blad1TZR3  @@  & notes monextint { wL0&aU$?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?VV:?V&HX{!?V:?V&HX{!?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?VV:?V&HX{!?V:?V&HX{!?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?VV:?V&HX{!?V:?V&HX{!?~)&aU$?55&aU$?55&aU$?55&aU$?555&HX{!?55&HX{!?55&aU$?55&aU$?55&aU$?55&aU$?55555?5555?5555?5555?5555?5555?555&HX{!?55&HX{!?55&aU$?&aU$?&aU$?&aU$?&HX{!?&HX{!?&aU$?&aU$?&aU$?&aU$?&HX{!?&HX{!?&aU$?&aU$?&aU$?&aU$?&HX{!?&HX{!?&aU$?&aU$?&aU$?&aU$?{ wL0&aU$?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?VV:?V&HX{!?V:?V&HX{!?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?VV:?V&HX{!?V:?V&HX{!?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?V&aU$?V:?VV:?V&HX{!?V:?V&HX{!?~)&aU$?55&aU$?55&aU$?55&aU$?555&HX{!?55&HX{!?55&aU$?55&aU$?55&aU$?55&aU$?55555?5555?5555?5555?5555?5555?555&HX{!?55&HX{!?55&aU$?&aU$?&aU$?&aU$?&HX{!?&HX{!?&aU$?&aU$?&aU$?&aU$?&HX{!?&HX{!?&aU$?&aU$?&aU$?&aU$?&HX{!?&HX{!?&aU$?&aU$?&aU$?&aU$?cc   d-C6?_%;*+&ffffff?'ffffff?(?)?" d,, ` `? ` `?U} ;;;;            PH0(  >@gg   FMicrosoft Excel 97-TabelleBiff8Oh+'0  px  H.Merijn BrandH.Merijn Brand0@@@b.@lVR՜.+,D՜.+,\H AppVersion DocSecurityHyperlinksChangedLinksUpToDate ScaleCrop ShareDoc12.0000 Root EntryFWorkbook'CompObjIOle SummaryInformation(PDocumentSummaryInformation8 dSpreadsheet-Read-0.84/files/merged.ods0000644000031300001440000003532312474071347020355 0ustar00merijnusers00000000000000PKl[Fl9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKl[FuYThumbnails/thumbnail.pngPNG  IHDRsIDATx]kU_׮ZFiIZTXd={H^if&}ɂ/AE=f%J/%D_Z{_p\wY5gf;::?ޫW/ӝ}:^,3hDJ©##39?Eb!3#̑CTv|d1Sz2SRr@ _"=J5{r)nؽzmr`{Lv,SK&Hc9-nNtЇױcl Z[ѣG[n=]Ƿw(.*vqF-+BCU aXm ?]߿OΚ5^>|x>},޽ pJӯ_?{ ͰJGlo׎eJci 4'sTT/|ǰ{3f 2_~3gέ޺y:thȑ'Ofu5\hѢ6l…a3s=w\+yy@ɮc[Jtst)t lm۶mҥv}Nj7O_r%ӧO߿I^k>cǎ U z+d=7tu/c"D2pHGmӞ-gyڵc|M߾}j-[ƌg]{&LzjO>_PT5uLS+ PXdrV-)D龺;`رܹG5{oٲe/[of[o&[LO?q֭[{Ymb!3ZW@2ds䥐N9ȚFuir/^bŊܹ6N=Է~{Ĉꫯ._ov9tЖ-[f̘_lڴiڴiv_^ӧO 6lݺNJސ1.Б9c`GegABҕMPfR@2GE2Y ӹEVy=۱ ,_|ɷ~Ν{wx]dɪU> ͚t"I5 Lȑ#cƌYh zGˑ#GΟ?ߊ@̙3>lV[g3\b8@X?%GXrL$y#3h^ 9^#8qcǎΝ;[۷۷ϖu;)֎Sd~2͚5eM|PG>߫۷ l7iUW]e]wec&Q7niO'xPKDT s ̒ B9&Bi 4c/ rJ˱de˖ovڐ!C8`2㎉'Z1E+%jzQ$U1hYtlKr-$UsͶ#sK65uY.y'_~ ؉r(k6t~w1ۺ8kkϽ:vI^#2TB6KU #e(Wac9䑴h Kr(w]miQ M Gݻ7] 3iv3gλku=_׻wP3<#\~%%ҼQW kPqHUmwCxw}r#G̞={ݺuW\qĉΝ{w} cǎ\R$mX>|x޽v`cβqF "֯_?y3gWYe,=e\͛7k֬>}ח_~yŊVx=x=\owرvZk֬y饗&LhѢO?ꫯ{Ǐ< Vmb$[qGIx!;qxr--h߷oW_:th]wG}믿{ z׻Qvt=@HS.e6lMd@sf4=Qh&`{M#(sHj̱kң5Z(shF\\=qYҬiBYU#+ tR3KYCXgC$ 3#<eHkg9)~_SBȆ|(T5u&tJ:c!u<$gѬYYugW:`/j!_ 9H !g畈$}Dy 5(rz ͚'KtPx&}r1 ILrv^LWIP(/B*y#Tsv 4gVsY3fMIUQR%= Ifc,Z|u5Rt=׌цLd/ *F:"gW)!0H&9t 0[S1МYMO|\Ra!TXFٞc9s{n+ՖzSl1Mzʝz?OO-٨ct=< '#?y 8*I΢GYH2Ul1f- M:%*$WQ1f- mIJ tjm-)DBA28BX<!RQ^P1r֙,f=(I],~pT$Ek֬k4JJ$ Mn׸SxJe"ЁtB~쇤6 x9Xa%@s2ZrWR!iJJEǏիWc]' {W "HI8u$@`጑Q^T5u&9DBή +@1SGE2Y4kj֬q4<=}TfIH%Ώ"W֏V0+̹hNF}׬k~Yُ|P YK$΢H2SicfѲKؖZHT)fm{tE˂nmIJRMIwPaU40[hc94Z3hALT5kGYiԬ)rNi:㔾ݡG^T5u&9DBή +@1S5O5JJ$Q$ĘY,MlK͉hkjY'(8}|IENDB`PKl[F settings.xmlo0W5*Lkn>LrU)$iW4^q>߇9~wVwc{S>[W[1fG/ ˹t T: 9ϗ9TXQ~ӷJmqݣ#;ͧzgt^WT6{S" Jdʤz΁}Zk%7Lӳ?8^ TAئ~ַHgI!Uk*P`hjAʕ5ۏ!_L!Zߙ~t(ռ_u퀄m}( =Jh: C|Jh;ti-9! O)p #~"!Q\J{!g`; z\憌/C ;7E=S<=EDŽ+S|>6r*m6vT 4 HMvCZH?.0(h1jOn \p3YT QJ}EBIΑؔ]?*K:R@RTyی0Ynu\)vg)rB!CQ@3LNPw>l`_ XHz1g@|ݖ.4[t+*".3n#B\N TP&NV>~Ę1Hߕշn[F"FS.T!xۺNR鮸\1nF'HPo ??9[HKd ٍ7>b(Ms~} .޿D|~qOEjB0 JxOi>Z}~A(@&xv+ԂДH8<8eF}_' NG!ܼ]a^d!K,W'цrЋ1Ct=x'5/pa&;Wq[^57W<t[e4ZJ w߻\T?PKCgPKl[F content.xmlYo6~_axhYN&^bЧn[A̖"~GR)Erۂ/NL~w~ܾ>|J3)b9QIDq7t=}ݭs5Y]RaP&3zwk5kK&[ˊVjΖ_OwXЃ*lYnفci~łSc\N>hr ^/+lXŁ3n5Z'~_/RIzss@8 VܡHPN14i%5x*?)P55GQĜ(׮]byT SIJ%6ۑ^'`}{{+UNeWeUѱ2PryzWP ,x\CN\ѝMPDzD`dT_޾϶G021 G(ѓ^%VR|zh)x밻-P BEm魧&qHńp*Z3衢-̝غ!`." F(o?iPԐ ZG{CilK5> Cڄ };^ÌrQDhay[w_'g={T4V2p7WRa|QimBٷ )Ӧ{cDL}|sIj?jO~Іϱy:=W8OJIFgǹ=ƞc2:+e >;'d5]? ץ"2Y.EgPҠКn56=#vzX-:+875M}Ĭ]RVl,WW?ӄkM +1Gt_C|uFׯ-{],aH UK{pL ajVuPl,xRP23:Ô6Uae_ j[Lkn9BCb9+ҲVCF!Óu ^E^VB""Lp._> 7, M魂72hA`h~@[jmX$U4\mްn>v7j%VܦtVׄ}^lm KE4޷<ll$y8΂Do)5IwkmJ w 4v48o LrhXQmӀj)اXY<6%qt:šA?ʪڡi['P5s6M`2ͺCocQ?KsO8SpgM;f}3ŗ~/PK2\PPKl[F styles.xml\6~Oa(Ndw++AڻWe(Pz7yT$7$Z-ڍ6 g~p5u)Gc{Ù.H{xlWsŒ3*7I QpW,a>hU^p%\-;XʖƢ3+h]R0-߰bjn BTx$ ,kMw),KKj]-%*)ϵ0rrXI٢Ia<`$P-1ǔfףE7ϔp*s?U^qlĶ%{T%eKPDLcT9 ]ܙm_YsAz)D`^w;]D]8 @9 ?J\:ݪyaq1.!Й饺m_759s -,ݛR.i)bؖK'[`ÒK] ~0' Q5lUPd e'RhO36.Rf:6 ra4EI,7ÿ$Q>_dcRR)eM%<ޑ86iH +r/JDD'CL;cs. xjn[]v06~gie JhV3[U.1]LG#hkF Ĵ A L^p=prY*C[a+B?A>T59>3*LH(1D rۼ'ӘwC](~[[RU~Ӏ.-QdO M 8DĀA&1i*DZ?ڹBD%kƓv'ڐ9㫉B9c!0ՀL^ig3m'ڐq5)=HɳB3}<|/m?gtZ{7zy漸gBOh=ݷٗD'X @_ݒP`FkYŽ>Txy|N9 ω6u]L;J-T`iv53du]QU~/S4:}Nf?'qevT|Qri5Ϧj xvq5\|!8gseQǿSШi5;V?=چPj/"W`./tt Vy}zyWTisr(gsA8/84PF(s);%yGj< 6|>U<`*<^ëP@OyT)jȔx5XJ:3%..2eq˜xq_0 L{ʏFiCf`vqf T3.^_h9{=_Kֽ2^u۳n:ҋfF[ݾ}Sg{Q! ^-Re}Lq𹴭~nU€jU1 8N$j+9k3dҧ5Ϣ#hF_?,_aYGw?~XK z"+K2;8'{ "nO '9%!ebF"#|Jk&UsqrPXpf'SVijBO/c LGQb,F<90һB~9NxS +7\yg*fkZs^03D q\}iҮiU.g vͼ#&E,%Gc45\'4R`cgԶ9Ց=[No\]Aj3ۘPl 2q|GDԐwK{L↮41h2?e?Ap`'(v℠GH+doO'Bg̙E,[;|X~(5u80HYke[S۷ojcUP["$Zbg(}d_;| &X5A){IYy˲Ot$ؓS9A-Ԁ(TjR.zӍJ$UY̜k6άMrz^?&bXEA!z, m_{ҏϋ{Xݬʕ:Ơ8YYj~PKPz UPKl[F manifest.rdf͓n0؉{*6*t>ۉQGC4hKd^.ލX/+bY{,xDH"弌p,F{*qS0$H ?~< <d9}[W.(ͷ Rhc䠧kX= >k9%Ҷf܀fgަ2@D0-@\HZƭ^Y:c}4Ӏ @7VL-.i@D"AgA"~wx+󓄬?vW^vj ВP8) M)H8bo)1C+*o_v+pDU8b1 F료$E*PHSehˮdMU$ƔApgkOb6k@bV=D( "E&aPC,i%p+4eV놃NTavjTOwrn_ZgHs {Zow/vJ;R3y(]kbg?:'G1N1TpZp|/"n:8%VRyZW.,/3n>(h%H<{=ɎZe- wǻ Xd<,!a¾o^^ţx O0N&(άY)f5"v˻K<_,0l6F ne37R3`Vƞ.6݃x(?AT`>[#Jx(nxxvD#ttr?pʗGJA^-,OX {$jm>mrAb?G%9ps#,_W5}"TAa .su[8dl-ZbgșUeeqPBS{#%2HU+̺5ZyRi}Mvb̰ v$;JBd Hx#ӢJ uuL]S $ THRla["(5̴ 9lv8(#uCh`8Zo$/*O{"p I&SEDǦܔQ{QUV&q C  =*A.>'|fȑbe)Du){digڥJ_+TU/ZZL?ғy}m(\8}M(VuEP=ئ-gϴa&AiuYH>[DsՋXYTyҔ!pZy<@Ksk#(͟p6XIF=m?/t5+f;"%AU1'g!0j,饵략$Dy6́:qj4B8zzdkҀ-X+Ns~Dk3Y357_8S:$QYXpA*:xߘ^ۀRnٖ[Գ OpenOffice.org 1.1.3 (Linux)H.Merijn Brand2005-05-12T13:31:18H.Merijn Brand2005-05-12T13:36:16en-US4PT4M58SPK\2 settings.xmlmw8pyC3AjѶ Jڐp ڝ2X=;{!7{?7Dž dQrOJJ/uU|qg}yAG6:@V""ZB)-|!?"WxZZٛކh쭍\ٶ"".B7 FhFW6&`uT\09Z\YT14d*ЏMPB߃Pl1 qʺ#!S#9Gr24D0wԅA(cC&s(z*UL|htqFxs=JZBP57+ZQ H( G9 ȿ' YՋeہ_d5iS;{/ Qm2{vDoINK:eFcgg;buuO?)M)(92g9,܃Oš-1ՠx+gJ֧ z^i.C}bҨ +q)4wC(0"?my\ ,j.`zXY ×y0!㝙w4~m/. ~N:u>E?#(As ,\p(OK !~bg[D >Kz<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK!JaGxl/_rels/workbook.xml.rels (j0 ѽqP:{)0Mlc?y6У$41f9#u)(ڛε ^OW 3H./6kNOd@"8R`ÃT[4e>KAsc+EY5iQw~ om4]~ ɉ -i^Yy\YD>qW$KS3b2k T>:3[/%s* }+4?rV PK!5$4H,xl/workbook.xmlQMO1eE$5r1$"k;6tۦ-.{%(<ͼyofC78/pS!׻ %>0-2*zOͬ7ne̎mC,󼅎1ױm3o0[Щq1IaaFrx6|߁'߷zZ`}ڈ0kYs%"dQ{ۧT1[cտK.ZBFjazdMz3zDЧFqǣQyܶdVم|IGgDM%:n!Qт$k"a+_:M/ʇLG?PK!P xl/styles.xmlSMk0@KX.{ ,PH {D#Ї!v{ٽoF73oFYv1%/i FN)VZ## $#B^;H՞N TAΊb(ϫۅΣQR] .҃ӣ3U3i%,rTe :l›%u׼B󋬾PK! 1#xl/worksheets/_rels/sheet2.xml.relsj1 E>Lx lC<סv Mw.::hY9V780x=@Ih \Y`=>l"k&7'\PK!j%mП˓9%ڰ`Bg"!IkC "y AH)U U;pEB?[3D_8dY2ohMO@0u;MӸن2 ZON&{),p]$Է_E (Vw05-1=x+wW Nثg̰4VrGG1; :C߹ .1e4b/ 8@-ͯ=hPfKCqzb'7VjeK^͎S} 9vG!ҿ~ V &ܶ"9da !jmq uoLUD@d6.FOÛ;UټָL'f1ǟORal:fۑX\nIe㆒%"xB>ax> qo&xqS .XˢrO龬'jvV6| V0Ek{b 6Nٍ#{a4P9Sl!Q/KPK!D xl/theme/theme1.xmlYOo6w toc'vuر-MniPFI|úa0l+t&[HJkf%~||~|8:$BR՚H&aۻ;_YT8 0 i{S"sD)/-IS11V(¥@#Zmu)4Pc{g<>Ebo#c!QRwL h\ppP9]&!fmhH ^6/lS Ɩ_6.,"JFV!zn^3T;Fe@9/[k.$enέNlesB 6sjcs7f WkՆ7`g ȘJj|h(KD- ?dXiJ؇8x$(:7˗s]Zj{rb&^=^=rO=:y IXO#ӯ_>/_>B f'>{O~q|SQ>169B<ø3'#qSg@v螊)fUqwO{ToN8sDbh(vѺJNZqVqmooAؾg{ X$! wݧԱ.|}:VdHGN m2Z3ڱ=j[EBB`V1!aoq!Y෰&9 I )ޒw0Vw4vBу*0e?F8NDe{B= ~Bwߣq. )DK`jc3 llc&lMU)}Ļ'Xx.yw<.峲`{u` cS&Nj1elܒP[}Ǧ4f.،ANȮ{ZH(3ѡD)p3ݕ5 ueφM}j ^cAsE+ZY\˄²DY]OfjmŒKšP (^ʫpJתp x"]$#Gz>'b v*|OzZI[K} mgqRY]c{of+_uv["RmaY U,њ`֋Z7?6 Z2_]Ѷ"bGh&buz*z0~4mm%,WXg1K#ѭN<-q1Trfq_I ZJ9gK >\ t=.Tā҈}2!ZB^CP/ȡos0i >OC$(G*-{zwY,d"4]i!aĆzoPn$;sAP9|s8,+&' |l2>MAۿbŮjǛ{geV# PV ZYڿιZƚ[r3xq~YD) >#&:6ha6Wl4ANYJ'mο߅S3;i8s9x,-45xtB8?ǘ[oO|wfFL{I&:"ox M3=X!:P$@o^TCT7 7!0[8[q7E6Lzx]j*\v*G/vbY"G%^|&A/ %jK)<&,v2H); lc ʢq$ڝ#LT݁1g4ŰA {/i}my >*󠝒7Fycm(Җj,Xrmox86th˂ r`PK!Ikixl/worksheets/sheet1.xmlMs0ScvU f2ۜeX@."x̴>xVZ«b{0V* D#mqfQTP˯ƒ6϶@F xX/<&t LR 5gk"uI?J!+*,̿h, t+VĀHB֖a*5b_՘{q蜿K83C} BJ Vf h݂FQ$(HxLz8smZqoX )\j$S,5L>^#|Ї[yDWE}`/*֢~SI(5~YpV}6G^UCv.sg㎝^h'z%:eM٪Ϧ;3lQ3u.l~Ζ}:נ=ZU\V)Lgq3Podm5.߀՘fg/2mL7pWLFo&,4n"^kFHlga-{JەFWAkZV'zLzk]P2$/kGRUA}t)0`~Cc?:Ͷwb/ /Ʈ{IPK!)? xl/drawings/vmlDrawing1.vmlV[k0~?/Nc;uۨvSVEXcluwd9Kaek |wCIB64\2dPЦP7=~Lf֦}h3 I9+b+XPњ\Nm Kv.{>&I\U)w7Qy$x-ڇAwA%FLW+Uъ>9d*XRfk!\fSȼb\ mRaz@kgUxZ׳SJ(8{+%qTB-Mٴ4Uj.@8Ks 4vGMNcTBsCBRsҰZNfEsɹGd&@AzR= ow[3I8V̖6}84~nۍ6{ᑀG* uμfϺA .ZL$\6oU sMmӎ&.6t.i镲3I>NpwdoBW4PvEYr\$I$əOF>9ŗ> o [>fVݿRZڸl]xӸ!lQ.Fj$k~MB653R U K ?_P,ZGp7,*uKDt—&8')ÈQB7EI j"k[#Z-c&LMʤwLNTyI}^wc PK! xl/comments1.xmlJ1}.& EAŃ>@؝gno&_~I@;W˒3t ㌢r2ޡG$Ţi"dH!ѥJU1a4T ҎF}i rRu:ES$,`/,?w2!54DlL_!I[bVjsbu17Hn 򛣾.GU,<\W檋DVM4Y9#PK!QA2docProps/core.xml (|N O;4ܷF.&j̹pSa\і@뾽SƘp|lʭsS342X|j}##~CTr,(MDCj5!ݛ@+ 54`c`K7lL:i>[8?],3zF͍R@R+MA,wTSA֋yٹGԛ ۮ: Bqr$P]OVd -BM)kA (YVU\{HJ>?Vf<Ŏ+ FUron߉y朝rVGwPK!c"docProps/app.xml (Ak0{V% !!P:yb"$wl7PN3oO#lzU}J<W_E |Hj=+l &7ZHΪo+K-A9+kŮ!ƃm>PXdJ51yz 3ʶ}avL]ؼ9k* s-MoGN TIBpbM ގyu5NC zr\o/xvB8ޝgx_PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK!DGxl/_rels/workbook.xml.rels (j0{Ӗ"R !$} n\E3^}PY Y"[ % #1z#g],khE˖Édva0ehЛdBgIdοqtOöK+d9M/K8T~W6Ͳ QltQ(y'47]b[5QNp_y}ġQX 6l$AT2ĝ$:ZU•Bk2.^C,0 ʘt2NE!%%<=f0PK!iRVxl/theme/theme1.xmlYMoE#F{oc'vGuر[HF[x=ޝfvg53NjHH q Jĥ@wfv;&%!>Ǽ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK!Lɑ- xl/styles.xml=k0B( 4v(PH ]H09=َcOXu+ٷFA9jMg'-Su:<> v[ۘ7RXlUb!xs7ŒYڋIcJVq/D!y4(d@ho]x+3=37!jtS]{f:L{PK!k3q]Dxl/worksheets/sheet3.xmlQj0BZvJۡ4P(b-[+M}v ؗffgw߉h2KR)UX[}uu/E$jݡB Eyy1l .R2똠ǝCЪzwj aMc+Xb>2-DTe>~Z_X#ns]tUfWAmGobf͙`Iym2lj(2ߕ׹1SŏOwoj5h%XnEֺ(:hXP:aR7%~TF"% 7tJsƢНmݗ%sd9ytPK!^)2Cxl/worksheets/sheet2.xmlMk0 F2Vv}DM)I[fYzwdWrRoFDʷʡJ!E}~V0n *im@R(Ih)a0>n$jZz!X/z#A-d6K[am[ȏ̓A ~j8X)Xx r{UV` و p3e|BߌszQCMoϒ֊T{<?c"c)Ude>Y TǯOSx9+k4Y\pdu[m0а4~R7%nTE"ǰIgAS˜Sm3^ etk4u,)PK!UgdocProps/core.xml (|N0EHC}⸥/+I%A v=m#lCۿIڐ 3w;r<:*rDE\s9ϔ`V8,no2n(6`}. $(79{o(ƎA2 ͭ;l`;4b nGO[1 AyIBփρ3PʟLt;d 5{Up8$qk#'mF+܊*2)ŦV;J[-(kM8q* .jC-څt^ǫr XLcBѬ$cz7d켚olvy1d])II&hH(PK!=E=docProps/app.xml (Ao0  0 bH;avgV$OzOgVw&WfV Jz!"{YRzd>K4֚^*mlN~&Ʒn6OgKmY,ok\d6'#l K-֗RpWq]:sLeU0WR6KPnQEi~;~Ȱ%Z # ӥ:drWg9Kml  r]g0J)ISP=i_Q|g~mYAtl|T, YD *f:ljq4`ߒ=i6so"TN[^a طh}m"[н_E@-#x|UxźcExBE2庿P>JX<0쵴b,& ڬƅpQ@Rawl>xMcg9n=,gZ 5RF8O2(0zxZ%7 ބɼ@|*8T<=r;iK좹hie$"Ԅ,ibZw&o#pSǷ|9գ"/nA%N]ojҜbQmLq xMN5o%ͫ|s+V ' o<`(nPKTPKjBP styles.xml\o6 C+vpn⠽^ t`$JUoHlTp4Pgm0 c+#X&{|z/vKXxaSk〫p4Aqc͂Eqւ8H.cqlۻSV MndL>\F+70&{SQ- $TT: y_b+e~B8G|Ӎ:>yж﹄,x:M'vq,ϽAű2z#,K aű _!'xWZ|J{4w4p:ύC̈B"3 %7no7jQ?3=N_ԁqf>Nt}>G44BIG* 8f4\F={$ DoV&'lKg4clhBwKQLPHkM5Cx6S !粢h›&T12Yi[m42!+[tI}=`a25m eoa15er:VMYXEˬy AhO|⽤Z DU:;zDAԠNJ\ܨJE[E%p ֩ D v&}xն`^"]imH&Z{IjN ZTZ36z'QyrẠ[497J j үQg(N 5x~p1ѕSb۱kUθhkМH] _ ͹=l6ls B8ӓ#8=ȐKDÓ98=H?vD 7{E9{IV&=qRъY&+zU HQSm4dqrJC%'f 7E<)^ nW9"8;r)trUrᰇ*o*n.V\(J-rE pkg&j duL[v]$[Vl'[u,fSRJ7Tho:&:1׶})%Ði I`(馃nM[,9.;#Q%ݥr%Tepl9=[NweMuV7rfL`;%4P3;ȋiûJ"0C,u.1z2! iXs#_وϡv>8"nPx\^WlrE#ݍ.sV!S ~ B)v_ }":|;蘘sNH?i#Nedƴl-ދFkN[$ڌ #X3?ڃt'f %x |z̩לʎ_P3:y8zbY1/bJ E9o(;=#<đ?d'Oϳe8[;X`!mH.$H(9l-[a;WG}{V&MN -hCQKM;R\7tK~ }CijZBXB$s $Xg) XsTrSSlR׊66𧌅vJ9O}_G̅;ЬY,\i)ԑdObm4X6FGh~}q+<7WqjXu/ A|"57/=._>?sa˫F)#wg"t|Ւ8D|OÔ͐'0sld!X;8.-.Efш>[3[iѥo:QȖQh꺥R z V\00Z1i +A@-+K}G_<їFzB[̈́TU N3Xf aWܠ vܠ-  3dV/ӥHDKdB1!@릮3U_]ORݪmD/Bϯ cjވϖBfN7aٿf18@~i9mgeϣ82u!e+˕RI^B5PKN UPKjBP settings.xmlZ[s8~_N4ta:Nɶ5d +w)v<}& 2(UwrG}DxԾKXfȃUzQP9_W=JfH.R@^^U_Ϯ6#+"JqQ6/iJMhrޯDQJJlftU}_\+ەL+v_> $'*Rdu`jʡu_G.`DCewSCyԛҷ ?|g ~6|Xp}I0>G.>F_=%`J-C&{z):v (GBzקmOIrr2B 1ԇ_Pv!+ }Oox-an20ω޿7瘵5ʙj AJDɕ pMaZ^>Zи~v)&XOtIcBWQ3L{8:K `!̔u;M!q\2WEse ~l>'hz0'1d4՟< ~A1e颗tö`.R( &*DP@Sz?FBZ.܂=!)㻲xI!c$q3Ng8Y[#j.>ϴi `B.ɕWh>Lx+r}DsoTui ު GynO 7i m:H^TL~{GG.`k4t< 5{8~ q[Gߝ:1Ce +TiOjLUgګ۸z<AEّ/I%G:{/*vV 38A{Ν׎#۟U7i}8ެy3u+I}~?;t&}<wv5+R?}KsjX~/nŸKej^ga3lӺxt5Ss'3&>z?1Ҽph3mG-ij5jiK3.?>nෝO @YR]t<0Ld):ZDK:lK{?PK]vi#PKjBPmeta.xml]O0+"[IBkAP4qv\4v89_]*m >9y}dzV J=Cq47Bb_f0^vx TWBzrl6p3 -HE#R/6_Q_a݉5);]Pm55l u6Ń%Ov#]UIx26;︲'P86_S Y ?]`Qk~w=Wm rUAyIqǖ 07v.A]le!!+X,`%5lN Cw2P'a~?Df]2E,8\~mݼ0UvgW0ػyKc0?SU#_.̅?Ǚ5gh?1 ~&o>%g;PK'DPKjBP'S22Thumbnails/thumbnail.pngPNG  IHDRQcPLTE'#!*%!/(".,+/26212679>86;;<=>@>ADA>=C<@ME=PG?CCDCGICHNIEAKIGKKKDJQHPUKQYRICWOIYMDSPNYSOUUUUWXVZ_[UQ[W[_YS[[[FSeMVaMZkRZbR]i]_a[cn\ftaVKj[O`XWd\[l_Xp_Raa_mf^ygW|jZabbefhojekkkdmylkqft~jr}rjerki}sluv{}vu|||kyn|ty~szzyn^p_p`ymtcygzk{s~p}i}n|~ruy}~Üģɧť̪Ϋѵǰ˸ȭ˯Ӵλ̳԰ضӵۺѻҼ°ó̻żûijɺIDATxOUuqXYWJXvS9&V](w ,( U (yKL/jKAp9R.{ ^k~kgcg<9?q2[`CV,:5=TY r#Xee(m"KcRyg['rdTݱuӍaʪL9P-d]:g9ZyucHA.nV|_Oc^yC66A^MJ՝{x!vu(#| 5r4N8NS T:dXq皐 Uܔ/sݛdtX c'z`C}ʧGmIC`Z KʹMhT:q/PKNt2,PKjBPl9..mimetypePKjBPT Tcontent.xmlPKjBPN U styles.xmlPKjBP]vi# settings.xmlPKjBP'Dmeta.xmlPKjBP'S22,Thumbnails/thumbnail.pngPKjBPConfigurations2/accelerator/PKjBPConfigurations2/statusbar/PKjBP Configurations2/toolpanel/PKjBP> Configurations2/toolbar/PKjBPt Configurations2/progressbar/PKjBP Configurations2/menubar/PKjBP Configurations2/floater/PKjBP!Configurations2/popupmenu/PKjBPR!Configurations2/images/Bitmaps/PKjBPh !manifest.rdfPKjBPNt2,"META-INF/manifest.xmlPKeC$Spreadsheet-Read-0.84/files/values.xls0000644000031300001440000003300010313232324020400 0ustar00merijnusers00000000000000ࡱ>  0@\ppc16 Ba==hKL;#8X@"1Arial1Arial1Arial1Arial7" "\ #,##0_-;" "\ #,##0\-A" "\ #,##0_-;[Red]" "\ #,##0\-C" "\ #,##0.00_-;" "\ #,##0.00\-M$" "\ #,##0.00_-;[Red]" "\ #,##0.00\-q*6_-" "\ * #,##0_-;_-" "\ * #,##0\-;_-" "\ * "-"_-;_-@_-,)'_-* #,##0_-;_-* #,##0\-;_-* "-"_-;_-@_-,>_-" "\ * #,##0.00_-;_-" "\ * #,##0.00\-;_-" "\ * "-"??_-;_-@_-4+/_-* #,##0.00_-;_-* #,##0.00\-;_-* "-"??_-;_-@_-                + )  , *  ` Blad1`i@ A1 labelspaceemptynulonequoteu < 0@ W  dMbP?_*+%"??U  ?       @>@7 Oh+'0@HXh pc16fpc16fMicrosoft Excel@2 L@N9L՜.+,0 PXp x  PROCURA B.V.We Blad1  Werkbladen Root Entry FWorkbookSummaryInformation(DocumentSummaryInformation8Spreadsheet-Read-0.84/files/clear.ods0000644000031300001440000001315510327656236020200 0ustar00merijnusers00000000000000PKTZ3l9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKTZ3Configurations2/PKTZ3 Pictures/PKTZ3 content.xmlVMs0W0ziPۙtzJNi;b1胑q}%pô2^iYz8A:n$U9ut>l>TQ0 Yh-@ZDodtZff2ILU ,Fgm1Om`=v%[p5i=֙ 5|0ʹ.*bٙgeVM̚LL{\Ukޢr/f|6GKXdk%onw'bDOzyĖ#wraxz<͂Sky*Y5̀J^'wn,N)w\K9;~f|4gZ '0{4HL{ts\p@'*f ߇_:ƬH~&3f&nx:H*e^4jTR7{h)')MS_ځD^rDJc0t a9/܃ݙRD!JRπka&v)& ՊO d3F~bCB֩5O0kY;}b:\\~Hk3 B<:Wi2*0/GT' P~RSynYB>Vy])*s. Q±RW?zݿNgKfݔ#ULU#Ozg FEN!N}s;.&VW1L7fv(a=/ >[}J}R8P?$rCބ<'pzかLgV77eB]Dc[h8!~ҽev_i Sx#s~ImtB5(lUHd{zܙoUW0.<_lV3®cz40]RZ OpenOffice.org/2.0$Linux OpenOffice.org_project/680m3$Build-8968H.Merijn Brand2005-10-26T12:37:22H.Merijn Brand2005-10-26T12:37:57en-US2PT35SPKTZ3Thumbnails/thumbnail.png sb``p @ H1}e``ltq #'ρ-O94!uC^c3w 2hxZw֚atsYPK-jPKTZ3 settings.xml[SJϯzJ1 x[IҒLjfB_"[%.p\t$g>9srT:tzڷ?g ;p@)qSHϵCE>t,x; /'e((:jGOK]KP'PվRWJJIuJ$#D {ꘪN]d`*wHI) iEK58^7~e-j7[㹟\J-eq`MZ䡫C{kkvLTպ>j s塇cUx^\;;nۡ~s|7}CttbӾ~kFwC]"Nbad/:O'rdVߺ"payn:;YHG9Ÿnt5pjh/ ц牅<,@3'a~P0!CB BT9+f:@PR1Za,rCfq_W)`'PKpMWPKTZ3META-INF/manifest.xmln0<{춧" T-¡G7Ky޾)@E.3fgOwe[h')Rޒ>,^-X)IuZ~O\eirgs"[g{<¯q(kʃwhP9]*U&58Rc2bgpi,$Q0:} )mkM) G/qi! ?C`mjڤ\ry''bW*gRϷCW&oH1 <"-H6qXE몡 DqOՎՆN~PKЃ99PKTZ3l9..mimetypePKTZ3TConfigurations2/PKTZ3 Pictures/PKTZ3 content.xmlPKTZ3u_b  styles.xmlPKTZ3t meta.xmlPKTZ3-j Thumbnails/thumbnail.pngPKTZ3pMW ?settings.xmlPKTZ3Ѓ99META-INF/manifest.xmlPK BSpreadsheet-Read-0.84/files/Dates.xls0000644000031300001440000004000011057177657020166 0ustar00merijnusers00000000000000ࡱ>  ^@\p H.M. Brand Ba==<F!8X@"1,LettrGoth12 BT1,LettrGoth12 BT1,LettrGoth12 BT1,LettrGoth12 BT1,LettrGoth12 BT1,LettrGoth12 BT1,LettrGoth12 BT3" "\ #,##0;\-" "\ #,##0=" "\ #,##0;[Red]\-" "\ #,##0?" "\ #,##0.00;\-" "\ #,##0.00I"" "\ #,##0.00;[Red]\-" "\ #,##0.00q*6_-" "\ * #,##0_-;\-" "\ * #,##0_-;_-" "\ * "-"_-;_-@_-,)'_-* #,##0_-;\-* #,##0_-;_-* "-"_-;_-@_-,>_-" "\ * #,##0.00_-;\-" "\ * #,##0.00_-;_-" "\ * "-"??_-;_-@_-4+/_-* #,##0.00_-;\-* #,##0.00_-;_-* "-"??_-;_-@_- yyyymmdd mm\/dd\/yyyyddd\,\ dd\ mmm\ yyyy m/d/yy                + ) , *     ! " #      1 2 3        ` DateTest`i 08 Aug 2008 12 Aug 2008 08 Dec 2008 13 Aug 2008Locale settings on this PCShort: dd-MM-yyyyLong: ddd, dd MMM yyyyDefault format 0x0E * ^@ &  dMbP?_*+%,M \\dc242\Hold S odXXLetterPRIV0''''`4 \KhCbP`SMTJPDocuColor 242-252-260 PSResolution600dpiEFMMInUseFalseEFMMInsTypeNoneEFMMCoverPrintFrontEFMMTabShiftFalseEFColorModeEFColorModeDEFEFRGBOverrideEFRGBOverrideDEFEFRGBOtherWtPtEFRGBOtherWtPtDEFEFRGBOtherGammaEFRGBOtherGammaDEFEFRGBOtherPhosEFRGBOtherPhosDEFEFColorRendDictEFColorRendDictDEFEFRGBSepEFRGBSepDEFEFSimulationEFSimulationDEFEFSimSpeedEFSimSpeedDEFEFOutProfileEFOutProfileDEFEFSpotColorsEFSpotColorsDEFEFPureBlackEFPureBlackDEFEFBlkOvpCtrlEFBlkOvpCtrlDEFEFCompOverprintFalseEFKOnlyGrayCMYKEFKOnlyGrayCMYKDEFEFKOnlyGrayRGBEFKOnlyGrayRGBDEFEFSubstColorsFalseEFSeparationsFalseEFTrappingFalseEFSortCollateEFStaplerFalseEFOutputBinAutoSelectEFImageAlignFalseEFImageUnitInchesEFFoldFalseEFImageFlagFalseEFOffsetJobsEFOffsetJobsDEFEFPunchEdgeNoneEFPunchHoleTypeNoneEFFaceDownEFFaceDownDEFEFImageSmoothFalseEFBrightness00.00EFImageEnhanceEFImageEnhanceDEFEFCompressionNormalQualityEFCopierModeEFCopierModeDEFEFGlossAdjustFalseEFTextGfxQualNormalEFRasterFalseEFDuplexFalseEFUserRotate180FalseEFRIPBookletFalseEFBookCoverTrayEFBookCoverTrayDEFEFBookFrCoverNoneEFBookBkCoverNoneEFCopierBookletFalseEFCenteringMiddleEFBookletCreepFalseEFBookletReduceTrueEFManualDuplexFalseEFMediaTypeAnyInputSlotAutoSelectEFTrayAlignmentFalseEFSlipsheetFalseEFSlipsheetSizeLetterEFSlipsheetTrayTray5EFMediaInterlvFalseEFInterlvTrayTray5EFMedQualCoatd1EFMedQualCoatd1DEFEFMedQualCust1EFMediaQualityCustom1DEFEFMedQualCust2EFMedQualCust2DEFEFMedQualCust3EFMedQualCust3DEFEFMedQualCust4EFMedQualCust4DEFEFMedQualCust5EFMedQualCust5DEFEFMedQualHeavy1EFMedQualHeavy1DEFEFMedQualHeavy2EFMedQualHeavy2DEFEFMedQualPlainEFMedQualPlainDEFEFMedQualRcycldEFMedQualRcycldDEFEFPrintSizeEFPrintSizeDEFEFCreateMasterNoneEFUseMasterNoneEFPPTSlideFalseEFPrintMasterEFPrintMasterDEFPageSizeLetterPageRegionLeadingEdgeIIFE2IFE" dX??U} X@X@X@X@X@X@X@^@^@ ^@!^@ "_@_@_@_@ "m@m@m@m@ " _@ _@ _@ _@ " ## $ $ $ _@% _@& _@x0000*>@ 7 Oh+'0@H`t H.Merijn Brand H.M. BrandaMicrosoft Excel@S} @v ՜.+,0 PXp x  PROCURA B.V.eTe2  DateTest  Worksheets Root Entry F T WorkbookSSummaryInformation( DocumentSummaryInformation8Spreadsheet-Read-0.84/files/Active2.xls0000644000031300001440000005600013111550441020405 0ustar00merijnusers00000000000000ࡱ>  ) !"#$%&'(*,+Root Entry FWorkbook 4_VBA_PROJECT_CUR" VBA \pH.Merijn Brand Ba= ThisWorkbook=hP<-8X@"1&: DejaVu Sans1&: DejaVu Sans1&: DejaVu Sans1&: DejaVu Sans1&: DejaVu Sans1h8:Cambria1&,8: DejaVu Sans1&8: DejaVu Sans1&8: DejaVu Sans1&: DejaVu Sans1&: DejaVu Sans1&<: DejaVu Sans1&>: DejaVu Sans1&?: DejaVu Sans1&4: DejaVu Sans1&4: DejaVu Sans1& : DejaVu Sans1& : DejaVu Sans1&: DejaVu Sans1&: DejaVu Sans1& : DejaVu Sans"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)                                                                     ff  `      + )  P  P               a>   , *   ||>q}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(} 00\);_(*}(}  00\);_(*}(}  00\);_(*}(}  00\);_(*}(}  00\);_(*}(}  00\);_(*}(} 00\);_(*}(} 00\);_(*}(}- 00\);_(*}(}. 00\);_(*}(}: 00\);_(*}(}; 00\);_(*}(}6 00\);_(*}-}7 00\);_(*}<}/ 00\);_(*_)?_);_(}<}0 00\);_(*?_)?_);_(}<}1 00\);_(*23_)?_);_(}(}2 00\);_(*}<}+ a00\);_(*_)?_);_(}<}5 00\);_(*_)?_);_(}<}3 e00\);_(*_)?_);_(}}, ??v00\);_(*̙_)?_);_(   }}9 ???00\);_(*_)?_);_(??? ??? ??? ???}}( }00\);_(*_)?_);_(   }<}* }00\);_(*_)?_);_(}}) 00\);_(*_)?_);_(??? ??? ??? ???}(}= 00\);_(*}}4 00\);_(*_)?_);_(   }(}< 00\);_(*}P}8 00\);_(*_)?_);_( }<}" 00\);_(*_)?_);_(}<} 00\);_(*ef_)?_);_(}<} 00\);_(*L_)?_);_(}<} 00\);_(*23_)?_);_(}<}# 00\);_(*_)?_);_(}<} 00\);_(*ef_)?_);_(}<} 00\);_(*L_)?_);_(}<} 00\);_(*23_)?_);_(}<}$ 00\);_(*_)?_);_(}<} 00\);_(*ef_)?_);_(}<} 00\);_(*L_)?_);_(}<} 00\);_(*23_)?_);_(}<}% 00\);_(*_)?_);_(}<} 00\);_(*ef_)?_);_(}<} 00\);_(*L_)?_);_(}<} 00\);_(*23_)?_);_(}<}& 00\);_(*_)?_);_(}<} 00\);_(*ef_)?_);_(}<} 00\);_(*L_)?_);_(}<}  00\);_(*23_)?_);_(}<}' 00\);_(* _)?_);_(}<} 00\);_(*ef _)?_);_(}<} 00\);_(*L _)?_);_(}<}! 00\);_(*23 _)?_);_( 20% - Accent1H 20% - Accent1 ef  20% - Accent2H" 20% - Accent2 ef  20% - Accent3H& 20% - Accent3 ef  20% - Accent4H* 20% - Accent4 ef  20% - Accent5H. 20% - Accent5 ef  20% - Accent6H2 20% - Accent6  ef  40% - Accent1H 40% - Accent1 L  40% - Accent2H# 40% - Accent2 L湸  40% - Accent3H' 40% - Accent3 L  40% - Accent4H+ 40% - Accent4 L  40% - Accent5H/ 40% - Accent5 L  40% - Accent6H3 40% - Accent6  Lմ  60% - Accent1H 60% - Accent1 23  60% - Accent2H$ 60% - Accent2 23ٗ  60% - Accent3H( 60% - Accent3 23֚  60% - Accent4H, 60% - Accent4 23  60% - Accent5H0 60% - Accent5 23 ! 60% - Accent6H4 60% - Accent6  23  "Accent1<Accent1 O  #Accent2<!Accent2 PM  $Accent3<%Accent3 Y  %Accent4<)Accent4 d  &Accent5<-Accent5 K  'Accent6<1Accent6  F ( Berekeningz Berekening  } ) Controlecel| Controlecel  ????????? ???*Gekoppelde celLGekoppelde cel } +Goed6Goed  a ,InvoerrInvoer ̙ ??v - Komma.( Komma [0] /Kop 1:Kop 1 I}O 0Kop 2:Kop 2 I}? 1Kop 3:Kop 3 I}23 2Kop 4,Kop 4 I} 3Neutraal>Neutraal  e 4Notitieh Notitie   5Ongeldig>Ongeldig  6$Procent4 Standaard  7Titel1Titel I}% 8TotaalJTotaal OO 9UitvoertUitvoer  ???????????? ???:"Valuta;* Valuta [0]<Verklarende tekstD5Verklarende tekst =WaarschuwingstekstF Waarschuwingstekst XTableStyleMedium9PivotStyleLight16` y-Blad1 /Blad2 1Blad3gD A1B2C3D4D1C2B3A4A3B4C1D2, ,4ccggBĘ7ɹq1  .//  dMbP?_*+%;&ffffff?'ffffff?(?)?";Ę7333333?333333?1&<3U;;;;     <>@ggD  0Q1  dMbP?_*+%;&ffffff?'ffffff?(?)?";333333?333333?&<3U;;;;     <>@ggD  23  dMbP?_*+%;&ffffff?'ffffff?(?)?";333333?333333?&<3U;;;;         <>@ggD Module1ThisWorkbook _VBA_PROJECTh dirC   !"#$%&'()*+,-./0123456789:;<=>?@ABDEFGHIJKMOPQRSUVWYZ[\^|xME(<<< <@0%@tGRx"Attribute VB_Name = "Module1" Z#xME (SLSS<N0{00020819-0000-0000-C000-000000000046}8(%HxAttribute VB_Name = "ThisWorkbook" Bas0{00020P819-0C$0046} |GlobalSpacFalse dCreatablPredeclaIdTru BExposeTemplateDerivBustomizD2a  *\G{000204EF-0000-0000-C000-000000000046}#4.0#9#C:\PROG~FBU\COMM~CP1\MICR~NEI\VBA\VBA6\VBE6.DLL#Visual Basic For Applications*\G{00020813-0000-0000-C000-000000000046}#1.6#0#C:\Program Files\Microsoft Office\Office12\EXCEL.EXE#Microsoft Excel 12.0 Object Library*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\windows\system32\stdole2.tlb#OLE Automation(*\G{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}#2.4#0#C:\Program Files\Common Files\Microsoft Shared\OFFICE12\MSO.DLL#Microsoft Office 12.0 Object Library tGRModule10652c047ccModule1ThisWorkbook015af84d84!ThisWorkbookZ %@ UCbD39*BoU*`Xu_>J%$>h&Excel+VBAWin16~Win32MacVBA6#Project1 stdole` VBAProjectOfficeuModule1b _Evaluate PasteValueRange  SelectionZCopyƿ ThisWorkbook|WorkbookkT!$0* pHd VBAProject4@j = r tGR J< rstdole>stdole h%^*\G{00020430-C 0046}#2.0#0#C:\windows\syst em32\e2.tlb#OLE Automation`EOffDicEOficEE2DF8D04C-5BFA-101B-BDE5EAAC42Egram Files\CommonMicrosoft Shared\OFFICE12\MSO.0DLL#M 1q Ob Li`braryK Modul`e1GdDu1 2E HB1pB,B!B+BqThisWorkbookG@T@sisW rkbo 2 $%b$Z"B#$Module1Module1ThisWorkbookThisWorkbookID="{58B0B1F8-B010-4070-8AC2-6A72FF08AF79}" Module=Module1 Document=ThisWorkbook/&H00000000 Name="VBAProject" HelpContextID=PROJECTwm LAPROJECTNYSummaryInformation( TDocumentSummaryInformation8X"0" VersionCompatible32="393222000" CMG="E6E435E9CD192F1D2F1D2F1D2F1D" DPB="44469747ABA4ACA4ACA4" GC="A2A0712DCE2ECE2E31" [Host Extender Info] &H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 Oh+'0@H`x H.Merijn BrandH.Merijn BrandMicrosoft Excel@'@3T՜.+,0 PXd lt|  Blad1Blad2Blad3  Werkbladen F%Microsoft Office Excel 2003-werkbladBiff8Excel.Sheet.89qCompObj]qSpreadsheet-Read-0.84/files/empty.txt0000644000031300001440000000000011275744326020264 0ustar00merijnusers00000000000000Spreadsheet-Read-0.84/files/macosx.csv0000644000031300001440000000164311123134730020372 0ustar00merijnusers00000000000000"'\'\\'\\\'""\""\\""\\\""",,,,,,,,,,,,,, Exported 12/16/2008 10:30 AM,,,,,,Category,Category name,,,,,Category name 2,, Username,Last Name,First Name M.,Section/Group,Status,Notes,Assignment,Category name 1,Category name 2,Category name 3,woot!,dqwdqwd,Category name 2 1,Total Score,Class Grade ,,,,,,Grading scale,Points,Points,Points,Points,Points,Points,, ,,,,,,Points possible,11,11,11,11,11,11,, dcwalker,,,,Dropped,,,1,34,1,,,,109, jdr99,,,devs,Active,"qwd qwd qwd",,12,0,1,,,,39, jlaney,,,devs,Active,,,,2,23,,,,114, mcrawfor,,,devs,Active,"line 1 line 2 line 3 XX fwe and so on yea!",,,,,,,,, ,,,,,,,,,,,,,, ,,,,,,Mean,6.5,12.0,8.33,#DIV/0!,#DIV/0!,#DIV/0!,87.33, ,,,,,,Median,6.5,2.0,1.0,#NUM!,#NUM!,#NUM!,109.0, ,,,,,,Mode,#N/A,#N/A,1.0,#N/A,#N/A,#N/A,#N/A, ,,,,,,Min,1.0,0.0,1.0,0.0,0.0,0.0,39.0, ,,,,,,Max,12.0,34.0,23.0,0.0,0.0,0.0,114.0, ,,,,,,Std. Dev.,7.78,19.08,12.7,#DIV/0!,#DIV/0!,#DIV/0!,41.93,Spreadsheet-Read-0.84/files/attr.xls0000644000031300001440000005700010452463445020077 0ustar00merijnusers00000000000000ࡱ> -, 0@\ppc09 Ba==xKB}(8X@"1Arial1Arial1Arial1Arial1 Arial1Arial1 Arial1 Arial1 Arial1 Arial1(Arial1Arial10Arial Unicode MS1* Letter Gothic1,LettrGoth12 BT1,Lucida Console16Lucida Sans Unicode1Arial10Arial Unicode MS1* Letter Gothic1,LettrGoth12 BT1,Lucida Console16Lucida Sans Unicode1Arial10Arial Unicode MS1* Letter Gothic1,LettrGoth12 BT1,Lucida Console16Lucida Sans Unicode1Arial10Arial Unicode MS1* Letter Gothic1,LettrGoth12 BT1,Lucida Console16Lucida Sans Unicode1Arial10Arial Unicode MS1* Letter Gothic1,LettrGoth12 BT1,Lucida Console16Lucida Sans Unicode1xArial10xArial Unicode MS1*x Letter Gothic1,xLettrGoth12 BT1,xLucida Console16xLucida Sans Unicode1hArial10hArial Unicode MS1*h Letter Gothic1,hLettrGoth12 BT1,hLucida Console16hLucida Sans Unicode7" "\ #,##0_-;" "\ #,##0\-A" "\ #,##0_-;[Red]" "\ #,##0\-C" "\ #,##0.00_-;" "\ #,##0.00\-M$" "\ #,##0.00_-;[Red]" "\ #,##0.00\-q*6_-" "\ * #,##0_-;_-" "\ * #,##0\-;_-" "\ * "-"_-;_-@_-,)'_-* #,##0_-;_-* #,##0\-;_-* "-"_-;_-@_-,>_-" "\ * #,##0.00_-;_-" "\ * #,##0.00\-;_-" "\ * "-"??_-;_-@_-4+/_-* #,##0.00_-;_-* #,##0.00\-;_-* "-"??_-;_-@_-#" "\ #,##0.00_-d/m h:mm 00.00.00.000**\ #,###,#00,000.00,**                + )  , *                      @  H  H  H  H   H   H   H   H  @  H  H  H  H   H   H   H   H  @  H  H  H  H   H   H   H   H  @  H  H  H  H   H   H   H   H  @  H  H  H  H   H   H   H   H  @  H  H  H  H   H   H   H   H  @(  H(  H(  H(  H(   H(   H(   H(   H(  @  H  H  H  H   H   H   H   H ! " #         0 1 2 3 $   4                                           !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /  0  1  2  3  4  5      ,               1         `xColourse)Formatz, Alignment i/Fonts`iLredgreenbluewhiteyellow lightgreen lightblueautograyleftmiddlerighttopbottomjustifyfillArialArial Unicode MS Letter GothicLettrGoth12 BTLucida ConsoleLucida Sans Unicodebolditalic bold italic underline6 point18 pointmergedunlockedhidden"  PR 0@  #)  dMbP?_*+%MxeroxS 4dXXA4PRIV0''''P4(/h " dXX??U             & / 8 A J S \   ' 0 9 B K T ]   ( 1 : C L U ^    ) 2 ; D M V _  ! * 3 < E N W `  " + 4 = F O X a  # , 5 > G P Y b  $ - 6 ? H Q Z c  % . 7 @ I R [ d"~~~~~~~~>@7 0@  !*,  dMbP?_*+%"??U}     ~ @~ @ ~ @ ~ @ ~ @~ @~ @~ @~ @~ @~ @~ @&>@ 7 0@ 6- /  dMbP?_*+%"??U}  @@@@@  e f g t h i j k u l m n o v  e f g t p q r s wPFFFF>@7 0@ 37  dMbP?_*+%MxeroxS 4dXXA4PRIV0''''P4(/h " dXX??U} } } I} m} }  } m$  }       }      x ~      y       z       {       |      :xbbbbbb>@  7 Oh+'0@HXh pc09fpc09fMicrosoft Excel@($F@*A@j՜.+,0 PXp x  PROCURA B.V.lig ColoursFormat AlignmentFonts  Werkbladen  !"#%&'()*+Root Entry FWorkbook7SummaryInformation(DocumentSummaryInformation8$Spreadsheet-Read-0.84/files/perc.ods0000644000031300001440000003474313701334513020037 0ustar00merijnusers00000000000000PK'bPl9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPK'bPConfigurations2/images/Bitmaps/PK'bPConfigurations2/accelerator/PK'bPConfigurations2/toolpanel/PK'bPConfigurations2/progressbar/PK'bPConfigurations2/statusbar/PK'bPConfigurations2/toolbar/PK'bPConfigurations2/floater/PK'bPConfigurations2/popupmenu/PK'bPConfigurations2/menubar/PK'bP manifest.rdf͓n0AoZ9)V _-u Sw]s<8[飼h'֒(ZHZ@E #Kw,qmqƎReMQ =v/sh<cCRG`E뷷qvZfLt'QO&1p*|4 d^OEVη[3yh@q{kX hHFNE$h8+ O B,dp5/n7 lYj0z睵U9>+ÙL؉6@>7j(Ꮉ@E6:AenJAڧ$SUTPix457͖|s(Z(jP~z܅j2J)aMEט5rFL*{C5m|?PKiQPK'bP styles.xml\mo8~PXE$7q- m`$-% 'GR.NDp8pp({x^Lm(Xk~O?!]> W oDˆ&u4hFsIf.Mʝ(ٽb,zZW./Ng4 sYIbAaH(ˤ]G 1Ru 0,2+KivVHo[.;9Oj|ȊP} b[Bpv"z++];ZS }@߾lb˚fD=ҷiB\oɵW};Nd)`ln)ZSAA?Aڻo@=vc5Qy$N<n/6BDټF )T ,2.nE68/qgo p3 R:|8/]c~[ Z&+ϧ$-CQ؛ s8Z sZmRXLmm᫦.x\ _(\!_2׬n;SQ35?D?WBmTR-% Z(*I9|7LL }T05bł/`E|пصwm$sʬtbS$/12P \!Y2ēKs-$]1u_]~X -92K^ YpagBs U43YUV*X(V _*UU=ʱi}q,^VGS+喼EtQN7tf!Q{Tʴ^eTWUcU+'^}[l, !% Fc5(x6uV$GUcFPheo+w}(=÷~\U0)8z)B213jTk@ q' Hw 8el=B{^֜yҾl4~(ˢɹm=̽:lЛm~ 51#Ԣ@81۽<ȌvL8[vHLJ@P3N ́N/؜f<- "(TN[pz!sDÓ9h'AnW38=[c{szpؕfkw S{{䰺ԬY.au9C[a*37c"wY㣣omgT';(!n oVeS sOh-nzgfCaqXwbzT7n`kLx{Lx?&nd®rzNE/bc'HގN6{gəqtO91{]DxiO@9=kB~N,x?*퉊gqؤ0tϸ'4P#@'ϐzX=kv|hkI02rCM;V'X=^— bZU' u7231ɤ!{ [7)J:ҀI!pӺ'\Bz#MaO #d8UZNe{<`3'7B߸$ddzEh-WL@ݭ:6dEW$16wkiޏOFG Ҩn~?/?~!Ʃ|v$蘘sn5`<0"F8 bFZ$ڌ g.ѡf qN2G>S4onSƌҎ#_Pf=J=qU`h&Yomē .lVǎ!aHA )GmG[V#mNcضoO }l\ق_^aqJ)Wl1GA|#^1S07XȪ"gCUd-%1+1-AN/"ݫ{MGA64%P|}⊛TgOy;]W*ƈ*J#V"Cz,DRǺk6v{RCn##a1Fmz ^,++k5jHDL)H T C Ϝtr)#Ei EKk)@դ%k5Y+qTM i~:B϶9/yr=(}a4"O/)ߊ:ATe;-gCú+ 5] o;hfINjPKǣHo 2YPK'bP content.xml\]o6}߯0+׵GJ]Ӎ*l{52 t;cދ0 `=NZBr<0rܠ.`: Ab`ZWͱ:y])J,U/c $ͅԕ7j缐ܺ(*E,Ѩdh_pʤ9f"vh lv7d6 !{DG`k;'Sm%T)xh.g~~CGYBɱ~ M\ap\[z"ZfHT CEQ{ˤ.ı(2j葺dZf֩YOv8tio 5Eޛ*W3QNUpR-ߦw~Ozcهς7`?޼nPvtEE n T=c[<8.\M荒!3qDWwv' }1U2 BQ9?TίlLK;#a~ƹPt\t mQB32Z9=`fk|L JsaXy6|nov\hHYl g k$u-@jLA@D9N(r=¯2c212߄Z؜ RA (H=x@8J9,9d?J"`\ԘRc<pVM#Jꔒ/fZ9pDvh`̉aΒ )QHslǼH?\?(n$1WGil! (wnnVɨI&v]$[We^;$Ybw Jm`>"-PL:~k|M'(R[-fC/ b\?{ufb q0Ml} fWp q[iGzlPy9`DPcsTFiamU6`bLɁMTZ-xUmYx H&;* MݩHg qg:k{OޏQ3V53KӟE{Q^Ծ/QԂޫDiX 򰿊pr%jC{΁n( #bbf y'3@Br14ѝy6c^[I%Q%+tKww,-RDXS(,H0 vjT?`\65K97pџETF 4<{"ʔQ9h!(AGڛ^Ͼ K \*Bc\XhF<~ܴp:: ^>S XO[QCPIBC~gn>Gܗ H=Z| qv.S :+߀<ˁYAeYB?D@,Ơb,F |R T^"0Ly ,jԷ'M8ҀXhQcKF Mm@ƠB/D*ը1H((BxA驱]4> Tخ>B?i|^izڀ(Q3Lox8gb?s_%#uC5:>gL>F#I ? ||ZHtO3*%}*W8t='GI5|= I 6= I*6= 'Dvtkϖ˛c</35[&iv_jtr^}u(wPKa|[EPK'bP settings.xmlZms8~"\Iq I7a/H2l$#3)-=^=zvW:d'+"qڧ-azxr9 ЏC!A)=D\>9b]$J|#inj,f?8K"L49;EhPD|h3V뼙]?Nulc_{]? 496nK-չ?_o+}B$<ifN@z{zJaX#WpQje}$,Σ[Uc@`%& W"1T` ku9d ol % nLe>NKIJ2 dlFDiоh_Cl i, 0_ֿy 'TxG.˳Nb-jY-e@<@@VxKPJm2A>b$e@Z?rt:` I4 @)봬Y*+ڝ_+]8ދg]QY~MWN[Smt%"o,˜mO_<@& bӛ shtcARC=I ofp3m$?QլGICiC7CV*&_=0!toEtk唡tǖnq'܇ Tx5~,eAoPKP6 PK'bPlWThumbnails/thumbnail.pngPNG  IHDRkPLTE:*!:::)1@<>A<@E>M^E5)C<9C@>XF9FDDGLTKRZTLGROR\SLZWYHUdW\gY_p^`^Yaj[dtbWMgZUq]Ip^Vg`Wab^m`Ulb[u`LqbUsdZui^xfVxf\~iT|k]ffhckwkr{vlexrlzvv\mambqdufxiulxkzk}u|mt{z~stu{}|z}~m]n`vf}x~lv|mryt{u{z}~œŤǨг÷ȹöӺȴӲصڹӻռܼߺŲǸûʾѽ­ȶιѽStIDATxPSǻٶ ȏ1T^Hj-pF+hR׵N^w+ݶ6PzE- A,ka41))Y7! p8HNl}ߙ 9ϛg83{ #4G߂cG0 Uy#|pQHQC'!5umqacԂJFa3Nz̗y&SUlsdlG֠:醵Yo4j )DPL܍ٱ.S6DT.?@Gs"kt[ZE^4^p zLd"鶬[wF͉5T -5E Z6b6#Q $#QQ/1zHB[@Q)0Tn,3'V5du7;UjyFZ5uү6VVdnUIFn陆6tsY5|QNOĨ?95+RHhe#m5qe&U M}IH5q39^];~S:HPy_Yil0g`uo//cs[YHԉ_kT%ʘe_qjzLљH=nV֝皢U3i=B݉V1z~L+d`>Bə\w tkV4cMM~-8 Т>b{r Ӣy!:lкvO-_=P#[(j7}' -;siaEeʭ?o{j^hUȭ; tk4-_a6UgqK*1J2 )vYV +AnJ{I4tsB9D9 Tẋ LCnڥaֱja |OQ+G\zJW=tDFOaOsVZT܎"&8ؗ"קɺz7|v^G֓"קʺpn& Kl0j_ZlQ[wT C{rmRkbb5ɯc G/L5kh/vEo>̙;+_oOȼʗ8۾s-LY,5q~PFʺBTZ1mnUU_qʺTbv9 2 ]5_F&>$5F-R TG7mIh=nAQlHf)l^˘bD},ʋT) sXa0 YjaySsMwO7*cR_Xp~sAd{Uv=Jr[ٽBA% Tu( PdK7 -ђq[~fo)fiJ6[bbc=0^r ~ @Ak-Bw̩}f[(IXB&VLPƜ3UCLomXgQշ Zs1d ]Y/ͣQ;UJ%[s-XdZ@,U휉\V\B?b?O̗EystYt}z1i3Х^2_xͼ|c{fӣ5okz@ƋN^fcvcԟw,}Qs8vU|X[_Y=#>BDּGo/T5Qo}vn!I|Q|GcfE/h?˿+> K };k2\}uIVC6j/jchWETs EBSU8qMa{v#>ED )B@o8{nrevL3ߖKC/Śe/Fɲji3O>Y^cQ Q1_r!ߝ@'be~iCf Jkd%jCYZsb=}s%A1ZzwHC̶k~~%Ţ=;O`WN|7rbO{4LXvmsUd_2r |w_+>*`DZTpBIhYK=^KȃykQD#/{"a_^ .y%o: 61_Hyf|\oX-ֺ̎7!|#=rM$S:u?j#ûw/1_6wЂj^VЪ)Kd?Ńc8F]ن||m-J gv|/|\U.1]:1B30vƏpsY%(h c73CEh/rUntOGlBQUYXoJcv됅ۼ/%(Kw~N2;Uzl|'E|K4z76$ewo|wo ޚ>%oO%Me^Qhn\ePȘV/?p|f~?!9\(k,XEDdWU^g1͕\֜QmT^"Mx}E!91bD}-| ڝ G r;ӹ2&@vMg~.3_T34EǕo;G0 0{JXo 0Aw٭XOmgdk<{1_+m;WpQu+ sɊW2GQ*d;^r_|ZLTɀ̒07Us-!aD},"g;A>C˜cg㳝g 6n\2*|OΜZi/H1{}wf*T'6|>_#Y;Y`UЗ3-L+ڀ̗|8|gjۯ}延AuϗNl뺩whRi/%ve%IocY*1mArKDQ?CQ|fmJ^ŗlݿc%X!%{M[xN:>)3q|G U$9HEt1SAo[U{*JlӸx3>@F1֭lokul'\Q2*Kvn|=QíK%Ҭ鳝 %[QSvm~[;;_WbLI7a̸C<+^"a>15ſCKlT>||q0H3ೝвsL?f( ̶ S_`f`|@ 3SD,l.]]o*fA/~K`{\)`cTh9LVE^d龎g6BDg|kWk‰RRxR]K~.1֠R>g5Uv)X2b6A*},=6_k)- Wl܏7KSa%_czloK7] cm9!fɃ|%JpZ҉Q{zX˞W{3&>vΖO&fY=Km&v _^pפW5D ;ck0V1ߠw1{ư3Y$pUk]{md515_{ FX櫶6@j2OأwW< g*ɓW~y` s35.mEBNeщ'56cRE?E|@s-;usoTyG>_6g!p!Y^$:h*/7sej㛚JxoAUb4+l?E }iü}cN}Fr;zy/k WK`JX滸TD> {曨7gG~"U馤Qn}g#|j=y|PCgDKDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQDEDQצmIENDB`PK'bPMETA-INF/manifest.xmlMn F9Ŷ2Bqfp`[q⪊K31Ի1Y {kV^[?n DrTa9*$Q$@[/Ǥl&.h4qc''R} Sh-7ƶ g1inW0A]&`suPthukhj:h vG|_At &|z4q7BKxOk3W"!vJL|8 e ye} 0HM!ӷ!阘rpbͼ0gt{M#}HL3_JZPK4PK2Nxl/sharedStrings.xml5j1 D Cn=xh!@bWֲk!8\5fy7 Lyr}CP#i#1T))xVd8y("Q9m@ OAee X-h [\8G{tKPRdrjbx?de8z0z:Miv*?IYuFOrooB=l}A.'ҮoGTPK`:IrPK2N xl/styles.xmlY]O0}߯B/4:MZ&4ʴ xppqώ4A{r:s4)"%ac߆3Mb4AJD9}8)L>XVG8F>O0S#!1+&VTbj5mcň0:lcOva(n&)a(6:ΗZj-NC]7lnLYKzU]YUBNR4I-*R#Kbl#Q NFz,D1s3jk!2,ٮF>hY'6爥㌯F:af@)cT>\1phg?'ѫPZ&4IXhuԻjd~4o4%@֨c.U @@Є3D/> M1,L~rPJXI[K&&rqs]h˧UY^XQKs_ܚHJ:r$Lc8\*cJ&,+gKˬNffA# *ɢ.*My!x&rLNdYb5FbXɔ4 r iN*T\V*_oLsGf '[;2;2;2;2;2O!:/eQ+6Zi։+w/Oue>I+'MSmz|X4\VWX@U\G/"YeWuTT۵Rl}^%ґbp}rۇ_=-6* 3=kpvp.ԩ:AS!0[Tr*&z abb!PKPVPK2NdocProps/custom.xmlMo0>E;PPT `4;,ޕ"d6mu3˾NK6oi8y+pREеlfa P W!\J.%U$0Bk1vE ZceefVr.kP%)'2x rPז6o|8iSI8<@^2G'i#AbȝYA/Zh7E0B  S!v=ȣWMiL Tt?^g'~s]MwnwMA\Aُ8ͳɪd*)0ӬE_8wf𠃟s+6<Śv&&X6?wϹ~ PKOW)PK2NdocProps/core.xml}Rn0 +ۤ0DHlB; iEvRam%/-&`.YPyEt̹T[]9P@ G1ZХyE.7gгFxb]Qmn^P849 Bf!=;#oǧlR1 3@7H1t@ &-z`ʺ-= 2\[/5-35û-OÐȀ}Jzvvi6il?7ѠO\l-X>W5PK$0EyPK2NdocProps/app.xmlM0+Jڤ)"iD]$(Reo%L5KAJ7 | W֔h3V*s.ѱH(D#xdotY]PH0D܂/.DZlb!Ll(VL yFLkx*O" kyF#lm4ik!~mW9&[eu1KZx7uZ>g  ~9m~'PK YgPK2N4 _rels/.relsPK2Nm'xl/sharedStrings.xmlPK2NOz%xl/_rels/workbook.xml.relsPK2Nzy5xl/worksheets/sheet1.xmlPK2N`:Irxl/workbook.xmlPK2NPV 9 xl/styles.xmlPK2NOW) docProps/custom.xmlPK2N$0Ey\docProps/core.xmlPK2N,3"docProps/app.xmlPK2N YgQ[Content_Types].xmlPK Spreadsheet-Read-0.84/files/test_x.txt0000644000031300001440000000005011275744471020442 0ustar00merijnusers00000000000000A1=B1==D1 A2=_B2_== A3==C3=D3 A4=B4=C4= Spreadsheet-Read-0.84/files/blank.xls0000644000031300001440000003400012536775410020212 0ustar00merijnusers00000000000000ࡱ;  Root Entry  \pCalc Ba==@ 8X@"1Arial1Arial1Arial1Arial GENERAL                + ) , *  `g$Sheet1TZR3  @@     @ ̪<@@FIXED_NUMBERy2pper`<Q<Q<Q<@`<Ѓpxƪ<dFormatskey3.LocaleDataP@Q<Q<Q<`U<U<U<U<U<`<`<@CurrencyFormatskey3 ` [$$-409]#,##0;[RED]-[$$-409]#,##0@@ENCY!@P@CurrencyFormatskey4p[$$-409]#,##0.00;[RED]-[$$-409]#,##0.00Q@ENCY0!@ОP@CurrencyFormatskey5`xƪ<0.00 CCCQ`xƪ<ENCY!@П@CurrencyFormatskey6p3  @@  axƪ< 3  @@  H0(   #,##0;-[$$-409]* #,##0 q xƪ<!!@P@CurrencyFormatskey8`[$$-409]* #,##0.00;-[$$-409]* #,##0.00`xƪ<@@DateFormatskey1xƪ<xƪ<!xƪ<`@DateFormatskey9/axƪ< YYYY`<!xƪ<Pxƪ<@@`DateFormatskey8pxƪ<A!xƪ<p@DateFormatskey7 xƪ<AP!xƪ<p@DateFormatskey10`<A xƪ<`<A!`xƪ<p@@DateFormatskey11 xƪ<A!xƪ<p@DateFormatskey16< xƪ<A`!xƪ<p@DateFormatskey121 xƪ<ormA!pxƪ<p@PDateFormatskey17<` xƪ<y6A! xƪ<p@DateFormatskey13@ xƪ<YAp!Ъxƪ<p@DateFormatskey2@! xƪ<A !xƪ<p@`DateFormatskey14qxƪ<YYYYp1xƪ<Pxƪ<@@PDateFormatskey15xƪ<YYYY@ ̪<@@FIXED_NUMBERy2pper`<Q<Q<Q<@`<Ѓpxƪ<dFormatskey3.LocaleDataP@Q<Q<Q<`U<U<U<U<U<`<`<@CurrencyFormatskey3 ` [$$-409]#,##0;[RED]-[$$-409]#,##0@@ENCY!@P@CurrencyFormatskey4p[$$-409]#,##0.00;[RED]-[$$-409]#,##0.00Q@ENCY0!@ОP@CurrencyFormatskey5`xƪ<0.00 CCCQ`xƪ<ENCY!@П@CurrencyFormatskey6p3  @@  axƪ< 3  @@  H0(   #,##0;-[$$-409]* #,##0 q xƪ<!!@P@CurrencyFormatskey8`[$$-409]* #,##0.00;-[$$-409]* #,##0.00`xƪ<@@DateFormatskey1xƪ<xƪ<!xƪ<`@DateFormatskey9/axƪ< YYYY`<!xƪ<Pxƪ<@@`DateFormatskey8pxƪ<A!xƪ<p@DateFormatskey7 xƪ<AP!xƪ<p@DateFormatskey10`<A xƪ<`<A!`xƪ<p@@DateFormatskey11 xƪ<A!xƪ<p@DateFormatskey16< xƪ<A`!xƪ<p@DateFormatskey121 xƪ<ormA!pxƪ<p@PDateFormatskey17<` xƪ<y6A! xƪ<p@DateFormatskey13@ xƪ<YAp!Ъxƪ<p@DateFormatskey2@! xƪ<A !xƪ<p@`DateFormatskey14qxƪ<YYYYp1xƪ<Pxƪ<@@PDateFormatskey15xƪ<YYYYcc   dMbP?_%,*+&ffffff?'ffffff?(?)?" d,, ` `? ` `?U} % PH0(  >@gg   FMicrosoft Excel 97-TabelleBiff8Oh+'0 px TuxH.Merijn Brand3@e@@l@-E՜.+,D՜.+,\Root EntryFWorkbook/&CompObjIOle SummaryInformation(DDocumentSummaryInformation8 tSpreadsheet-Read-0.84/files/perc.xls0000644000031300001440000003300011131150660020033 0ustar00merijnusers00000000000000ࡱ>  F\pH.Merijn Brand Ba==xUn78X@"1Arial1Arial1Arial1Arial1Arial "?"#,##0_);\("?"#,##0\)% "?"#,##0_);[Red]\("?"#,##0\)&!"?"#,##0.00_);\("?"#,##0.00\)+&"?"#,##0.00_);[Red]\("?"#,##0.00\)=*8_("?"* #,##0_);_("?"* \(#,##0\);_("?"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)E,@_("?"* #,##0.00_);_("?"* \(#,##0.00\);_("?"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_) "€"#,##0_);\("€"#,##0\)% "€"#,##0_);[Red]\("€"#,##0\)&!"€"#,##0.00_);\("€"#,##0.00\)+&"€"#,##0.00_);[Red]\("€"#,##0.00\)=8_("€"* #,##0_);_("€"* \(#,##0\);_("€"* "-"_);_(@_)E@_("€"* #,##0.00_);_("€"* \(#,##0.00\);_("€"* "-"??_);_(@_) 0.0% 0.000%                + )     A A  ` <Blad1Tcc F   dMbP?_*+%"??U} I      @@$@$@y@@@i@@@Y@??D@D@D@4@4@4@$@$@$@@@@@@@ ???~ D@ Mbp? Mbp?~ 4@ Mb`? Mb`?~ $@ MbP? MbP?~ @ -C6:? -C6:?~ @-C6*?-C6*?~ ?-C6?-C6?Mbp?h㈵?h㈵?Mb`?h㈵>h㈵>MbP?h㈵>h㈵>*bh22222266>@7  Oh+'0@HXp merijnH.Merijn BrandMicrosoft Excel@x2m@xp ՜.+,0 PXp x  PROCURA B.V.WoA Blad1  Worksheets Root Entry FWorkbookSummaryInformation(DocumentSummaryInformation8Spreadsheet-Read-0.84/files/attr.ods0000644000031300001440000004455310614353563020066 0ustar00merijnusers00000000000000PKp4l9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKp4Configurations2/PKp4 content.xml]r+TJ%-zXrڝ$v*UNeIHb"T$eY{U/. B3e[$xpp? b}Х.߾lLt>]rQw"ab4L{:MS'Y>q隄S3JdzćO'5>=zy#g"g }8M 9>ƜR_?5eva;@fawn,H@Rx`}eIiCDq,xYt"07;;]9ɲNGv3eυhJkp6ԇSJw 4s6 |z{66$w&wݕ8]UKg X 4?-{%Zx.'/'60N0-"Oe <.Y4K AcN^9ćw~qL_Hªg,}o5p*MS gBvڴ_ςo\sz?0G?JUU[k ozj{|iB@AqiR׷5)C}rx&Y"%%78D# iu˭g'|}~ZނS4`/#aUl wY̗R!LmåoO?hy ˱A]X\w6 e)52;2y Z;lFf'/눍J'qoNYn<6v`Sb|{0Yw~ 9ݖsևd8sn^Mܨ1s997iF3ϹKn:lt8sn֖s6+9sQ]3vЭVzqI2Iƚ̆ ˛t+'0O q&@7rܾY;AyMnдyMdoxq&7sMZrAruٖ.t2"#yqFl) ts/Tyux* : 'z'6ȚvI:~yg准&d,zM!@Yg9rYPe!QO0>fUq@QM|]=yqw뚆Qy۾Xޙ{o&> Ϲb$:W=R$%o*},Qnv`pג`&(-C"D&8)8h|n,!$r4rx+n$ˈn:>K +fW-s\+- dRY:^ph9 =e>aEX;)E7w҇ÛYw+IYOWZkw4 |b@44TE=D1\N{Cz((u:(*QtRI#v=(*n}(O4L?MNu3N:]Us Vg+>ZD'0-,$IQ ˴ʤːHQ,,C3EZReHJ8S!ɨzL2%Xb`+eZSeH/ yǽTh v1˴ڗXE=%X־tcjQO /sL }阫,SeK\,Ӣ,k_:`aYq1qqRX: kq'{p ]Caօ1.WX?UN1|&r#W^Mw(L}m|W>g]&py$ʅH6KF>3$> qЈ&rƋlmsbAש+ND;[p ԛcKVߍs?9.*Kz(Y: ᬜhF@̜ju.okgW"NWꊵHWRu:_e:%rsЏ'ʧujZ͚VX:62EaݬQe9#кu[enrBE'V C7 =-^ZEsmU|J{&A[t-߮u3F+F|b-)$.e[THM?MLztkd;O}@y%< -]V'@$~8DN # &SkdBnLOߞ~@!$(e^I›RTB!oJ?Iݼdk)y'7ն1Y!pqI.Ȟu>H: fc]{4yXȃynh5M˞{u9:4|'N72_/ezk:s&џi2aIoVa.=-%&4@=klоC68 dSF\`Y=Huocf4b'1{":R \ibןqP|`hf4"EDHnB7]17ni'p3BJx9o|F-rpb5+^Ed ,2h=PfXmaJ%&"$E" UXhh6+$,b!a1 mZHhwMr4EJ[e0.0p[8`#Xâp`1)  fÕQlXBB‚`a m [HhXBBEh ,T6Q* ,xaٰ7/,,~aa &wa$XlWX$Äa rh#XTÄ"&P!a它z`*YevHr GCA8B@p9$i#!!rDw@Z ]jBW0FЅ 1,MK`wK )t]*W9ݾTo累iY_Nf4-;}>`.AAmWbpOiS>ظ7c; l\t|ܶx%{(& |3 p`$x[xoko_}Ey1GM PK"PKp4 styles.xml][s~pݙRH.٤aĻ}$DaB>W/]DٴL6s'S!92T6vP.߾h3v^#.l> ѝ#5ERTc,0P8AhQ^љls!\lMmeKmB!`+ۘ2LXSikE-<T7 ]nx\v.RC"z&C dED@Aͫѣ+͈G{47pٽcG޽ctⓙ~*ſ@|ٱl *PDc$TkDO N-A)n~hLԙ9MU% !b6h{&V^$ P&#oݍB,U BXJT-\@V>v d&OR~9^c9@`%F1[5@EQ$տ=@l}}UA HqA~% a6%4ً{("jFO9OF@+$UѶҸg;ݷ&eI{xls`kTy{uOHlNasto,޶,I&54zNfCS3}خ F>`4ZnXlpj(]šsz;a^k@e06JAjkO T!8Y]eSվkzi}2M+oI4 /y2,G ]A. ,5aDŽ=i(Ӹx eE=͜Wu'WI9Jcuvպǡ/ pLmcஇzm?|aq,2t|b+~K\ahk%bU,2aj }'g^uιi̺'eN }1bvR!L/L~bqoʬ0b~#L]14? <ǔ$Xmr [-9[Sy@9EG0!ѕw+S3{0cJՒo#ydJag+9o}]ksoZ=]묹;Z;,m|ɵ2ʮZSH2$ B0r>0r>09j9=a20/`J[Ș&}zV:/)ae{ْq!{YK5NfjmdvP 0?;sНb=7-Awsi!kY]=K`YzG^-LKŠ*PsԲ ؖ}WKh妤{lBYM*5! BV l \s$D"EO5J#a+CFKeͅ4cZqS`q͘Ƅ^{jWQ2˜,&WM)bRx۵ϋIًPqϟZ3˼b߮U%+bM|Wzc %tQ,Re&&oE GV5w ,n>Dۙ~zsV7OVPKD aPKp4r7-(77meta.xml OpenOffice.org/2.0$Linux OpenOffice.org_project/680$Build-8825pc092006-07-04T10:45:04H.Merijn Brand2006-07-04T16:04:452006-07-04T16:01:26en-US2PT3M19SPKp4Thumbnails/thumbnail.png헇3C Q#",у艶X5Doj=z Dh,Q6Jz*o~3?μw3s9ߙ;Q'{޽{dT ;ѿKqkW vWJl_I3/]F"B<(NiCn /YRSՎ)ufeJ!&Tiލ (f~m19RPRI "/h~ƽO퍛-J;$B|{$K}u /o+'pxa|KmvwW(C&W.wR~ݤl%5=mnw8oUH1##r=hoW6h`EsE[`g.+ZF|Z6k{%bdNE TvhsC; 4A8돛λW `AlbW]+\Ȯtl%BZ4{yN^rgBY'G|,6?_{|nApyrW^@k̏1GА"j ֦ w@-5 L@~~zs/x5 LMCX"?QXyx,Y}!_?V~] 4C3:Bfo`ͦ:/_? VF`4 w_AP LbG~͉>F<.&UB;mJ! W5>ڑwk$-1Yi+8 em8xuo=־U˦h~>x> Tu[߫CxeO /vefs ᾨ gk+Fx_*ݳw=PpPS^sXw犆#h_p3 V _Dm:g&zh1AC -r™\XRF[ޱ:w:Cؼ\hKH hvt*Zm gh{;i<_|̽eI{ fՠEwcbxg,ݍPi QOHQ;Iţ+&&ȕzbD ħF,Jޏڮ@C$;$#0JRG.h@hw.vҡdzO:X$:,Ր+!HN%[~ޮ˞/JmJ$fbRJ}vKUգkj֋rm+eX!*w``B}[P6]X{YmU6WNfR/'&-G. ݀nIV7t՛wלpH ;<+ICRuS77]OY*[nYdcE(穴H(y\ZIْ,;J+O㴵f[Ue=n-dKuH̏/[vU%9 M> (S%zvȥ8Y|P{B`Mԩ"m+HAf/P'"(>ÂȂsR/Z:]q?zkPgKZyGHꆿIKʴ0z/=%~& wRd,MIzUL^90ֹ*Xv~=0`hXh~V3o͝lPڻJ7"CV191-pKG;+A`rT7@65YDLم2jZ1N Hk >^MAx4Q7gp̿߂L%Ŏ~nٟ5 ܑQ43kx[}#oZ' ٛVYD-$mS"l޳jca,ڬ!ef2c1_04MnqNBG8 \mb3J^[oIU>%eTwߚ-%}aIOq/L,is`\Ϣ=H}1s= p,_h_GKkp=mDk|k{~SbHb em6~p.d&KCˎ{ wD"kdJwe 8l1iߺCae}~B̈ENףyN珝'^Ŷ}} ;j[U)ZtY ;qʪZ9l*yՔF*`󰧏If~S 0(ާX\$yz ĊyWPYNcI]Lr`_^Sw^SoQOcΟ8+꾭.WU)&*vd;?LX:X@"siAZѽ-#X,{=f,*N AxVkfQ骒1R%CCI%w+򀑛F/ 3zZJ޸%Fۣop J1F/=&-e/qLԳд6A|HRBqVȒE8NDT.ۊnsSOOwW,|gM,0w'}tut4Xh҈ԁU7W@}xft^28Ci V3_ P |Gd+R'yHá+60HG \ K;iQǚӥ>Q8v)#pQ>&{Swe? _v}͢jY_68n5*l19iMq٬7NH^*W3)j<9p 1 _%OX/R'$_wp3jn9{7Wxz aaTvP*~R և )OncVuATEN]01@ rOJDd##|O0!|f{<yZij)Eܺvbkٲ÷*O~]eˠM9hF4KO%y\HZaoUkV=i[ڂ q1~l`@iJOuX¤ ?StjrG] (,ZҾ:TqZAxY|ȐonDԔoWWYKz(>s_]=,?roܦƻ-;Tw2K=[Y܍sXh 0>y>x2'N0訓tbahmu铻n| 5_=f8 %[A`@ek ݲU%6VJ>t̅չc6 O}W;$UmTldCSC&fH{!GqΘ2<'S+1[]S!":,M\x D/c vɇluu}ylV:^F֖42.CԷL*ӇKfԨg(LуIu#1,_[C~OC3^dl_I6rogCWwD 2f.%"ќ*0';&Գɮ}CŮ;%œG؂ '.f=-ՆzDFUgrAg`h²B?ݔ8{ s$88 IK71uJWyƵ+xcp;翧H1+,Lc;Σ jn> b |iK$ Ru\e{J(9C|yeY.sp,uiàx9/oC-±S=ʌJz[2pWW:ܲ7^ciٿF|9q>AtE>e3U^uSLd+XZ"wWp\\1oq{NRxDcˀd=KIR:PVv֢ qz qƤCO(0кbAi-\q(i_os-JԳu|́炩(1gӹc@ҰR.c!t)򟚽UtϾ'cF.4k󐔜x`2|`xF,Cr^#4Ac_0cEkJʬ\HٕԼzYZ"|".|O5HK0cP.uurTʕРNR!}opG$g#˅5kGCUsg@M1ǸqUVwiu})oV}ȍtITBާ\!%3`Gx{ I2cƆ\6^e{eOvhF$[w9.䣔GЌj<"fW_^~zwWqڤr>Πe|Q׃}-hD0Ic0Y9EXxbKϐ 3;GA7~Uڥ8CAIl(AFc)sTd,/:_wSh$r/cƎhq/xa݅NJVDEdNQջΟ[Ȍ &u,FY Iw\Ҝ zCWt${d9N}cO{7v}j ,RW&Ovϳz=I$EJbwNKݗl24īOgB,IU qPـ Fْ, [:[ZdA[w_]54<]O0DWY6lL;78OVlH1l+i?kfΤȴHejXHŔhl<-^@[`{'%w1VPfP55%g!~I[Ψ~ 9Ne%J]0y ૵h.rL{s 5 QͶGrmp{ m0&L+ޤ,i4'ⶺ373 iB/i2 Tj s9T30! HK&re_9ޓr.+'@Yl/$$xC.72:+qIw3R\1#`v9֨ J f8}PBBb`xM&, ]Pܝ%,8A J+2sq*0MgqH`;\)4y@ 1x/lx|;qNDVTF`\Qi\q11f7S}D԰VpU~$YIFCxU(ᚓǨ w)jqmLmd3G~~vQ~YeJSƙ>c`0/54ܛ̈K~X+B[$W?,f\73Q},zblɑ,e!-;5Pw% EJ'r~2TU+:0!Pm09W,o~gȜJVV&b! 7F) uY͎4Dt {#ɟV }d b3VXI$@J'bwgţvp&ښt"C{I{#>t=Q<Y9.\~%o)ˁ[:*JVaPK+\dPKp4 settings.xmlZ[SJ~?)J VEmdt2\ Td._wf#{S3zP9NNlH=<` "t*qpZgH`QQv@oGDsBaIzaѻj3'G{MY+B|(niuX~E@%x4GhJd}!|]5mռsFX` -;WJQ<.|%< bGKowꕣ)}LMZQ( aIh)$W5җ4@zZ)~AF .aKwֻn/#ga?3*+@r\Ʒ0rۻBOh\,;7l@7Y7cZšXeKl |dR2 +?ub)ΆAj9 3 gB3Ü?ro0¾L @r #u݋ɦ(ڼVO 3B,Vʾ1c@d 3h1 DOS]F #x@D@z1clX'@` k&w8Y9B<MXEa\VR= n]f]3S=чdLDH"L$$$7: ϊ3 & _$n ,O8Z3,sjQ )(eBgrzqCQ_yǍYܸi;H3Ua򐔇?#$NHBoIUǵXs3 \9oXHa)sa ؞^5O4 | 5+_ GMp謹YoZ9GC{4* rU[>lss}Yfpza]=ԯFJ9.g]"W0a+ʳf-*V{T߆~#A1lfH͹"les-DW785F& Њb&4QFO"L"Ig<3BAJ":8gV QR*S;y{X>WXcPK "y.")PKp4META-INF/manifest.xmln0wTY*! ,%g+>#x,m_;]۰-t: tbu=d4/gjZ@/j:c7Ƕ@۰b/Զ Rx;X J{X^PK&.PKp4l9..mimetypePKp4TConfigurations2/PKp4" content.xmlPKp4D a styles.xmlPKp4r7-(77)meta.xmlPKp4+\d"Thumbnails/thumbnail.pngPKp4 "y.") 0Asettings.xmlPKp4&.FMETA-INF/manifest.xmlPKwGSpreadsheet-Read-0.84/files/empty.sxc0000644000031300001440000000000010313232324020220 0ustar00merijnusers00000000000000Spreadsheet-Read-0.84/files/test_t.csv0000644000031300001440000000005010614363313020376 0ustar00merijnusers00000000000000A1 B1 D1 A2 B2 A3 'C3' D3 A4 B4 C4 Spreadsheet-Read-0.84/files/macosx.xls0000644000031300001440000002000010313232324020367 0ustar00merijnusers00000000000000ࡱ>   R F+%Tk WorkbookSummaryInformation(DocumentSummaryInformation8  K(\p Abe Timmerman Ba===480@"1Verdana1Verdana1Verdana1Verdana1Verdana1 Verdana1$Verdana"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)                + ) , *     ` Sheet1Sheet2Sheet3ail#ly+x眿 )\m\mz`Upt0, `C+)`t0+*R@J~)D`+/`` `Chigo])h~)DD$"+0<x2`xDy uBH- \@yĿ0P]+&ܿP#lllzy&8^\#^H6lnzy&8^\zy&8^\^p͘lsqxDrpuBHy+x眿 t0]&$yy+$`y&@p<luBHCy+pt0\,RCrc[`},;@$luBHTy+hPM- lh0$$pt0xD]Zy uBH'uBHz`P@y+ (KKpK͘lt0 K͘ K(  #  dMbP?_*+%"??U HBCn` A<#ЅC @ C   0  DCE<@  , ~ ?~ ?~ @~ @~ @~ @~ @~ @~ @~ @~ @~ @~ @~ @~  @~  @~ "@~ "@~ $@~ $@~ &@~ &@~ (@~ (@~ *@~ *@~ ,@~ ,@~ .@~ .@~ 0@~ 0@~ 1@~ 1@~ 2@~ 3@~ 4@~ 5@~ 6@~ 7@~ 8@~ 9@6@>@ K( B  dMbP?_*+%"??U >@ K( ?  dMbP?_*+%"??U >@   Oh+'08@Xp 'Abe TimmermanxAbe TimmermanxMicrosoft Excel@Ck ՜.+,0 PXh px 'ztreeth Sheet1Sheet2Sheet3  Worksheets FMicrosoft Excel Worksheet8FIBExcel.Sheet.8CompObj XSpreadsheet-Read-0.84/files/content.xml0000644000031300001440000001063410313232324020555 0ustar00merijnusers00000000000000 A1B1D1A2B2A3C3D3A4B4C4xxxNote 1xxxNote 2Note 2Note 2Note 3Note 3xxSpreadsheet-Read-0.84/files/merged.xlsx0000644000031300001440000002017012474016202020545 0ustar00merijnusers00000000000000PK!ȣ4v[Content_Types].xml (Tn0W?DVCUU]-LT b4T4DÌqDl ?t4*f;+@{졗Fio{SmAg`2k? Ly&`Cwvݙ|^zv*uJw}\Y%ACB$qskMmQ6-<+ց_ݥ㸋G|g6 PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK!>xl/_rels/workbook.xml.rels (J0nӮ""Ej}Lm2㟾ۅef2k&WP%&w ޚ[= &$W4KH"xR㣔dNҨ9ɨAw(7ey/O ނhm| }Dg"$4FY.2#59鳔Y]bd @%s"ݚ0tB)[ȓPK!BE T,xl/workbook.xmlN0H;MT:*@8lMcձ#!۳NH'{vo=( IMf1%K#>2{[P<ׂ+ 8.noVcN1Z{.ȕ54L ; (1r.\ qG T,є]ڏ {|eh} (Q'!=F(M k7T7K0QZ÷{JTS~c:O<BD{ I1UA _3"j/ G|-@~`q̰=(.}.%n0**K\Iy0Ьjm_/N,}W:=RY}H9EbAwk}m PK!iRVxl/theme/theme1.xmlYMoE#F{oc'vGuر[HF[x=ޝfvg53NjHH q Jĥ@wfv;&%!>Ǽ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK!&^ xl/styles.xmlTK0]%)]b{YX IKKU08;{*e{曑vU!jrq\vu>r"(޾"F9oBIJQo#O$5"A)qxUad-fCgvC=EVzCVMO7 \LXmuH*G$6fwHPd- Y>-Us3%06 b,Xd$t2QEto{ޒ 5ށ!Q2f)14_ bG_diH7) 6ao`YjE65ãѵ*pSY~ʔWF]& 1:N^31ߋ-c`is~!6٥[]gG_aZGЛM{yq|);iG״PPK!/7 xl/worksheets/sheet1.xmlTMo W@ܻxֲڊCc66&(@rrH|QC)+14)'JC;9@JwI;X Iik3e =73`H-u-nuÌ+_wlEY@CCֵ(塇 ߴB%;Pt3eY 85|J 6ww.Op9t7 I|=V|Ӥ:]hZٕgY@ sT<b(F&ׯXX^PgaoS2c4xEOvH-ofof<.b *!;Kv?ņ0̈́>÷q6po+׍ FhvEV*Kke?Z:ak)Aǻ{PDqz'LS KI@W(nV{*χMYPK!90x'xl/printerSettings/printerSettings1.bin`(`0c`0a0```8|3:/I At#='s132a`fd`ddm‘dMcBf v``H[23!ÉI`s" PK!;ssMmdocProps/core.xml (|QK0C{sNB[Hh$ߛ[L|Lι_ι$u}u29 AQIe9z^/9ύee Gph^\^dfhW@2:G;k;%a>\|-ks=-0":"-;J`4j@ZC:R;5II#uUiw%LXྲ}MaIK*l|@.gsG`wU@F!뫜zILҘ52B k _cӖdF(2|AoPK!:fdocProps/app.xml (n0 `@V+zذI3+ӉPY$Hmqɟ90e|%RMUa{wUJ1}ISb.JRlBYiBj8M; EOrQ_$}u|3㲣|q{ շ5@J˚rhq0蔜6h^.jcኍu.為G臶V-;4RBϐǩDɂ'd]̔g5z%a,wz>4pp ,\"n-9̿5$zx>%F;WNEXBYx~Z6iECšpuσL7Y>/?/f%a姚篬PK-!ȣ4v[Content_Types].xmlPK-!U0#L _rels/.relsPK-!>pxl/_rels/workbook.xml.relsPK-!BE T,xl/workbook.xmlPK-!^% xl/sharedStrings.xmlPK-!;m2KB# xl/worksheets/_rels/sheet1.xml.relsPK-!iRV xl/theme/theme1.xmlPK-!&^ xl/styles.xmlPK-!/7 xl/worksheets/sheet1.xmlPK-!90x'<xl/printerSettings/printerSettings1.binPK-!;ssMmdocProps/core.xmlPK-!:f}docProps/app.xmlPK &<Spreadsheet-Read-0.84/files/misc_ws.xls0000644000031300001440000001400011761614021020552 0ustar00merijnusers00000000000000ࡱ;   Root Entry  !"#$%'*+,.  \pCalc Ba==@ 8X@"1Arial1Arial1Arial1Arial GENERAL                + ) , *  ` misc E foo11Tjb( 3  @@   1 n cc   dMbP?_%*+&?'?('}'}?)'}'}?" d,, ` `? ` `?U PH0(  >@gg   dMbP?_%*+&?'?('}'}?)'}'}?" d,, ` `? ` `?UPH 0(  >@gg   dMbP?_%*+&?'?('}'}?)'}'}?" d,, ` `? ` `?U~ PH0 0(   >@gg  FMicrosoft Excel 97-TabelleBiff8Oh+'0HPp Microsoft CorporationMax Maischein1@@@&\iܻ@>՜.+,D՜.+,\Root EntryF Workbookk CompObj&IOle (SummaryInformation()DocumentSummaryInformation8-tSpreadsheet-Read-0.84/files/test_t.txt0000644000031300001440000000005011275744454020437 0ustar00merijnusers00000000000000A1 B1 D1 A2 B2 A3 'C3' D3 A4 B4 C4 Spreadsheet-Read-0.84/files/test.gnumeric0000644000031300001440000000355613223172672021114 0ustar00merijnusers00000000000000ZO6Y&7&myA)T*iĴI9__I>6mZ@B|wO/a=aFk8O~NQh}qA&QbT_q[sk!fkQl?}=}IHE+Nh|={+%EXNĶsK&aޫhvLI׮ $ݏ6J@0[0lCY'BT*Y&P[ ~dEe 8 c4 O(HJA-;4px,X\7S &0H qh8 AM$><á=Ș,'ԩȢ(!DXܳh*k[@d9q[Vm9^,Z;$mHv+-C u:/5ZvR3̯ٔX ߳|N6;A8to=g~>i糹1,6C2pbv5rE:Gr(uQtc-;..HuDY">-qY!$ي7)ĉl0 3- { =/ʶ~<'c9uM@DXWʛbq HgÚp+Ĩp/\RFUCz]w5ӄd 3l`f'o"t&H)Q_}xגvqajk[dK`8[ "lM["Q** 9 2 / >o3d*c@$"OTAk5c#;Ю=Y_(!u[ K(g\(xudrH# n!Ý\$Wv{v\HD%;*KdSGgx)#$S9R6;H }}#0 HNƗSҞڳܽ;qk]P.w85Q<9 3ӏؗ9K)P ?׏*@AB$8q1-$U 8 ]CwLGxLp G@˕x`mV<.\[/COr"]|N[Qu{Gz-(@M6XÖ NSm{bffnlf 'v2kbc5֫,JqkT\^zpEȴ<+TEґ!b"Ɔ> {oss= }̷={{oq>[^цd8wFc{rZRMɯ'蕦\shסQn<{M}$Uи JK)x)]zaʩ}rK™*8 zYߔm/j~=0EKM33j6hӌ6hӌ6hӌ6fJfYm";i"w[B`6?F iې47! inHsC#ͥE1_ 4;h-|,Spreadsheet-Read-0.84/files/values.xlsx0000644000031300001440000001655611130422501020605 0ustar00merijnusers00000000000000PK!zғb[Content_Types].xml (TN0#(q!ԴG|7UǶ=VJ${24.[CB|)Hdu0/Jߊ Iy\P-M//&oRDNJ54 *FJ/ht#urj1t5Ug08Is\0*Fg"V.aCUY &U\Evբ d* W;Qaz8]g >~PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK!>xl/_rels/workbook.xml.rels (J0nӮ""Ej}Lm2㟾ۅef2k&WP%&w ޚ[= &$W4KH"xR㣔dNҨ9ɨAw(7ey/O ނhm| }Dg"$4FY.2#59鳔Y]bd @%s"ݚ0tB)[ȓPK!]kHxl/workbook.xmlQN0#itSJ zA=xXiI8l':/`:) alZ֞AB"_T MJ4TSk\ 1h%q<4-KY-& DWoJ0(b_&Lq (2Qi[pMki<(7*JfIovV$QWQa du)!%- g*dWqG#G^Nq1;u>n-)q{w㫂t_LE=/PK!UU_xl/sharedStrings.xmldJC1EfoB$)"/L̤ؿ7-%.{gk?)V,l7(9/>?AxZ|̄ȰwwYT[XENkWL7 wKT ~'| Psn$^@5 džoΈ{-苺?gVzBpjpۈ p#T?ےƮ->Ӌ%ΐ ?ggɬӲQ>mzs̄bXoA'kA'Vt@'NjZl n͜OnxM=v9KzmjkoPK!iRVxl/theme/theme1.xmlYMoE#F{oc'vGuر[HF[x=ޝfvg53NjHH q Jĥ@wfv;&%!>Ǽ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK!3xl/worksheets/sheet1.xmlSn0#ﬓnUm$T$ҿgoCB9pͼfήyeMUʴ9|wřGij?7ɺG #s![!|A/`i%յd=Zd#z [?iT{[=`08ɿyՊs&ݖk.lT~Pp3Cy *Yh`cHDe;:Q# I_q_O#C]./&{Ȝ=1 9 NR E,4{,LI:cs,]b_w1WnGIi= r7Y cxmSp;>,Xb9YbwsrEM^&,6g>tQUg<7vgU ҵx!$,xA;#NcM .; CR?!M{w%)^b7A\=>,7mU۸ ^b}P*~= 5dyPnnXv9GMZPK-!zғb[Content_Types].xmlPK-!U0#L o_rels/.relsPK-!>[xl/_rels/workbook.xml.relsPK-!]kHxl/workbook.xmlPK-!UU_ xl/sharedStrings.xmlPK-!{  xl/styles.xmlPK-!iRV xl/theme/theme1.xmlPK-!3xl/worksheets/sheet1.xmlPK-!4GVdocProps/core.xmlPK-!H뤖 docProps/app.xmlPK Spreadsheet-Read-0.84/files/Active2.xlsx0000644000031300001440000002053513111550441020601 0ustar00merijnusers00000000000000PK!q9+p[Content_Types].xml (̔MN0H!%nj?Kؓƪc[g PTDQ4f|[d9g#NiCz*a|v~6}y-欌pJ`t6i5lDV,D"5<qFz,m k "RrkBKPN+Zjqg[ 2Y+wBMLDq}̨iKǡ]?wVoέNMUB}%-iփ@\J=IB̺iޛ1"o^AAGc,ER'?_rM?;67PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK! (xl/_rels/workbook.xml.rels (j0 }qne:A[&Q6'o?C@.$}?ЧjU%)Z(8>< ֶҝ`@CqNsD$%襤`)qm.cuy rxl/workbook.xmlRn0W?X< E$Hʥ!7±#!$%U=yY/WJ+Jh0)k.!ÜLj njsk}$HlBKټىAaЦbSslmq[Jz^ńCIM $$s(ߖ4]Bv؈~c>KJ$ <3Lu ? ׍]7#'0Pe)PF ׾NEYCgV@kɺwBq&t1ä;;]Џѵ P:9Y 2J7˻یCރdǼ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK![3(xl/worksheets/sheet2.xmlN0EH=I -EUB@Bn2I,OqF`ig7N;p^$J[`mɗ盳+)<)[*2^.ӓt7$lEV;|RkqwTCϓ2nrpU `тRYXH82,6SiU(J6@-\c)ኾ*Lٛ ;nz+(Rq n΢lqHý`Kx"ߩ`d1Q nXe,,˧i~̌`xΎ5#xyW86۩@LͥpC}LL-a{~W$Y!! ?e|7PK!#Pxl/worksheets/sheet3.xmlN0H;qR$ZZr7$p#-69"q1q4'waXo.1`UBJ'SU8'm{+@< m z1 .6@57s#[O?t)y ě6M؟ƊssgU7I/Eo)wB:x;X}ta@pේfh@hm{mmOFD)/gqtZ~ PK!2 Hbxl/worksheets/sheet1.xmlMO0&w)lV7=޻0@!mwWSȢQH:3}f}ihvcGA nn9NB6!`*HNhp:hڹ.5؁JBS Eh|T9l0?@#okY% )_GfE3Bv{_x,Rm/ٰJyh @U#זrNf#AIoO/h'ה%̯zDi^N1#8(;48);ip1q84dOTJ[@I338ԟv}v*| ZDte_PK!a&8NmdocProps/core.xml (|QK0C{[UB[Hh$ߛ[L|Lι_ι$]2cU3D#ТJo3\Xǵe!Ch_^a6hS`OҖ&C;;C{qS;4[pcBpK8a3)ňl>MPBYL#Le蕉RNǸS8Vƶmv)~]?WbORfeJR Ǵi`^[$e^XsohLϗZ}Yķ߬I!Nɩn5Y:RQm 8\qneTP`S֪eB*c[28 YXm< A^I6͡z}o>`aqkaެ!_o;|b +*#JÔ7Uh## /1n=^ຩ6{HXKC=CV{;O?~_ƟBaMN=%/PK-!q9+p[Content_Types].xmlPK-!U0#L |_rels/.relsPK-! (hxl/_rels/workbook.xml.relsPK-!t>rxl/workbook.xmlPK-!iRVI xl/theme/theme1.xmlPK-![3(xl/worksheets/sheet2.xmlPK-!#Pxl/worksheets/sheet3.xmlPK-!zxl/sharedStrings.xmlPK-!KV xl/styles.xmlPK-!2 HbTxl/worksheets/sheet1.xmlPK-!a&8NmdocProps/core.xmlPK-!9ДDqdocProps/app.xmlPK ;Spreadsheet-Read-0.84/files/test.xls0000644000031300001440000002000010313232324020054 0ustar00merijnusers00000000000000ࡱ;   Root Entry  !"#$%&'()*+,-./0123456789:;<=>?ADEFGH  \pH.Merijn Brand Ba=@=Z?N*8X"1Arial1Arial1Arial1Arial1Arial#,##0\ "$";\-#,##0\ "$"!#,##0\ "$";[Red]\-#,##0\ "$""#,##0.00\ "$";\-#,##0.00\ "$"'"#,##0.00\ "$";[Red]\-#,##0.00\ "$";*6_-* #,##0\ "$"_-;\-* #,##0\ "$"_-;_-* "-"\ "$"_-;_-@_-8)3_-* #,##0\ _$_-;\-* #,##0\ _$_-;_-* "-"\ _$_-;_-@_-C,>_-* #,##0.00\ "$"_-;\-* #,##0.00\ "$"_-;_-* "-"??\ "$"_-;_-@_-@+;_-* #,##0.00\ _$_-;\-* #,##0.00\ _$_-;_-* "-"??\ _$_-;_-@_- GENERAL                + ) , *   83ffff̙̙3f3fff3f3f33333f33333`Sheet1G Second SheetbZ 3  @@  _A1B1D1A2B2A3C3D3A4B4C4xxxxxxxx 0   dMbP?*+_%$!&C&"Times New Roman,Regular"&12&A)&&C&"Times New Roman,Regular"&12Page &P&333333?'333333?(333333?)333333?"d,,>>?>>?U}             PH0(  >@   dMbP?*+_%$!&C&"Times New Roman,Regular"&12&A)&&C&"Times New Roman,Regular"&12Page &P&333333?'333333?(333333?)333333?"d,,>>?>>?U}          (  x  6XPP? i&] <Note 1<xx  6XPP? i&] <Note 2 Note 2 Note 2<xx  6XPP? i&] <Note 3 Note 3<HMBHMBHMB>@  FMicrosoft Excel 97-TabelleBiff8Oh+'0  p x 4@1@0:@xV@GVH.Merijn BrandH.Merijn BrandRoot EntryF0Pd@WorkbookCompObj@IOle B_SX_DB_CURSummaryInformation(CPSpreadsheet-Read-0.84/files/misc.xls0000644000031300001440000003300010614376235020052 0ustar00merijnusers00000000000000ࡱ>  1@\ppc09 Ba==x$8X@"1Arial1Arial1Arial1Arial7" "\ #,##0_-;" "\ #,##0\-A" "\ #,##0_-;[Red]" "\ #,##0\-C" "\ #,##0.00_-;" "\ #,##0.00\-M$" "\ #,##0.00_-;[Red]" "\ #,##0.00\-q*6_-" "\ * #,##0_-;_-" "\ * #,##0\-;_-" "\ * "-"_-;_-@_-,)'_-* #,##0_-;_-* #,##0\-;_-* "-"_-;_-@_-,>_-" "\ * #,##0.00_-;_-" "\ * #,##0.00\-;_-" "\ * "-"??_-;_-@_-4+/_-* #,##0.00_-;_-* #,##0.00\-;_-* "-"??_-;_-@_-"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)72_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).)_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)61_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)"F"\ #,##0_-;"F"\ #,##0\-#"F"\ #,##0_-;[Red]"F"\ #,##0\-$"F"\ #,##0.00_-;"F"\ #,##0.00\-)$"F"\ #,##0.00_-;[Red]"F"\ #,##0.00\-;6_-"F"\ * #,##0_-;_-"F"\ * #,##0\-;_-"F"\ * "-"_-;_-@_-C>_-"F"\ * #,##0.00_-;_-"F"\ * #,##0.00\-;_-"F"\ * "-"??_-;_-@_-                + )    ` * misc a  h foo8 1@   dMbP?_*+%"??U~ ?">@7 1@   dMbP?_*+%"??U>@7 1@ $ ^  dMbP?_*+%"??U~ @">@7 Oh+'0@Hhx Microsoft Corporationpc09Microsoft Excel@&\iܻ@ш՜.+,0 PXd lt| " misc foo  Werkbladen Root Entry FWorkbookSummaryInformation(DocumentSummaryInformation8Spreadsheet-Read-0.84/files/test_m.csv0000644000031300001440000000005010614362642020373 0ustar00merijnusers00000000000000A1;B1;;D1 A2;B2;; A3;;"C3";D3 A4;B4;C4; Spreadsheet-Read-0.84/files/test.ods0000644000031300001440000001562510327656236020075 0ustar00merijnusers00000000000000PKyTZ3l9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKyTZ3Configurations2/PKyTZ3 Pictures/PKyTZ3 content.xmlZo6_!xhYv^{+hJ@R~GRi[r$"H}xw zfg# >D |ff˭HF,)׈g\w>(% qS5d& kY[6-nW`de c} 'Fe(x6Z0\d(*ihä,*&!ͨ1h56`}x/QVwE<:BCR,{׆wO$esӎ܄v v/TD1ڗB4wA*t=$|-҃p3D\mA\GSM@q Xŝ{ )̾F+Ln.*l 4O`BQLIr>$VZRQU4k|β|.Q0M8d ܕX{'e]`?g #k ɪ[̤9J7Jz?9Or+AVOsCC5*픆y9Ԓ>Ԍ %ZRИ5V5M/^s7ǀ{XRJ_ '`H8C%nf5+2g"ʟJ\Ġ)H/G$.RF_Ͼ7fSop hfAx+!^)ű:}G LYx)Zep!DbbPMicp#- UkRhm!=>JqS81{DMQ6YCq 2IVa}:Z%jPᑱ l^\`٥Cp TAZvD&ҩ*Ev^ Lf4*eJpl>0%-zS2JSi}V~$]̣R;]&T[FfR\pVyQPvQqza8WFF7kpۼoez{t@lh^ݑI3F:mRuSG;c)n .i)zq&^MwQ ܡȅd\^y[5l}JE KL[\ynUB'v稜 CFn6€kUC-&*qk8+n @& ]΀_:6~_U߆7Լ ~|N^4ʮa uUj&C _.nc2#Xi!޿ φCI/ƣ5hy4/ *EqpGiO⣀]o,8woqjG*i~{*Gaۮ&+17Y ?I|izflmDZ~^PKR5_ PKyTZ3 styles.xmlYn6S*PdI&n`0"-춠%J&JII/<{=I,n+It~ȹ-B~|gk_ :9I*i]b((3klő$rPJ+^a*qe%\uj+|*klOm{6v&~]U4yBEqK JU0ق"///CN5, 1ڙ E+47>rljB]1"v5ٵae{uuK9_P Kc{TTi]}ι U+j]FO}'{Axz":y9F2 ][I{G8pJerekˉ=9Z/J`TzcwZ|I*._u|TDD_~x::%`koo.^rSKw37myFI&fX(X'q`V8umQMZn4/H1~ ?JyКJI`S*$P!PjEpΫ #R!8*˃nC5Qs5*` 3#Hy͔-}xDlXkE1pX[:X׭۱l;̘NH+tKgÒ#{ y* Sp` шMg#QnU=q YYJ1pWn8m9QӅvdExfw?Ӽued]}fOջ)_az|i_+]_kKO*w@XFvDžzv6l<+9/7d8Ӻ%U{8UӼC(I[{\ x -FrJ ȞdzpESbcRla:=ZrbO~T^~H~ĜhBHLk[\Nn[Wi20/GT{Z'P~0SP{e*!u{}V)r, (m1k S%\!- ӛ7qD'B"G؀Y5cK9"oygËc,l>w'vkiFѬңx\?_ŀРQ͡F>M'9r:* }ox8aD3b$ X8y >nREo8c^8P$ ф ܟ8"DLgE*ُE|*n,kɣ4ߎƊjdoM/pjJ$ yьP[:5Euj'WC۪-[pr}}} IuQu]#17Zj7z+̓ڎI!z !xoqIbbSX"v!逇#0E -Ρg~GB6`>^W zzo%]yK./@+J/?PK#}LUPKyTZ30W+  meta.xml OpenOffice.org/2.0$Linux OpenOffice.org_project/680m3$Build-8968H.Merijn Brand2005-05-12T13:31:18H.Merijn Brand2005-05-12T13:36:16en-US4PT4M58SPKyTZ3Thumbnails/thumbnail.png sb``p @ H1}e`` tq C"~߶UEUs>[Pm7??4}/._{IjqG{{>7||jkz[վ^[|=WM6|]=oo\{m^/mYԗ?-sδ~?=1(kmۮ;{ZxR{{/YW֫v&oe^+N=z͍S JN<-;A8˪p ӓ7/eĄy6\};Ykvx_v~i~Gmjy3v2eO^lx!01xsJhPKg3xPKyTZ3 settings.xmlZr8}߯`L&S S \Kxmk%$cG0xpق`]iK"_>. ㈒t*H"2QVJZ뚾"V\>$C!^ $7JHxp*4d3vteE1""QGs&ŒUfC+J~KE)IOHYizQLwKSݬkЏצnMQ$ee`sՔm l Ee)DD(U+ȧ8e`Do+rW3gp4j.`ݔ\0J5,}4eSzP> !u(GBQ%GehI`$ ӛQvC&s,󘾵# M@&˳ lY6foPkTxKNJ)#~R> I@N HV*wuWYMFڔac4UgϕS['#ӨzOg_ hd>0W?)|R Qs?2gDű c:Ŕ1OPI,kڗ\ĤQ WG!Y#s(0"myA.$= ,^-X)IuZ~O\eirgs"[g{<¯q(kʃwhP9]*U&58Rc2bgpi,$Q0:} )mkM) G/qi! ?C`mjڤ\ry''bW*gRϷCW&oH1 <"-H6qXE몡 DqOՎՆN~PKЃ99PKyTZ3l9..mimetypePKyTZ3TConfigurations2/PKyTZ3 Pictures/PKyTZ3R5_ content.xmlPKyTZ3#}LU styles.xmlPKyTZ30W+  3 meta.xmlPKyTZ3g3xeThumbnails/thumbnail.pngPKyTZ3 ϭ #settings.xmlPKyTZ3Ѓ99META-INF/manifest.xmlPK jSpreadsheet-Read-0.84/files/misc.ods0000644000031300001440000002023213701055232020023 0ustar00merijnusers00000000000000PKZPl9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKZPConfigurations2/images/Bitmaps/PKZPConfigurations2/accelerator/PKZPConfigurations2/toolpanel/PKZPConfigurations2/progressbar/PKZPConfigurations2/statusbar/PKZPConfigurations2/toolbar/PKZPConfigurations2/floater/PKZPConfigurations2/popupmenu/PKZPConfigurations2/menubar/PKZP manifest.rdf͓n08~D#g5jֈ*ZNu j,A_ゟKխP HH Øؓ5gb ~wjEƔmaobX_ |q]y;JX$&&э.mԦֆYGOUlZp:\D1NfxBs׸N/<8qtoi<QY+wܬjO4mj$n>B8UΗgc|޲ul&Orr%CNoBc6Bdn0R((zdwT?Cy{k6LsvKEt:t1UAqE}ܗL65VSA3 K1no&>QrwPKږ LPKZP styles.xml\Y8~_a(AZՇv0{dwI#d[dH@-Riqq**߿3NhYW6‘C]_>Og.u!k:G|3̡ %cɢEYBg™GYYL ;A[ cZ]+|o#fq+ITcӼ1)u `7++,CQe+?/ c@)e!.CR$/]5-:=^ X ̵͕VCe!hXCBafa&a A up"X㫛0, |R#t<: P/T`hf"2EFIee=6%ʅ5/ɥ R|>Y5GS1ңD*%>@We8KƠ~m[̊g3,k-^'Aܑz@f w?iUF]jw*5妫jP(5ǻƉ!8\lQo䋟@q1vv#r(]@}y&|zb㡀 m8J{H#ޟv޴c _bG䜤x&9ѣnѝ?jQ-!Û =;ٻy:: .(.Rnr+|G۞IIO"q7_g1{J)1bzWL)_ǢԖ̋ !$ā]_׼ s ~+#k+3ܶݚl`{ھ~'~|@뿀6;- lT󇬗#W/.z^D> <`դsJ+4`ƍ8 ;z31_w*9V:"v H+< |@x#dB)qƣ"eE\%Z ѥԶ~uy5ITm9>d*mK>=T|KJeǑ@IPӣWt(p qZWCĢm+:(ge?!k-$f/fppzv Ömb!EH(`jm ۓff6W} 2|5t)*vCKkaj9[Bfɒye-M|w9zH]yF6sEi b!^-Roީ7V| ؃fZkr.Aߎ`t*rt V1.0^7ɛ+kujYMCS !C ϐtN $#)#Ż" uG46(yꦜRVCzHlc`T2oy@#_ZG>; 3iw:%"e;m.gC˺2%,N{{ޘ5'ԠUңQuT>'iKzP+5TDU@UhҗH ;n 1 TRMN̚kRҤ|R0CJp\>† gJ96u4 5T 8(S0͙JQUVQ$5NĢsU^tUjSl/՘ٗvS}Our0$j$]Muܜ^Y^$V`_;+ ɾ󼭃dz਷*Vkĉ*2^ЁԢ7q9ybNK'H7),ү0]*\:"9oN߿;Fɟ6S|X|r#ѽA3ے0hϻ.u{7-$xG pY?ǡ[w1Q E H;m VH.L.ٱauTq)5?Bzy k^]C:QLGOb#(~.'x9ZYI=kp}n2wס#^PKPKZP settings.xmlZs6~_HB pCK7a/H2+ېI|vE~ҷjk"gV .avW @E'Yӹ:TO"Tv9@vE~Zn,,a?X+nYxqbhv:Ft?F؉fe#~_Ulb/Lsavؿ~z.O*"v#a7V>[ʚz#tΠ/з)WV-ȻǰPfZeA7۝ч@L//;E딻7- %hw"B8rSJJ%[4M9#)7D1AIvJtt!m#\){5_o(}J2Qp~ "Z}} WAӌ=Gd@S"7w1F|b0Ò8HpߔQ" ' QaLNI%y"8ZR N*g4w \|M !4AƋڑ3I2%9 totFV[;.C-ނ|@PnF޷ƽPK ׫Z,PKZPLThumbnails/thumbnail.pngPNG  IHDR PLTE~OJIDATx1 Om N 1zIENDB`PKZPMETA-INF/manifest.xmlMn F9Ŷ2Bqfp`[q⪊K31Ի1Y {kV^[?n DrTa9*$Q$@[/Ǥl&.h4qc''R} Sh-7ƶ g1inW0A]&`suPthukhj:h vG|_At &|z4q7BKxOkT b4T4DÌqDl ?t4*f;+@{졗Fio{SmAg`2k? Ly&`Cwvݙ|^zv*uJw}\Y%ACB$qskMmQ6-<+ց_ݥ㸋G|g6 PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK!>xl/_rels/workbook.xml.rels (J0nӮ""Ej}Lm2㟾ۅef2k&WP%&w ޚ[= &$W4KH"xR㣔dNҨ9ɨAw(7ey/O ނhm| }Dg"$4FY.2#59鳔Y]bd @%s"ݚ0tB)[ȓPK!bLGxl/workbook.xmlQN0#ijJT5 ġgoi@qڧ3U Fb`+#>{yȁ9ϵh,j0ỉv4w(rU-w3ӡIml="A8^D-K SײXT}AU][}VwYH9f? wOT4?"-X^ɛɯtasb/qpƒR 3@^|A)|C8ygSY$"Aچ{ܑ:'RRb" ÊԌ!,c7PK!%xl/sharedStrings.xmltj0 yF(KiSm`b51$r)}1(קɮ}?8rLT(@SԔmV(`|KuBVk`2K\VdXiuyrHc%cynҘH 4*L'rtV)`35jqVi+ejm.OE @𾽶h(+aVUS}欇*5Ã:˫"?~PK!;m2KB#xl/worksheets/_rels/sheet1.xml.rels0ECx{օ CS7"Ubۗ{ep6<f,Ժch{-A8 -Iy0Ьjm_/N,}W:=RY}H9EbAwk}m PK!iRVxl/theme/theme1.xmlYMoE#F{oc'vGuر[HF[x=ޝfvg53NjHH q Jĥ@wfv;&%!>Ǽ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK!z7 xl/styles.xmlWK0#,47J"E7vZ#?6]!7<<'K)3*FLr5O%F%KU:{*JcR|EU`Tt|)̣4 IGHpZNPkeS|ڼB .O:.RmzO(Ӿo<i4 y֗=NK,K YR="ؓ" |vǩ 9h6+ʖyr^A$䉂 m6:w $ĽȒXˌU ١ _U~ݎsCV#yY2ӆؤf ë, ou ϙVKPNZh#TY3!QE'a7:]!0q]݅EˢQГՈ#Rb3f&@v:GAeԠs%$.\d3E m#8m8df[|=Ͷp9_˞i?j@=\ru8vT9?"4@/uv0v^%)֖V; 8#uZӭġt%=I⅗a8\2mQ?;MnmUຓ;$6%f5m;\˶g\F]7( cWFy-UA[v|Z{wU7 PK!s 2xl/worksheets/sheet1.xmlU]o0}`}$H "@>Lm}vXM6ݯߵE/s?]^ Q)B(/D&ſ~}HiKNSF>ZjJ5\ֺ[*j5TBDPnIJJm( %ca!'*VЕ(-!W5Ζ%BV)/ U:F<=ІcOB<=LQYH v4MyV Ά=rKd9sKx?+^]Bu1CcP\}7O1ǗI:HA8/5;S(gS| `-oxw媲-[*ĖÎRg1[ڂxrWCԬ^ ]k@E.xEM9Ȇ~#røB @&%pҕ{7Т3IhH# WB@C|`Ax :m)Ԓ0 BYu,h>I4*L/mpwV m#uinPK!" 'xl/printerSettings/printerSettings1.binUrDm'[*ȑ#7NPN6˖z-$/,U9ڌ5(ĜA/8rH*8`4_tRX)s A}G䏇^>?G)Sxup㫃C|?: ^xû&Q<ό/@>:{a-xc:uSz/?}ryI6vT'st;޻GgE59nRoOgU}}LCt4 sn%%( ART:9<"Q8N% |[\η2@qr*kÚd-7 j*S(D3t2lF\}#Mz1lXapebRt-h>^XkXam*LFa2)8OUfjJGJ.3Ah@mUHmH2E[@@+Xe 7%2\r+ _U[C/¼-!nJLS&+_kXQd 4F1}DB`#9҃,J˄ n 3ٰ*L#zg&b)miW ,=[.K6n((]7K)xCCCNSknI6R굏`Z,G#Ck/hmhPZq|!Նo*&2Ev 7k8,/7UzxyOjg%fn%|Xa}xU,5뾗Ɠh o SplC"QEQ$X;w]>9FI3Ԝ(K-yZaF窢NY[ٔ3ȷ3fgf\/(׼{/I9Z*X?v%n' ?,0tRtP YԿؖ,{=N:,%6HAlF+x2PνZkc05b`|l6ċ908@Xawã]]q{˾\I?};_>w(GX1/xHs Y<*}e^o؀IPK-!ȣ4v[Content_Types].xmlPK-!U0#L _rels/.relsPK-!>pxl/_rels/workbook.xml.relsPK-!bLGxl/workbook.xmlPK-!% xl/sharedStrings.xmlPK-!;m2KB#? xl/worksheets/_rels/sheet1.xml.relsPK-!iRVA xl/theme/theme1.xmlPK-!z7 xl/styles.xmlPK-!s 2#xl/worksheets/sheet1.xmlPK-!" 'fxl/printerSettings/printerSettings1.binPK-! O`docProps/core.xmlPK-!S`E docProps/app.xmlPK &#Spreadsheet-Read-0.84/files/attr.xlsx0000644000031300001440000003274412565655372020310 0ustar00merijnusers00000000000000PK!sA[Content_Types].xml (Un0W?DV@8ql`X$](}7ᡶ ^%gfgǛ,hm͜6vkADHjU8 X~*<`Ļ-"'RbC0v,P*0^e35me,U6c8!YRޓHY[z_PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK![axl/_rels/workbook.xml.rels (j0E}-IR"gS ٶ{ d4ӇM1f{}vxGG5 (&Ec*{ Hˮjnz^Ő;MIi]ٗΏBFi}{翵mY69>C,uGًjW!+-dybaZ;,^i:kK„&:%$ l!Zaa9%?%Rl%&LuZO cȾPK!Y|{xl/workbook.xmlRMo0 Or-„(h_h\C҈4¿ Sb%幒 2:Ĕ5ѯLjݼH@ٌճ(y ]JMp8Dv 3]"W7(בy!$l;EpﳤD2޸p3:P+aWxJM! HAyWv+'#[i!9Pr)%mw%]ġtG܉l3~Vġ$*h}R7yרgH 5}*QЉG?IqP^CkmXizqQCdN#,$ g[|PK!rK xl/worksheets/sheet4.xml[o:+?X[FT >Tz}v3XLɴןmQҗۋٽS葶u Zg(tDGӲ$w߽I9iO-<3\pTx 8DOAӏu߅)=tW?D`T"rڼ@%T*0jśe\ײP*0j]z@mQ-+% _RZDճ OMBZ~A|x]CklAY&.ѐt?;▩{`Ε؄bS!P!(aTZAAr1BKJ5t7V&tTPh>sAo;^-XAE6hhj dXdCQAEȰYi|FFk^Y(VPB,tP,*(UQC3>nO|ysjcf^CF,(VP*%2r`)$?J[54Sĩ5QrVdICF,(VPDAȁ4dR ?jhp'ODy4ط46+(NP <́ 44́ o~LSMtjXN)Hc ki&R 6?bڃ[ zП"V1U.ۿGҞYݡо1Q;tÍ $=4z > Fi~A ihs-#h Ֆ~Y \`P%FPK!,B#xl/worksheets/_rels/sheet4.xml.relsj0D{$;P%_J!&E^ۢJh%؄Bc0]Yc" n@!4D,|>X< ~IлKZ9fVBlaopqSFdLeRcLOhvM7ܝS 0N\8ƀ)Hτ%`9H=U˄bAGw swPK!;m2KB#xl/worksheets/_rels/sheet1.xml.rels0ECx{օ CS7"Ubۗ{ep6<f,Ժch{-A8 -Iy0Ьjm_/N,}W:=RY}H9EbAwk}m PK! Wxl/worksheets/sheet2.xmlVMo0 t_;I$E}r,ԖG3(wܗމ;˃gޢ .h>SNE%C׸G{:k5o7v>hcn&°~4E-M ׈ FqcFTk%Ϳa!5xq aTIvYp pk$(L٩[K PK!Zxl/worksheets/sheet3.xmlQo0';X~_mJTMh{TM`3$xV)}h sk۠%<,Ĉ\W)s#/H#8M.)9E֔* \V[k9R% ^*]OI1M0Û%c?!ʒt+}K2"=me:` )V8Ȓ!oFyFȳ/z[$mh%ЦI1 g4%w`G-ɾQ?+eU`PR.?jZbHtdpx8R.hGEG B#- "uy8B8Vs}K-3ٵNSdcSfkDS0\L^GÐ:L]caS֖7nIq,7nxœ1xqW>[L0q0=l-[fRЫKOZZs-:2`6̇8KǓT^8M[ b; X|p峰ȟk6ۖ/J}5Xl` y2# D6M,Z5΄0О'ߧg[gy^z+d}i>Eq@Zj՛ 8FWNd?*<\>ٯp<#Dl"AK9q$EFKrD⅄xK!| Ir$OH$#$\In&6{YiVyfIG$O<;G3!iyFr$-H$)D,YjVcSfG$lJ:Z#g$CHZIH3R"hYdլ{¡I<#tZDhyF2$>-H$)<#% ] d%YLϳ g$AHP8<# g$E<#g$GH"Z؇Yh=AwMOV:؉*Qs3_Z tߘMhՍ?{(}y== E)4/U?T_ktŢSZá9}yv lhUM}mm:E2;yPK!;;Bxl/sharedStrings.xmlln0 Ⱥqfv.kl%ғey) ztG4៳/Lk^h4;e>BOmR,D ΄kg0{0CfX5 is$IuW_"l.ڀ]+mkF@99;L(<|ȭIJ-yћc,%gSUxюE-}Q~G+aZP-W?X&k?IR Sۋl(|kblɩRE*R3#_չ?[r^)}r]& _ϳ#6iyl+%Qݫjy*zPK!aXL xl/styles.xmlĜnF a,'$75@R€A#- )}>UgZ.c$7 gػ]" ټjFiĉ8o.El~'KOFmeeIHeX3m܅Az2u3;V;}XW^Jm8= ۣMk]bAؑ9xA8}i9B(7鼰Ly純ͱ7>X75dnf)mس2yNb6%f71AUKXrŒ(K{JmO5*WW[Lf &<YV,d`20Lfޠ4yU`2̼&3o`2̼&3o0o*xL\_d½y3̼&3o0o*xLfI7d½y3̼&3oPQ 0yLf7d­]&3o`2F7d 0yLf7d­]&3oT  7d 0yLf7d­]&3ozU`2̼&3o`2̼&3ofuN_={ј]Na$S81$+UO\k$H,=ۭ-E1J¶OOġ' jb/O|8Mip84a{@U_#͂DYM=2sj ɪː3EqalBJ_SM\;LeTIuTGuqT!Тp`yB:t&4-ZHh#F:t@6mHh#F:NA:Ht A:t@E]UGMs({cӛ])%* OJ4T7IyCGr mvTir4U^t_0$}Y-m>^8KGł<\)U1uGȗW!r5J\ЫNҔz7ֶj6dngf!F/;rpzlVmYlW){Hk6Q8blϽqcn; & 7۟BZDom16PK!iRVxl/theme/theme1.xmlYMoE#F{oc'vGuر[HF[x=ޝfvg53NjHH q Jĥ@wfv;&%!>Ǽ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK!\ҍ'xl/printerSettings/printerSettings1.bin`He(bg` 00a8a G $u^w m1ɬ 632{oמͷBu\/c',@)O}oPK!^qdocProps/app.xml (n0( b(1rh#陡V6$ȵ`KIP,>UݙdZ' }2춫$ (L)5 ~akoxTaBNnAiGEHmSY_ ?P[UJ“ Y}pF0%w37 E`Ζi%ƿ?6 dn^xe)41WB`* H> w<IE''JXXtv=] qr<;՜ϻXLۀ$SĭB Z 7c⎡q ɇ1'Mk鮬I/N _eSFP#> a]SmC7lDƷX iŷ}]l_J @:HK3YzZÓVH&mmFl&pu+n] p !!c\9w@ŀlPBLteʅUY{#c۶AV?os?/UTPaB{ם>[4$4IیL32}x<:Ͷ0ĝVrUlݓ? P\c:a䓱OX4 а_Ki~PK4<^PKPFxl/_rels/workbook.xml.relsMk0 FIc8AQ6ֵ~.[ eГH4C vV͢h%؀I/Z8Y.b;]JNɺQ/IӜS[n+Psc _{0 r3Rb+/2m=?"#ʯR6w _fz o ۭP~$E|PKOz%PKPFxl/sharedStrings.xml5A 0ὧS]H.OI޸px{ټHд`m~yah`_/ k<ƭy}>\@+v`Sm=d d|lWY+){b`] [0>'Qe3@thGJYsų*|ſz+b&y>Z #>S*jPp&zr~OO'iyb* ſ-:Xopnx++:0Oax^M`%}7mr‹xb6zMpyطӷc5 : .$ mv z&XEv $Uo8z!8p[ (zEㅾy;Wώ,Mga80ÙO=2ޚ8_Z,nY4ʦw$NRWo:o1O[[jbNr,ڈvyjlrUTHCP4;3{-F~kvV6EEsmX. r(=ZPؗN>D*TuM3>&8c[);[(eZ$ٙ)b2Oy2NPK+ܺ?PKPF xl/styles.xmlN0GR Li02M"Mv&NbؑBsi68sǶ-KL)|HdD> F.,j =Ņ1IAKdEɤ*=])JRm+ 8 ŢKQ"€VB8cp2+߮n`/ ;! 3z$ O$ |>qV.p6W̊)_9yT.0mǫLb [?y[vBVD Ornǣ!}:} Nb*g5ݾj%p hoĎ9) VTE 6x<18$ %CAC& J^܇|}Z^lݠݶ:KAPgroPQt _VT>o w:dkNJ2o<3N4lW-a˰,5El_턿._#`,; |PKWPKPF[Content_Types].xmlK0+JҦ "v]$]-E)2pֵxY>b>TmʸQ-Ý>㝕^Eŵ Jj ,o.yLbV=1l0>j!_:EKP!tVɍ3hc 567x@HqNj`% 4`qlNgM#Cc}3Q9"%:;j PyH:2p/.hzDÿ!ZʺR}PKb4WPKPFf; _rels/.relsPKPFAqhdocProps/app.xmlPKPF4<^:docProps/core.xmlPKPFOz%xl/_rels/workbook.xml.relsPKPF}xl/sharedStrings.xmlPKPF+ܺ?xl/worksheets/sheet1.xmlPKPFT| I xl/styles.xmlPKPFW9 xl/workbook.xmlPKPFb4W[Content_Types].xmlPK ?Spreadsheet-Read-0.84/files/test.txt0000644000031300001440000000010211275744145020107 0ustar00merijnusers00000000000000A1,B1,,D1 A2,B2,, A3,,C3,D3 A4,B4,C4, ,,,,,,,,,,,,,,,,,,LASTFIELD Spreadsheet-Read-0.84/files/perc.xlsx0000644000031300001440000001710611130422501020227 0ustar00merijnusers00000000000000PK!~N[Content_Types].xml (N0EH-ݲ@5(`Ic/y="JEU6"k9s=mchcX8aYSur1@w|6,v Qu;)Q MW~R&Wj z4:T 56W<+O>rd!5cAzwUJjUs kj0Q=y^Sb90eP[DШ+qK6'LAڄG;=[^ٰPh{J @܀IB.vkD{4@ Cg>0PK!U0#L _rels/.rels (N0 HCnHLH!T$$@Jc?[iTb/Nú(A3b{jxVb"giaWl_xb#b4O r0Qahѓeܔ=P-<4Mox/}bN@;vCf ۨBI"c&\O8q"KH<ߊs@.h<⧄MdaT_PK!p-xl/_rels/workbook.xml.rels (j0E}=v ٔB!Ėf_@H6s$mw?NNCY_U} At;|N* TܢbS`NB~ #Z{Q"%ec~<X~'I֊/5Ao>jj34fl&ƋVPK!< ; xl/styles.xmlTM0Fvnwe[0ڲ*[#Їw${m'eB/Ɍ4<͌ȭF8$q]&tFSͨ4x?od{}Wnc:1VQm,̅$%6InB"ӽ*w6P|ƛ ?`4}1 jI6IäȔ_d "sБJHBTF1MbiPr& Au{nu K Ƹ+ѭCJ EVˠkǣ" !{oe7 &hk4`pEVs)wa;:5T"9%/IIvJУ9^G)Z:kW Y9腱:SsL Ċp|Vɴ#פ@ѫ2njX?V>k, c yo %X\t ae⭧B"+zoPK!iRVxl/theme/theme1.xmlYMoE#F{oc'vGuر[HF[x=ޝfvg53NjHH q Jĥ@wfv;&%!>Ǽ3zA/DҐi;I1f<%`FdpmwM O&nRʊ a<#)p`"Z | |Z$JqloO&4$4Kl{ $JꅐfMr]*΅"g:¬1?*@ K/A|+x3'bj mo>9]N0>\52E4*֕0z^g8 TKgQ<+ uw֬5\|ڂέNlXd67 o.nwů/WZ o@1ZϹ g7 orP1Zl Eɰ)RLpyHP%M+oR(0$CA30Ĝ߫߾zz᳓?̏U}ӏPBs^|gO^|<UCnct8՜(1uO 3C\=|XLHލ9puUpF~bZ`|ũ4Y$nL5tU(CB<ݣ |=:z]2#'D7hqlP;ٻ:!G. 3C7^S!NX7}Jf"zRA#8ꍉ>}C})=9"wa7IhWCHQ[!ӥK7;4rT'~3:ЩϚ1Ѝmm`&_I8ՂwO}onjv`fLNO@)͠,aaQ3")MY _" \}@U%}aV.˒LFUԕU{DŐꦛmNW(CNޜm^S4 |l1<gW{Ow(UV^o9Z۱,^mA-r ?Q2bXoC~  d%;x 'hYY棓vR)gks:\qN-^s;kK] =]4)N2&0懭oO|twSI&aI`=DCPK!a~ xl/worksheets/sheet1.xmln0+,g$ݍQ{Q)]PSpvӷgսHx fyV 6ՊEHRͫxvMIx公Ċ-[<̈́PV͔oM3Qv!kQM6&,( /nYCvy*dZJ"(,[^nsH#v+znvCҠZD[%zgR/(%["E D $ @Y/h![㯅.EULe99%%3Ve.ŗQLɳhc)I_[%˧.Jbz#VkݞSa0\ PvEӆbyyp:j]90hgsz5wCFG6j ;.=ZZAs`pO7{VU٪û.N5b#ue՞7˻97&=oTgpt DYoc˰(Qv ,ݳExl D[̱m:.{A6|s/OgnIuNp 746+vSFbВk{o/9{Cs Kqm{bzgNp+C'faYyCfv:oy =*m{pBlst>k@x9%9 n~dhWнVu[N'?cvw3֬gNp٫`Vy NVJOo u%Yuj_yϫb^Cഈ7JڬɳT0 fl,T ڣyHx﫧\eEOzb&?PK!2'CXdocProps/core.xml (AK0ߡަYv-$o[ICMY;1=R>:$Eh w%zE3-Xj(ZU7lkz . $(7%{o(ƎA1mkhw0vizx&gf"R i>l3Ѐ& ?YV?/ YRI4a-؜'`uI 0j,u+*X <+kqs.`=@Dߝ^*\)Ӭ&% gg{N/$dIs2#~/T_PK!H뤖docProps/app.xml (Mo0  k90 M7Aѳ*ӉPY$HGp=M'%Eq}llBLƻeയۗlue JvĮ/b}RF.'}Fʎ*BJ6~m!wGWAu hM+;ۜKq5Z!R1:k~5XEAtkЯIOS’elς mLLRhAY2ils=NZrHX]ې |lUNpj>NcM .; CR?!M{w%)^b7A\=>,7mU۸ ^b}P*~= 5dyPnnXv9GMZPK-!~N[Content_Types].xmlPK-!U0#L ^_rels/.relsPK-!p-Jxl/_rels/workbook.xml.relsPK-!R'Fjxl/workbook.xmlPK-!< ; xl/styles.xmlPK-!iRV! xl/theme/theme1.xmlPK-!a~ xl/worksheets/sheet1.xmlPK-!2'CXdocProps/core.xmlPK-!H뤖&docProps/app.xmlPK >Spreadsheet-Read-0.84/files/empty.xlsx0000644000031300001440000000000011130415007020420 0ustar00merijnusers00000000000000Spreadsheet-Read-0.84/files/Dates.ods0000644000031300001440000003222713701055455020146 0ustar00merijnusers00000000000000PKZPl9..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKZPConfigurations2/images/Bitmaps/PKZPConfigurations2/accelerator/PKZPConfigurations2/toolpanel/PKZPConfigurations2/progressbar/PKZPConfigurations2/statusbar/PKZPConfigurations2/toolbar/PKZPConfigurations2/floater/PKZPConfigurations2/popupmenu/PKZPConfigurations2/menubar/PKZP manifest.rdf͓n0_ 켉f}6.JV^ӱw,ʐV> F`jc|4挴`ϢGN6tG5 -HUm(0/>Ix+3P`\ +X%Lʺɢ:@64Itp\`B`'6ϟ#Ci҉bw5Wdw9UGz|-oi}N'`ظSYBhHM-J?޽77Q̶Te/@6TqyEν3_ĨWpo7Qw8?MPKWPKZP styles.xml\ko8PY;I\Lg4X0%s+EqDemME^^{xyH"߿A6]_O~{yȁ3;FTO:ɀYL`:$ad&3p Yf&Mӝ$mAi<3j5\ӟ)|F.MBW)mӼ11HxI!: 7,1%5; @3BE⫖eØ!.˚\Z˖b`džG:cA].\j[Պ I.B T^}m-k:"7j%I{ sRZBY"6CL4ӂcE ,{x$| ,( K\!%̾>ku: s-LWǦF>!RX^hȚ HQy4 { Q$(g\#0EE-:gI[۪l듙{|@j- 3Xܡz(d1%s^>X,]QE<xOUUЪ֔_>j q(]ӽ` ߾?=qd1e Mx>u; }rt{a// GGSq( ߣLBq)w9V HP7EЅll삵ya#lraZ z ¯A)g PໃpPv1-X%Ij5:Aђ2Rh>v@a6#ܡ uw2ľD{<샣٨V!X-iGaR?sWvLۃ{17fko sNauf#[_&$U˸}d=POULBj]Fuv #!8(!nSPPlVe@ZsOڗ-H󛕿u/F;Iu;BNp . DŽwb»L7XN.ivUɵLα03LN=N4=N.3'Ɂ8sqzke^\#4{X"z:H*F*6#Ϸm^ѡY#@^َ^i L:ǥA+"9z?Xc)2=υ1fJ^ #a@( ?j:ܗ (6Vޞhqo(XV&ϸ&=}ך-?v!jtVCP7A%= Ot(''N !b=CNoh)[ŨP\6A1+.<͓#܄.NNl?S=f91 ^mmTS|ncLK#„e_P__l\2(a+k'svݚl{vf6u?b w-(3p]8E+G*<ʲe׊"; ;x31O7q$>F4؈0a+@/Dٰk#:[5XI' ?a#eDtˏ,%]F g6/c0vwҝKwUi޶1#\RRȩ@ɈO N%E@u=& $u&YLN{!g/H[qY2ݭC*!mXȐ8Q,l= :l4mYa6:5l41jad|=ȍμKZcZZP7+$,=h|#EK(`1G׬ yoV`67sգN Nڔ8h5 jcaJ]{j~d:"fly;f+Цq* հ^9  !o1OݐA*UY(Ua M'm7,=ZjNd0u&|L,)XvVy(U)8.0T+53GvU QYla_HhngÔj>$ aY7ljNL2N&0 bO u4R:s#ɐ=/U`[XB$mS!wOTek]f^Ċ)CJ.'IQ^ kR}kp~A\Cc}aFhK۞hqs~N%){3pp2RdǠėOJ\q>VL>Y+LJ} VL{N~w|w}'d[}kK[j+dv[ E{s`edwC$iG柤s{N^t:ke)DVИ^ lq6Rvzu~y6ROx}n~L?7WxR`!뜺^wAo F6+# RpU)a& Up`-$* &( = 爮TuNj]Ȟ#4B$p] IekĶkT(ԟ<_|\ (U;ϜTTҗLp*e1Z__ =KϹ@Y֤d>-$H$\[luVjl {@_8Fwq|s>Pop]; !l~!V->S-oĨ՟aҜKl]՟Ĵ:C:E*$1z0y]4ފXȚ{ /#8#/=&:E=K>qNL{{u%umί9}QIۣ.t'L |g3R6w(8X[ Ըs'|wq8aFwE^jus';Wc-_^$86[=20BlF0~G g:lI9%NNN Znװϸ'ctP,&W0KA]Z[4hw`[Vig>NL{xwls)tM[նu34s)W-)*;zZ_>;_ /|?PKRPKZP settings.xmlZs8~"ûIӆIq쫯M20v`2 w]Vz ȯi:Oںwo[߮p>zQ\$(=KCzB$DRisgc͇";,tj_vo:Yhά~Ww vb.k SԬy/.H((;嬷/.C#|YmXrY۬~7 E \(¢"jhS7d &wA=Gd@W"{:໰QwX0'$޶ւ0YaT8"4T$<t@DT 7)}(7vz HW/? gTlu E)]zgޛ΋e5(3G@| 1cy)> Ȥ ߈#]?'YI6X:.ΈTP$U2`NYe &WekvEPx'tMe ;_:`Cň@NU׮tv} jF$H¦| ?ltCCuk2HJy3#l{/Ea8J1 E5T7Xɲs"r"V_ϴ:(qҎpF{̗!ەA&tLCW*L3""C¼UIS5(sBٯ쳾(?=CvSaA id?3Px w|PbMX~ yqOEGUN낮X~}v4y2 -·{PC*wU?0PK&<; PKZPMxg))Thumbnails/thumbnail.pngPNG  IHDRRmPLTE %6&;8;,8G7<#dwxڝ~(b<\b*%[^CҪ8l]-Y/98W,|D"ok6p~L8ܔ"lJWESln/?㠰j'2ץ]4Xr{Ϝ1y$5de[/lѺ1m͎"gBf(+(fWe 2 m=W>BF:#F={.POF07I3Um6s+7D EEx`1Ď w[CQvd - 4 )3Pt MF%=8녃$!nTŪ4b0l?񏀺u̞yVr80;Dj5$kٚQ<]X>M̽0HØCylӃe;UAMuy`eNha@;Smwr["QVѩOcblcb i=J0Bۥ v3m%7#aH)[zEWB!Bu;7#ztEGMѽoz.GPc2b H:UN.k hZKH'-4ؽ$CQ= (.>R(RwM}n P;bp{ILː5*j˺8$QfuIM@{G.F ;Ϣ9"o&&( sOk?S$ (u)Rь)A$$G7QNxn}=mjbIed5 vNov*J6>?ЎNJXL˨lןfq*(g;~d1DGm{`aIE.{Эtqdf]~B1BUɹ* u!T9/v;?Җg߁E;mt (Ƴe,}1=?|' P P P P m( d+ A!.&4-X mXtr-; ?B=LJG 0I$bоq59?&2o1< =/XP#K02n-OBp"l8CȆР#-H/ρكqOq~^YfxL^O5s<sߟLӸf"lہ(]ڣWb<9- <ԃ+qܕ'yeP\H9 ܬpK+5\R[:V,-Ri.N!oqeZ3,zћDW#R(R(R(~7_L74JrrVYޛ ]^S!i;J^:{a sI˶~Z5 tN7eN46$^,wbȟvzb;gsIPx/u9_{]G4l#f+3THIMlOf{2kjjg|d7Dwr &rHMwU_"9'&pw{*fj! 7pOczzFs`0́<€WW }BZSG.hR8BJY@g`Aat$nlPh H ^2zHAdoѓպ_%2NaIO|=6&G,(?F%[X0f<_D]pKq:sDì6*kH̴wNʅ`Wn0$$u 9 I$ꗰ's^v);h41y5ܘQ.e\$|I cŒ(U1ID\KL`۳gGq>ۏJ>ewΩV2K(Tm)f{鏳ۖ>!&M[@?tIԑFFeq%$eAWĢ$ueppkӉ5$䷰ PC |_zttl}i}փtaSOn"=R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R(R L?*IENDB`PKZPMETA-INF/manifest.xmlMn F9Ŷ2Bqfp`[q⪊K31Ի1Y {kV^[?n DrTa9*$Q$@[/Ǥl&.h4qc''R} Sh-7ƶ g1inW0A]&`suPthukhj:h vG|_At &|z4q7BKxOkGmX3øiJK9zSCG׼kg啪'̞eVK1Ik4tM #{n6#jE?8DGvg bn7k[ۃ"%4E$Et'+Fs|{Q^qBͺb__K47eK(Fw9~MS&zr͏}> D4Ӕ83`J$ UAgW鏬]I>_S( vG+^%$<Iwԗ\D3pvDŽ?JKDS{TQ{~Ԁol'h}Nh̒9[PKއPKVP styles.xml\o6~@e=ď&ۻ`lqDɼR@qDem 3f8^  4khj:E>'8s `ax0EƼ0)cE1g!`ae A7 HS/i1|#B~)A b}4$ +¾ma'U =iՕINUYHw Z | )CTKHK!P6= Q ;JE[B#3 B|NlpxZbdzV*mQRY秺DbZ%Uq,QU"$}>Yҕ'S0 ҫ2|bA([Pm}63+^7+5x -Czyr͸܂ԺUէd=T*\D|Lls_(LJƉT.J6W/? p ^cOhQLvTo@v'ip%FQwy+ 6{6ˊF3.x\&(7f®rrIU/&Rccg(NN6'3'˙ɞ*k{avG/zDu:T<=\*(O7a7{ծ^>  :yC^vk8- X(:o #c1_T;?5'GtGBXxJ!cb-bJs6usi4S-A04gW)Fe[F<2k>;$mgEaϳz}}Ҳ{\;F/2|tPK-øW WPKVP content.xmlXKo6W*M?4QŞ@Ѥ@o R@R;%r$Ghz#뛙C*_NZXd\% (?&~%wɗtIмʡp ,18LjfM MOu EgIa[u2e]jQ/#Nv{#ެV[9F;{H;L 5I#}>LZ"#btĹ|{~:+SqYR6W.+5)(`-]/}7ar=ڢ*R&/;aX=׋E^ sͽnlW {C9SOֽ)WU_ Uspln,;ŏi~{s"h!&w5k7os{n@O7Q*߁'{dGMQg}?3]"Бҁwո޼{(śzENݶ<0h'GpSg%MpMr{9p~w;L; s|ebAyv" d/.lnZ/dxG @pev#}L~gJLxTt*To$62[Cڄ^,q6[Žvg5J8vȌl6о L 7 WvОFShY04~z4V}e3|RU^$eHJ`t3~ ѡylk)ݬۛq\5$(3=KGzB,DRrtb|?}9Mew6gT6I'sfꪙ>E;,i5UUvo:EhNowiP1vh59jNѼss}d~Hrz oBAjUiuG.W_t7B5(`A$ş("Ud䜔J oԀro7D1AIf55_Eȕ#y~E"F@>+G-չ>_o+}J$<֬Y{i[vQoQ) k4J6ylY_0Eмl}LfQX0Lư$ւ0YbT8!Uq]JWF9_ cs"JEr>e6nu4` W/_=3*[vA CQHeӹZʐHy)&C nID+nۆsd҃|~H :~F8Kt"IhS"IU XSjY0UX;T<|qwq$lF2oruή/ AUߵnĂ6eS8-a`;]XP_R0=g wm(B5IUXX-ڭY&2T6 n)'b4L"/(nWJ?R "'Xu!+Hzo#cUJ#S5Vq8焲)g}QwTAva A d4ҬƔ?=D`'b7 {>`(mHv$ ys_ŤأCW6H~ܝX{VvLwl}8@J7ͲPK8 PKVPɻԚThumbnails/thumbnail.pngPNG  IHDRQc PLTE~OLIDATx1 Om *{pIENDB`PKVPMETA-INF/manifest.xmlMn F9Ŷ2Bqfp`[q⪊K31Ի1Y {kV^[?n DrTa9*$Q$@[/Ǥl&.h4qc''R} Sh-7ƶ g1inW0A]&`suPthukhj:h vG|_At &|z4q7BKxOk "No CSV parser found"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.csv"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.csv"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadData ("files/test.csv"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadData ("files/test_m.csv"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadData ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } foreach my $attr ("strip", "trim") { { # RT#74976 - Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.csv", $attr => $strip); ok ($ref, "File with no content - $attr $strip"); } } # blank.csv has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.csv", clip => 0, $attr => 0); ok ($ref, "!clip $attr 0"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 0, $attr => 1); ok ($ref, "!clip $attr 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, $attr => 1, cells => 0); ok ($ref, "!clip $attr 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, $attr => 2, rc => 0); ok ($ref, "!clip $attr 2"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.csv", clip => 0, $attr => 3, cells => 0, rc => 0); ok ($ref, "!clip $attr 3"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, $attr => 0); ok ($ref, " clip $attr 0"); is ($ref->[1]{maxrow}, 1, "maxrow 3"); is ($ref->[1]{maxcol}, 1, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 1, $attr => 1); ok ($ref, " clip $attr 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, $attr => 1, cells => 0); ok ($ref, " clip $attr 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, $attr => 2, rc => 0); ok ($ref, " clip $attr 2"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, $attr => 3, cells => 0, rc => 0); ok ($ref, " clip $attr 3"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } } foreach my $attr ("pivot", "transpose") { ok ($csv = ReadData ("files/test.csv", $attr => 1), "Read/Parse csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$r][$c], $cell, "Unformatted cell $cell"); my $llec = cr2cell ($r, $c); is ($csv->[1]{$llec}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$r][$c], "", "Unformatted cell $cell"); my $llec = cr2cell ($r, $c); is ($csv->[1]{$llec}, "", "Formatted cell $cell"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/214_csv.t0000644000031300001440000000602213016541261017072 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_XS"; } my $tests = 118; use Test::More; require Test::NoWarnings; use Spreadsheet::Read qw( ReadData cell2cr row cellrow ); my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; sub ReadDataCSV { ReadData (@_, parser => "csv"); } # ReadDataCSV { my $ref; $ref = ReadDataCSV ("files/empty.txt"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadDataCSV ("files/test.txt"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } my @row = ("A3", "", "C3", "D3", (undef) x 15); is_deeply ([ row ($csv->[1], 3) ], \@row, "Formatted row 3"); is_deeply ([ cellrow ($csv->[1], 3) ], \@row, "Unformatted row 3"); ok ($csv = ReadDataCSV ("files/test_m.txt"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataCSV ("files/test_x.txt", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/37_merged.t0000644000031300001440000000507613701561751017504 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("xls") or plan skip_all => "No M\$-Excel parser found"; ok (my $ss = ReadData ("files/merged.xls", attr => 1)->[1], "Read merged xls"); is ($ss->{attr}[1][1]{merged}, 0, "unmerged A1"); is ($ss->{attr}[2][1]{merged}, 1, " merged B1"); is ($ss->{attr}[3][1]{merged}, 1, " merged C1"); is ($ss->{attr}[1][2]{merged}, 1, " merged A2"); is ($ss->{attr}[2][2]{merged}, 1, " merged B2"); is ($ss->{attr}[3][2]{merged}, 1, " merged C2"); is ($ss->{attr}[1][3]{merged}, 1, " merged A3"); is ($ss->{attr}[2][3]{merged}, 0, "unmerged B3"); is ($ss->{attr}[3][3]{merged}, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); ok ($ss = Spreadsheet::Read->new ("files/merged.xls", attr => 1, merge => 1)->sheet (1), "Read merged xls"); is ($ss->attr (1, 1)->merged, 0, "unmerged A1"); is ($ss->attr (2, 1)->merged, "B1", " merged B1"); is ($ss->attr (3, 1)->merged, "B1", " merged C1"); is ($ss->attr (1, 2)->merged, "A2", " merged A2"); is ($ss->attr (2, 2)->merged, "B1", " merged B2"); is ($ss->attr (3, 2)->merged, "B1", " merged C2"); is ($ss->attr (1, 3)->merged, "A2", " merged A3"); is ($ss->attr (2, 3)->merged, 0, "unmerged B3"); is ($ss->attr (3, 3)->merged, 0, "unmerged C3"); is ($ss->attr ("A1")->merged, 0, "unmerged A1"); is ($ss->attr ("B1")->merged, "B1", " merged B1"); is ($ss->attr ("C1")->merged, "B1", " merged C1"); is ($ss->attr ("A2")->merged, "A2", " merged A2"); is ($ss->attr ("B2")->merged, "B1", " merged B2"); is ($ss->attr ("C2")->merged, "B1", " merged C2"); is ($ss->attr ("A3")->merged, "A2", " merged A3"); is ($ss->attr ("B3")->merged, 0, "unmerged B3"); is ($ss->attr ("C3")->merged, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); is ($ss->merged_from ("A1"), "", "merged_from (A1)"); is ($ss->merged_from (1, 1), "", "merged_from (1, 1)"); is ($ss->merged_from ("B1"), "B1", "merged_from (B1)"); is ($ss->merged_from (2, 1), "B1", "merged_from (2, 1)"); is ($ss->merged_from ("C2"), "B1", "merged_from (C2)"); is ($ss->merged_from (3, 2), "B1", "merged_from (3, 2)"); # out of range is ($ss->merged_from ("E5"), undef, "merged_from (E5)"); # illegal ID is ($ss->merged_from (999), undef, "merged_from (999)"); is ($ss->merged_from ("9X"), undef, "merged_from (9X)"); is ($ss->merged_from (999, 99), undef, "merged_from (999, 99)"); is ($ss->merged_from (9, 9, 9), undef, "merged_from (9, 9, 9)"); done_testing; Spreadsheet-Read-0.84/t/617_merged.t0000644000031300001440000000536113701561237017564 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; $parser eq "Spreadsheet::XLSX" and plan skip_all => "No merged cell support in $parser"; ok (my $ss = ReadData ("files/merged.xlsx", attr => 1)->[1], "Read merged xlsx"); is ($ss->{attr}[1][1]{merged}, 0, "unmerged A1"); is ($ss->{attr}[2][1]{merged}, 1, " merged B1"); is ($ss->{attr}[3][1]{merged}, 1, " merged C1"); is ($ss->{attr}[1][2]{merged}, 1, " merged A2"); is ($ss->{attr}[2][2]{merged}, 1, " merged B2"); is ($ss->{attr}[3][2]{merged}, 1, " merged C2"); is ($ss->{attr}[1][3]{merged}, 1, " merged A3"); is ($ss->{attr}[2][3]{merged}, 0, "unmerged B3"); is ($ss->{attr}[3][3]{merged}, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); ok ($ss = Spreadsheet::Read->new ("files/merged.xlsx", attr => 1, merge => 1)->sheet (1), "Read merged xlsx"); is ($ss->attr (1, 1)->merged, 0, "unmerged A1"); is ($ss->attr (2, 1)->merged, "B1", " merged B1"); is ($ss->attr (3, 1)->merged, "B1", " merged C1"); is ($ss->attr (1, 2)->merged, "A2", " merged A2"); is ($ss->attr (2, 2)->merged, "B1", " merged B2"); is ($ss->attr (3, 2)->merged, "B1", " merged C2"); is ($ss->attr (1, 3)->merged, "A2", " merged A3"); is ($ss->attr (2, 3)->merged, 0, "unmerged B3"); is ($ss->attr (3, 3)->merged, 0, "unmerged C3"); is ($ss->attr ("A1")->merged, 0, "unmerged A1"); is ($ss->attr ("B1")->merged, "B1", " merged B1"); is ($ss->attr ("C1")->merged, "B1", " merged C1"); is ($ss->attr ("A2")->merged, "A2", " merged A2"); is ($ss->attr ("B2")->merged, "B1", " merged B2"); is ($ss->attr ("C2")->merged, "B1", " merged C2"); is ($ss->attr ("A3")->merged, "A2", " merged A3"); is ($ss->attr ("B3")->merged, 0, "unmerged B3"); is ($ss->attr ("C3")->merged, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); is ($ss->merged_from ("A1"), "", "merged_from (A1)"); is ($ss->merged_from (1, 1), "", "merged_from (1, 1)"); is ($ss->merged_from ("B1"), "B1", "merged_from (B1)"); is ($ss->merged_from (2, 1), "B1", "merged_from (2, 1)"); is ($ss->merged_from ("C2"), "B1", "merged_from (C2)"); is ($ss->merged_from (3, 2), "B1", "merged_from (3, 2)"); # out of range is ($ss->merged_from ("E5"), undef, "merged_from (E5)"); # illegal ID is ($ss->merged_from (999), undef, "merged_from (999)"); is ($ss->merged_from ("9X"), undef, "merged_from (9X)"); is ($ss->merged_from (999, 99), undef, "merged_from (999, 99)"); is ($ss->merged_from (9, 9, 9), undef, "merged_from (9, 9, 9)"); done_testing; Spreadsheet-Read-0.84/t/410_ods.t0000644000031300001440000001652413733615702017102 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 128; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; my $pv = $parser->VERSION; print STDERR "# Parser: $parser-$pv\n"; my $notyet = $pv lt "0.25" and $tests -= 10; { my $ref; $ref = ReadData ("no_such_file.ods"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.ods"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $ods, "<", "files/test.ods" or die "files/test.ods: $!"; binmode $ods; $content = <$ods>; close $ods; } my $ods; foreach my $base ( [ "files/test.ods", "Read/Parse ods file" ], # [ $content, "Parse ods data" ], ) { my ($txt, $msg) = @$base; ok ($ods = ReadData ($txt), $msg); ok (1, "Base values"); is (ref $ods, "ARRAY", "Return type"); is ($ods->[0]{type}, "ods", "Spreadsheet type"); is ($ods->[0]{sheets}, 2, "Sheet count"); is (ref $ods->[0]{sheet}, "HASH", "Sheet list"); unless (is (scalar keys %{$ods->[0]{sheet}}, 2, "Sheet list count")) { diag $_ for keys %{$ods->[0]{sheet}}; diag Spreadsheet::Read::_dump ("List count fail", $ods); } my $xvsn = $ods->[0]{version}; $xvsn =~ s/_[0-9]+$//; # remove beta part cmp_ok ($xvsn, ">=", 0.07, "Parser version"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($ods->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell") or diag Spreadsheet::Read::_dump ("Unformatted cell", $ods->[1]); is ($ods->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($ods->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($ods->[1]{$cell}, undef, "Formatted cell $cell"); } my @row = Spreadsheet::Read::rows ($ods->[1]); is (scalar @row, 4, "Row'ed rows"); is (scalar @{$row[3]}, 4, "Row'ed columns"); is ($row[0][3], "D1", "Row'ed value D1"); is ($row[3][2], "C4", "Row'ed value C4"); } # Tests for empty thingies ok ($ods = ReadData ("files/values.ods"), "True/False values"); ok (my $ss = $ods->[1], "first sheet"); is ($ss->{cell}[1][1], "A1", "unformatted plain text"); is ($ss->{cell}[2][1], " ", "unformatted space") unless $notyet; is ($ss->{cell}[3][1], undef, "unformatted empty"); is ($ss->{cell}[4][1], "0", "unformatted numeric 0") or diag Spreadsheet::Read::_dump ("Unformatted numeric 0", $ss->{cell}->[4]->[1]); is ($ss->{cell}[5][1], "1", "unformatted numeric 1"); is ($ss->{cell}[6][1], "'", "unformatted a single '"); is ($ss->{A1}, "A1", "formatted plain text"); is ($ss->{B1}, " ", "formatted space") unless $notyet; is ($ss->{C1}, undef, "formatted empty"); is ($ss->{D1}, "0", "formatted numeric 0"); is ($ss->{E1}, "1", "formatted numeric 1"); is ($ss->{F1}, "'", "formatted a single '"); { # RT#74976] Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.ods", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.ods has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.ods", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '") unless $notyet; is ($ref->[1]{A1}, " ", "A1 = ' '") unless $notyet; $ref = ReadData ("files/blank.ods", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)") unless $notyet; is ($ref->[1]{A1}, "", "undef A1") unless $notyet; $ref = ReadData ("files/blank.ods", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)") unless $notyet; is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.ods", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1") unless $notyet; $ref = ReadData ("files/blank.ods", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.ods", clip => 1, strip => 0); ok ($ref, " clip strip 0"); my ($_mxr, $_mxc) = $pv lt "0.25" ? (0, 0) : (1, 1); is ($ref->[1]{maxrow}, $_mxr, "maxrow 1") or Spreadsheet::Read::_dump ("Maxrow 1", $ref); is ($ref->[1]{maxcol}, $_mxc, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '") unless $notyet; is ($ref->[1]{A1}, " ", "A1 = ' '") unless $notyet; $ref = ReadData ("files/blank.ods", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "empty (1, 1)"); is ($ref->[1]{A1}, undef, "empty A1"); $ref = ReadData ("files/blank.ods", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "empty (1, 1)"); is ($ref->[1]{A1}, undef, "empty A1"); $ref = ReadData ("files/blank.ods", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "empty (1, 1)"); is ($ref->[1]{A1}, undef, "empty A1"); $ref = ReadData ("files/blank.ods", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "empty (1, 1)"); is ($ref->[1]{A1}, undef, "empty A1"); } { sub chk_test { my ($msg, $ods) = @_; is (ref $ods, "ARRAY", "Return type for $msg"); is ($ods->[0]{type}, "ods", "Spreadsheet type ODS"); is ($ods->[0]{sheets}, 2, "Sheet count") } # chk_test my $data = $content; open my $fh, "<", "files/test.ods"; binmode $fh; chk_test ( " FH parser", ReadData ( $fh, parser => "ods")); close $fh; chk_test ("\\DATA parser", ReadData (\$data, parser => "ods")); chk_test ( " DATA no parser", ReadData ( $data )); chk_test ( " DATA parser", ReadData ( $data, parser => "ods")); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/601_clr.t0000644000031300001440000000273112564056346017076 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 257; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; my $xls; ok ($xls = ReadData ("files/attr.xlsx", attr => 1), "Excel Attributes testcase"); SKIP: { ok (my $clr = $xls->[$xls->[0]{sheet}{Colours}], "colors"); defined $clr->{attr}[2][2]{fgcolor} or skip "$xls->[0]{parser} $xls->[0]{version} does not reliably support colors yet", 255; is ($clr->{cell}[1][1], "auto", "Auto"); is ($clr->{attr}[1][1]{fgcolor}, undef, "Unspecified font color"); is ($clr->{attr}[1][1]{bgcolor}, undef, "Unspecified fill color"); my @clr = ( [], [ "auto", undef ], [ "red", "#ff0000" ], [ "green", "#008000" ], [ "blue", "#0000ff" ], [ "white", "#ffffff" ], [ "yellow", "#ffff00" ], [ "lightgreen", "#00ff00" ], [ "lightblue", "#00ccff" ], [ "gray", "#808080" ], ); foreach my $col (1 .. $#clr) { my $bg = $clr[$col][1]; is ($clr->{cell}[$col][1], $clr[$col][0], "Column $col header"); foreach my $row (1 .. $#clr) { my $fg = $clr[$row][1]; is ($clr->{cell}[1][$row], $clr[$row][0], "Row $row header"); is ($clr->{attr}[$col][$row]{fgcolor}, $fg, "FG ($col, $row)"); is ($clr->{attr}[$col][$row]{bgcolor}, $bg, "BG ($col, $row)"); } } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/213_csv.t0000644000031300001440000000577013016541245017104 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_XS"; } my $tests = 117; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; sub ReadDataStream { my $file = shift; open my $fh, "<", $file or return undef; ReadData ($fh, parser => "csv", @_); } # ReadDataStream { my $ref; $ref = ReadDataStream ("no_such_file.csv"); ok (!defined $ref, "Nonexistent file"); $ref = ReadDataStream ("files/empty.csv"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadDataStream ("files/test.csv"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataStream ("files/test_m.csv", sep => ";"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataStream ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/34_dates.t0000644000031300001440000000447612266462015017337 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 103; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xls") or plan skip_all => "No M\$-Excel parser found"; BEGIN { delete @ENV{qw( LANG LC_ALL LC_DATE )}; } my $xls; ok ($xls = ReadData ("files/Dates.xls", attr => 1, dtfmt => "yyyy-mm-dd"), "Excel Date testcase"); my %fmt = ( A1 => [ "8-Aug", undef ], A2 => [ "12-Aug", undef ], A3 => [ "8-Dec", undef ], A4 => [ "13-Aug", undef ], A6 => [ "Short: dd-MM-yyyy", undef ], A7 => [ "2008-08-13", "yyyy-mm-dd" ], B1 => [ 20080808, "yyyymmdd" ], B2 => [ 20080812, "yyyymmdd" ], B3 => [ 20081208, "yyyymmdd" ], B4 => [ 20080813, "yyyymmdd" ], B6 => [ "Long: ddd, dd MMM yyyy", undef ], B7 => [ "Wed, 13 Aug 2008", "ddd, dd mmm yyyy" ], C1 => [ "2008-08-08", "yyyy-mm-dd" ], C2 => [ "2008-08-12", "yyyy-mm-dd" ], C3 => [ "2008-12-08", "yyyy-mm-dd" ], C4 => [ "2008-08-13", "yyyy-mm-dd" ], C6 => [ "Default format 0x0E", undef ], C7 => [ "8/13/08", "m/d/yy" ], D1 => [ "08/08/2008", "mm/dd/yyyy" ], D2 => [ "08/12/2008", "mm/dd/yyyy" ], D3 => [ "12/08/2008", "mm/dd/yyyy" ], D4 => [ "08/13/2008", "mm/dd/yyyy" ], E1 => [ "08 Aug 2008", undef ], E2 => [ "12 Aug 2008", undef ], E3 => [ "08 Dec 2008", undef ], E4 => [ "13 Aug 2008", undef ], ); ok (my $ss = $xls->[1], "sheet"); ok (my $attr = $ss->{attr}, "attr"); my @date = (undef, 39668, 39672, 39790, 39673); my @fmt = (undef, undef, "yyyymmdd", "yyyy-mm-dd", "mm/dd/yyyy"); foreach my $r (1 .. 4) { is ($ss->{cell}[$_][$r], $date[$r], "Date value row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{type}, "date", "Date type row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{format}, $fmt[$_], "Date format row $r col $_") for 1 .. 4; } foreach my $r (1..4,6..7) { foreach my $c (1..5) { my $cell = cr2cell ($c, $r); my $fmt = $ss->{attr}[$c][$r]{format}; defined $ss->{$cell} or next; is ($ss->{$cell}, $fmt{$cell}[0], "$cell content"); is ($fmt, $fmt{$cell}[1], "$cell format"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/420_sxc.t0000644000031300001440000000756613701337130017110 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 301; use Test::More; require Test::NoWarnings; BEGIN { $ENV{SPREADSHEET_READ_SXC} = "Spreadsheet::ReadSXC"; } use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("sxc") or plan skip_all => "No SXC parser found"; my $pv = $parser->VERSION; $pv >= "0.25" and plan skip_all => "Use Spreadsheet::ParseODS instead please"; diag ("# Parser: $parser-$pv"); my $content; { local $/; open my $xml, "<", "files/content.xml" or die "files/content.xml: $!\n"; binmode $xml; $content = <$xml>; close $xml; } { my $ref; $ref = ReadData ("no_such_file.sxc"); ok (!defined $ref, "Nonexistent file"); # Too noisy #eval { $ref = ReadData ("files/empty.sxc") }; #ok (!defined $ref, "Empty file"); #like ($@, qr/too short/); } my @base = ( [ "files/test.sxc", "Read/Parse sxc file" ], [ "files/content.xml", "Read/Parse xml file" ], [ $content, "Parse xml data" ], ); if ($parser->VERSION > 0.23) { open my $fh, "<", "files/test.sxc" or die "files/test.sxc: $!\n"; push @base => [ $fh, "Parse sxc file handle" ]; $tests += 100; } foreach my $base (@base) { my ($txt, $msg) = @$base; my $sxc; my @options = ref $txt ? (parser => "sxc") : (); ok ($sxc = ReadData ($txt, @options), $msg); ok (1, "Base values"); is (ref $sxc, "ARRAY", "Return type"); is ($sxc->[0]{type}, "sxc", "Spreadsheet type"); is ($sxc->[0]{sheets}, 2, "Sheet count"); is (ref $sxc->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$sxc->[0]{sheet}}, 2, "Sheet list count"); # This should match the version required in Makefile.PL's PREREQ_PM cmp_ok ($sxc->[0]{version}, ">=", 0.12, "Parser version"); ok (1, "Sheet 1"); # Simple sheet with cells filled with the cell label: # -- -- -- -- # A1 B1 D1 # A2 B2 # A3 C3 D3 # A4 B4 C4 ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($sxc->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[1]{$cell}, undef, "Formatted cell $cell"); } ok (1, "Nonexistent fields"); foreach my $cell (qw( A9 X6 B17 AB4 BE33 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[1]{$cell}, undef, "Formatted cell $cell"); } ok (1, "Sheet 2"); # Sheet with merged cells and notes/annotations # x x x # x x # x x x ok (1, "Defined fields"); foreach my $cell (qw( A1 C1 E1 B2 D2 A3 C3 E3 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[2]{cell}[$c][$r], "x", "Unformatted cell $cell"); is ($sxc->[2]{$cell}, "x", "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B1 D1 A2 C2 E2 B3 D3 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[2]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[2]{$cell}, undef, "Formatted cell $cell"); } ok (1, "Nonexistent fields"); foreach my $cell (qw( A9 X6 B17 AB4 BE33 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[2]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[2]{$cell}, undef, "Formatted cell $cell"); } # Sheet order ok (exists $sxc->[0]{sheet}{Sheet1}, "Sheet labels in metadata"); my @sheets = map { $sxc->[$_]{label} } 1 .. $sxc->[0]{sheets}; SKIP: { $sxc->[0]{version} < 0.20 and skip "Not supported", 1; is ("@sheets", "@{['Sheet1','Second Sheet']}", "Sheet order"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/223_csv.t0000644000031300001440000000577013016541271017104 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_PP"; } my $tests = 117; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; sub ReadDataStream { my $file = shift; open my $fh, "<", $file or return undef; ReadData ($fh, parser => "csv", @_); } # ReadDataStream { my $ref; $ref = ReadDataStream ("no_such_file.csv"); ok (!defined $ref, "Nonexistent file"); $ref = ReadDataStream ("files/empty.csv"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadDataStream ("files/test.csv"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataStream ("files/test_m.csv", sep => ";"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataStream ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/33_misc.t0000644000031300001440000000275313231321026017152 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 6; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xls") or plan skip_all => "No M\$-Excel parser found"; my $xls; { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xls", # All defaults reversed rc => 0, cells => 0, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[0]{sheets}, 3, "Sheet Count"); { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xls", # All defaults reversed, but undef rc => undef, cells => undef, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[1]{cell}[1], undef, "undef works as option value for 'rc'"); ok (!exists $xls->[1]{A1}, "undef works as option value for 'cells'"); { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc_ws.xls", # No cells generated, but we strip whitespace. We don't want any warning cells => 0, strip => 3, debug => 5, ); } ok ($xls, "Open with options, let's see if we get any warnings"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/627_merged.t0000644000031300001440000000020313701561424017551 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; ok (1, "No merged cell support in Spreadsheet::XLSX"); done_testing; Spreadsheet-Read-0.84/t/224_csv.t0000644000031300001440000000602213016541274017077 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_PP"; } my $tests = 118; use Test::More; require Test::NoWarnings; use Spreadsheet::Read qw( ReadData cell2cr row cellrow ); my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; sub ReadDataCSV { ReadData (@_, parser => "csv"); } # ReadDataCSV { my $ref; $ref = ReadDataCSV ("files/empty.txt"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadDataCSV ("files/test.txt"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } my @row = ("A3", "", "C3", "D3", (undef) x 15); is_deeply ([ row ($csv->[1], 3) ], \@row, "Formatted row 3"); is_deeply ([ cellrow ($csv->[1], 3) ], \@row, "Unformatted row 3"); ok ($csv = ReadDataCSV ("files/test_m.txt"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataCSV ("files/test_x.txt", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/417_merged.t0000644000031300001440000000561613733616427017574 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 22; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; my $pv = $parser->VERSION; # ReadSXC is in transition to ParseODS by CORION $parser eq "Spreadsheet::ParseODS" && $pv lt "0.25" and plan skip_all => "No merged cell support in $parser-$pv"; ok (my $ss = ReadData ("files/merged.ods", attr => 1)->[1], "Read merged ods"); is ($ss->{attr}[1][1]{merged}, 0, "unmerged A1"); is ($ss->{attr}[2][1]{merged}, 1, "unmerged B1"); is ($ss->{attr}[3][1]{merged}, 1, "unmerged C1"); is ($ss->{attr}[1][2]{merged}, 1, "unmerged A2"); is ($ss->{attr}[2][2]{merged}, 1, "unmerged B2"); is ($ss->{attr}[3][2]{merged}, 1, "unmerged C2"); is ($ss->{attr}[1][3]{merged}, 1, "unmerged A3"); is ($ss->{attr}[2][3]{merged}, 0, "unmerged B3"); is ($ss->{attr}[3][3]{merged}, 0, "unmerged C3"); # A2:A3 B1:C2 is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); ok ($ss = Spreadsheet::Read->new ("files/merged.ods", attr => 1, merge => 1)->sheet (1), "Read merged ods"); is ($ss->attr (1, 1)->merged, 0, "unmerged A1"); is ($ss->attr (2, 1)->merged, "B1", " merged B1"); is ($ss->attr (3, 1)->merged, "B1", " merged C1"); is ($ss->attr (1, 2)->merged, "A2", " merged A2"); is ($ss->attr (2, 2)->merged, "B1", " merged B2"); is ($ss->attr (3, 2)->merged, "B1", " merged C2"); is ($ss->attr (1, 3)->merged, "A2", " merged A3"); is ($ss->attr (2, 3)->merged, 0, "unmerged B3"); is ($ss->attr (3, 3)->merged, 0, "unmerged C3"); is ($ss->attr ("A1")->merged, 0, "unmerged A1"); is ($ss->attr ("B1")->merged, "B1", " merged B1"); is ($ss->attr ("C1")->merged, "B1", " merged C1"); is ($ss->attr ("A2")->merged, "A2", " merged A2"); is ($ss->attr ("B2")->merged, "B1", " merged B2"); is ($ss->attr ("C2")->merged, "B1", " merged C2"); is ($ss->attr ("A3")->merged, "A2", " merged A3"); is ($ss->attr ("B3")->merged, 0, "unmerged B3"); is ($ss->attr ("C3")->merged, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); is ($ss->merged_from ("A1"), "", "merged_from (A1)"); is ($ss->merged_from (1, 1), "", "merged_from (1, 1)"); is ($ss->merged_from ("B1"), "B1", "merged_from (B1)"); is ($ss->merged_from (2, 1), "B1", "merged_from (2, 1)"); is ($ss->merged_from ("C2"), "B1", "merged_from (C2)"); is ($ss->merged_from (3, 2), "B1", "merged_from (3, 2)"); # out of range is ($ss->merged_from ("E5"), undef, "merged_from (E5)"); # illegal ID is ($ss->merged_from (999), undef, "merged_from (999)"); is ($ss->merged_from ("9X"), undef, "merged_from (9X)"); is ($ss->merged_from (999, 99), undef, "merged_from (999, 99)"); is ($ss->merged_from (9, 9, 9), undef, "merged_from (9, 9, 9)"); done_testing; Spreadsheet-Read-0.84/t/600_xlsx.t0000644000031300001440000001412113231322052017265 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 116; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.xlsx"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.xlsx"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $xls, "<", "files/test.xlsx" or die "files/test.xlsx: $!"; binmode $xls; $content = <$xls>; close $xls; } my $xls; foreach my $base ( [ "files/test.xlsx", "Read/Parse xlsx file" ], # [ $content, "Parse xlsx data" ], ) { my ($txt, $msg) = @$base; ok ($xls = ReadData ($txt), $msg); ok (1, "Base values"); is (ref $xls, "ARRAY", "Return type"); is ($xls->[0]{type}, "xlsx", "Spreadsheet type"); is ($xls->[0]{sheets}, 2, "Sheet count"); is (ref $xls->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$xls->[0]{sheet}}, 2, "Sheet list count"); like ($xls->[0]{version}, qr{[0-9]}, "Has version with digit"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($xls->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($xls->[1]{$cell}, undef, "Formatted cell $cell"); } my @row = Spreadsheet::Read::rows ($xls->[1]); is (scalar @row, 4, "Row'ed rows"); is (scalar @{$row[3]}, 4, "Row'ed columns"); is ($row[0][3], "D1", "Row'ed value D1"); is ($row[3][2], "C4", "Row'ed value C4"); } # Tests for empty thingies ok ($xls = ReadData ("files/values.xlsx"), "True/False values"); ok (my $ss = $xls->[1], "first sheet"); is ($ss->{cell}[1][1], "A1", "unformatted plain text"); is ($ss->{cell}[2][1], " ", "unformatted space"); is ($ss->{cell}[3][1], undef, "unformatted empty"); is ($ss->{cell}[4][1], "0", "unformatted numeric 0"); is ($ss->{cell}[5][1], "1", "unformatted numeric 1"); is ($ss->{cell}[6][1], "", "unformatted a single '"); is ($ss->{A1}, "A1", "formatted plain text"); is ($ss->{B1}, " ", "formatted space"); is ($ss->{C1}, undef, "formatted empty"); is ($ss->{D1}, "0", "formatted numeric 0"); is ($ss->{E1}, "1", "formatted numeric 1"); is ($ss->{F1}, "", "formatted a single '"); { # RT#74976] Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.xlsx", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.xlsx has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/613_misc.t0000644000031300001440000000232513231322512017232 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } my $tests = 5; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xlsx", # All defaults reversed rc => 0, cells => 0, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[0]{sheets}, 3, "Sheet Count"); { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xlsx", # All defaults reversed, but undef rc => undef, cells => undef, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[1]{cell}[1], undef, "undef works as option value for 'rc'"); ok (!exists $xls->[1]{A1}, "undef works as option value for 'cells'"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/222_csv.t0000644000031300001440000000244612543027300017074 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_PP"; } my $tests = 4; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; my $csv; ok ($csv = ReadData ("files/macosx.csv"), "Read/Parse csv file"); #use DP; DDumper $csv; is ($csv->[1]{maxrow}, 16, "Last row"); is ($csv->[1]{maxcol}, 15, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "", "Last field"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); __END__ ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } is ($csv->[0]{sepchar}, ",", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); Spreadsheet-Read-0.84/t/205_csv.t0000644000031300001440000002352713505433730017107 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; # OO version of 200_csv.t my $tests = 261; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "No CSV parser found"; { my $ref; is (Spreadsheet::Read->new ("no_such_file.csv"), undef, "Open nonexisting file"); ok ($@, "No sheets read: $@"); # No such file or directory is (Spreadsheet::Read->new ("files/empty.csv"), undef, "Open empty file"); is ($@, "files/empty.csv is empty", "No sheets read"); } my $csv; ok ($csv = Spreadsheet::Read->new ("files/test.csv"), "Read/Parse csv file"); ok ($csv->parses ("CSV"), "Parses CSV"); is ($csv->cr2cell (1, 1), "A1", "method cr2cell"); ok (1, "Base values"); is (ref $csv, "Spreadsheet::Read", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is_deeply ([$csv->cellrow (1, 1)], ["A1","B1","","D1",(undef) x 15], "row 1"); is ($csv->cellrow (1, 255), undef, "No such row 255"); is ($csv->cellrow (1, -55), undef, "No such row -55"); is ($csv->cellrow (1, 0), undef, "No such row 0"); is ($csv->cellrow (0, 1), undef, "No such sheet 0"); is ($csv->cellrow (-2, 1), undef, "Wrong sheet -2"); is ($csv->cellrow (-20, 1), undef, "No such sheet -20"); is_deeply ([$csv->row (1, 1)], ["A1","B1","","D1",(undef) x 15], "row 1"); is ($csv->row (1, 255), undef, "No such row 255"); is ($csv->row (1, -55), undef, "No such row -55"); is ($csv->row (1, 0), undef, "No such row 0"); is ($csv->row (0, 1), undef, "No such sheet 0"); is ($csv->row (-2, 1), undef, "Wrong sheet -2"); is ($csv->row (-20, 1), undef, "No such sheet -20"); is ($csv->sheet ( 0), undef, "Sheet 0"); is ($csv->sheet (255), undef, "Sheet 255"); is ($csv->sheet (-55), undef, "Sheet -55"); is ($csv->sheet ("="), undef, "Sheet '='"); is (Spreadsheet::Read::sheet (undef, 1), undef, "Don't be silly"); is (Spreadsheet::Read::sheet ($csv, -9), undef, "Don't be silly"); ok (my $sheet = $csv->sheet (1), "Sheet 1"); is ($sheet->maxrow, 5, "Last row"); is ($sheet->maxcol, 19, "Last column"); is ($sheet->cell ($sheet->maxcol, $sheet->maxrow), "LASTFIELD", "Last field"); is_deeply ([$sheet->cellrow (1)], ["A1","B1","","D1",(undef) x 15], "row 1"); is ($sheet->cellrow (255), undef, "No such row 255"); is ($sheet->cellrow (-55), undef, "No such row -55"); is ($sheet->cellrow ( 0), undef, "No such row 0"); is_deeply ([$sheet->row (1)], ["A1","B1","","D1",(undef) x 15], "row 1"); is ($sheet->row (255), undef, "No such row 255"); is ($sheet->row (-55), undef, "No such row -55"); is ($sheet->row ( 0), undef, "No such row 0"); is_deeply ([$sheet->cellcolumn (1)], ["A1","A2","A3","A4",""], "col 1"); is ($sheet->cellcolumn (255), undef, "No such col 255"); is ($sheet->cellcolumn (-55), undef, "No such col -55"); is ($sheet->cellcolumn ( 0), undef, "No such col 0"); is_deeply ([$sheet->column (1)], ["A1","A2","A3","A4",""], "col 1"); is ($sheet->column (255), undef, "No such col 255"); is ($sheet->column (-55), undef, "No such col -55"); is ($sheet->column ( 0), undef, "No such col 0"); ok (my @rows = $sheet->rows, "All rows"); is ($rows[0][0], "A1", "A1"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = $csv->cell2cr ($cell); is ($sheet->{cell}[$c][$r], $cell, "Unformatted cell $cell direct"); is ($sheet->{$cell}, $cell, "Formatted cell $cell direct"); is ($sheet->cell ($c, $r), $cell, "Unformatted cell $cell method"); is ($sheet->cell ($cell), $cell, "Formatted cell $cell method"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = $csv->cell2cr ($cell); is ($sheet->{cell}[$c][$r], "", "Unformatted cell $cell direct"); is ($sheet->{$cell}, "", "Formatted cell $cell direct"); is ($sheet->cell ($c, $r), "", "Unformatted cell $cell method"); is ($sheet->cell ($cell), "", "Formatted cell $cell method"); } ok ($csv = Spreadsheet::Read->new ("files/test_m.csv"), "Read/Parse M\$ csv file"); ok ($sheet = $csv->sheet (1), "Sheet 1"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = $sheet->cell2cr ($cell); is ($sheet->cell ($c, $r), $cell, "Unformatted cell $cell"); is ($sheet->cell ($cell), $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = $sheet->cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = Spreadsheet::Read->new ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } { # RT#74976 - Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = Spreadsheet::Read->new ("files/blank.csv", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.csv has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.csv", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 3"); is ($ref->[1]{maxcol}, 1, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } ok ($csv = Spreadsheet::Read->new ("files/test.csv"), "Read/Parse csv file"); ok ($csv->add ("files/test.csv"), "Add the same file"); is ($csv->sheets, 2, "Two sheets"); is_deeply ([ $csv->sheets ], [qw( files/test.csv files/test.csv[2] )], "Sheet names"); is_deeply ($csv->sheet ("files/test.csv"), $csv->sheet (2), "Compare sheets"); ok (my $sheet2 = $csv->sheet (2), "The new sheet"); is ($sheet2->label, "files/test.csv", "Original label"); is ($sheet2->label ("Hello"), "Hello", "New label"); ok (my $sheet3 = $csv->sheet ("Hello"), "Found by new label"); is_deeply ($sheet2, $sheet3, "Compare sheets"); ok ($csv->add ("files/test.csv", label => "Test"), "Add with label"); is_deeply ([ $csv->sheets ], [qw( files/test.csv files/test.csv[2] Test )], "Sheet names"); is ($csv->col2label (4), "D", "col2label as book method"); is ($csv->sheet (1)->col2label (27), "AA", "col2label as sheet method"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/412_fmt.t0000644000031300001440000000517313733616250017102 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 40; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; my $ods; ok ($ods = ReadData ("files/attr.ods", attr => 1), "Excel Attributes testcase"); my $parser = $ods->[0]{parser}; SKIP: { ok (my $fmt = $ods->[$ods->[0]{sheet}{Format}], "format"); $fmt->{attr}[2][2]{merged} or skip "$parser $ods->[0]{version} does not reliably support attributes yet", 38; # The return value for the invisible part of merged cells differs for # the available parsers my $mcrv = $parser =~ m/::ParseODS/ ? undef : ""; is ($fmt->{B2}, "merged", "Merged cell left formatted"); is ($fmt->{C2}, $mcrv, "Merged cell right formatted"); is ($fmt->{cell}[2][2], "merged", "Merged cell left unformatted"); is ($fmt->{cell}[3][2], $mcrv, "Merged cell right unformatted"); is ($fmt->{attr}[2][2]{merged}, 1, "Merged cell left merged"); is ($fmt->{attr}[3][2]{merged}, 1, "Merged cell right merged"); is ($fmt->{B3}, "unlocked", "Unlocked cell"); is ($fmt->{attr}[2][3]{locked}, 0, "Unlocked cell not locked"); is ($fmt->{attr}[2][3]{merged}, 0, "Unlocked cell not merged"); is ($fmt->{attr}[2][3]{hidden}, 0, "Unlocked cell not hidden"); is ($fmt->{B4}, "hidden", "Hidden cell"); is ($fmt->{attr}[2][4]{hidden}, 1, "Hidden cell hidden"); is ($fmt->{attr}[2][4]{merged}, 0, "Hidden cell not merged"); foreach my $r (1 .. 4, 7 .. 12) { # 1 .. 12 when date/time fixed is ($fmt->{cell}[1][$r], 12345, "Unformatted valued A$r"); } foreach my $r (5, 6) { local $TODO = "Date/time value representation is not yet unified"; is ($fmt->{cell}[1][$r], 12345, "Unformatted valued A$r"); } is ($fmt->{attr}[1][1]{format}, undef, "Default format"); is ($fmt->{cell}[1][1], $fmt->{A1}, "Formatted valued A1"); is ($fmt->{cell}[1][10], $fmt->{A10}, "Formatted valued A10"); # String foreach my $r (2 .. 9, 11) { # 2 .. 12 when date/time fixed isnt ($fmt->{cell}[1][$r], $fmt->{"A$r"}, "Unformatted valued A$r"); } foreach my $r (12) { local $TODO = "Date/time value representation is not yet unified"; isnt ($fmt->{cell}[1][$r], $fmt->{"A$r"}, "Unformatted valued A$r"); } # Not yet. needs more digging #foreach my $r (2 .. 12) { # ok (defined $fmt->{attr}[1][$r]{format}, "Defined format A$r"); # } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/622_fmt.t0000644000031300001440000000436112543027365017104 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::XLSX"; } my $tests = 40; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; ok ($xls = ReadData ("files/attr.xlsx", attr => 1), "Excel Attributes testcase"); my $parser = $xls->[0]{parser}; SKIP: { ok (my $fmt = $xls->[$xls->[0]{sheet}{Format}], "format"); $fmt->{attr}[2][2]{merged} or skip "$parser $xls->[0]{version} does not reliably support attributes yet", 38; # The return value for the invisible part of merged cells differs for # the available parsers my $mcrv = $parser =~ m/::XLSX/ ? undef : ""; is ($fmt->{B2}, "merged", "Merged cell left formatted"); is ($fmt->{C2}, $mcrv, "Merged cell right formatted"); is ($fmt->{cell}[2][2], "merged", "Merged cell left unformatted"); is ($fmt->{cell}[3][2], $mcrv, "Merged cell right unformatted"); is ($fmt->{attr}[2][2]{merged}, 1, "Merged cell left merged"); is ($fmt->{attr}[3][2]{merged}, 1, "Merged cell right merged"); is ($fmt->{B3}, "unlocked", "Unlocked cell"); is ($fmt->{attr}[2][3]{locked}, 0, "Unlocked cell not locked"); is ($fmt->{attr}[2][3]{merged}, 0, "Unlocked cell not merged"); is ($fmt->{attr}[2][3]{hidden}, 0, "Unlocked cell not hidden"); is ($fmt->{B4}, "hidden", "Hidden cell"); is ($fmt->{attr}[2][4]{hidden}, 1, "Hidden cell hidden"); is ($fmt->{attr}[2][4]{merged}, 0, "Hidden cell not merged"); foreach my $r (1 .. 12) { is ($fmt->{cell}[1][$r], 12345, "Unformatted valued A$r"); } is ($fmt->{attr}[1][1]{format}, undef, "Default format"); is ($fmt->{cell}[1][1], $fmt->{A1}, "Formatted valued A1"); is ($fmt->{cell}[1][10], $fmt->{A10}, "Formatted valued A10"); # String foreach my $r (2 .. 9, 11, 12) { isnt ($fmt->{cell}[1][$r], $fmt->{"A$r"}, "Unformatted valued A$r"); } # Not yet. needs more digging #foreach my $r (2 .. 12) { # ok (defined $fmt->{attr}[1][$r]{format}, "Defined format A$r"); # } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/615_perc.t0000644000031300001440000000250613110546002017231 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } my $tests = 77; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; ok ($xls = ReadData ("files/perc.xlsx", attr => 1), "Excel Percentage testcase"); my $ss = $xls->[1]; my $attr = $ss->{attr}; foreach my $row (1 .. 19) { my @type = map { $ss->{attr}[$_][$row]{type} } 0 .. 3; is ($ss->{attr}[1][$row]{type}, "numeric", "Type A$row numeric"); foreach my $col (2, 3) { my $cell = ("A".."C")[$col - 1].$row; my $xvsn = $xls->[0]{version}; $xvsn =~ s/_[0-9]+$//; # remove beta part my $expect = $xvsn < 0.23 && $type[$col] eq "numeric" ? "numeric" : "percentage"; is ($type[$col], $expect, "Type $cell percentage"); } SKIP: { $ss->{B18} =~ m/[.]/ and skip "$xls->[0]{parser} $xls->[0]{version} has format problems", 1; my $i = int $ss->{"A$row"}; # Allow edge case. rounding .5 will be different in -Duselongdouble perl my $f = $ss->{"B$row"}; $row == 11 && $f eq "1%" and $i = 1; is ($f, "$i%", "Formatted values for row $row\n"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/10_basics.t0000644000031300001440000001070114016141176017456 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 118; use Test::NoWarnings; use Spreadsheet::Read qw(:DEFAULT parses rows ); is (Spreadsheet::Read::Version (), $Spreadsheet::Read::VERSION, "Version check"); ok (my @ext = parses (undef), "No sheet type"); is_deeply ([ grep m/^sc/ => @ext ], [ "sc" ], "Supports Squirrelcalc"); is (parses ("zzz0"), 0, "Unknown sheet type"); is (parses ("zzz1"), "", "Too old sheet type"); is (parses ("zzz2"), "Z20::Just::For::Testing", "Testing sheet type"); is (parses ("zzz3"), 0, "Unsupported sheet type"); is (parses ("xls"), parses ("excel"), "Excel alias type"); is (parses ("ods"), parses ("oo"), "OpenOffice alias type 1"); is (parses ("ods"), parses ("OpenOffice"), "OpenOffice alias type 2"); is (parses ("sc"), parses ("scalc"), "SquirrelCalc alias type"); foreach my $x ([ "A1", 1, 1 ], [ "Z26", 26, 26 ], [ "AB12", 28, 12 ], [ "A", 0, 0 ], [ "19", 0, 0 ], [ "a9", 1, 9 ], [ "aAa9", 703, 9 ], [ "", 0, 0 ], [ undef, 0, 0 ], [ "x444444", 24, 444444 ], [ "xxxxxx4", 296559144, 4 ], ) { my $cell = $x->[0]; my ($c, $r) = cell2cr ($x->[0]); defined $cell or $cell = ""; is ($c, $x->[1], "Col for $cell"); is ($r, $x->[2], "Row for $cell"); } foreach my $x ([ 1, 1, "A", "A1" ], [ 26, 26, "Z", "Z26" ], [ 28, 12, "AB", "AB12" ], [ 0, 0, "", "" ], [ -2, 0, "", "" ], [ 0, -12, "", "" ], [ 1, -12, "A", "" ], [ undef, 1, "", "" ], [ 2, undef, "B", "" ], [ 1, 9, "A", "A9" ], [ 703, 9, "AAA", "AAA9" ], [ 24, 444444, "X", "X444444" ], [ 296559144, 4, "XXXXXX", "XXXXXX4" ], ) { my $cell = cr2cell ($x->[0], $x->[1]); my ($c, $r) = map { defined $_ ? $_ : "--undef--" } $x->[0], $x->[1]; is ($cell, $x->[3], "Cell for ($c, $r)"); is (Spreadsheet::Read::col2label ($x->[0]), $x->[2], "Col $c eq $x->[2]"); } # Some illegal rows () calls for (undef, "", " ", 0, 1, [], {}) { my @rows = rows ($_); my $arg = defined $_ ? $_ : "-- undef --"; is (scalar @rows, 0, "Illegal rows ($arg)"); } for (undef, "", " ", 0, 1, [], {}) { my @rows = rows ({ cell => $_}); my $arg = defined $_ ? $_ : "-- undef --"; is (scalar @rows, 0, "Illegal rows ({ cell => $arg})"); } for (undef, "", " ", 0, 1, [], {}) { my @rows = rows ({ maxrow => 1, cell => $_}); my $arg = defined $_ ? $_ : "-- undef --"; is (scalar @rows, 0, "Illegal rows ({ maxrow => 1, cell => $arg })"); } for (undef, "", " ", 0, 1, [], {}) { my @rows = rows ({ maxcol => 1, cell => $_}); my $arg = defined $_ ? $_ : "-- undef --"; is (scalar @rows, 0, "Illegal rows ({ maxcol => 1, cell => $arg })"); } # Some illegal ReadData () calls for (undef, "", " ", 0, 1, [], {}) { my $ref = ReadData ($_); my $arg = defined $_ ? $_ : "-- undef --"; is ($ref, undef, "Illegal ReadData ($arg)"); } for (undef, "", " ", 0, 1, [], {}) { my $ref = ReadData ([ $_ ]); my $arg = defined $_ ? $_ : "-- undef --"; is ($ref, undef, "Illegal ReadData ([ $arg ])"); } SKIP: { -c "/dev/null" or skip "/dev/null cannot be used for tests", 7; for (undef, "", " ", 0, 1, [], {}) { my $ref = ReadData ("/dev/null", separator => $_); my $arg = defined $_ ? $_ : "-- undef --"; is ($ref, undef, "Illegal ReadData ({ $arg })"); } } for (undef, "", " ", 0, 1, [], {}) { my $ref; eval { $ref = ReadData ("Read.pm", sep => $_); }; my $arg = defined $_ ? $_ : "-- undef --"; is ($ref, undef, "Illegal ReadData ({ $arg })"); } my $sr = "Spreadsheet::Read"; ok (my @p = $sr->parsers (), "Parser info"); is_deeply ((grep { $_->{ext} eq "sc" } @p)[0], { ext => "sc", min => "0.01", mod => $sr, vsn => $sr->VERSION, def => "*" }, "SquirrelCalc is internal"); Spreadsheet-Read-0.84/t/614_dates.t0000644000031300001440000000510612543027701017407 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } my $tests = 103; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; BEGIN { delete @ENV{qw( LANG LC_ALL LC_DATE )}; } my $xls; ok ($xls = ReadData ("files/Dates.xlsx", attr => 1, dtfmt => "yyyy-mm-dd"), "Excel Date testcase"); my %fmt = ( A1 => [ "8-Aug", "d-mmm" ], A2 => [ "12-Aug", "d-mmm" ], A3 => [ "8-Dec", "d-mmm" ], A4 => [ "13-Aug", "d-mmm" ], A6 => [ "Short: dd-MM-yyyy", undef ], A7 => [ "2008-08-13", "yyyy-mm-dd" ], B1 => [ 20080808, "yyyymmdd" ], B2 => [ 20080812, "yyyymmdd" ], B3 => [ 20081208, "yyyymmdd" ], B4 => [ 20080813, "yyyymmdd" ], B6 => [ "Long: ddd, dd MMM yyyy", undef ], B7 => [ "Wed, 13 Aug 2008", "ddd, dd mmm yyyy" ], C1 => [ "2008-08-08", "yyyy-mm-dd" ], C2 => [ "2008-08-12", "yyyy-mm-dd" ], C3 => [ "2008-12-08", "yyyy-mm-dd" ], C4 => [ "2008-08-13", "yyyy-mm-dd" ], C6 => [ "Default format 0x0E", undef ], C7 => [ "8/13/08", "m/d/yy" ], D1 => [ "08/08/2008", "mm/dd/yyyy" ], D2 => [ "08/12/2008", "mm/dd/yyyy" ], D3 => [ "12/08/2008", "mm/dd/yyyy" ], D4 => [ "08/13/2008", "mm/dd/yyyy" ], E1 => [ "08 Aug 2008", undef ], E2 => [ "12 Aug 2008", undef ], E3 => [ "08 Dec 2008", undef ], E4 => [ "13 Aug 2008", undef ], ); SKIP: { ok (my $ss = $xls->[1], "sheet"); ok (my $attr = $ss->{attr}, "attr"); defined $attr->[2][1]{format} or skip "$xls->[0]{parser} $xls->[0]{version} does not reliably support formats", 100; my @date = (undef, 39668, 39672, 39790, 39673); my @fmt = (undef, "d-mmm", "yyyymmdd", "yyyy-mm-dd", "mm/dd/yyyy"); foreach my $r (1 .. 4) { is ($ss->{cell}[$_][$r], $date[$r], "Date value row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{type}, "date", "Date type row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{format}, $fmt[$_], "Date format row $r col $_") for 1 .. 4; } foreach my $r (1..4,6..7) { foreach my $c (1..5) { my $cell = cr2cell ($c, $r); my $fmt = $ss->{attr}[$c][$r]{format}; defined $ss->{$cell} or next; is ($ss->{$cell}, $fmt{$cell}[0], "$cell content"); is ($fmt, $fmt{$cell}[1], "$cell format"); } } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/425_ods.t0000644000031300001440000000756713701337225017113 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 301; use Test::More; require Test::NoWarnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ReadSXC"; } use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("ods") or plan skip_all => "No SXC parser found"; my $pv = $parser->VERSION; $pv >= "0.25" and plan skip_all => "Use Spreadsheet::ParseODS instead please"; diag ("# Parser: $parser-$pv"); my $content; { local $/; open my $xml, "<", "files/content.xml" or die "files/content.xml: $!\n"; binmode $xml; $content = <$xml>; close $xml; } { my $ref; $ref = ReadData ("no_such_file.ods"); ok (!defined $ref, "Nonexistent file"); # Too noisy #eval { $ref = ReadData ("files/empty.ods") }; #ok (!defined $ref, "Empty file"); #like ($@, qr/too short/); } my @base = ( [ "files/test.ods", "Read/Parse ods file" ], [ "files/content.xml", "Read/Parse xml file" ], [ $content, "Parse xml data" ], ); if ($parser->VERSION > 0.24) { open my $fh, "<", "files/test.ods" or die "files/test.ods: $!\n"; push @base => [ $fh, "Parse ods file handle" ]; $tests += 100; } foreach my $base (@base) { my ($txt, $msg) = @$base; my $sxc; my @options = ref $txt ? (parser => "ods") : (); ok ($sxc = ReadData ($txt, @options), $msg); ok (1, "Base values"); is (ref $sxc, "ARRAY", "Return type"); is ($sxc->[0]{type}, "sxc", "Spreadsheet type"); is ($sxc->[0]{sheets}, 2, "Sheet count"); is (ref $sxc->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$sxc->[0]{sheet}}, 2, "Sheet list count"); # This should match the version required in Makefile.PL's PREREQ_PM cmp_ok ($sxc->[0]{version}, ">=", 0.12, "Parser version"); ok (1, "Sheet 1"); # Simple sheet with cells filled with the cell label: # -- -- -- -- # A1 B1 D1 # A2 B2 # A3 C3 D3 # A4 B4 C4 ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($sxc->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[1]{$cell}, undef, "Formatted cell $cell"); } ok (1, "Nonexistent fields"); foreach my $cell (qw( A9 X6 B17 AB4 BE33 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[1]{$cell}, undef, "Formatted cell $cell"); } ok (1, "Sheet 2"); # Sheet with merged cells and notes/annotations # x x x # x x # x x x ok (1, "Defined fields"); foreach my $cell (qw( A1 C1 E1 B2 D2 A3 C3 E3 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[2]{cell}[$c][$r], "x", "Unformatted cell $cell"); is ($sxc->[2]{$cell}, "x", "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B1 D1 A2 C2 E2 B3 D3 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[2]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[2]{$cell}, undef, "Formatted cell $cell"); } ok (1, "Nonexistent fields"); foreach my $cell (qw( A9 X6 B17 AB4 BE33 )) { my ($c, $r) = cell2cr ($cell); is ($sxc->[2]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($sxc->[2]{$cell}, undef, "Formatted cell $cell"); } # Sheet order ok (exists $sxc->[0]{sheet}{Sheet1}, "Sheet labels in metadata"); my @sheets = map { $sxc->[$_]{label} } 1 .. $sxc->[0]{sheets}; SKIP: { $sxc->[0]{version} < 0.20 and skip "Not supported", 1; is ("@sheets", "@{['Sheet1','Second Sheet']}", "Sheet order"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/624_dates.t0000644000031300001440000000510112543027367017413 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::XLSX"; } my $tests = 103; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; BEGIN { delete @ENV{qw( LANG LC_ALL LC_DATE )}; } my $xls; ok ($xls = ReadData ("files/Dates.xlsx", attr => 1, dtfmt => "yyyy-mm-dd"), "Excel Date testcase"); my %fmt = ( A1 => [ "8-Aug", "d-mmm" ], A2 => [ "12-Aug", "d-mmm" ], A3 => [ "8-Dec", "d-mmm" ], A4 => [ "13-Aug", "d-mmm" ], A6 => [ "Short: dd-MM-yyyy", undef ], A7 => [ "2008-08-13", "yyyy-mm-dd" ], B1 => [ 20080808, "yyyymmdd" ], B2 => [ 20080812, "yyyymmdd" ], B3 => [ 20081208, "yyyymmdd" ], B4 => [ 20080813, "yyyymmdd" ], B6 => [ "Long: ddd, dd MMM yyyy", undef ], B7 => [ "Wed, 13 Aug 2008", "ddd, dd mmm yyyy" ], C1 => [ "2008-08-08", "yyyy-mm-dd" ], C2 => [ "2008-08-12", "yyyy-mm-dd" ], C3 => [ "2008-12-08", "yyyy-mm-dd" ], C4 => [ "2008-08-13", "yyyy-mm-dd" ], C6 => [ "Default format 0x0E", undef ], C7 => [ "8/13/08", "m/d/yy" ], D1 => [ "08/08/2008", "mm/dd/yyyy" ], D2 => [ "08/12/2008", "mm/dd/yyyy" ], D3 => [ "12/08/2008", "mm/dd/yyyy" ], D4 => [ "08/13/2008", "mm/dd/yyyy" ], E1 => [ "08 Aug 2008", undef ], E2 => [ "12 Aug 2008", undef ], E3 => [ "08 Dec 2008", undef ], E4 => [ "13 Aug 2008", undef ], ); SKIP: { ok (my $ss = $xls->[1], "sheet"); ok (my $attr = $ss->{attr}, "attr"); defined $attr->[2][1]{format} or skip "$xls->[0]{parser} $xls->[0]{version} does not reliably support formats", 100; my @date = (undef, 39668, 39672, 39790, 39673); my @fmt = (undef, "d-mmm", "yyyymmdd", "yyyy-mm-dd", "mm/dd/yyyy"); foreach my $r (1 .. 4) { is ($ss->{cell}[$_][$r], $date[$r], "Date value row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{type}, "date", "Date type row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{format}, $fmt[$_], "Date format row $r col $_") for 1 .. 4; } foreach my $r (1..4,6..7) { foreach my $c (1..5) { my $cell = cr2cell ($c, $r); my $fmt = $ss->{attr}[$c][$r]{format}; defined $ss->{$cell} or next; is ($ss->{$cell}, $fmt{$cell}[0], "$cell content"); is ($fmt, $fmt{$cell}[1], "$cell format"); } } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/414_dates.t0000644000031300001440000000510513733607341017412 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 103; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; BEGIN { delete @ENV{qw( LANG LC_ALL LC_DATE )}; } my $ods; ok ($ods = ReadData ("files/Dates.ods", attr => 1, dtfmt => "yyyy-mm-dd"), "Excel Date testcase"); my %fmt = ( A1 => [ "8-Aug", "d-mmm" ], A2 => [ "12-Aug", "d-mmm" ], A3 => [ "8-Dec", "d-mmm" ], A4 => [ "13-Aug", "d-mmm" ], A6 => [ "Short: dd-MM-yyyy", undef ], A7 => [ "2008-08-13", "yyyy-mm-dd" ], B1 => [ 20080808, "yyyymmdd" ], B2 => [ 20080812, "yyyymmdd" ], B3 => [ 20081208, "yyyymmdd" ], B4 => [ 20080813, "yyyymmdd" ], B6 => [ "Long: ddd, dd MMM yyyy", undef ], B7 => [ "Wed, 13 Aug 2008", "ddd, dd mmm yyyy" ], C1 => [ "2008-08-08", "yyyy-mm-dd" ], C2 => [ "2008-08-12", "yyyy-mm-dd" ], C3 => [ "2008-12-08", "yyyy-mm-dd" ], C4 => [ "2008-08-13", "yyyy-mm-dd" ], C6 => [ "Default format 0x0E", undef ], C7 => [ "8/13/08", "m/d/yy" ], D1 => [ "08/08/2008", "mm/dd/yyyy" ], D2 => [ "08/12/2008", "mm/dd/yyyy" ], D3 => [ "12/08/2008", "mm/dd/yyyy" ], D4 => [ "08/13/2008", "mm/dd/yyyy" ], E1 => [ "08 Aug 2008", undef ], E2 => [ "12 Aug 2008", undef ], E3 => [ "08 Dec 2008", undef ], E4 => [ "13 Aug 2008", undef ], ); SKIP: { ok (my $ss = $ods->[1], "sheet"); ok (my $attr = $ss->{attr}, "attr"); defined $attr->[2][1]{format} or skip "$ods->[0]{parser} $ods->[0]{version} does not reliably support formats", 100; my @date = (undef, 39668, 39672, 39790, 39673); my @fmt = (undef, "d-mmm", "yyyymmdd", "yyyy-mm-dd", "mm/dd/yyyy"); foreach my $r (1 .. 4) { is ($ss->{cell}[$_][$r], $date[$r], "Date value row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{type}, "date", "Date type row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{format}, $fmt[$_], "Date format row $r col $_") for 1 .. 4; } foreach my $r (1..4,6..7) { foreach my $c (1..5) { my $cell = cr2cell ($c, $r); my $fmt = $ss->{attr}[$c][$r]{format}; defined $ss->{$cell} or next; is ($ss->{$cell}, $fmt{$cell}[0], "$cell content"); is ($fmt, $fmt{$cell}[1], "$cell format"); } } } #unless ($ENV{AUTOMATED_TESTING}) { # Test::NoWarnings::had_no_warnings (); # $tests++; # } done_testing ($tests); Spreadsheet-Read-0.84/t/413_misc.t0000644000031300001440000000251013733610070017232 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 5; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $pt = Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; my $pv = $pt->VERSION; $pv lt "0.25" and plan skip_all => "$pt-$pv won't reliably read the test file"; my $ods; { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $ods = ReadData ("files/misc.ods", # All defaults reversed rc => 0, cells => 0, attr => 1, clip => 1, debug => 5, ); } ok ($ods, "Open with options"); is ($ods->[0]{sheets}, 3, "Sheet Count"); { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $ods = ReadData ("files/misc.ods", # All defaults reversed, but undef rc => undef, cells => undef, attr => 1, clip => 1, debug => 5, ); } ok ($ods, "Open with options"); is ($ods->[1]{cell}[1], undef, "undef works as option value for 'rc'"); ok (!exists $ods->[1]{A1}, "undef works as option value for 'cells'"); #unless ($ENV{AUTOMATED_TESTING}) { # Test::NoWarnings::had_no_warnings (); # $tests++; # } done_testing ($tests); Spreadsheet-Read-0.84/t/212_csv.t0000644000031300001440000000244612543027252017101 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_XS"; } my $tests = 4; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; my $csv; ok ($csv = ReadData ("files/macosx.csv"), "Read/Parse csv file"); #use DP; DDumper $csv; is ($csv->[1]{maxrow}, 16, "Last row"); is ($csv->[1]{maxcol}, 15, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "", "Last field"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); __END__ ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } is ($csv->[0]{sepchar}, ",", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); Spreadsheet-Read-0.84/t/623_misc.t0000644000031300001440000000232013231322235017230 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::XLSX"; } my $tests = 5; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xlsx", # All defaults reversed rc => 0, cells => 0, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[0]{sheets}, 3, "Sheet Count"); { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xlsx", # All defaults reversed, but undef rc => undef, cells => undef, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[1]{cell}[1], undef, "undef works as option value for 'rc'"); ok (!exists $xls->[1]{A1}, "undef works as option value for 'cells'"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/31_clr.t0000644000031300001440000000247413411413207017000 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 256; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xls") or plan skip_all => "No M\$-Excel parser found"; my $xls; ok ($xls = ReadData ("files/attr.xls", attr => 1), "Excel Attributes testcase"); my $clr = $xls->[$xls->[0]{sheet}{Colours}]; is ($clr->{cell}[1][1], "auto", "Auto"); is ($clr->{attr}[1][1]{fgcolor}, undef, "Unspecified font color"); is ($clr->{attr}[1][1]{bgcolor}, undef, "Unspecified fill color"); my @clr = ( [], [ "auto", undef ], [ "red", "#ff0000" ], [ "green", "#008000" ], [ "blue", "#0000ff" ], [ "white", "#ffffff" ], [ "yellow", "#ffff00" ], [ "lightgreen", "#00ff00" ], [ "lightblue", "#00ccff" ], [ "gray", "#808080" ], ); foreach my $col (1 .. $#clr) { my $bg = $clr[$col][1]; is ($clr->{cell}[$col][1], $clr[$col][0], "Column $col header"); foreach my $row (1 .. $#clr) { my $fg = $clr[$row][1]; is ($clr->{cell}[1][$row], $clr[$row][0], "Row $row header"); is ($clr->{attr}[$col][$row]{fgcolor}, $fg, "FG ($col, $row)"); is ($clr->{attr}[$col][$row]{bgcolor}, $bg, "BG ($col, $row)"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/625_perc.t0000644000031300001440000000226112643415517017250 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::XLSX"; } my $tests = 77; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; ok ($xls = ReadData ("files/perc.xlsx", attr => 1), "Excel Percentage testcase"); my $ss = $xls->[1]; my $attr = $ss->{attr}; foreach my $row (1 .. 19) { is ($ss->{attr}[1][$row]{type}, "numeric", "Type A$row numeric"); ok ($ss->{attr}[2][$row]{type} eq "numeric" || $ss->{attr}[2][$row]{type} eq "percentage", "Type B$row percentage"); is ($ss->{attr}[3][$row]{type}, "percentage", "Type C$row percentage"); SKIP: { $ss->{B18} =~ m/[.]/ and skip "$xls->[0]{parser} $xls->[0]{version} has format problems", 1; my $i = int $ss->{"A$row"}; # Allow edge case. rounding .5 will be different in -Duselongdouble perl my $f = $ss->{"B$row"}; $row == 11 && $f eq "1%" and $i = 1; is ($f, "$i%", "Formatted values for row $row\n"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/612_fmt.t0000644000031300001440000000436612543027355017107 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } my $tests = 40; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; ok ($xls = ReadData ("files/attr.xlsx", attr => 1), "Excel Attributes testcase"); my $parser = $xls->[0]{parser}; SKIP: { ok (my $fmt = $xls->[$xls->[0]{sheet}{Format}], "format"); $fmt->{attr}[2][2]{merged} or skip "$parser $xls->[0]{version} does not reliably support attributes yet", 38; # The return value for the invisible part of merged cells differs for # the available parsers my $mcrv = $parser =~ m/::XLSX/ ? undef : ""; is ($fmt->{B2}, "merged", "Merged cell left formatted"); is ($fmt->{C2}, $mcrv, "Merged cell right formatted"); is ($fmt->{cell}[2][2], "merged", "Merged cell left unformatted"); is ($fmt->{cell}[3][2], $mcrv, "Merged cell right unformatted"); is ($fmt->{attr}[2][2]{merged}, 1, "Merged cell left merged"); is ($fmt->{attr}[3][2]{merged}, 1, "Merged cell right merged"); is ($fmt->{B3}, "unlocked", "Unlocked cell"); is ($fmt->{attr}[2][3]{locked}, 0, "Unlocked cell not locked"); is ($fmt->{attr}[2][3]{merged}, 0, "Unlocked cell not merged"); is ($fmt->{attr}[2][3]{hidden}, 0, "Unlocked cell not hidden"); is ($fmt->{B4}, "hidden", "Hidden cell"); is ($fmt->{attr}[2][4]{hidden}, 1, "Hidden cell hidden"); is ($fmt->{attr}[2][4]{merged}, 0, "Hidden cell not merged"); foreach my $r (1 .. 12) { is ($fmt->{cell}[1][$r], 12345, "Unformatted valued A$r"); } is ($fmt->{attr}[1][1]{format}, undef, "Default format"); is ($fmt->{cell}[1][1], $fmt->{A1}, "Formatted valued A1"); is ($fmt->{cell}[1][10], $fmt->{A10}, "Formatted valued A10"); # String foreach my $r (2 .. 9, 11, 12) { isnt ($fmt->{cell}[1][$r], $fmt->{"A$r"}, "Unformatted valued A$r"); } # Not yet. needs more digging #foreach my $r (2 .. 12) { # ok (defined $fmt->{attr}[1][$r]{format}, "Defined format A$r"); # } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/50_sc.t0000644000031300001440000000305713746002117016631 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 48; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("sc") or plan skip_all => "No SquirrelCalc parser found"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.sc"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.sc"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $sc, "<", "files/test.sc" or die "files/test.sc: $!\n"; binmode $sc; $content = <$sc>; close $sc; isnt ($content, undef, "Content is defined"); isnt ($content, "", "Content is filled"); } foreach my $txt ("files/test.sc", $content) { foreach my $clip (0, 2) { my $sc; ok ($sc = ReadData ($txt, clip => $clip, strip => 2), "Read/Parse sc file ".($clip?"clipped":"unclipped")); ok (1, "Base values"); is (ref $sc, "ARRAY", "Return type"); is ($sc->[0]{type}, "sc", "Spreadsheet type"); is ($sc->[0]{sheets}, 1, "Sheet count"); is (ref $sc->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$sc->[0]{sheet}}, 1, "Sheet list count"); is ($sc->[0]{version}, $Spreadsheet::Read::VERSION, "Parser version"); is ($sc->[1]{maxcol}, 10 - $clip, "Columns"); is ($sc->[1]{maxrow}, 28 - $clip, "Rows"); is ($sc->[1]{cell}[1][22], " Workspace", "Just checking one cell"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/201_csv.t0000644000031300001440000000171512524343302017071 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 12; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("csv") or plan skip_all => "No CSV parser found"; my $csv; ok ($csv = ReadData ("files/test.csv"), "Read/Parse csv file"); is ($csv->[0]{sepchar}, ",", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); ok ($csv = ReadData ("files/test_m.csv"), "Read/Parse csv file (;)"); is ($csv->[0]{sepchar}, ";", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); ok ($csv = ReadData ("files/test_t.csv", quote => "'"), "Read/Parse csv file (tabs)"); is ($csv->[0]{sepchar}, "\t", "{sepchar}"); is ($csv->[0]{quote}, "'", "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/415_perc.t0000644000031300001440000000224313701335444017241 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 77; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; my $ods; ok ($ods = ReadData ("files/perc.ods", attr => 1), "Excel Percentage testcase"); my $ss = $ods->[1]; my $attr = $ss->{attr}; foreach my $row (1 .. 19) { my @type = map { $ss->{attr}[$_][$row]{type} } 0 .. 3; is ($ss->{attr}[1][$row]{type}, "numeric", "Type A$row numeric"); foreach my $col (2, 3) { my $cell = ("A".."C")[$col - 1].$row; is ($type[$col], "percentage", "Type $cell percentage"); } SKIP: { $ss->{B18} =~ m/[.]/ and skip "$ods->[0]{parser} $ods->[0]{version} has format problems", 1; my $i = int $ss->{"A$row"}; # Allow edge case. rounding .5 will be different in -Duselongdouble perl my $f = $ss->{"B$row"}; $row == 11 && $f eq "1%" and $i = 1; is ($f, "$i%", "Formatted values for row $row\n"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/620_xlsx.t0000644000031300001440000001423013234273527017307 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::XLSX"; } my $tests = 116; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.xlsx"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.xlsx"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $xls, "<", "files/test.xlsx" or die "files/test.xlsx: $!"; binmode $xls; $content = <$xls>; close $xls; } my $xls; foreach my $base ( [ "files/test.xlsx", "Read/Parse xlsx file" ], # [ $content, "Parse xlsx data" ], ) { my ($txt, $msg) = @$base; ok ($xls = ReadData ($txt), $msg); ok (1, "Base values"); is (ref $xls, "ARRAY", "Return type"); is ($xls->[0]{type}, "xlsx", "Spreadsheet type"); is ($xls->[0]{sheets}, 2, "Sheet count"); is (ref $xls->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$xls->[0]{sheet}}, 2, "Sheet list count"); cmp_ok ($xls->[0]{version}, ">=", 0.07, "Parser version"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($xls->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($xls->[1]{$cell}, undef, "Formatted cell $cell"); } my @row = Spreadsheet::Read::rows ($xls->[1]); is (scalar @row, 4, "Row'ed rows"); is (scalar @{$row[3]}, 4, "Row'ed columns"); is ($row[0][3], "D1", "Row'ed value D1"); is ($row[3][2], "C4", "Row'ed value C4"); } # Tests for empty thingies ok ($xls = ReadData ("files/values.xlsx"), "True/False values"); ok (my $ss = $xls->[1], "first sheet"); is ($ss->{cell}[1][1], "A1", "unformatted plain text"); is ($ss->{cell}[2][1], " ", "unformatted space"); is ($ss->{cell}[3][1], undef, "unformatted empty"); is ($ss->{cell}[4][1], "0", "unformatted numeric 0"); is ($ss->{cell}[5][1], "1", "unformatted numeric 1"); is ($ss->{cell}[6][1], "", "unformatted a single '"); is ($ss->{A1}, "A1", "formatted plain text"); is ($ss->{B1}, " ", "formatted space"); is ($ss->{C1}, undef, "formatted empty"); is ($ss->{D1}, "0", "formatted numeric 0"); is ($ss->{E1}, "1", "formatted numeric 1"); is ($ss->{F1}, "", "formatted a single '"); { # RT#74976] Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.xlsx", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.xlsx has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/999_fail.t0000644000031300001440000000054213234277602017246 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Test::More"; } my $tests = 2; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; is (Spreadsheet::Read::parses ("xlsx"), 0, "Invalid module name for xlsx"); like ($@, qr/^Test::More is not supported/, "Error reason"); done_testing ($tests); Spreadsheet-Read-0.84/t/202_csv.t0000644000031300001440000000233411163712203017066 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 4; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("csv") or plan skip_all => "No CSV parser found"; my $csv; ok ($csv = ReadData ("files/macosx.csv"), "Read/Parse csv file"); #use DP; DDumper $csv; is ($csv->[1]{maxrow}, 16, "Last row"); is ($csv->[1]{maxcol}, 15, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "", "Last field"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); __END__ ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } is ($csv->[0]{sepchar}, ",", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); Spreadsheet-Read-0.84/t/211_csv.t0000644000031300001440000000202712543027246017076 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_XS"; } my $tests = 12; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; my $csv; ok ($csv = ReadData ("files/test.csv"), "Read/Parse csv file"); is ($csv->[0]{sepchar}, ",", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); ok ($csv = ReadData ("files/test_m.csv"), "Read/Parse csv file (;)"); is ($csv->[0]{sepchar}, ";", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); ok ($csv = ReadData ("files/test_t.csv", quote => "'"), "Read/Parse csv file (tabs)"); is ($csv->[0]{sepchar}, "\t", "{sepchar}"); is ($csv->[0]{quote}, "'", "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/35_perc.t0000644000031300001440000000151311163712567017163 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 77; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xls") or plan skip_all => "No M\$-Excel parser found"; my $xls; ok ($xls = ReadData ("files/perc.xls", attr => 1), "Excel Percentage testcase"); my $ss = $xls->[1]; my $attr = $ss->{attr}; foreach my $row (1 .. 19) { is ($ss->{attr}[1][$row]{type}, "numeric", "Type A$row numeric"); is ($ss->{attr}[2][$row]{type}, "percentage", "Type B$row percentage"); is ($ss->{attr}[3][$row]{type}, "percentage", "Type C$row percentage"); my $i = int $ss->{"A$row"}; is ($ss->{"B$row"}, "$i%", "Formatted values for row $row\n"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/602_fmt.t0000644000031300001440000000424612545741253017105 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 40; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; my $xls; ok ($xls = ReadData ("files/attr.xlsx", attr => 1), "Excel Attributes testcase"); my $parser = $xls->[0]{parser}; SKIP: { ok (my $fmt = $xls->[$xls->[0]{sheet}{Format}], "format"); $fmt->{attr}[2][2]{merged} or skip "$parser $xls->[0]{version} does not reliably support attributes yet", 38; # The return value for the invisible part of merged cells differs for # the available parsers my $mcrv = $parser =~ m/::XLSX$/ ? undef : ""; is ($fmt->{B2}, "merged", "Merged cell left formatted"); is ($fmt->{C2}, $mcrv, "Merged cell right formatted"); is ($fmt->{cell}[2][2], "merged", "Merged cell left unformatted"); is ($fmt->{cell}[3][2], $mcrv, "Merged cell right unformatted"); is ($fmt->{attr}[2][2]{merged}, 1, "Merged cell left merged"); is ($fmt->{attr}[3][2]{merged}, 1, "Merged cell right merged"); is ($fmt->{B3}, "unlocked", "Unlocked cell"); is ($fmt->{attr}[2][3]{locked}, 0, "Unlocked cell not locked"); is ($fmt->{attr}[2][3]{merged}, 0, "Unlocked cell not merged"); is ($fmt->{attr}[2][3]{hidden}, 0, "Unlocked cell not hidden"); is ($fmt->{B4}, "hidden", "Hidden cell"); is ($fmt->{attr}[2][4]{hidden}, 1, "Hidden cell hidden"); is ($fmt->{attr}[2][4]{merged}, 0, "Hidden cell not merged"); foreach my $r (1 .. 12) { is ($fmt->{cell}[1][$r], 12345, "Unformatted valued A$r"); } is ($fmt->{attr}[1][1]{format}, undef, "Default format"); is ($fmt->{cell}[1][1], $fmt->{A1}, "Formatted valued A1"); is ($fmt->{cell}[1][10], $fmt->{A10}, "Formatted valued A10"); # String foreach my $r (2 .. 9, 11, 12) { isnt ($fmt->{cell}[1][$r], $fmt->{"A$r"}, "Unformatted valued A$r"); } # Not yet. needs more digging #foreach my $r (2 .. 12) { # ok (defined $fmt->{attr}[1][$r]{format}, "Defined format A$r"); # } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/51_sc.t0000644000031300001440000000322613746002122016624 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 26; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("sc") or plan skip_all => "No SquirrelCalc parser found"; sub ReadDataStream { my $file = shift; open my $fh, "<", $file or return undef; ReadData ($fh, parser => "sc", @_); } # ReadDataStream { my $ref; $ref = ReadDataStream ("no_such_file.sc"); ok (!defined $ref, "Nonexistent file"); $ref = ReadDataStream ("files/empty.sc"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $sc, "<", "files/test.sc" or die "files/test.sc: $!\n"; binmode $sc; $content = <$sc>; close $sc; isnt ($content, undef, "Content is defined"); isnt ($content, "", "Content is filled"); } foreach my $clip (0, 2) { my $sc; ok ($sc = ReadDataStream ("files/test.sc", clip => $clip, strip => 2), "Read/Parse sc file ".($clip?"clipped":"unclipped")); ok (1, "Base values"); is (ref $sc, "ARRAY", "Return type"); is ($sc->[0]{type}, "sc", "Spreadsheet type"); is ($sc->[0]{sheets}, 1, "Sheet count"); is (ref $sc->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$sc->[0]{sheet}}, 1, "Sheet list count"); is ($sc->[0]{version}, $Spreadsheet::Read::VERSION, "Parser version"); is ($sc->[1]{maxcol}, 10 - $clip, "Columns"); is ($sc->[1]{maxrow}, 28 - $clip, "Rows"); is ($sc->[1]{cell}[1][22], " Workspace", "Just checking one cell"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/426_clr.t0000644000031300001440000000024513701341075017067 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; require Test::NoWarnings; ok (1, "Spreadsheet::ReadSXC never supported colors"); done_testing (1); Spreadsheet-Read-0.84/t/604_dates.t0000644000031300001440000000476512543027450017421 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 103; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; BEGIN { delete @ENV{qw( LANG LC_ALL LC_DATE )}; } my $xls; ok ($xls = ReadData ("files/Dates.xlsx", attr => 1, dtfmt => "yyyy-mm-dd"), "Excel Date testcase"); my %fmt = ( A1 => [ "8-Aug", "d-mmm" ], A2 => [ "12-Aug", "d-mmm" ], A3 => [ "8-Dec", "d-mmm" ], A4 => [ "13-Aug", "d-mmm" ], A6 => [ "Short: dd-MM-yyyy", undef ], A7 => [ "2008-08-13", "yyyy-mm-dd" ], B1 => [ 20080808, "yyyymmdd" ], B2 => [ 20080812, "yyyymmdd" ], B3 => [ 20081208, "yyyymmdd" ], B4 => [ 20080813, "yyyymmdd" ], B6 => [ "Long: ddd, dd MMM yyyy", undef ], B7 => [ "Wed, 13 Aug 2008", "ddd, dd mmm yyyy" ], C1 => [ "2008-08-08", "yyyy-mm-dd" ], C2 => [ "2008-08-12", "yyyy-mm-dd" ], C3 => [ "2008-12-08", "yyyy-mm-dd" ], C4 => [ "2008-08-13", "yyyy-mm-dd" ], C6 => [ "Default format 0x0E", undef ], C7 => [ "8/13/08", "m/d/yy" ], D1 => [ "08/08/2008", "mm/dd/yyyy" ], D2 => [ "08/12/2008", "mm/dd/yyyy" ], D3 => [ "12/08/2008", "mm/dd/yyyy" ], D4 => [ "08/13/2008", "mm/dd/yyyy" ], E1 => [ "08 Aug 2008", undef ], E2 => [ "12 Aug 2008", undef ], E3 => [ "08 Dec 2008", undef ], E4 => [ "13 Aug 2008", undef ], ); SKIP: { ok (my $ss = $xls->[1], "sheet"); ok (my $attr = $ss->{attr}, "attr"); defined $attr->[2][1]{format} or skip "$xls->[0]{parser} $xls->[0]{version} does not reliably support formats", 100; my @date = (undef, 39668, 39672, 39790, 39673); my @fmt = (undef, "d-mmm", "yyyymmdd", "yyyy-mm-dd", "mm/dd/yyyy"); foreach my $r (1 .. 4) { is ($ss->{cell}[$_][$r], $date[$r], "Date value row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{type}, "date", "Date type row $r col $_") for 1 .. 4; is ($attr->[$_][$r]{format}, $fmt[$_], "Date format row $r col $_") for 1 .. 4; } foreach my $r (1..4,6..7) { foreach my $c (1..5) { my $cell = cr2cell ($c, $r); my $fmt = $ss->{attr}[$c][$r]{format}; defined $ss->{$cell} or next; is ($ss->{$cell}, $fmt{$cell}[0], "$cell content"); is ($fmt, $fmt{$cell}[1], "$cell format"); } } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/603_misc.t0000644000031300001440000000220413231321663017233 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 5; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; my $xls; { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xlsx", # All defaults reversed rc => 0, cells => 0, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[0]{sheets}, 3, "Sheet Count"); { local *STDERR; # We want the debug activated, but not shown open STDERR, ">", "/dev/null" or die "/dev/null: $!\n"; $xls = ReadData ("files/misc.xlsx", # All defaults reversed, but undef rc => undef, cells => undef, attr => 1, clip => 1, debug => 5, ); } ok ($xls, "Open with options"); is ($xls->[1]{cell}[1], undef, "undef works as option value for 'rc'"); ok (!exists $xls->[1]{A1}, "undef works as option value for 'cells'"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/610_xlsx.t0000644000031300001440000001545313366776074017331 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } my $tests = 128; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.xlsx"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.xlsx"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $xls, "<", "files/test.xlsx" or die "files/test.xlsx: $!"; binmode $xls; $content = <$xls>; close $xls; } my $xls; foreach my $base ( [ "files/test.xlsx", "Read/Parse xlsx file" ], # [ $content, "Parse xlsx data" ], ) { my ($txt, $msg) = @$base; ok ($xls = ReadData ($txt), $msg); ok (1, "Base values"); is (ref $xls, "ARRAY", "Return type"); is ($xls->[0]{type}, "xlsx", "Spreadsheet type"); is ($xls->[0]{sheets}, 2, "Sheet count"); is (ref $xls->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$xls->[0]{sheet}}, 2, "Sheet list count"); my $xvsn = $xls->[0]{version}; $xvsn =~ s/_[0-9]+$//; # remove beta part cmp_ok ($xvsn, ">=", 0.07, "Parser version"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($xls->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($xls->[1]{$cell}, undef, "Formatted cell $cell"); } my @row = Spreadsheet::Read::rows ($xls->[1]); is (scalar @row, 4, "Row'ed rows"); is (scalar @{$row[3]}, 4, "Row'ed columns"); is ($row[0][3], "D1", "Row'ed value D1"); is ($row[3][2], "C4", "Row'ed value C4"); } # Tests for empty thingies ok ($xls = ReadData ("files/values.xlsx"), "True/False values"); ok (my $ss = $xls->[1], "first sheet"); is ($ss->{cell}[1][1], "A1", "unformatted plain text"); is ($ss->{cell}[2][1], " ", "unformatted space"); is ($ss->{cell}[3][1], undef, "unformatted empty"); is ($ss->{cell}[4][1], "0", "unformatted numeric 0"); is ($ss->{cell}[5][1], "1", "unformatted numeric 1"); is ($ss->{cell}[6][1], "", "unformatted a single '"); is ($ss->{A1}, "A1", "formatted plain text"); is ($ss->{B1}, " ", "formatted space"); is ($ss->{C1}, undef, "formatted empty"); is ($ss->{D1}, "0", "formatted numeric 0"); is ($ss->{E1}, "1", "formatted numeric 1"); is ($ss->{F1}, "", "formatted a single '"); { # RT#74976] Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.xlsx", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.xlsx has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.xlsx", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xlsx", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } { sub chk_test { my ($msg, $xls) = @_; is (ref $xls, "ARRAY", "Return type for $msg"); is ($xls->[0]{type}, "xlsx", "Spreadsheet type XLSX"); is ($xls->[0]{sheets}, 2, "Sheet count"); } # chk_test my $data = $content; open my $fh, "<", "files/test.xlsx"; chk_test ( " FH parser", ReadData ( $fh, parser => "xlsx")); close $fh; chk_test ("\\DATA parser", ReadData (\$data, parser => "xlsx")); chk_test ( " DATA no parser", ReadData ( $data )); chk_test ( " DATA parser", ReadData ( $data, parser => "xlsx")); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/605_perc.t0000644000031300001440000000226112730716541017244 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 77; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; my $xls; ok ($xls = ReadData ("files/perc.xlsx", attr => 1), "Excel Percentage testcase"); my $ss = $xls->[1]; my $attr = $ss->{attr}; foreach my $row (1 .. 19) { my @type = map { $ss->{attr}[$_][$row]{type} } 0 .. 3; is ($type[1], "numeric", "Type A$row numeric"); foreach my $col (2, 3) { # Allow numeric for percentage in main test my $cell = ("A".."C")[$col - 1].$row; my $expect = $type[$col] eq "numeric" ? "numeric" : "percentage"; is ($type[$col], $expect, "Type B$row percentage"); } SKIP: { $ss->{B18} =~ m/[.]/ and skip "$xls->[0]{parser} $xls->[0]{version} has format problems", 1; my $i = int $ss->{"A$row"}; # Allow edge case. rounding .5 will be different in -Duselongdouble perl my $f = $ss->{"B$row"}; $row == 11 && $f eq "1%" and $i = 1; is ($f, "$i%", "Formatted values for row $row\n"); } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/11_call.t0000644000031300001440000000157413746002111017130 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; use Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("sc") or plan skip_all => "No SquirrelCalc parser found"; plan tests => 81; # Base attributes foreach my $onoff (0, 1) { for ( [ ], [ rc => $onoff ], [ cell => $onoff ], [ rc => 0, cell => $onoff ], [ rc => 1, cell => $onoff ], [ clip => $onoff ], [ cell => 0, clip => $onoff ], [ cell => 1, clip => $onoff ], [ attr => $onoff ], [ cell => 0, attr => $onoff ], ) { my $ref = ReadData ("files/test.sc", @$_); ok ($ref, "Open with options (@$_)"); ok (ref $ref, "Valid ref"); $ref = ReadData ("files/test.sc", { @$_ }); ok ($ref, "Open with options {@$_}"); ok (ref $ref, "Valid ref"); } } # TODO: test and catch unsupported option. # Currently they are silently ignored Spreadsheet-Read-0.84/t/221_csv.t0000644000031300001440000000202712543027277017103 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_PP"; } my $tests = 12; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; my $csv; ok ($csv = ReadData ("files/test.csv"), "Read/Parse csv file"); is ($csv->[0]{sepchar}, ",", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); ok ($csv = ReadData ("files/test_m.csv"), "Read/Parse csv file (;)"); is ($csv->[0]{sepchar}, ";", "{sepchar}"); is ($csv->[0]{quote}, '"', "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); ok ($csv = ReadData ("files/test_t.csv", quote => "'"), "Read/Parse csv file (tabs)"); is ($csv->[0]{sepchar}, "\t", "{sepchar}"); is ($csv->[0]{quote}, "'", "{quote}"); is ($csv->[1]{C3}, "C3", "cell C3"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/220_csv.t0000644000031300001440000001430713231317266017101 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_PP"; } my $tests = 171; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.csv"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.csv"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadData ("files/test.csv"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadData ("files/test_m.csv"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadData ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } { # RT#74976 - Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.csv", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.csv has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.csv", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 3"); is ($ref->[1]{maxcol}, 1, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/30_xls.t0000644000031300001440000002040713231317773017034 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser; if ($parser = Spreadsheet::Read::parses ("xls")) { print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; plan tests => 272; Test::NoWarnings->import; } else { plan skip_all => "No M\$-Excel parser found"; } { my $ref; $ref = ReadData ("no_such_file.xls"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.xls"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $xls, "<", "files/test.xls" or die "files/test.xls: $!"; binmode $xls; $content = <$xls>; close $xls; } my $xls; foreach my $base ( [ "files/test.xls", "Read/Parse xls file" ], [ $content, "Parse xls data" ], ) { my ($txt, $msg) = @$base; ok ($xls = ReadData ($txt), $msg); ok (1, "Base values"); is (ref $xls, "ARRAY", "Return type"); is ($xls->[0]{type}, "xls", "Spreadsheet type"); is ($xls->[0]{sheets}, 2, "Sheet count"); is (ref $xls->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$xls->[0]{sheet}}, 2, "Sheet list count"); cmp_ok ($xls->[0]{version}, ">=", 0.26, "Parser version"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($xls->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($xls->[1]{$cell}, undef, "Formatted cell $cell"); } my @row = Spreadsheet::Read::rows ($xls->[1]); is (scalar @row, 4, "Row'ed rows"); is (scalar @{$row[3]}, 4, "Row'ed columns"); is ($row[0][3], "D1", "Row'ed value D1"); is ($row[3][2], "C4", "Row'ed value C4"); } # This files is generated under Mac OS/X Tiger ok (1, "XLS File fom Mac OS X"); ok ($xls = ReadData ("files/macosx.xls", clip => 0), "Read/Parse Mac OS X xls file"); ok (1, "Base values"); is ($xls->[0]{sheets}, 3, "Sheet count"); is ($xls->[0]{sheet}{Sheet3}, 3, "Sheet labels"); is ($xls->[1]{maxrow}, 25, "MaxRow"); is ($xls->[1]{maxcol}, 3, "MaxCol"); is ($xls->[2]{label}, "Sheet2", "Sheet label"); is ($xls->[2]{maxrow}, 0, "Empty sheet maxrow"); is ($xls->[2]{maxcol}, 0, "Empty sheet maxcol"); ok (1, "Content"); is ($#{$xls->[1]{cell}[3]}, $xls->[1]{maxrow}, "cell structure"); ok (defined $xls->[1]{cell}[$xls->[1]{maxcol}][$xls->[1]{maxrow}], "last cell"); foreach my $x (1 .. 17) { my $cell = cr2cell (1, $x); is ($xls->[1]{$cell}, $x, "Cell $cell"); is ($xls->[1]{cell}[1][$x], $x, "Cell 1, $x"); } foreach my $x (1 .. 25) { my $cell = cr2cell (3, $x); is ($xls->[1]{$cell}, $x, "Cell $cell"); is ($xls->[1]{cell}[3][$x], $x, "Cell 3, $x"); } foreach my $cell (qw( A18 B1 B6 B20 C26 D14 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Cell $cell"); is ($xls->[1]{$cell}, undef, "Cell $c, $r"); } eval { eval "use ".$parser."::FmtDefault"; my ($pm) = map { $INC{$_} } grep m{FmtDefault.pm$}i => keys %INC; if (open my $ph, "<", $pm) { my $l; $l = <$ph> for 1 .. 68; close $ph; if ($l =~ m/'C\*'/) { print STDERR "\n", "# If the next tests give warnings like\n", "# Character in 'C' format wrapped in pack at\n", "# $pm line 68\n", "# Change C* to U* in line 68\n", "# patch -p0 ; s/\bPM\b/$pm/ for @patch; open $ph, ">", "SPE68.diff" or die "SPE68.diff: $!\n"; print $ph @patch; close $ph; } } }; # Tests for empty thingies ok ($xls = ReadData ("files/values.xls"), "True/False values"); ok (my $ss = $xls->[1], "first sheet"); is ($ss->{cell}[1][1], "A1", "unformatted plain text"); is ($ss->{cell}[2][1], " ", "unformatted space"); is ($ss->{cell}[3][1], undef, "unformatted empty"); is ($ss->{cell}[4][1], "0", "unformatted numeric 0"); is ($ss->{cell}[5][1], "1", "unformatted numeric 1"); is ($ss->{cell}[6][1], "", "unformatted a single '"); is ($ss->{A1}, "A1", "formatted plain text"); is ($ss->{B1}, " ", "formatted space"); is ($ss->{C1}, undef, "formatted empty"); is ($ss->{D1}, "0", "formatted numeric 0"); is ($ss->{E1}, "1", "formatted numeric 1"); is ($ss->{F1}, "", "formatted a single '"); { # RT#74976] Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.xls", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.xls has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.xls", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 2, "maxrow 2"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xls", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 2, "maxrow 2"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.xls", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 2, "maxrow 2"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xls", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 2, "maxrow 2"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.xls", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 2, "maxrow 2"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xls", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 1"); is ($ref->[1]{maxcol}, 1, "maxcol 1"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.xls", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xls", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xls", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.xls", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 1"); is ($ref->[1]{maxcol}, 0, "maxcol 1"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } __END__ --- PM 2005-09-15 14:16:36.163623616 +0200 +++ PM 2005-09-15 14:11:56.289171000 +0200 @@ -65,7 +65,7 @@ sub new($;%) { sub TextFmt($$;$) { my($oThis, $sTxt, $sCode) =@_; return $sTxt if((! defined($sCode)) || ($sCode eq '_native_')); - return pack('C*', unpack('n*', $sTxt)); + return pack('U*', unpack('n*', $sTxt)); } #------------------------------------------------------------------------------ # FmtStringDef (for Spreadsheet::ParseExcel::FmtDefault) Spreadsheet-Read-0.84/t/36_xls.t0000644000031300001440000001465713411412624017043 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser; if ($parser = Spreadsheet::Read::parses ("xls")) { plan tests => 188; Test::NoWarnings->import; } else { plan skip_all => "No M\$-Excel parser found"; } sub ReadDataStream { my $file = shift; open my $fh, "<", $file or return undef; ReadData ($fh, parser => "xls", @_); } # ReadDataStream { my $ref; $ref = ReadDataStream ("no_such_file.xls"); ok (!defined $ref, "Nonexistent file"); $ref = ReadDataStream ("files/empty.xls"); ok (!defined $ref, "Empty file"); } my $content; { local $/; open my $xls, "<", "files/test.xls" or die "files/test.xls: $!"; binmode $xls; $content = <$xls>; close $xls; } my $xls; foreach my $base ( [ "files/test.xls", "Read/Parse xls file" ], # [ $content, "Parse xls data" ], ) { my ($txt, $msg) = @$base; ok ($xls = ReadDataStream ($txt), $msg); ok (1, "Base values"); is (ref $xls, "ARRAY", "Return type"); is ($xls->[0]{type}, "xls", "Spreadsheet type"); is ($xls->[0]{sheets}, 2, "Sheet count"); is (ref $xls->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$xls->[0]{sheet}}, 2, "Sheet list count"); cmp_ok ($xls->[0]{version}, ">=", 0.26, "Parser version"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($xls->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Unformatted cell $cell"); is ($xls->[1]{$cell}, undef, "Formatted cell $cell"); } my @row = Spreadsheet::Read::rows ($xls->[1]); is (scalar @row, 4, "Row'ed rows"); is (scalar @{$row[3]}, 4, "Row'ed columns"); is ($row[0][3], "D1", "Row'ed value D1"); is ($row[3][2], "C4", "Row'ed value C4"); } # This files is generated under Mac OS/X Tiger ok (1, "XLS File fom Mac OS X"); ok ($xls = ReadDataStream ("files/macosx.xls", clip => 0), "Read/Parse Mac OS X xls file"); ok (1, "Base values"); is ($xls->[0]{sheets}, 3, "Sheet count"); is ($xls->[0]{sheet}{Sheet3}, 3, "Sheet labels"); is ($xls->[1]{maxrow}, 25, "MaxRow"); is ($xls->[1]{maxcol}, 3, "MaxCol"); is ($xls->[2]{label}, "Sheet2", "Sheet label"); is ($xls->[2]{maxrow}, 0, "Empty sheet maxrow"); is ($xls->[2]{maxcol}, 0, "Empty sheet maxcol"); ok (1, "Content"); is ($#{$xls->[1]{cell}[3]}, $xls->[1]{maxrow}, "cell structure"); ok (defined $xls->[1]{cell}[$xls->[1]{maxcol}][$xls->[1]{maxrow}], "last cell"); foreach my $x (1 .. 17) { my $cell = cr2cell (1, $x); is ($xls->[1]{$cell}, $x, "Cell $cell"); is ($xls->[1]{cell}[1][$x], $x, "Cell 1, $x"); } foreach my $x (1 .. 25) { my $cell = cr2cell (3, $x); is ($xls->[1]{$cell}, $x, "Cell $cell"); is ($xls->[1]{cell}[3][$x], $x, "Cell 3, $x"); } foreach my $cell (qw( A18 B1 B6 B20 C26 D14 )) { my ($c, $r) = cell2cr ($cell); is ($xls->[1]{cell}[$c][$r], undef, "Cell $cell"); is ($xls->[1]{$cell}, undef, "Cell $c, $r"); } eval { eval "use ".$parser."::FmtDefault"; my ($pm) = map { $INC{$_} } grep m{FmtDefault.pm$}i => keys %INC; if (open my $ph, "<", $pm) { my $l; $l = <$ph> for 1 .. 68; close $ph; if ($l =~ m/'C\*'/) { print STDERR "\n", "# If the next tests give warnings like\n", "# Character in 'C' format wrapped in pack at\n", "# $pm line 68\n", "# Change C* to U* in line 68\n", "# patch -p0 ; s/\bPM\b/$pm/ for @patch; open $ph, ">", "SPE68.diff" or die "SPE68.diff: $!\n"; print $ph @patch; close $ph; } } }; # Tests for empty thingies ok ($xls = ReadDataStream ("files/values.xls"), "True/False values"); ok (my $ss = $xls->[1], "first sheet"); is ($ss->{cell}[1][1], "A1", "unformatted plain text"); is ($ss->{cell}[2][1], " ", "unformatted space"); is ($ss->{cell}[3][1], undef, "unformatted empty"); is ($ss->{cell}[4][1], "0", "unformatted numeric 0"); is ($ss->{cell}[5][1], "1", "unformatted numeric 1"); is ($ss->{cell}[6][1], "", "unformatted a single '"); is ($ss->{A1}, "A1", "formatted plain text"); is ($ss->{B1}, " ", "formatted space"); is ($ss->{C1}, undef, "formatted empty"); is ($ss->{D1}, "0", "formatted numeric 0"); is ($ss->{E1}, "1", "formatted numeric 1"); is ($ss->{F1}, "", "formatted a single '"); # Test extended attributes (active) ok ($xls = Spreadsheet::Read->new ("files/Active2.xls", attr => 1), "Active sheet"); is ($xls->sheets, 3, "Book has 3 sheets"); SKIP: { my $v = $xls->[0]{version}; $v < 0.61 and skip "$xls->[0]{parser}-$v does not support the active flag", 3; is ($xls->sheet (1)->{active}, 0, "Sheet 1 is not active"); is ($xls->[2]{active}, 1, "Sheet 2 is active"); is ($xls->sheet (3)->active, 0, "Sheet 3 is not active"); } is ($xls->sheet (1)->attr ("A1")->{type}, "text", "Attr through method A1"); is ($xls->sheet (1)->attr (2, 2)->{type}, "text", "Attr through method B2"); ok ($xls = Spreadsheet::Read->new ("files/attr.xls", attr => 1), "Attributes OO"); is ($xls->[1]{attr}[3][3]{fgcolor}, "#008000", "C3 Forground color direct"); is ($xls->sheet (1)->attr (3, 3)->{fgcolor}, "#008000", "C3 Forground color OO rc hash"); is ($xls->sheet (1)->attr ("C3")->{fgcolor}, "#008000", "C3 Forground color OO cell hash"); is ($xls->sheet (1)->attr (3, 3)->fgcolor, "#008000", "C3 Forground color OO rc method"); is ($xls->sheet (1)->attr ("C3")->fgcolor, "#008000", "C3 Forground color OO cell method"); is ($xls->[1]{attr}[3][3]{bogus_attribute}, undef, "C3 bogus attribute direct"); is ($xls->sheet (1)->attr ("C3")->{bogus_attr}, undef, "C3 bogus attribute OO hash"); is ($xls->sheet (1)->attr ("C3")->bogus_attr, undef, "C3 bogus attribute OO method"); __END__ --- PM 2005-09-15 14:16:36.163623616 +0200 +++ PM 2005-09-15 14:11:56.289171000 +0200 @@ -65,7 +65,7 @@ sub new($;%) { sub TextFmt($$;$) { my($oThis, $sTxt, $sCode) =@_; return $sTxt if((! defined($sCode)) || ($sCode eq '_native_')); - return pack('C*', unpack('n*', $sTxt)); + return pack('U*', unpack('n*', $sTxt)); } #------------------------------------------------------------------------------ # FmtStringDef (for Spreadsheet::ParseExcel::FmtDefault) Spreadsheet-Read-0.84/t/621_clr.t0000644000031300001440000000304512564056336017076 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::XLSX"; } my $tests = 257; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; ok ($xls = ReadData ("files/attr.xlsx", attr => 1), "Excel Attributes testcase"); SKIP: { ok (my $clr = $xls->[$xls->[0]{sheet}{Colours}], "colors"); defined $clr->{attr}[2][2]{fgcolor} or skip "$xls->[0]{parser} $xls->[0]{version} does not reliably support colors yet", 255; is ($clr->{cell}[1][1], "auto", "Auto"); is ($clr->{attr}[1][1]{fgcolor}, undef, "Unspecified font color"); is ($clr->{attr}[1][1]{bgcolor}, undef, "Unspecified fill color"); my @clr = ( [], [ "auto", undef ], [ "red", "#ff0000" ], [ "green", "#008000" ], [ "blue", "#0000ff" ], [ "white", "#ffffff" ], [ "yellow", "#ffff00" ], [ "lightgreen", "#00ff00" ], [ "lightblue", "#00ccff" ], [ "gray", "#808080" ], ); foreach my $col (1 .. $#clr) { my $bg = $clr[$col][1]; is ($clr->{cell}[$col][1], $clr[$col][0], "Column $col header"); foreach my $row (1 .. $#clr) { my $fg = $clr[$row][1]; is ($clr->{cell}[1][$row], $clr[$row][0], "Row $row header"); is ($clr->{attr}[$col][$row]{fgcolor}, $fg, "FG ($col, $row)"); is ($clr->{attr}[$col][$row]{bgcolor}, $bg, "BG ($col, $row)"); } } } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/32_fmt.t0000644000031300001440000000340311163712315017004 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 39; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xls") or plan skip_all => "No M\$-Excel parser found"; my $xls; ok ($xls = ReadData ("files/attr.xls", attr => 1), "Excel Attributes testcase"); my $fmt = $xls->[$xls->[0]{sheet}{Format}]; is ($fmt->{B2}, "merged", "Merged cell left formatted"); is ($fmt->{C2}, "", "Merged cell right formatted"); is ($fmt->{cell}[2][2], "merged", "Merged cell left unformatted"); is ($fmt->{cell}[3][2], "", "Merged cell right unformatted"); is ($fmt->{attr}[2][2]{merged}, 1, "Merged cell left merged"); is ($fmt->{attr}[3][2]{merged}, 1, "Merged cell right merged"); is ($fmt->{B3}, "unlocked", "Unlocked cell"); is ($fmt->{attr}[2][3]{locked}, 0, "Unlocked cell not locked"); is ($fmt->{attr}[2][3]{merged}, 0, "Unlocked cell not merged"); is ($fmt->{attr}[2][3]{hidden}, 0, "Unlocked cell not hidden"); is ($fmt->{B4}, "hidden", "Hidden cell"); is ($fmt->{attr}[2][4]{hidden}, 1, "Hidden cell hidden"); is ($fmt->{attr}[2][4]{merged}, 0, "Hidden cell not merged"); foreach my $r (1 .. 12) { is ($fmt->{cell}[1][$r], 12345, "Unformatted valued A$r"); } is ($fmt->{attr}[1][1]{format}, undef, "Default format"); is ($fmt->{cell}[1][1], $fmt->{A1}, "Formatted valued A1"); is ($fmt->{cell}[1][10], $fmt->{A10}, "Formatted valued A10"); # String foreach my $r (2 .. 9, 11, 12) { isnt ($fmt->{cell}[1][$r], $fmt->{"A$r"}, "Unformatted valued A$r"); } # Not yet. needs more digging #foreach my $r (2 .. 12) { # ok (defined $fmt->{attr}[1][$r]{format}, "Defined format A$r"); # } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/411_clr.t0000644000031300001440000000474313733607341017076 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_ODS} = "Spreadsheet::ParseODS"; } my $tests = 266; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("ods") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_ODS}"; my $ods; ok ($ods = ReadData ("files/attr.ods", attr => 1), "Excel Attributes testcase"); SKIP: { ok (my $clr = $ods->[$ods->[0]{sheet}{Colours}], "colors"); defined $clr->{attr}[2][2]{fgcolor} or skip "$ods->[0]{parser} $ods->[0]{version} does not reliably support colors yet", 255; is ($clr->{cell}[1][1], "auto", "Auto"); is ($clr->{attr}[1][1]{fgcolor}, undef, "Unspecified font color"); is ($clr->{attr}[1][1]{bgcolor}, undef, "Unspecified fill color"); my @clr = ( [], [ "auto", undef ], [ "red", "#ff0000" ], [ "green", "#008000" ], [ "blue", "#0000ff" ], [ "white", "#ffffff" ], [ "yellow", "#ffff00" ], [ "lightgreen", "#00ff00" ], [ "lightblue", "#00ccff" ], [ "gray", "#808080" ], ); foreach my $col (1 .. $#clr) { my $bg = $clr[$col][1]; is ($clr->{cell}[$col][1], $clr[$col][0], "Column $col header"); foreach my $row (1 .. $#clr) { my $fg = $clr[$row][1]; is ($clr->{cell}[1][$row], $clr[$row][0], "Row $row header"); is ($clr->{attr}[$col][$row]{fgcolor}, $fg, "FG ($col, $row)"); is ($clr->{attr}[$col][$row]{bgcolor}, $bg, "BG ($col, $row)"); } } } SKIP: { ok ($ods = Spreadsheet::Read->new ("files/attr.ods", attr => 1), "Attributes OO"); defined $ods->[1]{attr}[3][3]{fgcolor} or skip "$ods->[0]{parser} $ods->[0]{version} does not reliably support colors yet", 5; is ($ods->[1]{attr}[3][3]{fgcolor}, "#008000", "C3 Forground color direct"); is ($ods->sheet (1)->attr (3, 3)->{fgcolor},"#008000", "C3 Forground color OO rc hash"); is ($ods->sheet (1)->attr ("C3")->{fgcolor},"#008000", "C3 Forground color OO cell hash"); is ($ods->sheet (1)->attr (3, 3)->fgcolor, "#008000", "C3 Forground color OO rc method"); is ($ods->sheet (1)->attr ("C3")->fgcolor, "#008000", "C3 Forground color OO cell method"); } is ($ods->[1]{attr}[3][3]{bogus_attribute}, undef, "C3 bogus attribute direct"); is ($ods->sheet (1)->attr ("C3")->{bogus_attr}, undef, "C3 bogus attribute OO hash"); is ($ods->sheet (1)->attr ("C3")->bogus_attr, undef, "C3 bogus attribute OO method"); #unless ($ENV{AUTOMATED_TESTING}) { # Test::NoWarnings::had_no_warnings (); # $tests++; # } done_testing ($tests); Spreadsheet-Read-0.84/t/611_clr.t0000644000031300001440000000447313411413733017071 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_XLSX} = "Spreadsheet::ParseXLSX"; } my $tests = 266; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; Spreadsheet::Read::parses ("xlsx") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_XLSX}"; my $xls; ok ($xls = ReadData ("files/attr.xlsx", attr => 1), "Excel Attributes testcase"); SKIP: { ok (my $clr = $xls->[$xls->[0]{sheet}{Colours}], "colors"); defined $clr->{attr}[2][2]{fgcolor} or skip "$xls->[0]{parser} $xls->[0]{version} does not reliably support colors yet", 255; is ($clr->{cell}[1][1], "auto", "Auto"); is ($clr->{attr}[1][1]{fgcolor}, undef, "Unspecified font color"); is ($clr->{attr}[1][1]{bgcolor}, undef, "Unspecified fill color"); my @clr = ( [], [ "auto", undef ], [ "red", "#ff0000" ], [ "green", "#008000" ], [ "blue", "#0000ff" ], [ "white", "#ffffff" ], [ "yellow", "#ffff00" ], [ "lightgreen", "#00ff00" ], [ "lightblue", "#00ccff" ], [ "gray", "#808080" ], ); foreach my $col (1 .. $#clr) { my $bg = $clr[$col][1]; is ($clr->{cell}[$col][1], $clr[$col][0], "Column $col header"); foreach my $row (1 .. $#clr) { my $fg = $clr[$row][1]; is ($clr->{cell}[1][$row], $clr[$row][0], "Row $row header"); is ($clr->{attr}[$col][$row]{fgcolor}, $fg, "FG ($col, $row)"); is ($clr->{attr}[$col][$row]{bgcolor}, $bg, "BG ($col, $row)"); } } } ok ($xls = Spreadsheet::Read->new ("files/attr.xlsx", attr => 1), "Attributes OO"); is ($xls->[1]{attr}[3][3]{fgcolor}, "#008000", "C3 Forground color direct"); is ($xls->sheet (1)->attr (3, 3)->{fgcolor}, "#008000", "C3 Forground color OO rc hash"); is ($xls->sheet (1)->attr ("C3")->{fgcolor}, "#008000", "C3 Forground color OO cell hash"); is ($xls->sheet (1)->attr (3, 3)->fgcolor, "#008000", "C3 Forground color OO rc method"); is ($xls->sheet (1)->attr ("C3")->fgcolor, "#008000", "C3 Forground color OO cell method"); is ($xls->[1]{attr}[3][3]{bogus_attribute}, undef, "C3 bogus attribute direct"); is ($xls->sheet (1)->attr ("C3")->{bogus_attr}, undef, "C3 bogus attribute OO hash"); is ($xls->sheet (1)->attr ("C3")->bogus_attr, undef, "C3 bogus attribute OO method"); unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/203_csv.t0000644000031300001440000000720513144611370017075 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 125; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "No CSV parser found"; sub ReadDataStream { my $file = shift; open my $fh, "<", $file or return undef; ReadData ($fh, parser => "csv", @_); } # ReadDataStream { my $ref; $ref = ReadDataStream ("no_such_file.csv"); ok (!defined $ref, "Nonexistent file"); $ref = ReadDataStream ("files/empty.csv"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadDataStream ("files/test.csv"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataStream ("files/test_m.csv", sep => ";"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataStream ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } my $data = "a,b,c\n1,2,3\n"; ok ($csv = ReadData ( $data, parser => "csv"), "Parse from plain string"); is ($csv->[1]{C2}, 3, "C2 = 3"); ok ($csv = ReadData (\$data, parser => "csv"), "Parse from ref to plain string"); is ($csv->[1]{C2}, 3, "C2 = 3"); open my $rh, "<", \$data; ok ($csv = ReadData ($rh, parser => "csv"), "Parse from data-ref"); is ($csv->[1]{C2}, 3, "C2 = 3"); if (open my $dh, ">", $data) { print $dh $data; close $dh; ok ($csv = ReadData ($data, parser => "csv"), "Parse from file with bad name"); is ($csv->[1]{C2}, 3, "C2 = 3"); unlink $data; } else { ok (1, "Using a badly named file not allowed: GOOD!"); ok (1, "Using a badly named file not allowed: GOOD!"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/210_csv.t0000644000031300001440000001430713231317045017073 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{SPREADSHEET_READ_CSV} = "Text::CSV_XS"; } my $tests = 171; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "Cannot use $ENV{SPREADSHEET_READ_CSV}"; print STDERR "# Parser: $parser-", $parser->VERSION, "\n"; { my $ref; $ref = ReadData ("no_such_file.csv"); ok (!defined $ref, "Nonexistent file"); $ref = ReadData ("files/empty.csv"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadData ("files/test.csv"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadData ("files/test_m.csv"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadData ("files/test_x.csv", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } { # RT#74976 - Error Received when reading empty sheets foreach my $strip (0 .. 3) { my $ref = ReadData ("files/blank.csv", strip => $strip); ok ($ref, "File with no content - strip $strip"); } } # blank.csv has only one sheet with A1 filled with ' ' { my $ref = ReadData ("files/blank.csv", clip => 0, strip => 0); ok ($ref, "!clip strip 0"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 1); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, "", "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 1, cells => 0); ok ($ref, "!clip strip 1"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], "", "blank (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 2, rc => 0); ok ($ref, "!clip strip 2"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, "", "blank A1"); $ref = ReadData ("files/blank.csv", clip => 0, strip => 3, cells => 0, rc => 0); ok ($ref, "!clip strip 3"); is ($ref->[1]{maxrow}, 3, "maxrow 3"); is ($ref->[1]{maxcol}, 4, "maxcol 4"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 0); ok ($ref, " clip strip 0"); is ($ref->[1]{maxrow}, 1, "maxrow 3"); is ($ref->[1]{maxcol}, 1, "maxcol 4"); is ($ref->[1]{cell}[1][1], " ", "(1, 1) = ' '"); is ($ref->[1]{A1}, " ", "A1 = ' '"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 1); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 1, cells => 0); ok ($ref, " clip strip 1"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 2, rc => 0); ok ($ref, " clip strip 2"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); $ref = ReadData ("files/blank.csv", clip => 1, strip => 3, cells => 0, rc => 0); ok ($ref, " clip strip 3"); is ($ref->[1]{maxrow}, 0, "maxrow 0"); is ($ref->[1]{maxcol}, 0, "maxcol 0"); is ($ref->[1]{cell}[1][1], undef, "undef (1, 1)"); is ($ref->[1]{A1}, undef, "undef A1"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/204_csv.t0000644000031300001440000000571013016541232017072 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 118; use Test::More; require Test::NoWarnings; use Spreadsheet::Read qw( ReadData cell2cr row cellrow ); my $parser = Spreadsheet::Read::parses ("csv") or plan skip_all => "No CSV parser found"; sub ReadDataCSV { ReadData (@_, parser => "csv"); } # ReadDataCSV { my $ref; $ref = ReadDataCSV ("files/empty.txt"); ok (!defined $ref, "Empty file"); } my $csv; ok ($csv = ReadDataCSV ("files/test.txt"), "Read/Parse csv file"); ok (1, "Base values"); is (ref $csv, "ARRAY", "Return type"); is ($csv->[0]{type}, "csv", "Spreadsheet type"); is ($csv->[0]{sheets}, 1, "Sheet count"); is (ref $csv->[0]{sheet}, "HASH", "Sheet list"); is (scalar keys %{$csv->[0]{sheet}}, 1, "Sheet list count"); cmp_ok ($csv->[0]{version}, ">=", 0.01, "Parser version"); is ($csv->[1]{maxrow}, 5, "Last row"); is ($csv->[1]{maxcol}, 19, "Last column"); is ($csv->[1]{cell}[$csv->[1]{maxcol}][$csv->[1]{maxrow}], "LASTFIELD", "Last field"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } my @row = ("A3", "", "C3", "D3", (undef) x 15); is_deeply ([ row ($csv->[1], 3) ], \@row, "Formatted row 3"); is_deeply ([ cellrow ($csv->[1], 3) ], \@row, "Unformatted row 3"); ok ($csv = ReadDataCSV ("files/test_m.txt"), "Read/Parse M\$ csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } ok ($csv = ReadDataCSV ("files/test_x.txt", sep => "=", quote => "_"), "Read/Parse strange csv file"); ok (1, "Defined fields"); foreach my $cell (qw( A1 A2 A3 A4 B1 B2 B4 C3 C4 D1 D3 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], $cell, "Unformatted cell $cell"); is ($csv->[1]{$cell}, $cell, "Formatted cell $cell"); } ok (1, "Undefined fields"); foreach my $cell (qw( B3 C1 C2 D2 D4 )) { my ($c, $r) = cell2cr ($cell); is ($csv->[1]{cell}[$c][$r], "", "Unformatted cell $cell"); is ($csv->[1]{$cell}, "", "Formatted cell $cell"); } unless ($ENV{AUTOMATED_TESTING}) { Test::NoWarnings::had_no_warnings (); $tests++; } done_testing ($tests); Spreadsheet-Read-0.84/t/607_merged.t0000644000031300001440000000526413701561677017575 0ustar00merijnusers00000000000000#!/usr/bin/perl use strict; use warnings; my $tests = 22; use Test::More; require Test::NoWarnings; use Spreadsheet::Read; my $parser = Spreadsheet::Read::parses ("xlsx") or plan skip_all => "No MS-Excel parser found"; $parser eq "Spreadsheet::XLSX" and plan skip_all => "No merged cell support in $parser"; ok (my $ss = ReadData ("files/merged.xlsx", attr => 1)->[1], "Read merged xlsx"); is ($ss->{attr}[1][1]{merged}, 0, "unmerged A1"); is ($ss->{attr}[2][1]{merged}, 1, " merged B1"); is ($ss->{attr}[3][1]{merged}, 1, " merged C1"); is ($ss->{attr}[1][2]{merged}, 1, " merged A2"); is ($ss->{attr}[2][2]{merged}, 1, " merged B2"); is ($ss->{attr}[3][2]{merged}, 1, " merged C2"); is ($ss->{attr}[1][3]{merged}, 1, " merged A3"); is ($ss->{attr}[2][3]{merged}, 0, "unmerged B3"); is ($ss->{attr}[3][3]{merged}, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); ok ($ss = Spreadsheet::Read->new ("files/merged.xlsx", attr => 1, merge => 1)->sheet (1), "Read merged xlsx"); is ($ss->attr (1, 1)->merged, 0, "unmerged A1"); is ($ss->attr (2, 1)->merged, "B1", " merged B1"); is ($ss->attr (3, 1)->merged, "B1", " merged C1"); is ($ss->attr (1, 2)->merged, "A2", " merged A2"); is ($ss->attr (2, 2)->merged, "B1", " merged B2"); is ($ss->attr (3, 2)->merged, "B1", " merged C2"); is ($ss->attr (1, 3)->merged, "A2", " merged A3"); is ($ss->attr (2, 3)->merged, 0, "unmerged B3"); is ($ss->attr (3, 3)->merged, 0, "unmerged C3"); is ($ss->attr ("A1")->merged, 0, "unmerged A1"); is ($ss->attr ("B1")->merged, "B1", " merged B1"); is ($ss->attr ("C1")->merged, "B1", " merged C1"); is ($ss->attr ("A2")->merged, "A2", " merged A2"); is ($ss->attr ("B2")->merged, "B1", " merged B2"); is ($ss->attr ("C2")->merged, "B1", " merged C2"); is ($ss->attr ("A3")->merged, "A2", " merged A3"); is ($ss->attr ("B3")->merged, 0, "unmerged B3"); is ($ss->attr ("C3")->merged, 0, "unmerged C3"); is_deeply ($ss->{merged}, [[1,2,1,3],[2,1,3,2]], "Merged areas"); is ($ss->merged_from ("A1"), "", "merged_from (A1)"); is ($ss->merged_from (1, 1), "", "merged_from (1, 1)"); is ($ss->merged_from ("B1"), "B1", "merged_from (B1)"); is ($ss->merged_from (2, 1), "B1", "merged_from (2, 1)"); is ($ss->merged_from ("C2"), "B1", "merged_from (C2)"); is ($ss->merged_from (3, 2), "B1", "merged_from (3, 2)"); # out of range is ($ss->merged_from ("E5"), undef, "merged_from (E5)"); # illegal ID is ($ss->merged_from (999), undef, "merged_from (999)"); is ($ss->merged_from ("9X"), undef, "merged_from (9X)"); is ($ss->merged_from (999, 99), undef, "merged_from (999, 99)"); is ($ss->merged_from (9, 9, 9), undef, "merged_from (9, 9, 9)"); done_testing; Spreadsheet-Read-0.84/Read.pm0000755000031300001440000023706114016160005016500 0ustar00merijnusers00000000000000#!/pro/bin/perl package Spreadsheet::Read; =head1 NAME Spreadsheet::Read - Read the data from a spreadsheet =head1 SYNOPSIS use Spreadsheet::Read; my $book = ReadData ("test.csv", sep => ";"); my $book = ReadData ("test.sxc"); my $book = ReadData ("test.ods"); my $book = ReadData ("test.xls"); my $book = ReadData ("test.xlsx"); my $book = ReadData ("test.xlsm"); my $book = ReadData ($fh, parser => "xls"); Spreadsheet::Read::add ($book, "sheet.csv"); my $sheet = $book->[1]; # first datasheet my $cell = $book->[1]{A3}; # content of field A3 of sheet 1 my $cell = $book->[1]{cell}[1][3]; # same, unformatted # OO API my $book = Spreadsheet::Read->new ("file.csv"); my $sheet = $book->sheet (1); my $cell = $sheet->cell ("A3"); my $cell = $sheet->cell (1, 3); $book->add ("test.xls"); =cut use 5.8.1; use strict; use warnings; our $VERSION = "0.84"; sub Version { $VERSION } use Carp; use Exporter; our @ISA = qw( Exporter ); our @EXPORT = qw( ReadData cell2cr cr2cell ); our @EXPORT_OK = qw( parses rows cellrow row add ); use Encode qw( decode ); use File::Temp qw( ); use Data::Dumper; my @parsers = ( [ csv => "Text::CSV_XS", "0.71" ], [ csv => "Text::CSV_PP", "1.17" ], [ csv => "Text::CSV", "1.17" ], [ ods => "Spreadsheet::ParseODS", "0.26" ], [ ods => "Spreadsheet::ReadSXC", "0.26" ], [ sxc => "Spreadsheet::ParseODS", "0.26" ], [ sxc => "Spreadsheet::ReadSXC", "0.26" ], [ xls => "Spreadsheet::ParseExcel", "0.34" ], [ xlsx => "Spreadsheet::ParseXLSX", "0.24" ], [ xlsm => "Spreadsheet::ParseXLSX", "0.24" ], [ xlsx => "Spreadsheet::XLSX", "0.13" ], # [ prl => "Spreadsheet::Perl", "" ], [ sc => "Spreadsheet::Read", "0.01" ], [ zzz1 => "Z10::Just::For::Testing", "1.23" ], [ zzz2 => "Z20::Just::For::Testing", "" ], [ zzz3 => "Z30::Just::For::Testing", "1.00" ], # Helper modules [ ios => "IO::Scalar", "" ], [ dmp => "Data::Peek", "" ], ); my %can = ( supports => { map { $_->[1] => $_->[2] } @parsers }); foreach my $p (@parsers) { my $format = $p->[0]; $can{$format} and next; $can{$format} = ""; my $preset = $ENV{"SPREADSHEET_READ_\U$format"} or next; my $min_version = $can{supports}{$preset}; unless ($min_version) { # Catch weirdness like $SPREADSHEET_READ_XLSX = "DBD::Oracle" $can{$format} = "!$preset is not supported for the $format format"; next; } if (eval "local \$_; require $preset" and not $@) { # forcing a parser should still check the version my $ok; my $has = $preset->VERSION; $has =~ s/_[0-9]+$//; # Remove beta-part if ($min_version =~ m/^v([0-9.]+)/) { # clumsy versions my @min = split m/\./ => $1; $has =~ s/^v//; my @has = split m/\./ => $has; $ok = (($has[0] * 1000 + $has[1]) * 1000 + $has[2]) >= (($min[0] * 1000 + $min[1]) * 1000 + $min[2]); } else { # normal versions $ok = $has >= $min_version; } $ok or $preset = "!$preset"; } else { $preset = "!$preset"; } $can{$format} = $preset; } delete $can{supports}; for (@parsers) { my ($flag, $mod, $vsn) = @$_; $can{$flag} and next; eval "require $mod; \$vsn and ${mod}->VERSION (\$vsn); \$can{\$flag} = '$mod'" and next; $_->[0] = "! Cannot use $mod version $vsn: $@"; $can{$flag} = $@ =~ m/need to install|can(?:not|'t) locate/i ? 0 # Not found : ""; # Too old } $can{sc} = __PACKAGE__; # SquirrelCalc is built-in defined $Spreadsheet::ParseExcel::VERSION && $Spreadsheet::ParseExcel::VERSION < 0.61 and *Spreadsheet::ParseExcel::Workbook::get_active_sheet = sub { undef; }; defined $Spreadsheet::ParseODS::VERSION && $Spreadsheet::ParseODS::VERSION < 0.25 and *Spreadsheet::ParseODS::Workbook::get_active_sheet = sub { undef; }; my $debug = 0; my %def_opts = ( rc => 1, cells => 1, attr => 0, clip => undef, # $opt{cells}; strip => 0, pivot => 0, dtfmt => "yyyy-mm-dd", # Format 14 debug => 0, passwd => undef, parser => undef, sep => undef, quote => undef, label => undef, merge => 0, ); my @def_attr = ( type => "text", fgcolor => undef, bgcolor => undef, font => undef, size => undef, format => undef, halign => "left", valign => "top", bold => 0, italic => 0, uline => 0, wrap => 0, merged => 0, hidden => 0, locked => 0, enc => "utf-8", # $ENV{LC_ALL} // $ENV{LANG} // ... formula => undef, ); # Helper functions sub _dump { my ($label, $ref) = @_; if ($can{dmp}) { print STDERR Data::Peek::DDumper ({ $label => $ref }); } else { print STDERR Data::Dumper->Dump ([$ref], [$label]); } my @c = caller (1); print STDERR "<<- $c[1]:$c[2]|$c[3]\n"; } # _dump sub _parser { my $type = shift or return ""; $type = lc $type; my $ods = $can{ods} ? "ods" : "sxc"; # Aliases and fullnames $type eq "excel" and return "xls"; $type eq "excel2007" and return "xlsx"; $type eq "xlsm" and return "xlsx"; $type eq "oo" and return $ods; # $type eq "sxc" and return $ods; $type eq "openoffice" and return $ods; $type eq "libreoffice" and return $ods; $type eq "perl" and return "prl"; $type eq "scalc" and return "sc"; $type eq "squirrelcalc" and return "sc"; return exists $can{$type} ? $type : ""; } # _parser sub new { my $class = shift; my $r = ReadData (@_); unless ($r) { @_ and return; # new with arguments failed to open resource $r = [{ parsers => [], error => undef, sheets => 0, sheet => { }, }]; } bless $r => $class; } # new sub parsers { ref $_[0] eq __PACKAGE__ and shift; my @c; for (sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } grep { $_->[0] !~ m{^(?:dmp|ios|!.*)$} } @parsers) { my ($typ, $mod, $min) = @$_; eval "local \$_; require $mod"; my $vsn = $@ ? "-" : eval { $mod->VERSION }; push @c => { ext => $typ, mod => $mod, min => $min, vsn => $vsn, def => $can{$typ} eq $mod ? "*" : "", }; } @c; } # parsers # Spreadsheet::Read::parses ("csv") or die "Cannot parse CSV" sub parses { ref $_[0] eq __PACKAGE__ and shift; my $type = shift or return sort grep { !m/^(?:dmp|ios)/ && $can{$_} !~ m{^!} } keys %can; $type = _parser ($type) or return 0; if ($can{$type} =~ m/^!\s*(.*)/) { $@ = $1; return 0; } return $can{$type}; } # parses sub sheets { my $ctrl = shift->[0]; my %s = %{$ctrl->{sheet}}; wantarray ? sort { $s{$a} <=> $s{$b} } keys %s : $ctrl->{sheets}; } # sheets # col2label (4) => "D" sub col2label { ref $_[0] eq __PACKAGE__ and shift; my $c = shift; defined $c && $c > 0 or return ""; my $cell = ""; while ($c) { use integer; substr $cell, 0, 0, chr (--$c % 26 + ord "A"); $c /= 26; } $cell; } # col2label # cr2cell (4, 18) => "D18" # No prototype to allow 'cr2cell (@rowcol)' sub cr2cell { ref $_[0] eq __PACKAGE__ and shift; my ($c, $r) = @_; defined $c && defined $r && $c > 0 && $r > 0 or return ""; col2label ($c) . $r; } # cr2cell # cell2cr ("D18") => (4, 18) sub cell2cr { ref $_[0] eq __PACKAGE__ and shift; my ($cc, $r) = (uc ($_[0]||"") =~ m/^([A-Z]+)([0-9]+)$/) or return (0, 0); my $c = 0; while ($cc =~ s/^([A-Z])//) { $c = 26 * $c + 1 + ord ($1) - ord ("A"); } ($c, $r); } # cell2cr # my @row = cellrow ($book->[1], 1); # my @row = $book->cellrow (1, 1); sub cellrow { my $sheet = ref $_[0] eq __PACKAGE__ ? (shift)->[shift] : shift or return; ref $sheet eq "HASH" && exists $sheet->{cell} or return; exists $sheet->{maxcol} && exists $sheet->{maxrow} or return; my $row = shift or return; $row > 0 && $row <= $sheet->{maxrow} or return; my $s = $sheet->{cell}; map { $s->[$_][$row] } 1..$sheet->{maxcol}; } # cellrow # my @row = row ($book->[1], 1); # my @row = $book->row (1, 1); sub row { my $sheet = ref $_[0] eq __PACKAGE__ ? (shift)->[shift] : shift or return; ref $sheet eq "HASH" && exists $sheet->{cell} or return; exists $sheet->{maxcol} && exists $sheet->{maxrow} or return; my $row = shift or return; $row > 0 && $row <= $sheet->{maxrow} or return; map { $sheet->{cr2cell ($_, $row)} } 1..$sheet->{maxcol}; } # row # Convert {cell}'s [column][row] to a [row][column] list # my @rows = rows ($book->[1]); sub rows { my $sheet = ref $_[0] eq __PACKAGE__ ? (shift)->[shift] : shift or return; ref $sheet eq "HASH" && exists $sheet->{cell} or return; exists $sheet->{maxcol} && exists $sheet->{maxrow} or return; my $s = $sheet->{cell}; map { my $r = $_; [ map { $s->[$_][$r] } 1..$sheet->{maxcol} ]; } 1..$sheet->{maxrow}; } # rows sub sheet { my ($book, $sheet) = @_; $book && $sheet or return; my $class = "Spreadsheet::Read::Sheet"; $sheet =~ m/^[0-9]+$/ && $sheet >= 1 && $sheet <= $book->[0]{sheets} and return bless $book->[$sheet] => $class; exists $book->[0]{sheet}{$sheet} and return bless $book->[$book->[0]{sheet}{$sheet}] => $class; foreach my $idx (1 .. $book->[0]{sheets}) { $book->[$idx]{label} eq $sheet and return bless $book->[$idx] => $class; } return; } # sheet # If option "clip" is set, remove the trailing rows and # columns in each sheet that contain no visible data sub _clipsheets { my ($opt, $ref) = @_; $ref->[0]{sheets} or return $ref; my ($rc, $cl) = ($opt->{rc}, $opt->{cells}); my ($oc, $os, $oa) = ($opt->{clip}, $opt->{strip}, $opt->{attr}); # Strip leading/trailing spaces if ($os || $oc) { foreach my $sheet (1 .. $ref->[0]{sheets}) { $ref->[$sheet]{indx} = $sheet; my $ss = $ref->[$sheet]; $ss->{maxrow} && $ss->{maxcol} or next; my ($mc, $mr) = (0, 0); foreach my $row (1 .. $ss->{maxrow}) { foreach my $col (1 .. $ss->{maxcol}) { if ($rc) { defined $ss->{cell}[$col][$row] or next; $os & 2 and $ss->{cell}[$col][$row] =~ s/\s+$//; $os & 1 and $ss->{cell}[$col][$row] =~ s/^\s+//; if (length $ss->{cell}[$col][$row]) { $col > $mc and $mc = $col; $row > $mr and $mr = $row; } } if ($cl) { my $cell = cr2cell ($col, $row); defined $ss->{$cell} or next; $os & 2 and $ss->{$cell} =~ s/\s+$//; $os & 1 and $ss->{$cell} =~ s/^\s+//; if (length $ss->{$cell}) { $col > $mc and $mc = $col; $row > $mr and $mr = $row; } } } } $oc && ($mc < $ss->{maxcol} || $mr < $ss->{maxrow}) or next; # Remove trailing empty columns foreach my $col (($mc + 1) .. $ss->{maxcol}) { $rc and undef $ss->{cell}[$col]; $oa and undef $ss->{attr}[$col]; $cl or next; my $c = col2label ($col); delete $ss->{"$c$_"} for 1 .. $ss->{maxrow}; } # Remove trailing empty rows foreach my $row (($mr + 1) .. $ss->{maxrow}) { foreach my $col (1 .. $mc) { $cl and delete $ss->{cr2cell ($col, $row)}; $rc and undef $ss->{cell} [$col][$row]; $oa and undef $ss->{attr} [$col][$row]; } } ($ss->{maxrow}, $ss->{maxcol}) = ($mr, $mc); } } if ($opt->{pivot}) { foreach my $sheet (1 .. $ref->[0]{sheets}) { my $ss = $ref->[$sheet]; $ss->{maxrow} || $ss->{maxcol} or next; my $mx = $ss->{maxrow} > $ss->{maxcol} ? $ss->{maxrow} : $ss->{maxcol}; foreach my $row (2 .. $mx) { foreach my $col (1 .. ($row - 1)) { $opt->{rc} and ($ss->{cell}[$col][$row], $ss->{cell}[$row][$col]) = ($ss->{cell}[$row][$col], $ss->{cell}[$col][$row]); $opt->{cells} and ($ss->{cr2cell ($col, $row)}, $ss->{cr2cell ($row, $col)}) = ($ss->{cr2cell ($row, $col)}, $ss->{cr2cell ($col, $row)}); } } ($ss->{maxcol}, $ss->{maxrow}) = ($ss->{maxrow}, $ss->{maxcol}); } } $ref; } # _clipsheets # Convert a single color (index) to a color sub _xls_color { my $clr = shift; defined $clr or return undef; $clr eq "#000000" and return undef; $clr =~ m/^#[0-9a-fA-F]+$/ and return lc $clr; $clr == 0 || $clr == 32767 and return undef; # Default fg color return "#" . lc Spreadsheet::ParseExcel->ColorIdxToRGB ($clr); } # _xls_color # Convert a fill [ $pattern, $front_color, $back_color ] to a single background sub _xls_fill { my ($p, $fg, $bg) = @_; defined $p or return undef; $p == 32767 and return undef; # Default fg color $p == 0 && !defined $bg and return undef; # No fill bg color $p == 1 and return _xls_color ($fg); $bg < 8 || $bg > 63 and return undef; # see Workbook.pm#106 return _xls_color ($bg); } # _xls_fill sub ReadData { my $txt = shift or return; my %opt; if (@_) { if (ref $_[0] eq "HASH") { %opt = %{shift @_} } elsif (@_ % 2 == 0) { %opt = @_ } } # Aliasses exists $opt{transpose} && !exists $opt{pivot} and $opt{pivot} = delete $opt{transpose}; exists $opt{trim} && !exists $opt{strip} and $opt{strip} = delete $opt{trim}; exists $opt{rc} or $opt{rc} = $def_opts{rc}; exists $opt{cells} or $opt{cells} = $def_opts{cells}; exists $opt{attr} or $opt{attr} = $def_opts{attr}; exists $opt{clip} or $opt{clip} = $opt{cells}; exists $opt{strip} or $opt{strip} = $def_opts{strip}; exists $opt{dtfmt} or $opt{dtfmt} = $def_opts{dtfmt}; exists $opt{merge} or $opt{merge} = $def_opts{merge}; # $debug = $opt{debug} || 0; $debug = defined $opt{debug} ? $opt{debug} : $def_opts{debug}; $debug > 4 and _dump (Options => \%opt); my %parser_opts = map { $_ => $opt{$_} } grep { !exists $def_opts{$_} } keys %opt; my $_parser = _parser ($opt{parser}); my $io_ref = ref ($txt) =~ m/GLOB|IO/ ? $txt : undef; my $io_fil = $io_ref ? 0 : $txt =~ m/\0/ ? 0 : do { no warnings "newline"; -f $txt }; my $io_txt = $io_ref || $io_fil ? 0 : 1; $io_fil && ! -s $txt and do { $@ = "$txt is empty"; return }; $io_ref && eof $txt and do { $@ = "Empty stream"; return }; if ($opt{parser} ? $_parser eq "csv" : ($io_fil && $txt =~ m/\.(csv)$/i)) { $can{csv} or croak "CSV parser not installed"; my $label = defined $opt{label} ? $opt{label} : $io_fil ? $txt : "IO"; $debug and print STDERR "Opening CSV $label using $can{csv}-", $can{csv}->VERSION, "\n"; my @data = ( { type => "csv", parser => $can{csv}, version => $can{csv}->VERSION, parsers => [ { type => "csv", parser => $can{csv}, version => $can{csv}->VERSION, }], error => undef, quote => '"', sepchar => ',', sheets => 1, sheet => { $label => 1 }, }, { parser => 0, label => $label, maxrow => 0, maxcol => 0, cell => [], attr => [], merged => [], active => 1, }, ); my ($sep, $quo, $in) = (",", '"'); defined $opt{sep} and $sep = $opt{sep}; defined $opt{quote} and $quo = $opt{quote}; $debug > 8 and _dump (debug => { data => \@data, txt => $txt, io_ref => $io_ref, io_fil => $io_fil }); if ($io_fil) { unless (defined $opt{quote} && defined $opt{sep}) { open $in, "<", $txt or return; my $l1 = <$in>; $quo = defined $opt{quote} ? $opt{quote} : '"'; $sep = # If explicitly set, use it defined $opt{sep} ? $opt{sep} : # otherwise start auto-detect with quoted strings $l1 =~ m/["0-9];["0-9;]/ ? ";" : $l1 =~ m/["0-9],["0-9,]/ ? "," : $l1 =~ m/["0-9]\t["0-9,]/ ? "\t" : $l1 =~ m/["0-9]\|["0-9,]/ ? "|" : # If neither, then for unquoted strings $l1 =~ m/\w;[\w;]/ ? ";" : $l1 =~ m/\w,[\w,]/ ? "," : $l1 =~ m/\w\t[\w,]/ ? "\t" : $l1 =~ m/\w\|[\w,]/ ? "|" : "," ; close $in; } open $in, "<", $txt or return; } elsif ($io_ref) { $in = $txt; } elsif (ref $txt eq "SCALAR") { open $in, "<", $txt or croak "Cannot open input: $!"; } elsif ($txt =~ m/[\r\n,;]/) { open $in, "<", \$txt or croak "Cannot open input: $!"; } else { warn "Input type ", ref $txt, " might not be supported. Please file a ticket\n"; $in = $txt; # Now pray ... } $debug > 1 and print STDERR "CSV sep_char '$sep', quote_char '$quo'\n"; my $csv = $can{csv}->new ({ %parser_opts, sep_char => ($data[0]{sepchar} = $sep), quote_char => ($data[0]{quote} = $quo), keep_meta_info => 1, binary => 1, auto_diag => 1, }) or croak "Cannot create a csv ('$sep', '$quo') parser!"; while (my $row = $csv->getline ($in)) { my @row = @$row or last; my $r = ++$data[1]{maxrow}; @row > $data[1]{maxcol} and $data[1]{maxcol} = @row; foreach my $c (0 .. $#row) { my $val = $row[$c]; my $cell = cr2cell ($c + 1, $r); $opt{rc} and $data[1]{cell}[$c + 1][$r] = $val; $opt{cells} and $data[1]{$cell} = $val; $opt{attr} and $data[1]{attr}[$c + 1][$r] = { @def_attr }; } } $csv->eof () or $data[0]{error} = [ $csv->error_diag ]; close $in; for (@{$data[1]{cell}}) { defined or $_ = []; } return _clipsheets \%opt, [ @data ]; } if ($io_txt) { # && $_parser !~ m/^xlsx?$/) { if ( # /etc/magic: Microsoft Office Document $txt =~ m{\A(\376\067\0\043 |\320\317\021\340\241\261\032\341 |\333\245-\0\0\0)}x # /usr/share/misc/magic || $txt =~ m{\A.{2080}Microsoft Excel 5.0 Worksheet} || $txt =~ m{\A\x09\x04\x06\x00\x00\x00\x10\x00} ) { $can{xls} or croak "Spreadsheet::ParseExcel not installed"; my $tmpfile; if ($can{ios}) { # Do not use a temp file if IO::Scalar is available $tmpfile = \$txt; } else { $tmpfile = File::Temp->new (SUFFIX => ".xls", UNLINK => 1); binmode $tmpfile; print $tmpfile $txt; close $tmpfile; } open $io_ref, "<", $tmpfile or do { $@ = $!; return }; $io_txt = 0; $_parser = _parser ($opt{parser} = "xls"); } elsif ( # /usr/share/misc/magic $txt =~ m{\APK\003\004.{4,30}(?:\[Content_Types\]\.xml|_rels/\.rels)} ) { $can{xlsx} or croak "XLSX parser not installed"; my $tmpfile; if ($can{ios}) { # Do not use a temp file if IO::Scalar is available $tmpfile = \$txt; } else { $tmpfile = File::Temp->new (SUFFIX => ".xlsx", UNLINK => 1); binmode $tmpfile; print $tmpfile $txt; close $tmpfile; } open $io_ref, "<", $tmpfile or do { $@ = $!; return }; $io_txt = 0; $_parser = _parser ($opt{parser} = "xlsx"); } elsif ( # /usr/share/misc/magic $txt =~ m{\APK\003\004.{9,30}\Qmimetypeapplication/vnd.oasis.opendocument.spreadsheet} ) { $can{ods} or croak "ODS parser not installed"; my $tmpfile; if ($can{ios}) { # Do not use a temp file if IO::Scalar is available $tmpfile = \$txt; } else { $tmpfile = File::Temp->new (SUFFIX => ".ods", UNLINK => 1); binmode $tmpfile; print $tmpfile $txt; close $tmpfile; } open $io_ref, "<", $tmpfile or do { $@ = $!; return }; $io_txt = 0; $_parser = _parser ($opt{parser} = "ods"); } elsif (!$io_ref && $txt =~ m/\.xls[xm]?$/i) { $@ = "Cannot open $txt as file"; return; } } if ($opt{parser} ? $_parser =~ m/^(?:xlsx?)$/ : ($io_fil && $txt =~ m/\.(xls[xm]?)$/i && ($_parser = _parser ($1)))) { my $parse_type = $_parser =~ m/x$/i ? "XLSX" : "XLS"; my $parser = $can{lc $parse_type} or croak "Parser for $parse_type is not installed"; #$debug and print STDERR __FILE__, "#", __LINE__, " | $_parser | $parser | $parse_type\n"; $debug and print STDERR "Opening $parse_type ", $io_ref ? "" : $txt, " using $parser-", $can{lc $parse_type}->VERSION, "\n"; $opt{passwd} and $parser_opts{Password} = $opt{passwd}; my $oBook = eval { $io_ref ? $parse_type eq "XLSX" ? $can{xlsx} =~ m/::XLSX$/ ? $parser->new ($io_ref) : $parser->new (%parser_opts)->parse ($io_ref) : $parser->new (%parser_opts)->Parse ($io_ref) : $parse_type eq "XLSX" ? $can{xlsx} =~ m/::XLSX$/ ? $parser->new ($txt) : $parser->new (%parser_opts)->parse ($txt) : $parser->new (%parser_opts)->Parse ($txt); }; unless ($oBook) { # cleanup will fail on folders with spaces. (my $msg = $@) =~ s/ at \S+ line \d+.*//s; croak "$parse_type parser cannot parse data: $msg"; } $debug > 8 and _dump (oBook => $oBook); # WorkBook keys: # aColor _CurSheet Format SheetCount # ActiveSheet _CurSheet_ FormatStr _skip_chart # Author File NotSetCell _string_contin # BIFFVersion Flg1904 Object Version # _buffer FmtClass PkgStr Worksheet # CellHandler Font _previous_info my @data = ( { type => lc $parse_type, parser => $can{lc $parse_type}, version => $can{lc $parse_type}->VERSION, parsers => [{ type => lc $parse_type, parser => $can{lc $parse_type}, version => $can{lc $parse_type}->VERSION, }], error => undef, sheets => $oBook->{SheetCount} || 0, sheet => {}, } ); # Overrule the default date format strings my %def_fmt = ( 0x0E => lc $opt{dtfmt}, # m-d-yy 0x0F => "d-mmm-yyyy", # d-mmm-yy 0x11 => "mmm-yyyy", # mmm-yy 0x16 => "yyyy-mm-dd hh:mm", # m-d-yy h:mm ); $oBook->{FormatStr}{$_} = $def_fmt{$_} for keys %def_fmt; my $oFmt = $parse_type eq "XLSX" ? $can{xlsx} =~ m/::XLSX$/ ? Spreadsheet::XLSX::Fmt2007->new : Spreadsheet::ParseExcel::FmtDefault->new : Spreadsheet::ParseExcel::FmtDefault->new; $debug > 20 and _dump ("oBook before conversion", $oBook); if ($parse_type eq "ODS" and !exists $oBook->{SheetCount}) { my $styles = delete $oBook->{_styles}; my $sheets = delete $oBook->{_sheets}; if ($sheets && ref $sheets eq "ARRAY") { $styles = ($styles || {})->{styles} || {}; $data[0]{sheets} = $oBook->{SheetCount} = scalar @{$sheets}; $oBook->{Worksheet} = []; *S::R::Sheet::get_merged_areas = sub { [] }; my $x = 0; foreach my $sh (@{$sheets}) { push @{$oBook->{Worksheet}} => bless { Name => $sh->{label}, Cells => [], MinRow => $sh->{col_min}, MaxRow => $sh->{row_max}, MinCol => $sh->{col_min}, MaxCol => $sh->{row_max}, RowHidden => $sh->{hidden_rows}, ColHidden => $sh->{hidden_cols}, _SheetNo => $x++, } => "S::R::Sheet"; # header_cols # header_rows # print_areas # sheet_hidden # tab_color *S::R::Cell::Value = sub { $_[0]{Raw} }; *S::R::Cell::is_merged = sub { 0 }; my $r = 0; foreach my $row (@{$sh->{data}}) { $#$row > $oBook->{Worksheet}[-1]{MaxCol} and $oBook->{Worksheet}[-1]{MaxCol} = $#$row; $oBook->{Worksheet}[-1]{Cells}[$r++] = [ map { bless { Code => undef, Format => $_->{format}, Formula => $_->{formula}, Hidden => undef, Merged => undef, # use || instead of // for now # even though it is undesirable Type => $_->{type} || "", Val => $_->{value} || $_->{unformatted}, Raw => $_->{unformatted} || $_->{value}, _Style => $styles->{$_->{style} || ""} || $_->{style}, # hyperlink } => "S::R::Cell" } @{$row} ]; } --$r > $oBook->{Worksheet}[-1]{MaxRow} and $oBook->{Worksheet}[-1]{MaxRow} = $r; } } } $debug and print STDERR "\t$data[0]{sheets} sheets\n"; my $active_sheet = $oBook->get_active_sheet || $oBook->{ActiveSheet} || $oBook->{SelectedSheet}; my $current_sheet = 0; foreach my $oWkS (@{$oBook->{Worksheet}}) { $debug > 8 and _dump ("oWkS", $oWkS); $current_sheet++; $opt{clip} and !defined $oWkS->{Cells} and next; # Skip empty sheets my %sheet = ( parser => 0, label => $oWkS->{Name}, maxrow => 0, maxcol => 0, cell => [], attr => [], merged => [], active => 0, ); # $debug and $sheet{_parser} = $oWkS; defined $sheet{label} or $sheet{label} = "-- unlabeled --"; exists $oWkS->{MinRow} and $sheet{minrow} = $oWkS->{MinRow} + 1; exists $oWkS->{MaxRow} and $sheet{maxrow} = $oWkS->{MaxRow} + 1; exists $oWkS->{MinCol} and $sheet{mincol} = $oWkS->{MinCol} + 1; exists $oWkS->{MaxCol} and $sheet{maxcol} = $oWkS->{MaxCol} + 1; $sheet{merged} = [ map { $_->[0] } sort { $a->[1] cmp $b->[1] } map {[ $_, pack "NNNN", @$_ ]} map {[ map { $_ + 1 } @{$_}[1,0,3,2] ]} @{$oWkS->get_merged_areas || []}]; my $sheet_idx = 1 + @data; $debug and print STDERR "\tSheet $sheet_idx '$sheet{label}' $sheet{maxrow} x $sheet{maxcol}\n"; if (defined $active_sheet) { # _SheetNo is 0-based my $sheet_no = defined $oWkS->{_SheetNo} ? $oWkS->{_SheetNo} : $current_sheet - 1; $sheet_no eq $active_sheet and $sheet{active} = 1; } # Sheet keys: # _Book FooterMargin MinCol RightMargin # BottomMargin FooterMergin MinRow RightMergin # BottomMergin HCenter Name RowHeight # Cells Header NoColor RowHidden # ColFmtNo HeaderMargin NoOrient Scale # ColHidden HeaderMergin NoPls SheetHidden # ColWidth Kind Notes _SheetNo # Copis Landscape PageFit SheetType # DefColWidth LeftMargin PageStart SheetVersion # DefRowHeight LeftMergin PaperSize TopMargin # Draft LeftToRight _Pos TopMergin # FitHeight MaxCol PrintGrid UsePage # FitWidth MaxRow PrintHeaders VCenter # Footer MergedArea Res VRes if (exists $oWkS->{MinRow}) { my $hiddenRows = $oWkS->{RowHidden} || []; my $hiddenCols = $oWkS->{ColHidden} || []; if ($opt{clip}) { my ($mr, $mc) = (-1, -1); foreach my $r ($oWkS->{MinRow} .. $sheet{maxrow}) { foreach my $c ($oWkS->{MinCol} .. $sheet{maxcol}) { my $oWkC = $oWkS->{Cells}[$r][$c] or next; defined (my $val = $oWkC->{Val}) or next; $val eq "" and next; $r > $mr and $mr = $r; $c > $mc and $mc = $c; } } ($sheet{maxrow}, $sheet{maxcol}) = ($mr + 1, $mc + 1); } foreach my $r ($oWkS->{MinRow} .. $sheet{maxrow}) { foreach my $c ($oWkS->{MinCol} .. $sheet{maxcol}) { my $oWkC = $oWkS->{Cells}[$r][$c] or next; #defined (my $val = $oWkC->{Val}) or next; my $val = $oWkC->{Val}; if (defined $val and my $enc = $oWkC->{Code}) { $enc eq "ucs2" and $val = decode ("utf-16be", $val); } my $cell = cr2cell ($c + 1, $r + 1); $opt{rc} and $sheet{cell}[$c + 1][$r + 1] = $val; # Original my $fmt; my $FmT = $oWkC->{Format}; if ($FmT) { unless (ref $FmT) { $fmt = $FmT; $FmT = {}; } } else { $FmT = {}; } foreach my $attr (qw( AlignH AlignV FmtIdx Hidden Lock Wrap )) { exists $FmT->{$attr} or $FmT->{$attr} = 0; } exists $FmT->{Fill} or $FmT->{Fill} = [ 0 ]; exists $FmT->{Font} or $FmT->{Font} = undef; unless (defined $fmt) { $fmt = $FmT->{FmtIdx} ? $oBook->{FormatStr}{$FmT->{FmtIdx}} : undef; } lc $oWkC->{Type} eq "float" and $oWkC->{Type} = "Numeric"; if ($oWkC->{Type} eq "Numeric") { # Fixed in 0.33 and up # see Spreadsheet/ParseExcel/FmtDefault.pm $FmT->{FmtIdx} == 0x0e || $FmT->{FmtIdx} == 0x0f || $FmT->{FmtIdx} == 0x10 || $FmT->{FmtIdx} == 0x11 || $FmT->{FmtIdx} == 0x16 || (defined $fmt && $fmt =~ m{^[dmy][-\\/dmy]*$}) and $oWkC->{Type} = "Date"; $FmT->{FmtIdx} == 0x09 || $FmT->{FmtIdx} == 0x0a || (defined $fmt && $fmt =~ m{^0+\.0+%$}) and $oWkC->{Type} = "Percentage"; } defined $fmt and $fmt =~ s/\\//g; $opt{cells} and # Formatted value $sheet{$cell} = defined $val ? $FmT && exists $def_fmt{$FmT->{FmtIdx}} ? $oFmt->ValFmt ($oWkC, $oBook) : $oWkC->Value : undef; if ($opt{attr}) { my $FnT = $FmT->{Font}; my $fmi = $FmT->{FmtIdx} ? $oBook->{FormatStr}{$FmT->{FmtIdx}} : undef; $fmi and $fmi =~ s/\\//g; my $merged = (defined $oWkC->{Merged} ? $oWkC->{Merged} : $oWkC->is_merged) || 0; $sheet{attr}[$c + 1][$r + 1] = { @def_attr, type => lc $oWkC->{Type}, enc => $oWkC->{Code}, merged => $merged, hidden => ($hiddenRows->[$r] || $hiddenCols->[$c] ? 1 : defined $oWkC->{Hidden} ? $oWkC->{Hidden} : $FmT->{Hidden}) || 0, locked => $FmT->{Lock} || 0, format => $fmi, halign => [ undef, qw( left center right fill justify ), undef, "equal_space" ]->[$FmT->{AlignH}], valign => [ qw( top center bottom justify equal_space )]->[$FmT->{AlignV}], wrap => $FmT->{Wrap}, font => $FnT->{Name}, size => $FnT->{Height}, bold => $FnT->{Bold}, italic => $FnT->{Italic}, uline => $FnT->{Underline}, fgcolor => _xls_color ($FnT->{Color}), bgcolor => _xls_fill (@{$FmT->{Fill}}), formula => $oWkC->{Formula}, }; #_dump "cell", $sheet{attr}[$c + 1][$r + 1]; if ($opt{merge} && $merged and my $p_cell = Spreadsheet::Read::Sheet::merged_from (\%sheet, $c + 1, $r + 1)) { warn $p_cell; $sheet{attr}[$c + 1][$r + 1]{merged} = $p_cell; if ($cell ne $p_cell) { my ($C, $R) = cell2cr ($p_cell); $sheet{cell}[$c + 1][$r + 1] = $sheet{cell}[$C][$R]; $sheet{$cell} = $sheet{$p_cell}; } } } } } } for (@{$sheet{cell}}) { defined or $_ = []; } push @data, { %sheet }; # $data[0]{sheets}++; if ($sheet{label} eq "-- unlabeled --") { $sheet{label} = ""; } else { $data[0]{sheet}{$sheet{label}} = $#data; } } return _clipsheets \%opt, [ @data ]; } if ($opt{parser} ? $_parser =~ m/^(ods)$/ : ($io_fil && $txt =~ m/(ods)$/i && ($_parser = _parser ($1))) and ($can{$_parser} || "") !~ m/sxc/i) { my $parse_type = "ODS"; my $parser = $can{lc $parse_type} or croak "Parser for $parse_type is not installed"; #$debug and print STDERR __FILE__, "#", __LINE__, " | $_parser | $parser | $parse_type\n"; $debug and print STDERR "Opening $parse_type ", $io_ref ? "" : $txt, " using $parser-", $can{lc $parse_type}->VERSION, "\n"; $opt{passwd} and $parser_opts{Password} = $opt{passwd}; my $oBook = eval { $io_ref ? $parser->new (readonly => 1, %parser_opts)->parse ($io_ref) : $parser->new (readonly => 1, %parser_opts)->parse ($txt) }; unless ($oBook) { # cleanup will fail on folders with spaces. (my $msg = $@) =~ s/ at \S+ line \d+.*//s; croak "$parse_type parser cannot parse data: $msg"; } $debug > 8 and _dump (oBook => $oBook); my @data = ( { type => lc $parse_type, parser => $can{lc $parse_type}, version => $can{lc $parse_type}->VERSION, parsers => [{ type => lc $parse_type, parser => $can{lc $parse_type}, version => $can{lc $parse_type}->VERSION, }], error => undef, sheets => scalar $oBook->worksheets, sheet => {}, } ); # $debug and $data[0]{_parser} = $oBook; $debug and print STDERR "\t$data[0]{sheets} sheets\n"; my $active_sheet = $oBook->get_active_sheet; my $current_sheet = 0; foreach my $oWkS ($oBook->worksheets) { $current_sheet++; $opt{clip} && $oWkS->row_max < $oWkS->row_min && $oWkS->col_max < $oWkS->col_min and next; # Skip empty sheets my %sheet = ( parser => 0, label => $oWkS->label, maxrow => $oWkS->row_max+1, maxcol => $oWkS->col_max+1, cell => [], attr => [], merged => [], active => 0, ); # $debug and $sheet{_parser} = $oWkS; defined $sheet{label} or $sheet{label} = "-- unlabeled --"; $sheet{merged} = [ map { $_->[0] } sort { $a->[1] cmp $b->[1] } map {[ $_, pack "NNNN", @$_ ]} map {[ map { $_ + 1 } @{$_}[1,0,3,2] ]} @{$oWkS->get_merged_areas || []}]; my $sheet_idx = 1 + @data; $debug and print STDERR "\tSheet $sheet_idx '$sheet{label}' $sheet{maxrow} x $sheet{maxcol}\n"; if (defined $active_sheet) { my $sheet_no = $current_sheet - 1; $sheet_no eq $active_sheet and $sheet{active} = 1; } my $hiddenRows = $oWkS->hidden_rows || []; my $hiddenCols = $oWkS->hidden_cols || []; if ($opt{clip}) { my ($mr, $mc) = (-1, -1); foreach my $r ($oWkS->row_min .. $sheet{maxrow}-1) { foreach my $c ($oWkS->col_min .. $sheet{maxcol}-1) { my $oWkC = $oWkS->get_cell($r, $c) or next; defined (my $val = $oWkC->value) or next; $val eq "" and next; $r > $mr and $mr = $r; $c > $mc and $mc = $c; } } ($sheet{maxrow}, $sheet{maxcol}) = ($mr + 1, $mc + 1); } foreach my $r ($oWkS->row_min .. $sheet{maxrow}) { foreach my $c ($oWkS->col_min .. $sheet{maxcol}) { my $oWkC = $oWkS->get_cell($r, $c) or next; my $val = $oWkC->unformatted; #if (defined $val and my $enc = $oWkC->{Code}) { # $enc eq "ucs2" and $val = decode ("utf-16be", $val); # } my $cell = cr2cell ($c + 1, $r + 1); $opt{rc} and $sheet{cell}[$c + 1][$r + 1] = $val; # Original my $fmt; my $styleName = $oWkC->style; my $FmT; if ($styleName && defined (my $s = $oBook->_styles->{$styleName})) { $fmt = $s; } defined $fmt and $fmt =~ s/\\//g; $opt{cells} and # Formatted value $sheet{$cell} = defined $val ? $oWkC->value : undef; if ($opt{attr}) { my $FnT = $FmT ? $FmT->{font_face} : undef; my $fmi; #my $fmi = $FmT ? $FmT->{FmtIdx} # ? $oBook->{FormatStr}{$FmT->{FmtIdx}} # : undef; #$fmi and $fmi =~ s/\\//g; my $type = $oWkC->type || ''; $type eq "float" and $type = "numeric"; my $merged = $oWkC->is_merged || 0; $sheet{attr}[$c + 1][$r + 1] = { @def_attr, type => $type, # enc => $oWkC->{Code}, merged => $merged, hidden => ($hiddenRows->[$r] || $hiddenCols->[$c] ? 1 : $oWkC->is_hidden ? $oWkC->is_hidden : undef) || 0, # locked => $FmT->{Lock} || 0, format => $fmi, # halign => [ undef, qw( left center right # fill justify ), undef, # "equal_space" ]->[$FmT->{AlignH}], # valign => [ qw( top center bottom justify # equal_space )]->[$FmT->{AlignV}], # wrap => $FmT->{Wrap}, # font => $FnT->{Name}, # size => $FnT->{Height}, # bold => $FnT->{Bold}, # italic => $FnT->{Italic}, # uline => $FnT->{Underline}, # fgcolor => _xls_color ($FnT->{Color}), # bgcolor => _xls_fill (@{$FmT->{Fill}}), formula => $oWkC->formula, }; #_dump "cell", $sheet{attr}[$c + 1][$r + 1]; if ($opt{merge} && $merged and my $p_cell = Spreadsheet::Read::Sheet::merged_from(\%sheet, $c + 1, $r + 1)) { $sheet{attr}[$c + 1][$r + 1]{merged} = $p_cell; if ($cell ne $p_cell) { my ($C, $R) = cell2cr ($p_cell); $sheet{cell}[$c + 1][$r + 1] = $sheet{cell}[$C][$R]; $sheet{$cell} = $sheet{$p_cell}; } } } } } for (@{$sheet{cell}}) { defined or $_ = []; } push @data, { %sheet }; if ($sheet{label} eq "-- unlabeled --") { $sheet{label} = ""; } else { $data[0]{sheet}{$sheet{label}} = $#data; } } return _clipsheets \%opt, [ @data ]; } if ($opt{parser} ? _parser ($opt{parser}) eq "sc" : $io_fil ? $txt =~ m/\.sc$/ : $txt =~ m/^# .*SquirrelCalc/) { if ($io_ref) { local $/; my $x = <$txt>; $txt = $x; } elsif ($io_fil) { local $/; open my $sc, "<", $txt or return; $txt = <$sc>; close $sc; } $txt =~ m/\S/ or return; my $label = defined $opt{label} ? $opt{label} : "sheet"; my @data = ( { type => "sc", parser => "Spreadsheet::Read", version => $VERSION, parsers => [{ type => "sc", parser => "Spreadsheet::Read", version => $VERSION, }], error => undef, sheets => 1, sheet => { $label => 1 }, }, { parser => 0, label => $label, maxrow => 0, maxcol => 0, cell => [], attr => [], merged => [], active => 1, }, ); for (split m/\s*[\r\n]\s*/, $txt) { if (m/^dimension.*of ([0-9]+) rows.*of ([0-9]+) columns/i) { @{$data[1]}{qw(maxrow maxcol)} = ($1, $2); next; } s/^r([0-9]+)c([0-9]+)\s*=\s*// or next; my ($c, $r) = map { $_ + 1 } $2, $1; if (m/.* \{(.*)}$/ or m/"(.*)"/) { my $cell = cr2cell ($c, $r); $opt{rc} and $data[1]{cell}[$c][$r] = $1; $opt{cells} and $data[1]{$cell} = $1; $opt{attr} and $data[1]{attr}[$c + 1][$r] = { @def_attr }; next; } # Now only formula's remain. Ignore for now # r67c7 = [P2L] 2*(1000*r67c5-60) } for (@{$data[1]{cell}}) { defined or $_ = []; } return _clipsheets \%opt, [ @data ]; } if ($opt{parser} ? _parser ($opt{parser}) eq "sxc" : ($txt =~ m/^<\?xml/ or -f $txt)) { $can{sxc} or croak "Spreadsheet::ReadSXC not installed"; ref $txt && $can{sxc}->VERSION <= 0.23 and croak ("Sorry, references as input are not supported by Spreadsheet::ReadSXC before 0.23"); my $using = "using $can{sxc}-" . $can{sxc}->VERSION; my $sxc_options = { %parser_opts, OrderBySheet => 1 }; # New interface 0.20 and up my $sxc; if ($txt =~ m/\.(sxc|ods)$/i) { $debug and print STDERR "Opening \U$1\E $txt $using\n"; $debug and print STDERR __FILE__, "#", __LINE__, "\n"; $sxc = Spreadsheet::ReadSXC::read_sxc ($txt, $sxc_options) or return; } # treat all refs as a filehandle elsif (ref $txt) { $debug and print STDERR "Opening SXC filehandle\n"; $sxc = Spreadsheet::ReadSXC::read_sxc_fh ($txt, $sxc_options) or return; } elsif ($txt =~ m/\.xml$/i) { $debug and print STDERR "Opening XML $txt $using\n"; $sxc = Spreadsheet::ReadSXC::read_xml_file ($txt, $sxc_options) or return; } # need to test on pattern to prevent stat warning # on filename with newline elsif ($txt !~ m/^<\?xml/i and -f $txt) { $debug and print STDERR "Opening XML $txt $using\n"; open my $f, "<", $txt or return; local $/; $txt = <$f>; close $f; } !$sxc && $txt =~ m/^<\?xml/i and $sxc = Spreadsheet::ReadSXC::read_xml_string ($txt, $sxc_options); $debug > 8 and _dump (sxc => $sxc); if ($sxc) { my @data = ( { type => "sxc", parser => "Spreadsheet::ReadSXC", version => $Spreadsheet::ReadSXC::VERSION, parsers => [{ type => "sxc", parser => "Spreadsheet::ReadSXC", version => $Spreadsheet::ReadSXC::VERSION, }], error => undef, sheets => 0, sheet => {}, } ); my @sheets = ref $sxc eq "HASH" # < 0.20 ? map { { label => $_, data => $sxc->{$_}, } } keys %$sxc : @{$sxc}; foreach my $sheet (@sheets) { my @sheet = @{$sheet->{data} || []}; my %sheet = ( parser => 0, label => $sheet->{label}, maxrow => scalar @sheet, maxcol => 0, cell => [], attr => [], merged => [], active => 0, ); my $sheet_idx = 1 + @data; $debug and print STDERR "\tSheet $sheet_idx '$sheet{label}' $sheet{maxrow} rows\n"; foreach my $r (0 .. $#sheet) { my @row = @{$sheet[$r]} or next; foreach my $c (0 .. $#row) { defined (my $val = $row[$c]) or next; my $C = $c + 1; $C > $sheet{maxcol} and $sheet{maxcol} = $C; my $cell = cr2cell ($C, $r + 1); $opt{rc} and $sheet{cell}[$C][$r + 1] = $val; $opt{cells} and $sheet{$cell} = $val; $opt{attr} and $sheet{attr}[$C][$r + 1] = { @def_attr }; } } for (@{$sheet{cell}}) { defined or $_ = []; } $debug and print STDERR "\tSheet $sheet_idx '$sheet{label}' $sheet{maxrow} x $sheet{maxcol}\n"; push @data, { %sheet }; $data[0]{sheets}++; $data[0]{sheet}{$sheet->{label}} = $#data; } return _clipsheets \%opt, [ @data ]; } } if (!ref $txt and $txt =~ m/\.\w+$/) { # Return (localized) system message open my $fh, "<", $txt and croak "I can open file $txt, but I do not know how to parse it\n"; $@ = $!; } return; } # ReadData sub add { my $book = shift; my $r = ReadData (@_) or return; $book && (ref $book eq "ARRAY" || ref $book eq __PACKAGE__) && $book->[0]{sheets} or return $r; my $c1 = $book->[0]; my $c2 = $r->[0]; unless ($c1->{parsers}) { $c1->{parsers}[0]{$_} = $c1->{$_} for qw( type parser version ); $book->[$_]{parser} = 0 for 1 .. $c1->{sheets}; } my ($pidx) = (grep { my $p = $c1->{parsers}[$_]; $p->{type} eq $c2->{type} && $p->{parser} eq $c2->{parser} && $p->{version} eq $c2->{version} } 0 .. $#{$c1->{parsers}}); unless (defined $pidx) { $pidx = scalar @{$c1->{parsers}}; $c1->{parsers}[$pidx]{$_} = $c2->{$_} for qw( type parser version ); } foreach my $sn (sort { $c2->{sheet}{$a} <=> $c2->{sheet}{$b} } keys %{$c2->{sheet}}) { my $s = $sn; my $v = 2; while (exists $c1->{sheet}{$s}) { $s = $sn."[".$v++."]"; } $c1->{sheet}{$s} = $c1->{sheets} + $c2->{sheet}{$sn}; $r->[$c2->{sheet}{$sn}]{parser} = $pidx; push @$book, $r->[$c2->{sheet}{$sn}]; } $c1->{sheets} += $c2->{sheets}; return $book; } # add package Spreadsheet::Read::Attribute; use Carp; use vars qw( $AUTOLOAD ); sub AUTOLOAD { my $self = shift; (my $attr = $AUTOLOAD) =~ s/.*:://; $self->{$attr}; } # AUTOLOAD package Spreadsheet::Read::Sheet; sub cell { my ($sheet, @id) = @_; @id == 2 && $id[0] =~ m/^[0-9]+$/ && $id[1] =~ m/^[0-9]+$/ and return $sheet->{cell}[$id[0]][$id[1]]; @id && $id[0] && exists $sheet->{$id[0]} and return $sheet->{$id[0]}; } # cell sub attr { my ($sheet, @id) = @_; my $class = "Spreadsheet::Read::Attribute"; @id == 2 && $id[0] =~ m/^[0-9]+$/ && $id[1] =~ m/^[0-9]+$/ and return bless $sheet->{attr}[$id[0]][$id[1]] => $class; if (@id && $id[0] && exists $sheet->{$id[0]}) { my ($c, $r) = $sheet->cell2cr ($id[0]); return bless $sheet->{attr}[$c][$r] => $class; } undef; } # attr sub maxrow { my $sheet = shift; return $sheet->{maxrow}; } # maxrow sub maxcol { my $sheet = shift; return $sheet->{maxcol}; } # maxrow sub col2label { $_[0] =~ m/::/ and shift; # class unused return Spreadsheet::Read::col2label (@_); } # col2label sub cr2cell { $_[0] =~ m/::/ and shift; # class unused return Spreadsheet::Read::cr2cell (@_); } # cr2cell sub cell2cr { $_[0] =~ m/::/ and shift; # class unused return Spreadsheet::Read::cell2cr (@_); } # cell2cr sub label { my ($sheet, $label) = @_; defined $label and $sheet->{label} = $label; return $sheet->{label}; } # label sub active { my $sheet = shift; return $sheet->{active}; } # label # my @row = $sheet->cellrow (1); sub cellrow { my ($sheet, $row) = @_; defined $row && $row > 0 && $row <= $sheet->{maxrow} or return; my $s = $sheet->{cell}; map { $s->[$_][$row] } 1..$sheet->{maxcol}; } # cellrow # my @row = $sheet->row (1); sub row { my ($sheet, $row) = @_; defined $row && $row > 0 && $row <= $sheet->{maxrow} or return; map { $sheet->{$sheet->cr2cell ($_, $row)} } 1..$sheet->{maxcol}; } # row # my @col = $sheet->cellcolumn (1); sub cellcolumn { my ($sheet, $col) = @_; defined $col && $col > 0 && $col <= $sheet->{maxcol} or return; my $s = $sheet->{cell}; map { $s->[$col][$_] } 1..$sheet->{maxrow}; } # cellcolumn # my @col = $sheet->column (1); sub column { my ($sheet, $col) = @_; defined $col && $col > 0 && $col <= $sheet->{maxcol} or return; map { $sheet->{$sheet->cr2cell ($col, $_)} } 1..$sheet->{maxrow}; } # column # Convert {cell}'s [column][row] to a [row][column] list # my @rows = $sheet->rows (); sub rows { my $sheet = shift; my $s = $sheet->{cell}; map { my $r = $_; [ map { $s->[$_][$r] } 1..$sheet->{maxcol} ]; } 1..$sheet->{maxrow}; } # rows sub merged_from { my ($sheet, @id, $col, $row) = @_; my $ma = $sheet->{merged} or return; if (@id == 2 && $id[0] =~ m/^[0-9]+$/ && $id[1] =~ m/^[0-9]+$/) { ($col, $row) = @id; } elsif (@id && $id[0] && exists $sheet->{$id[0]}) { ($col, $row) = cell2cr ($id[0]); } defined $row && $row > 0 && $row <= $sheet->{maxrow} or return; defined $col && $col > 0 && $col <= $sheet->{maxcol} or return; foreach my $range (@{$ma}) { my ($ctl, $rtl, $cbr, $rbr) = @{$range}; $col >= $ctl && $col <= $cbr or next; $row >= $rtl && $row <= $rbr or next; return cr2cell ($ctl, $rtl); } } # cell 1; BEGIN { $INC{"Z10/Just/For/Testing.pm"} = $0; $INC{"Z20/Just/For/Testing.pm"} = $0; $Z10::Just::For::Testing::VERSION = "1.00"; $Z20::Just::For::Testing::VERSION = undef; } package Z10::Just::For::Testing; 1; package Z20::Just::For::Testing; 1; __END__ =head1 DESCRIPTION Spreadsheet::Read tries to transparently read *any* spreadsheet and return its content in a universal manner independent of the parsing module that does the actual spreadsheet scanning. For OpenOffice and/or LibreOffice this module uses L For Microsoft Excel this module uses L, L, or L (stronly discouraged). For CSV this module uses L or L. For SquirrelCalc there is a very simplistic built-in parser =head2 Data structure The data is returned as an array reference: $book = [ # Entry 0 is the overall control hash { sheets => 2, sheet => { "Sheet 1" => 1, "Sheet 2" => 2, }, parsers => [ { type => "xls", parser => "Spreadsheet::ParseExcel", version => 0.59, }], error => undef, }, # Entry 1 is the first sheet { parser => 0, label => "Sheet 1", maxrow => 2, maxcol => 4, cell => [ undef, [ undef, 1 ], [ undef, undef, undef, undef, undef, "Nugget" ], ], attr => [], merged => [], active => 1, A1 => 1, B5 => "Nugget", }, # Entry 2 is the second sheet { parser => 0, label => "Sheet 2", : : To keep as close contact to spreadsheet users, row and column 1 have index 1 too in the C element of the sheet hash, so cell "A1" is the same as C [1, 1] (column first). To switch between the two, there are helper functions available: C, C, and C. The C hash entry contains unformatted data, while the hash entries with the traditional labels contain the formatted values (if applicable). The control hash (the first entry in the returned array ref), contains some spreadsheet meta-data. The entry C is there to be able to find the sheets when accessing them by name: my %sheet2 = %{$book->[$book->[0]{sheet}{"Sheet 2"}]}; =head2 Formatted vs Unformatted The difference between formatted and unformatted cells is that the (optional) format is applied to the cell or not. This part is B implemented on the parser side. Spreadsheet::Read just makes both available if these are supported. Options provide means to disable either. If the parser does not provide formatted cells - like CSV - both values are equal. To show what this implies: use Spreadsheet::Read; my $file = "files/example.xlsx"; my $workbook = Spreadsheet::Read->new ($file); my $info = $workbook->[0]; say "Parsed $file with $info->{parser}-$info->{version}"; my $sheet = $workbook->sheet (1); say join "\t" => "Formatted:", $sheet->row (1); say join "\t" => "Unformatted:", $sheet->cellrow (1); Might return very different results depending one the underlying parser (and its version): Parsed files/example.xlsx with Spreadsheet::ParseXLSX-0.27 Formatted: 8-Aug Foo & Barr < Quux Unformatted: 39668 Foo & Barr < Quux Parsed files/example.xlsx with Spreadsheet::XLSX-0.15 Formatted: 39668 Foo & Barr < Quux Unformatted: 39668 Foo & Barr < Quux =head2 Functions and methods =head3 new my $book = Spreadsheet::Read->new (...) or die $@; All options accepted by ReadData are accepted by new. With no arguments at all, $book will be an object where sheets can be added using C my $book = Spreadsheet::Read->new (); $book->add ("file.csv"); $book->add ("file.cslx"); =head3 ReadData my $book = ReadData ($source [, option => value [, ... ]]); my $book = ReadData ("file.csv", sep => ',', quote => '"'); my $book = ReadData ("file.xls", dtfmt => "yyyy-mm-dd"); my $book = ReadData ("file.ods"); my $book = ReadData ("file.sxc"); my $book = ReadData ("content.xml"); my $book = ReadData ($content); my $book = ReadData ($content, parser => "xlsx"); my $book = ReadData ($fh, parser => "xlsx"); my $book = ReadData (\$content, parser => "xlsx"); Tries to convert the given file, string, or stream to the data structure described above. Processing Excel data from a stream or content is supported through a L temporary file or L when available. L does preserve sheet order as of version 0.20. Choosing between C<$content> and C<\\$content> (with or without passing the desired C option) may be depending on trial and terror. C does try to determine parser type on content if needed, but not all combinations are checked, and not all signatures are builtin. Currently supported options are: =over 2 =item parser X Force the data to be parsed by a specific format. Possible values are C, C (or C), C (or C), C (or C, C, C, C) C (or C), and C (or C). When parsing streams, instead of files, it is highly recommended to pass this option. Spreadsheet::Read supports several underlying parsers per spreadsheet type. It will try those from most favored to least favored. When you have a good reason to prefer a different parser, you can set that in environment variables. The other options then will not be tested for: env SPREADSHEET_READ_CSV=Text::CSV_PP ... =item cells X Control the generation of named cells ("C" etc). Default is true. =item rc Control the generation of the {cell}[c][r] entries. Default is true. =item attr Control the generation of the {attr}[c][r] entries. Default is false. See L below. =item clip If set, L|/ReadData> will remove all trailing rows and columns per sheet that have no data, where no data means only undefined or empty cells (after optional stripping). If a sheet has no data at all, the sheet will be skipped entirely when this attribute is true. =item trim =item strip If set, L|/ReadData> will remove trailing- and/or leading-whitespace from every field. strip leading strailing ----- ------- --------- 0 n/a n/a 1 strip n/a 2 n/a strip 3 strip strip C and C are aliases. If passed both, C is ignored because of backward compatibility. =item transpose =item pivot Swap all rows and columns. When a sheet contains data like A1 B1 C1 E1 A2 C2 D2 A3 B3 C3 D3 E3 using C or C will return the sheet data as A1 A2 A3 B1 B3 C1 C2 C3 D2 D3 E1 E3 C and C are aliases. If passed both, C is ignored because of backward compatibility. =item sep Set separator for CSV. Default is comma C<,>. =item quote Set quote character for CSV. Default is C<">. =item dtfmt Set the format for MS-Excel date fields that are set to use the default date format. The default format in Excel is "C", which is both not year 2000 safe, nor very useful. The default is now "C", which is more ISO-like. Note that date formatting in MS-Excel is not reliable at all, as it will store/replace/change the date field separator in already stored formats if you change your locale settings. So the above mentioned default can be either "C" OR "C" depending on what that specific character happened to be at the time the user saved the file. =item merge Copy content to all cells in merged areas. If supported, this will copy formatted and unformatted values from the top-left cell of a merged area to all other cells in the area. =item debug Enable some diagnostic messages to STDERR. The value determines how much diagnostics are dumped (using L). A value of C<9> and higher will dump the entire structure from the back-end parser. =item passwd Use this password to decrypt password protected spreadsheet. Currently only supports Excel. =back All other attributes/options will be passed to the underlying parser if that parser supports attributes. =head3 col2label my $col_id = col2label (col); my $col_id = $book->col2label (col); # OO C converts a C<(column)> (1 based) to the letters used in the traditional cell notation: my $id = col2label ( 4); # $id now "D" my $id = col2label (28); # $id now "AB" =head3 cr2cell my $cell = cr2cell (col, row); my $cell = $book->cr2cell (col, row); # OO C converts a C<(column, row)> pair (1 based) to the traditional cell notation: my $cell = cr2cell ( 4, 14); # $cell now "D14" my $cell = cr2cell (28, 4); # $cell now "AB4" =head3 cell2cr my ($col, $row) = cell2cr ($cell); my ($col, $row) = $book->cell2cr ($cell); # OO C converts traditional cell notation to a C<(column, row)> pair (1 based): my ($col, $row) = cell2cr ("D14"); # returns ( 4, 14) my ($col, $row) = cell2cr ("AB4"); # returns (28, 4) =head3 row my @row = row ($sheet, $row) my @row = Spreadsheet::Read::row ($book->[1], 3); my @row = $book->row ($sheet, $row); # OO Get full row of formatted values (like C<< $sheet->{A3} .. $sheet->{G3} >>) Note that the indexes in the returned list are 0-based. C is not imported by default, so either specify it in the use argument list, or call it fully qualified. See also the C method on sheets. =head3 cellrow my @row = cellrow ($sheet, $row); my @row = Spreadsheet::Read::cellrow ($book->[1], 3); my @row = $book->cellrow ($sheet, $row); # OO Get full row of unformatted values (like C<< $sheet->{cell}[1][3] .. $sheet->{cell}[7][3] >>) Note that the indexes in the returned list are 0-based. C is not imported by default, so either specify it in the use argument list, or call it fully qualified or as method call. See also the C method on sheets. =head3 rows my @rows = rows ($sheet); my @rows = Spreadsheet::Read::rows ($book->[1]); my @rows = $book->rows (1); # OO Convert C<{cell}>'s C<[column][row]> to a C<[row][column]> list. Note that the indexes in the returned list are 0-based, where the index in the C<{cell}> entry is 1-based. C is not imported by default, so either specify it in the use argument list, or call it fully qualified. =head3 parses parses ($format); Spreadsheet::Read::parses ("CSV"); $book->parses ("CSV"); # OO C returns Spreadsheet::Read's capability to parse the required format. L|/ReadData> will pick its preferred parser for that format unless overruled. See L|/parser>. C is not imported by default, so either specify it in the use argument list, or call it fully qualified. If C<$format> is false (C, C<"">, or C<0>), C will return a sorted list of supported types. @my types = parses (""); # e.g: csv, ods, sc, sxc, xls, xlsx =head3 parsers my @p = parsers (); C returns a list of hashrefs with information about supported parsers, each giving information about the parser, its versions and if it will be used as default parser for the given type, like: { ext => "csv", # extension or type mod => "Text::CSV_XS", # parser module min => "0.71", # module required version vsn => "1.45", # module installed version def => "*", # is default for ext } As the modules are actually loaded to get their version, do only use this to analyse prerequisites. =head3 Version my $v = Version () my $v = Spreadsheet::Read::Version () my $v = Spreadsheet::Read->VERSION; my $v = $book->Version (); # OO Returns the current version of Spreadsheet::Read. C is not imported by default, so either specify it in the use argument list, or call it fully qualified. This function returns exactly the same as C<< Spreadsheet::Read->VERSION >> returns and is only kept for backward compatibility reasons. =head3 sheets my $sheets = $book->sheets; # OO my @sheets = $book->sheets; # OO In scalar context return the number of sheets in the book. In list context return the labels of the sheets in the book. =head3 sheet my $sheet = $book->sheet (1); # OO my $sheet = $book->sheet ("Foo"); # OO Return the numbered or named sheet out of the book. Will return C if there is no match. Will not work for sheets I with a number between 1 and the number of sheets in the book. With named sheets will first try to use the list of sheet-labels as stored in the control structure. If no match is found, it will scan the actual labels of the sheets. In that case, it will return the first matching sheet. If defined, the returned sheet will be of class C. =head3 add my $book = ReadData ("file.csv"); Spreadsheet::Read::add ($book, "file.xlsx"); my $book = Spreadsheet::Read->new ("file.csv"); $book->add ("file.xlsx"); # OO =head2 Methods on sheets =head3 maxcol my $col = $sheet->maxcol; Return the index of the last in-use column in the sheet. This index is 1-based. =head3 maxrow my $row = $sheet->maxrow; Return the index of the last in-use row in the sheet. This index is 1-based. =head3 cell my $cell = $sheet->cell ("A3"); my $cell = $sheet->cell (1, 3); Return the value for a cell. Using tags will return the formatted value, using column and row will return unformatted value. =head3 attr my $cell = $sheet->attr ("A3"); my $cell = $sheet->attr (1, 3); Return the attributes of a cell. Only valid if attributes are enabled through option C. =head3 col2label my $col_id = $sheet->col2label (col); C converts a C<(column)> (1 based) to the letters used in the traditional cell notation: my $id = $sheet->col2label ( 4); # $id now "D" my $id = $sheet->col2label (28); # $id now "AB" =head3 cr2cell my $cell = $sheet->cr2cell (col, row); C converts a C<(column, row)> pair (1 based) to the traditional cell notation: my $cell = $sheet->cr2cell ( 4, 14); # $cell now "D14" my $cell = $sheet->cr2cell (28, 4); # $cell now "AB4" =head3 cell2cr my ($col, $row) = $sheet->cell2cr ($cell); C converts traditional cell notation to a C<(column, row)> pair (1 based): my ($col, $row) = $sheet->cell2cr ("D14"); # returns ( 4, 14) my ($col, $row) = $sheet->cell2cr ("AB4"); # returns (28, 4) =head3 col my @col = $sheet->column ($col); Get full column of formatted values (like C<< $sheet->{C1} .. $sheet->{C9} >>) Note that the indexes in the returned list are 0-based. =head3 cellcolumn my @col = $sheet->cellcolumn ($col); Get full column of unformatted values (like C<< $sheet->{cell}[3][1] .. $sheet->{cell}[3][9] >>) Note that the indexes in the returned list are 0-based. =head3 row my @row = $sheet->row ($row); Get full row of formatted values (like C<< $sheet->{A3} .. $sheet->{G3} >>) Note that the indexes in the returned list are 0-based. =head3 cellrow my @row = $sheet->cellrow ($row); Get full row of unformatted values (like C<< $sheet->{cell}[1][3] .. $sheet->{cell}[7][3] >>) Note that the indexes in the returned list are 0-based. =head3 rows my @rows = $sheet->rows (); Convert C<{cell}>'s C<[column][row]> to a C<[row][column]> list. Note that the indexes in the returned list are 0-based, where the index in the C<{cell}> entry is 1-based. =head3 merged_from my $top_left = $sheet->merged_from ("C2"); my $top_left = $sheet->merged_from (3, 2); If the parser supports merged areas, this method will return the label of the top-left cell in the merged area the requested cell is part of. If the requested ID is valid and withing the sheet cell range, but not part of a merged area, it will return C<"">. If the ID is not valid or out of range, it returns C. See L for more details. =head3 label my $label = $sheet->label; $sheet->label ("New sheet label"); Set a new label to a sheet. Note that the index in the control structure will I be updated. =head3 active my $sheet_is_active = $sheet->active; Returns 1 if the selected sheet is active, otherwise returns 0. Currently only works on XLS (as of Spreadsheed::ParseExcel-0.61). CSV is always active. =head2 Using CSV In case of CSV parsing, L|/ReadData> will use the first line of the file to auto-detect the separation character if the first argument is a file and both C and C are not passed as attributes. L (or L) is able to automatically detect and use C<\r> line endings. CSV can parse streams too, but be sure to pass C and/or C if these do not match the default C<,> and C<">. When an error is found in the CSV, it is automatically reported (to STDERR). The structure will store the error in C<< $ss->[0]{error} >> as anonymous list returned by Lerror_diag >>|https://metacpan.org/pod/Text::CSV_XS#error_diag>. See L for documentation. my $ss = ReadData ("bad.csv"); $ss->[0]{error} and say $ss->[0]{error}[1]; As CSV has no sheet labels, the default label for a CSV sheet is its filename. For CSV, this can be overruled using the I/L pair. =item Spreadsheet::Perl L offers a Pure Perl implementation of a spreadsheet engine. Users that want this format to be supported in Spreadsheet::Read are hereby motivated to offer patches. It is not high on my TODO-list. =item Spreadsheet::CSV L offers the interesting approach of seeing all supported spreadsheet formats as if it were CSV, mimicking the L interface. =item xls2csv L offers an alternative for my C, in the xls2csv tool, but this tool focuses on character encoding transparency, and requires some other modules. =back =head1 AUTHOR H.Merijn Brand =head1 COPYRIGHT AND LICENSE Copyright (C) 2005-2021 H.Merijn Brand This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Spreadsheet-Read-0.84/MANIFEST0000644000031300001440000000356314016160366016425 0ustar00merijnusers00000000000000Changes CONTRIBUTING.md cpanfile scripts/ss2tk scripts/ssdiff scripts/xlscat scripts/xlsx2csv examples/ss-dups-tk.pl files/Active2.xls files/Active2.xlsx files/attr.ods files/attr.xls files/attr.xlsx files/blank.csv files/blank.ods files/blank.xls files/blank.xlsx files/clear.ods files/content.xml files/Dates.ods files/Dates.xls files/Dates.xlsx files/empty.csv files/empty.ods files/empty.sc files/empty.sxc files/empty.txt files/empty.xls files/empty.xlsx files/example.xlsx files/macosx.csv files/macosx.xls files/merged.ods files/merged.xls files/merged.xlsx files/misc.ods files/misc_ws.xls files/misc.xls files/misc.xlsx files/perc.ods files/perc.xls files/perc.xlsx files/test.csv files/test.gnumeric files/test_m.csv files/test_m.txt files/test.ods files/test.sc files/test.sxc files/test_t.csv files/test_t.txt files/test.txt files/test_x.csv files/test.xls files/test.xlsx files/test_x.txt files/values.ods files/values.xls files/values.xlsx Makefile.PL MANIFEST README Read.pm t/10_basics.t t/11_call.t t/200_csv.t t/201_csv.t t/202_csv.t t/203_csv.t t/204_csv.t t/205_csv.t t/210_csv.t t/211_csv.t t/212_csv.t t/213_csv.t t/214_csv.t t/220_csv.t t/221_csv.t t/222_csv.t t/223_csv.t t/224_csv.t t/30_xls.t t/31_clr.t t/33_misc.t t/32_fmt.t t/34_dates.t t/35_perc.t t/36_xls.t t/37_merged.t t/410_ods.t t/411_clr.t t/412_fmt.t t/413_misc.t t/414_dates.t t/415_perc.t t/417_merged.t t/420_sxc.t t/425_ods.t t/426_clr.t t/50_sc.t t/51_sc.t t/600_xlsx.t t/601_clr.t t/602_fmt.t t/603_misc.t t/604_dates.t t/605_perc.t t/607_merged.t t/610_xlsx.t t/611_clr.t t/612_fmt.t t/613_misc.t t/614_dates.t t/615_perc.t t/617_merged.t t/620_xlsx.t t/621_clr.t t/622_fmt.t t/623_misc.t t/624_dates.t t/625_perc.t t/627_merged.t t/999_fail.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Spreadsheet-Read-0.84/scripts/0000755000031300001440000000000014016160366016754 5ustar00merijnusers00000000000000Spreadsheet-Read-0.84/scripts/ss2tk0000755000031300001440000001422013773573547017771 0ustar00merijnusers00000000000000#!/pro/bin/perl # ss2tk: show SpreadSheet file in Tk::TableMatrix::Spreadsheet (*) # (m)'17 [2017-07-03] Copyright H.M.Brand 2005-2021 use strict; use warnings; our $VERSION = "2.8"; sub usage { my $err = shift and select STDERR; print "usage: ss2tk [options] [X11 options] file.xls []\n", " -w use as column width\n", " -L Add spreadsheet tags to top (A, B, ..Z, AB, ...)\n", " and left (1, 2, ...)\n", " --fs[=7] Set font size (default 7 if no value)\n", " --fn=name Set font Face name (default is DejaVu Sans Mono\n", " if font size is given\n"; exit $err; } # usage use Getopt::Long qw(:config bundling passthrough); my $opt_fs; GetOptions ( "help|?" => sub { usage (0); }, "w|width=i" => \my $opt_w, "L|ss|labels!" => \my $opt_L, "a|align!" => \my $opt_a, "fn|font-name=s" => \my $opt_fn, "fs|font-size:7" => \ $opt_fs, "fs-4" => sub { $opt_fs = 4; }, "fs-5" => sub { $opt_fs = 5; }, "fs-6" => sub { $opt_fs = 6; }, "fs-7" => sub { $opt_fs = 7; }, "fs-8" => sub { $opt_fs = 8; }, "fs-9" => sub { $opt_fs = 9; }, # For restarts "G|geometry=s" => \my $geometry, "W|column-widths=s" => \my $col_widths, ) or usage (1); use Data::Peek; use Spreadsheet::Read; use Tk; use Tk::NoteBook; use Tk::TableMatrix::Spreadsheet; # This will allow ~/.Xdefaults to have lines like #ss2tk*font: -misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1 Tk::CmdLine->LoadResources (); # This will allow calls like # ss2tk -fg Blue4 blah.csv Tk::CmdLine->SetArguments (); @ARGV && -f $ARGV[0] or usage (1); my $title = $ARGV[0]; my $sfn = shift; my $ref = Spreadsheet::Read->new ($sfn) or die "Cannot read $sfn\n"; $ref->[0]{sheets} or die "No sheets in $title\n"; fork and exit; $opt_fn || $opt_fs and $opt_fn = "{".($opt_fn|| "DejaVu Sans Mono")."} ".($opt_fs||7); my $pat = @ARGV ? qr/$ARGV[0]/i : undef; my $mw = MainWindow->new (-title => $title); $geometry and $mw->geometry ($geometry); my $nb = $mw->NoteBook ()->pack (qw(-side top -expand 1 -fill both )); my @nb; foreach my $sht (1 .. $ref->[0]{sheets}) { my $s = $ref->[$sht]; $title .= " [ " . $s->{label} . " ]"; my ($data, @data) = ({}); my ($h, $w, @w) = get_data ($data, $s, \@data); $nb[$sht] = $nb->add ($sht, -label => $s->{label}, -state => "normal", -anchor => "nw"); my @ff = $opt_fn ? (-font => $opt_fn) : (); my $ss = $nb[$sht]->Scrolled ('Spreadsheet', -rows => $h, -cols => $w, -width => 10, -height => 20, -titlecols => $opt_L ? 1 : 0, -titlerows => $opt_L ? 2 : 1, -selectmode => "extended", -resizeborders => "both", -justify => "left", -anchor => "w", -variable => $data, @ff, )->pack (-expand => 1, -fill => "both", -side => "top", -anchor => "nw"); $ss->Subwidget ("${_}scrollbar")->configure (-width => 6) for qw( x y ); $ss->tagConfigure ("title", -bg => "#ffffe0", -justify => "left"); $ss->tagConfigure ("active", -bg => "#ffff40", -justify => "left"); $ss->tagConfigure ("sel", -bg => "gray95", -justify => "left"); my ($pv, $sv, $si) = ("", "", 0); sub search { $sv or return; $sv eq $pv && !$_[0] and return; $ss->selectionClear ("all"); foreach my $i ($_[0] .. $#data, 0 .. ($_[0] - 1)) { $data->{$data[$i]} =~ m/$sv/i or next; $si = $i; $ss->activate ($data[$si = $i]); $ss->selectionSet ($data[$si]); $ss->see ($data[$si]); $pv = $sv; last; } } # search my $reload = sub { $ss->clearCache; $data->{$_} = "" for @data; @data = (); $ref = Spreadsheet::Read->new ($sfn) or die "Cannot read $sfn\n"; $s = $ref->[$sht]; get_data ($data, $s, \@data); }; # reload # Search frame my $sf = $nb[$sht]->Frame ()->pack (-side => "left", -expand => 1, -fill => "both"); my $sl = $sf->Label ( -text => "Search", )->pack (-side => "left", -anchor => "sw"); my $sb = $sf->Entry ( -textvariable => \$sv, )->pack (-side => "left", -anchor => "sw"); $sb->bind ("" => sub { search ($si = 0); }); my $sn = $sf->Button ( -text => "Next", -command => sub { search (++$si) }, )->pack (-side => "left", -anchor => "sw"); # Control frame my $cf = $nb[$sht]->Frame ()->pack (-side => "right", -expand => 1, -fill => "both"); $cf->Button ( -text => "\x{2718}", -foreground => "#8b0000", -command => \&exit, )->pack (-side => "right", -anchor => "se"); $cf->Button ( -text => "\x{21f5}", -foreground => "#ffa500", -command => sub { my $geo = $mw->geometry; # Add column widths here exec $0, "--geometry=$geo"; }, )->pack (-side => "right", -anchor => "se"); $cf->Button ( -text => "\x{21bb}", -foreground => "#008b00", -command => $reload, )->pack (-side => "right", -anchor => "se"); my $swss = $ss->Subwidget ("spreadsheet"); # autosize columns on data (not on headers) $swss->colWidth (map { $_ => ($opt_w || $w[$_] || 4) } 0 .. $#w); $opt_a or next; $swss->tagConfigure ("numeric", -justify => "right"); foreach my $rc (keys %$data) { $data->{$rc} && $data->{$rc} =~ m/^\d+$/ or next; $swss->tagCell ("numeric", $rc); } DDumper $swss; } sub get_data { my ($dta, $s, $adta) = @_; my @c = (1, $s->{maxcol}); my ($h, $w, @w) = (0, 1, 0, (0) x $c[1]); # data height, -width, and default column widths if ($opt_L) { foreach my $c (0 .. $s->{maxcol}) { $dta->{"$h,$c"} = $c ? $ref->col2label ($c) : ""; push @$adta, "$h,$c"; } $h++; } foreach my $r (1 .. $s->{maxrow}) { my @row = map { defined $s->{cell}[$_][$r] ? $s->{cell}[$_][$r] : ""; } 1 .. $s->{maxcol}; $pat and "@row" =~ $pat || next; $opt_L and unshift @row, $r; foreach my $c (0 .. $#row) { length $row[$c] or next; $c >= $w and $w = $c + 1; $dta->{"$h,$c"} = $row[$c]; push @$adta, "$h,$c"; my $l = length $row[$c]; $l > $w[$c] and $w[$c] = $l; } ++$h % 100 or printf STDERR "%6d x %6d\r", $w, $h; } printf STDERR "%6d x %6d\n", $w, $h; #use DP;DDumper { S => $dta, A => $adta }; ($h, $w, @w); } # get_data MainLoop; Spreadsheet-Read-0.84/scripts/xlscat0000755000031300001440000004405714006243145020206 0ustar00merijnusers00000000000000#!/pro/bin/perl # xlscat: show supported spreadsheet file as Text # xlsgrep: grep pattern # (m)'21 [2021-02-02] Copyright H.M.Brand 2005-2021 use strict; use warnings; our $VERSION = "3.20"; my $is_grep = $0 =~ m/grep$/; sub usage { my $err = shift and select STDERR; (my $scrpt = $0) =~ s{.*[\/]}{}; my $p = $is_grep ? " pattern" : ""; print "usage: $scrpt\t[-s ] [-L] [-n] [-A] [-u] [Selection]$p file.xls\n", " \t[-c | -m] [-u] [Selection]$p file.xls\n", " \t -i [-S sheets]$p file.xls\n", " Generic options:\n", " -v[#] Set verbose level (xlscat/xlsgrep)\n", " -d[#] Set debug level (Spreadsheet::Read)\n", " --list Show supported spreadsheet formats and exit\n", " -u Use unformatted values\n", " --strip[=#] Strip leading and/or traing spaces of all cells\n", " --noclip Do not strip empty sheets and\n", " trailing empty rows and columns\n", " --no-nl[=R] Replace all newlines in cells with R (default space)\n", " -e Set encoding for input and output\n", " -b Set encoding for input\n", " -a Set encoding for output\n", " -U Set encoding for output to utf-8 (short for -a utf-8)\n", " Input CSV:\n", " --in-sep=c Set input sep_char for CSV (c can be 'TAB')\n", " Input XLS:\n", " --dtfmt=fmt Specify the default date format to replace 'm-d-yy'\n", " the default replacement is 'yyyy-mm-dd'\n", " --passwd=pw Specify the password for workbook\n", " if pw = -, read password from keyboard\n", " --formulas Show the formula instead of the value\n", " Output Text (default):\n", " -s Use separator . Default '|', \\n allowed\n", " Overrules ',' when used with --csv\n", " -L Line up the columns\n", " -n [skip] Number lines (prefix with column number)\n", " optionally skip (header) lines\n", " -A Show field attributes in ANSI escapes\n", " -h[#] Show # header lines\n", " -D Dump each record with Data::Peek or Data::Dumper\n", " --hash Like -D but as hash with first row as keys\n", $is_grep ? ( " Grep options:\n", " -i Ignore case\n", " -w Match whole words only\n") : ( " Output Index only:\n", " -i Show sheet names and size only\n"), " Output CSV:\n", " -c Output CSV, separator = ','\n", " -m Output CSV, separator = ';'\n", " Output HTML:\n", " -H Output HTML\n", " Selection:\n", " -S Only print sheets . 'all' is a valid set\n", " Default only prints the first sheet\n", " -R Only print rows . Default is 'all'\n", " -C Only print columns . Default is 'all'\n", " -F Only fields e.g. -FA3,B16\n", " Ordering (column numbers in result set *after* selection):\n", " --sort=spec Sort output (e.g. --sort=3,2r,5n,1rn+2)\n", " +# - first # lines do not sort (header)\n", " # - order on column # lexical ascending\n", " #n - order on column # numeric ascending\n", " #r - order on column # lexical descending\n", " #rn - order on column # numeric descending\n", "\n", "Examples:\n", " xlscat -i foo.xls\n", " xlscat --in-sep=: --sort=3n -L /etc/passwd\n"; @_ and print join "\n", @_, ""; exit $err; } # usage use Data::Dumper; use Encode qw( encode decode ); use Spreadsheet::Read; use Getopt::Long qw(:config bundling noignorecase passthrough); my $opt_c; # Generate CSV my $opt_F = ""; # Fields to print my $opt_v = 0; # Verbosity for xlscat my $opt_d = 0; # Debug level for Spreadsheet::Read my $opt_h = 0; # Number of header lines for grep or -L my $opt_D = 0; # Dump: 0 = none, 1 = array, 2 = hash my $clip = 1; my $enc_i; # Input encoding my $enc_o; # Output encoding GetOptions ( "help|?" => sub { usage (0); }, # Input CSV "c|csv" => sub { $opt_c = "," }, "m|ms" => sub { $opt_c = ";" }, "insepchar". "|in-sep". "|in-sep-char=s" => \my $sep, # Input field sep for CSV # Input XLS "dtfmt". "|date-format=s" => \my $dtfmt, # Default date-format for Excel "f|formulas!" => \my $opt_f, # Show the formula instead of the value "password=s" => \my $passwd, # For encrypted spreadsheets # Output "i|index". "|ignore-case!" => \my $opt_i, # Index (cat) | ignore_case (grep) "s|separator|sep". "|outsepchar". "|out-sep". "|out-sep-char=s" => \my $opt_s, # Text separator "S|sheets=s" => \my $opt_S, # Sheets to print "R|rows=s" => \my $opt_R, # Rows to print "C|columns=s" => \my $opt_C, # Columns to print "F|fields=s" => \ $opt_F, "L|fit|align!" => \my $opt_L, # Auto-size/align columns "P|pivot!" => \my $pivot, "n|number:0" => \my $opt_n, # Prefix lines with column number "A|ansi|color!" => \my $opt_A, # Show field colors in ANSI escapes "u|unformatted!" => \my $opt_u, # Show unformatted values "v|verbose:1" => \$opt_v, "d|debug:1" => \$opt_d, "D|dump!" => \ $opt_D, # Use Data::Peek or Data::Dumper "hash!" => sub { $opt_D = 2 }, "H|html:1" => \my $opt_H, # Output in HTML "noclip" => sub { $clip = 0 }, "strip:3" => \my $strip, "sort=s" => \my $sort_order, "N|no-nl:s" => \my $opt_N, "list!" => \my $list, # Encoding "e|encoding=s" => sub { $enc_i = $enc_o = $_[1] }, "b|encoding-in=s" => \$enc_i, "a|encoding-out=s" => \$enc_o, "U|utf-8|utf8" => sub { $enc_o = "utf-8" }, # Grep "w|word!" => \my $opt_w, # Grep words "h|header:1" => \$opt_h, ) or usage 1, "GetOpt: $@"; if ($list) { print "Ext Parser module Req Has Def\n"; print "----- ----------------------- ----- ----- ---\n"; for (Spreadsheet::Read::parsers ()) { printf "%-5s %-23s %5s %5s %s\n", $_->{ext}, $_->{mod}, $_->{min}, $_->{vsn}, $_->{def} ? "<==" : ""; } exit 0; } unless ($is_grep) { $opt_i && $opt_L and usage 1, "Options i and L are mutually exclusive"; $opt_i && $opt_s and usage 1, "Options i and s are mutually exclusive"; $opt_i && $opt_c and usage 1, "Options i and c are mutually exclusive"; $opt_i && $opt_u and usage 1, "Options i and u are mutually exclusive"; $opt_i && $opt_S and usage 1, "Options i and S are mutually exclusive"; $opt_i && $opt_R and usage 1, "Options i and R are mutually exclusive"; $opt_i && $opt_C and usage 1, "Options i and C are mutually exclusive"; $opt_i && $opt_F and usage 1, "Options i and F are mutually exclusive"; $opt_i && $opt_H and usage 1, "Options i and H are mutually exclusive"; } $opt_c && $opt_H and usage 1, "Options c and H are mutually exclusive"; $opt_s && $opt_H and usage 1, "Options s and H are mutually exclusive"; my %e = (a => "\a", b => "\b", e => "\e", f => "\f", n => "\n", r => "\r", t => "\t"); $opt_s and $opt_s =~ s/\\+([abefnrt])/$e{$1}/g; defined $opt_S or $opt_S = $opt_i || $is_grep ? "all" : "1"; defined $opt_N && !length $opt_N and $opt_N = " "; $opt_i && !$is_grep && $opt_v < 1 and $opt_v = 1; $opt_f and $opt_A = 1; if ($opt_c) { $opt_L = 0; # Cannot align CSV if ($opt_s) { $opt_c = $opt_s; $opt_s = undef; } $opt_c =~ m/^1?$/ and $opt_c = ","; $opt_c = Text::CSV_XS->new ({ binary => 1, sep_char => $opt_c, eol => "\r\n", }); } # Debugging. Prefer Data::Peek over Data::Dumper if available { my $dp = 0; eval q{ use Data::Peek; $dp = 1; }; sub ddumper { $dp ? DDumper (@_) : print STDERR Dumper (@_); } # ddumper } my @RDarg; for (reverse 0 .. $#ARGV) { $ARGV[$_] =~ m/^--([-\w]+)(?:=(.*))?$/ or next; push @RDarg, $1, defined $2 ? $2 : 1; $RDarg[-2] =~ tr/-/_/; splice @ARGV, $_, 1; } my $pattern; if ($is_grep) { $pattern = shift or usage 1; $opt_w and $pattern = "\\b$pattern\\b"; $opt_i and $pattern = "(?i:$pattern)"; $pattern = qr{$pattern}; $opt_v > 1 and warn "Matching on $pattern\n"; } my $file = shift; if (defined $file and $file ne "-") { $opt_v > 1 and warn "Using $file as input\n"; -f $file or usage 1, "the file argument is not a regular file"; -s $file or usage 1, "the file is empty"; } else { $opt_v > 1 and warn "Working as a pipe\n"; $file = *ARGV; } if ($opt_c) { Spreadsheet::Read::parses ("csv") or die "No CSV module found\n"; eval q{use Text::CSV_XS}; } if ($opt_H) { $enc_o = "utf-8"; $opt_H = sub { $_[0]; }; eval q{ use HTML::Entities; $opt_H = sub { encode_entities (Encode::is_utf8 ($_[0]) ? $_[0] : decode ("utf-8", $_[0])); }; }; } if ($sep) { my %sep = ( tab => "\t", pipe => "|", colon => ":", semicolon => ";", comma => ",", ); $sep = $sep{lc $sep} || $sep; } push @RDarg, debug => $opt_d, clip => $clip; $opt_A and push @RDarg, attr => 1; defined $sep and push @RDarg, sep => $sep, parser => "csv"; defined $dtfmt and push @RDarg, dtfmt => $dtfmt; $strip and push @RDarg, strip => $strip; $pivot and push @RDarg, pivot => $pivot; if ($passwd) { if ($passwd eq "-") { print STDERR "Password: "; eval "use Term::ReadKey;"; eval { ReadMode ("noecho"); }; chomp ($passwd = ); eval { ReadMode ("echo"); }; } push @RDarg, passwd => $passwd; } $opt_v > 4 and warn "ReadData ($file, @RDarg);\n"; my $xls = ReadData ($file, @RDarg) or die "cannot read $file\n"; $opt_v > 7 and ddumper ($xls); my $sc = $xls->[0]{sheets} or die "No sheets in $file\n"; $opt_v > 1 and warn "Opened $file with $sc sheets\n"; $opt_S eq "all" and $opt_S = "1..$sc"; # all $opt_S =~ s/-$/-$sc/; # 3,6- $opt_S =~ s/-/../g; my %print; eval "%{\$print{sheet}} = map { \$_ => 1 } $opt_S"; my $v_fmt = $opt_C || $opt_R || $opt_F ? "" : "%6d x %6d%s"; # New style xterm (based on ANSI colors): # 30 Black # 31 Red # 32 Green # 33 Yellow # 34 Blue # 35 Magenta # 36 Cyan # 37 White sub color_reduce { my ($rgb, $base) = @_; defined $rgb or return ""; my ($r, $g, $b) = map { hex >> 7 } ($rgb =~ m/^\s*#?([\da-f]{2})([\da-f]{2})([\da-f]{2})/); $base + 4 * $b + 2 * $g + $r; } # color_reduce sub ansi_color { my ($fg, $bg, $bold, $ul) = @_; # warn "$fg on $bg $bold $ul\n"; my $attr = join ";", 0, grep { /\S/ } $bold ? 1 : "", $ul ? 4 : "", color_reduce ($fg, 30), color_reduce ($bg, 40); "\e[${attr}m"; } # ansi_color sub css_color { my ($fg, $bg, $bold, $ul, $ha) = @_; my @css; $bold and push @css, "font-weight: bold"; $ul and push @css, "text-decoration: underline"; $fg and push @css, "color: $fg"; $bg and push @css, "background: $bg"; $ha and push @css, "text-align: $ha"; local $" = "; "; @css ? qq{ style="@css"} : ""; } # css_color binmode STDERR, ":utf8"; $enc_o and binmode STDOUT, ":encoding($enc_o)"; if ($opt_H) { print < $file EOH } my $name_len = 30; if ($opt_i) { my $nl = 0; foreach my $sn (keys %{$xls->[0]{sheet}}) { length ($sn) > $nl and $nl = length $sn; } $nl and $name_len = $nl; } my @opt_F = split m/[^A-Z\d]+/ => $opt_F; foreach my $si (1 .. $sc) { my @data; exists $print{sheet}{$si} or next; $opt_v > 1 and warn "Opening sheet $si ...\n"; my $s = $xls->[$si] or next; $opt_v > 5 and ddumper ($s); my @r = (1, $s->{maxrow}); my @c = (1, $s->{maxcol}); my ($sn, $nr, $nc) = ($s->{label}, $r[-1], $c[-1]); defined $nr or next; defined $nc or next; defined $sn or $sn = ""; my $active = $s->{active} ? " (Active)" : ""; $opt_v and printf STDERR "%s - %02d: [ %-*s ] %3d Cols, %5d Rows%s\n", $file, $si, $name_len, $sn, $nc, $nr, $active; $opt_i && !$is_grep and next; if (@opt_F) { foreach my $fld (@opt_F) { $is_grep && defined $s->{$fld} && $s->{$fld} !~ $pattern and next; print "$fld:",$s->{$fld},"\n"; } next; } if (my $rows = $opt_R) { $rows eq "all" and $rows = "1..$nr"; # all $rows =~ s/-$/-$nr/; # 3,6- $rows =~ s/-/../g; eval "%{\$print{row}} = map { \$_ => 1 } $rows"; } if (my $cols = $opt_C) { $cols eq "all" and $cols = "1..$nc"; # all if ($cols =~ m/[A-Za-z]/) { # -C B,D => -C 2,4 my %ct = map { my ($cc, $rr) = cell2cr (uc "$_".1); ($_ => $cc) } ($cols =~ m/([a-zA-Z]+)/g); $cols =~ s/([A-Za-z]+)/$ct{$1}/g; } $cols =~ s/-$/-$nc/; # 3,6- $cols =~ s/-/../g; eval "\$print{col} = [ map { \$_ - 1 } $cols ]"; $nc = @{$print{col}}; } $opt_v >= 8 and ddumper (\%print); $opt_H and print qq{

$sn

\n\n\n}; my $undef = $opt_v > 2 ? "-- undef --" : ""; my ($h, @w) = (0, (0) x $nc); # data height, -width, and default column widths my @align = ("") x $nc; foreach my $r ($r[0] .. $r[1]) { exists $print{row} && !exists $print{row}{$r} and next; my @att; my @row = map { my $cell = cr2cell ($_, $r); my ($uval, $fval) = map { defined $_ ? $enc_i ? decode ($enc_i, $_) : $_ : $undef } $s->{cell}[$_][$r], $s->{$cell}; if (defined $opt_N) { s/\n/$opt_N/go for grep { defined } $uval, $fval; } $opt_v > 2 and warn "$_:$r '$uval' / '$fval'\n"; $opt_A and push @att, [ @{$s->{attr}[$_][$r]}{qw( fgcolor bgcolor bold uline halign )} ]; $opt_f && $s->{attr}[$_][$r]{formula} ? "=".$s->{attr}[$_][$r]{formula} : defined $s->{cell}[$_][$r] ? $opt_u ? $uval : $fval : ""; } $c[0] .. $c[1]; exists $print{col} and @row = @row[grep{$_<@row}@{$print{col}}]; $is_grep && $r > $opt_h && ! grep { defined $_ && $_ =~ $pattern } @row and next; if ($opt_D) { ddumper ($opt_D == 1 ? \@row : { map { $s->{cell}[$_ + 1][1] => $row[$_] } 0 .. $#row }); next; } if ($opt_H) { # HTML print " "; if (defined $opt_n) { my $x = $r - $opt_n; $x <= 0 and $x = ""; my $c = $r % 2 ? qq{ class="odd"} : ""; print qq{}; } foreach my $c (0 .. $#row) { my $css = css_color (@{$att[$c]}); $r % 2 and $css .= qq{ class="odd"}; my $td = $opt_H->($row[$c]); print "$td"; } print "\n"; next; } if (defined $opt_n) { unshift @row, $r; unshift @att, [ "#ffffff", "#000000", 0, 0 ]; } if ($opt_L || $sort_order) { # Autofit / Align / order push @data, [ [ @row ], [ @att ] ]; next; } if ($opt_c) { # CSV $opt_c->print (*STDOUT, \@row) or die $opt_c->error_diag; next; } if ($opt_A) { foreach my $c (0 .. $#row) { $row[$c] = ansi_color (@{$att[$c]}). $row[$c] . "\e[0m"; } } line ($opt_s => @row); } continue { ++$h % 100 == 0 && $opt_v and printf STDERR $v_fmt, $nc, $h, "\r"; } $opt_H and print "
$x
\n\n"; $v_fmt and printf STDERR $v_fmt, $nc, $h, "\n"; if ($sort_order) { my @o; my @h; $sort_order =~ s/\+([0-9]+)\b// and @h = splice @data, 0, $1; for ($sort_order =~ m/([0-9]+[rn]*)/g) { m/^([0-9]+)(.*)/; push @o, { col => $1 - 1, map { $_ => 1 } split m// => $2 }; } my $sort = sub { my $d = 0; foreach my $o (@o) { my ($A, $B) = map { $_->[0][$o->{col}] || 0 } $a, $b; $d = $o->{n} ? $o->{r} ? $B <=> $A : $A <=> $B : $o->{r} ? $B cmp $A : $A cmp $B and return $d; } return $d; }; @data = (@h, sort $sort @data); } if ($opt_c && @data) { # CSV $opt_c->print (*STDOUT, $_->[0]) for @data; next; } $opt_L || $sort_order or next; if (defined $opt_n) { unshift @w, length $data[-1][0][0]; unshift @align, ""; } $opt_n = 0; if ($opt_L) { foreach my $r (0 .. $#data) { my $R = $data[$r][0]; foreach my $c (0 .. $#$R) { my $d = $R->[$c]; my $l = length $d; $l > $w[$c] and $w[$c] = $l; $r && $d =~ m/\S/ or next; $d =~ m/^\s*(?:-\s*)?[0-9][0-9 .,]*$/ or $align[$c] = "-"; } } } for (@data) { my ($row, $att) = @$_; my @row = @$row; for (0 .. $#row) { my $l = length $row[$_]; my $w = $l < $w[$_] ? " " x ($w[$_] - $l) : ""; if ($align[$_]) { $_ == $#row or $row[$_] .= $w; } else { substr $row[$_], 0, 0, $w; } if ($opt_A) { substr $row[$_], 0, 0, ansi_color (@{$att->[$_]}); $row[$_] .= "\e[0m"; } } line ($opt_s => @row); ++$opt_n == $opt_h and line ("+", map {"-"x$w[$_]} 0..$#row); } } $opt_H and print "\n\n"; sub line { my $sep = shift || " \x{2502} "; my $line = join $sep => @_; !$enc_o && Encode::is_utf8 ($line) and $line = encode ("utf-8", $line); print "$line\n"; } # show_line END { if ($opt_v >= 7) { my %seen; print "\nNon-CORE modules loaded:\n", "-" x 25, " ", "--------\n"; foreach my $mod (sort keys %INC) { my $path = $INC{$mod}; $mod =~ s{\.pm$}{} or next; $mod =~ s{/}{::}g; $path =~ s{.*/site_perl/}{} or next; grep { $mod =~ m/^${_}::/ } keys %seen and next; $seen{$mod}++; my $v = $mod->VERSION () || eval "\$${mod}::VERSION" || "?"; printf "%-25s %s\n", $mod, $v; } } } Spreadsheet-Read-0.84/scripts/ssdiff0000755000031300001440000000466013746031200020157 0ustar00merijnusers00000000000000#!/pro/bin/perl use 5.14.0; use warnings; our $VERSION = "0.03"; our $CMD = $0 =~ s{.*/}{}r; sub usage { my $err = shift and select STDERR; print "usage: $CMD [--verbose[=1]] file.xls file.xlsx\n"; exit $err; } # usage use Spreadsheet::Read; use List::Util qw( max ); use Getopt::Long qw(:config bundling); GetOptions ( "help|?" => sub { usage (0); }, "V|version" => sub { print "$CMD [$VERSION]\n"; exit 0; }, "ccdiff!" => \ my $opt_cc, "v|verbose:2" => \(my $opt_v = 1), ) or usage (1); my $file1 = shift or usage (1); my $file2 = shift or usage (1); binmode STDOUT, ":encoding(utf-8)"; my $ss1 = Spreadsheet::Read->new ($file1) or die "Cannot read $file1: $!\n"; my $ss2 = Spreadsheet::Read->new ($file2) or die "Cannot read $file2: $!\n"; say for $ss1->sheets; if ($opt_cc) { require App::ccdiff; $@ || $App::ccdiff::VERSION lt "0.29" and die "App::ccdiff-0.29 or higher required for --cc\n" } print "< $file1\t(", scalar $ss1->sheets, " sheets)\n"; print "> $file2\t(", scalar $ss2->sheets, " sheets)\n"; foreach my $s (1 .. max map { scalar $_->sheets } $ss1, $ss2) { my $s1 = $ss1->sheet ($s); my $s2 = $ss2->sheet ($s); unless ($s1) { print "$s: not in $file1\n"; last; } unless ($s2) { print "$s: not in $file2\n"; last; } printf "Sheet %d\n\t< %5d x %5d %s\n\t> %5d x %5d %s\n", $s, $s1->maxcol, $s1->maxrow, $s1->label, $s2->maxcol, $s2->maxrow, $s2->label; if ($opt_cc) { my @c; foreach my $ss ($s1, $s2) { push @c => [ map { join ("|" => @$_) . "\n" } [ map { $ss->col2label ($_) } 1 .. $ss->maxcol ], map { [ $ss->row ($_) ] } 1 .. $ss->maxrow ]; } App::ccdiff::ccdiff (@c, { header => 0, unified => 3, "utf-8" => 1 }); next; } my $mc = max map { $_->maxcol } $s1, $s2; foreach my $r (1 .. max map { $_->maxrow } $s1, $s2) { if ($r > $s1->maxrow) { print "$s: EOS in $file1 at row $r\n"; last; } if ($r > $s2->maxrow) { print "$s: EOS in $file2 at row $r\n"; last; } my @r1 = $s1->row ($r); my @r2 = $s2->row ($r); foreach my $c (1 .. $mc) { my $c1 = $r1[$c]; my $c2 = $r2[$c]; if (defined $c1) { if (defined $c2) { $c1 eq $c2 and next; print "$s: ($r, $c)\n\t< $c1\n\t> $c2\n"; next; } print "$s: ($r, $c)\n\t< $c1\n\t> -- undefined --\n"; next; } defined $c2 or next; print "$s: ($r, $c)\n\t< -- undefined --\n\t> $c2\n"; } } } Spreadsheet-Read-0.84/scripts/xlsx2csv0000755000031300001440000001463713773573561020527 0ustar00merijnusers00000000000000#!/pro/bin/perl # xls2csv: Convert supported spreadsheet formats to CSV # (m)'20 [2020-10-27] Copyright H.M.Brand 2008-2021 require 5.008001; use strict; use warnings; our $VERSION = "3.7"; (my $cmd = $0) =~ s{.*/}{}; use Text::CSV_XS; use List::Util qw( first ); use Spreadsheet::Read qw( ReadData row ); sub usage { my $err = shift and select STDERR; print "usage: $cmd [-A [-N | -J c] | -o file.csv] [-s sep] [-f] [-i] file.xls\n"; print " $cmd --help | --man | --info\n"; print " --list List supported spreadsheet formats and exit\n"; print " -A --all Export all sheets (filename-sheetname.csv)\n"; print " -N --no-pfx No filene prefix on -A (sheetname.csv)\n"; print " -Z --zip Convert sheets to CSV's in ZIP\n"; print " -J s --join=s Use s to join filename-sheetname (-)\n"; print " -o f --out=f Set output filename\n"; print " -i f --in=f Set infut filename\n"; print " -f --force Force overwrite output if exists\n"; print " -s s --sep=s Set CSV separator character\n"; print "Unless -A is used, all other options are passed on to xlscat\n"; @_ and print join "\n", @_, ""; exit $err; } # usage use Getopt::Long qw( :config bundling noignorecase passthrough ); GetOptions ( "help|?" => sub { usage 0; }, "V|version" => sub { print "$cmd [$VERSION]\n"; exit 0; }, "man" => sub { pod_nroff (); }, "info" => sub { pod_text (); }, "list" => sub { list_parsers (); }, "o|c|out=s" => \ my $csv, "i|s|in=s" => \ my $xls, "f|force!" => \ my $opt_f, "s|sep=s" => \ my $opt_s, "A|all!" => \ my $opt_A, "N|no-pfx!" => \ my $opt_N, "Z|zip!" => \ my $opt_Z, "J|join=s" => \(my $opt_J = "-"), ) or usage 1; sub list_parsers { print "Ext Parser module Req Has Def\n"; print "----- ----------------------- ----- ----- ---\n"; for (Spreadsheet::Read::parsers ()) { printf "%-5s %-23s %5s %5s %s\n", $_->{ext}, $_->{mod}, $_->{min}, $_->{vsn}, $_->{def} ? "<==" : ""; } exit 0; } # list_parsers sub pod_text { require Pod::Text::Color; my $m = $ENV{NO_COLOR} ? "Pod::Text" : "Pod::Text::Color"; my $p = $m->new (); open my $fh, ">", \my $out; $p->parse_from_file ($0, $fh); close $fh; print $out; exit 0; } # pod_text sub pod_nroff { first { -x "$_/nroff" } grep { -d } split m/:+/ => $ENV{PATH} or pod_text (); require Pod::Man; my $p = Pod::Man->new (); open my $fh, "|-", "nroff", "-man"; $p->parse_from_file ($0, $fh); close $fh; exit 0; } # pod_nroff unless ($xls) { foreach my $i (reverse 0 .. $#ARGV) { -f $ARGV[$i] or next; $xls = splice @ARGV, $i, 1; last; } } $xls or usage 1, "No input file"; -r $xls or usage 1, "Input file unreadable"; -s $xls or usage 1, "Input file empty"; my @known_ext = Spreadsheet::Read::parses (0); @known_ext or @known_ext = qw( csv ods sc sxc xls xlsx ); my $valid_ext = do { local $" = "|"; qr{ \. (?: @known_ext )}xi }; if ($opt_Z) { require Archive::Zip; $@ and die "--zip requires Archive::Zip, which could not be loaded\n"; } my %e = (n => "\n", t => "\t", e => "\e", r => "\r"); $opt_s and $opt_s =~ s/\\+([nter])/$e{$1}/g; if ($opt_A || $opt_Z) { my $ss = ReadData ($xls) or die "Cannot read/parse $xls\n"; my $az = $opt_Z ? Archive::Zip->new : undef; $csv and $xls = $csv; $xls =~ s/$valid_ext $//ix; $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 1, eol => "\r\n" }); $opt_s and $csv->sep_char ($opt_s); foreach my $si (1 .. $ss->[0]{sheets}) { my $s = $ss->[$si] or next; $s->{maxcol} or next; my $mr = $s->{maxrow} or next; my $sn = $s->{label} || "sheet-$si"; $sn =~ s/\s+$//; $sn =~ s/^\s+//; $sn =~ s/[^-\w.]+/_/g; # remove any special chars from worksheet name if ($opt_Z) { open my $fh, ">:encoding(utf-8)", \my $data; $csv->print ($fh, [ row ($s, $_) ]) for 1 .. $mr; close $fh; $az->addString ($data, "$sn.csv"); next; } my $fn = $opt_N ? "$sn.csv" : "$xls$opt_J$sn.csv"; -f $fn && !$opt_f and die "$fn already exists\n"; warn "Saving sheet to $fn ...\n"; open my $fh, ">:encoding(utf-8)", $fn or die "$fn: $!\n"; $csv->print ($fh, [ row ($s, $_) ]) for 1 .. $mr; close $fh; } if ($opt_Z) { my $fn = "$xls.zip"; -f $fn && $opt_f and unlink $fn; -f $fn and die "$fn already exists\n"; $az->writeToFileNamed ($fn) == Archive::Zip::AZ_OK or die "$fn: $!\n"; } exit; } $csv or ($csv = $xls) =~ s/$valid_ext $/.csv/xi; if (-f $csv) { $opt_f or die "$csv already exists\n"; unlink $csv; } warn "Converting $xls to $csv ...\n"; open STDOUT, ">", $csv or die "$csv: $!\n"; $^O eq "MSWin32" and $xls = qq{"$xls"}; $opt_s and unshift @ARGV, "--sep=$opt_s"; exec { "xlscat" } "xlscat", "-c", @ARGV, $xls; __END__ =pod =head1 NAME xlsx2csv - convert spreadsheet to CSV(s) =head1 SYNOPSIS xlsx2csv [ -A [ -N || -J str ] | -o file.csv ] [-f] [-i] file.xls xlsx2csv --help | --man | --info =head1 DESCRIPTION Convert a spreadsheet (all formats supported by L) to CSV (using L). =head1 OPTIONS =over =item -? =item --help Print short usage and exit. =item --man Print this help using nroff and exit. =item --info Print this help and exit. =item -V =item --version Print the version and exit. =item -f =item --force Overwrite existing output file. =item -A =item --all Output data from all sheets. Each sheet will go to extra file with name built from output CSV-file and sheet name. =item -N =item --no-pfx If specified, dump all will not use output CSV-file but sheet name only. =item -J str =item --join=str If specified, output file names under C<-A> will join on C instead of the default C<->. =item -o CSV-file =item -c CSV-file =item --out=CSV-file Output file name (used only with C<< --all >> and without C<< --no-pfx >>). Default value is derived from XLS-file. =item -i XLS-file =item -s XLS-file =item --in=XLS-file Allows to specify input xls file. Default: Last ARGUMENT file that exists. =back =head1 SEE ALSO L, L, L =head1 AUTHOR H.Merijn Brand =head1 COPYRIGHT AND LICENSE Copyright (C) 2008-2021 H.Merijn Brand This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Spreadsheet-Read-0.84/Changes0000644000031300001440000004307214016142167016565 0ustar00merijnusers000000000000000.84 - 26 Feb 2021, H.Merijn Brand * It's 2021 * Alias pivot to transpose (issue#36) * Alias strip to trim (issue#36) * Check for consistent return values of parses () 0.83 - 21 Dec 2020, H.Merijn Brand * Require ParseODS 0.26 * Add ::parsers to get list of supported formats * Add --list to xlscat and xls2csv * Update xls2csv to be identical to xlsx2csv * ::parses ("") will return list of supported types * Move installables from examples/ to scripts/ * Tested on FreeBSD-12.2-RELEASE with all supported backends * Fix META issue for bugtracker 0.82 - 26 Sep 2020, H.Merijn Brand * Move pod tests to xt (and do not distribute) * Fix some links in the docs * Add ".xlsm" to known XLSX file extensions * Spreadsheet::ReadSXC has a new maintainer (Corion) - support file handles - suggest version 0.24 (0.22 causes fails) * First attempt in supporting Spreadsheet::ParseODS (alpha code) - version 0.25 should now pass the limited tests - thanks to Corion for making this happen! * It's 2020 * Fallback to Pod::Text if nroff not available in tools * Extended support for merged cells with merge option - Added $sheet->merged_from ("C2") * Add --no-nl[=x] to xlscat * xlscat: Align-right more numerics on -L (was only positive integers) * xlsx2csv -Z : generate a ZIP file with a CSV for every sheet * Doc fix (issue#33) 0.81 - 25 Aug 2019, H.Merijn Brand * It's 2019 * Allow -c + --sep in xlscat * Add --sep= to xls2csv for -A * Add xlsx2csv to distribution (xlsx2csv has -A) * Add -J s / --join str to xlsx2csv * Add cpanfile * Add explicit documentation about formatted vs unformatted * Improve ->new behavior * Auto-detect fallback for CSV now includes '|' for sep_char (PR#26) 0.80 - 31 Dec 2018, H.Merijn Brand * Raise Spreadsheet::ParseXLSX minimum version to 0.24 * Improve docs on attributes * Add attribute accessors 0.79 - 29 Aug 2018, H.Merijn Brand * Environmant control hardening * ReadData () docs (opening from scalar ref: issue#21) * Check for XLSX content on opening from plain scalar content * Fix typo in ss-dup-tk.pl (PRC, Branislav Zahradnik) * Allow source from command line option in xls2csv (PRC, Branislav Zahradnik) * Allow --in-sep=tab in xlscat/xlsgrep * Add --hash to xlscat/xlsgrep * Help and usage for examples/xls2csv (PR#23) 0.78 - 29 Jan 2018, H.Merijn Brand * Spreadsheet::ParseExcel supports the active flag as of version 0.61 * Fix typo in docs (SPROUT, RT#124214) 0.77 - 22 Jan 2018, H.Merijn Brand * Note possible name clashes with example/tool files * Clipping and stripping more efficient 0.76 - 01 Jan 2018, H.Merijn Brand * Allow streaming in xlscat * Add --dump to xlscat * Add error for opening ODS/SXC from reference * It's 2018 0.75 - 09 Nov 2017, H.Merijn Brand * Windows does not like an exec with arguments that have spaces (PR#15) Three fixes by Andrew Gregory ). Thanks! * Fix column clipping * Manually generate cells to delete when clipping * Skip cell deletion if they were never generated * File names cannot have \0 in newer perls 0.74 - 27 Aug 2017, H.Merijn Brand * Re-enable opening files with bad characters in the filename (issue#14) 0.73 - 30 Jul 2017, H.Merijn Brand * Spreadsheet::XLSX::Reader::LibXML support completely dropped * New options for ss2tk (font specs and SS labels) * Safer xls2csv option parsing/passing * Pass unknown command-line options to the parser * Fix ReadData ("a,b,c\n1,2,3\n", parser => "csv") * Drop 5.8.0 support. 5.8.1 is now minimum 0.72 - 25 May 2017, H.Merijn Brand * get_active_sheet is only available as of Spreadsheet::ParseExcel 0.61 * Support password protected spreadsheets (implementation just for Excel) * Do not warn on undefined labels (xlscat) 0.71 - 13 May 2017, H.Merijn Brand * Use -w as intended * Add option pivot * No trailing spaces on xlscat -L * Lexicalize code snippet (issue#12) * Add attr method * Remove special chars from worksheet name component (Windows, PR#13) * Add refresh to ss2tk / csv2tk * Add shortcut for UTF-8 output to xlscat * Upgrade recommended modules to required for cpancover 0.70 - 02 Mar 2017, H.Merijn Brand * Add label functionality to ::Sheet * Add ->column and ->cellcolumn for ::Sheet * Add col2label sub/method * Sanitize xls2csv export filenames * Fix sorting in xlscat for un-aligned columns * It's 2017 * Be overly verbose about maxrow and maxcol being 1-based (RT#120476) 0.69 - 02 Dec 2016, H.Merijn Brand * Several OO fixes, more tests, more docs 0.68 - 29 Nov 2016, H.Merijn Brand * List non-core modules/version used on very verbose in xlscat * Option to export all sheets in a spreadsheet to CSV (UTF-8 only) * Add OO interface * Feature: add new spreadsheets to existing book (even of different types) 0.67 - 17 Jun 2016, H.Merijn Brand * CPANTESTERS showed that some versions really messed op numeric/percentage 0.66 - 16 Jun 2016, H.Merijn Brand * Remove Spreadsheet::XLSX::Reader::LibXML test files from distribution * Allow old versions of Spreadsheet::ParseXLSX to "fail" on percentage tests 0.65 - 15 Jun 2016, H.Merijn Brand * Test with perl-5.24.0 * Show parser-version used under debug * No more Spreadsheet::XLSX::Reader::LibXML * Cells will inherit hidden state from hidden rows and columns * Require 5.8.0 as 5.6.x does not include required Encode 0.64 - 22 Apr 2016, H.Merijn Brand * It's 2016 * Allow inconsistent Spreadsheet::XLSX releases on Debian (tests) * Decode utf-16be entries in Excel when appropriate * Two examples in xlscat 0.63 - 10 Oct 2015, H.Merijn Brand * Guard against negative MinRow in XLSX * Documentation updated * Support Spreadsheet::XLSX::Reader::LibXML disabled on author request * Fix warning in utilities * Check minimum parser version for pre-selected parser 0.62 - 16 Aug 2015, H.Merijn Brand * Fix documentation structure * Test all supported parsers (not just the preferred one) * Basic support for Spreadsheet::XLSX::Reader::LibXML (work in progress) * Copy example file if link fails (Alan Berndt) * Add a contributing guide 0.61 - 13 Jun 2015, H.Merijn Brand * Discourage Spreadsheet::XLSX * A space is not an empty field in XLS * Strip the correct selection (RT#105197) 0.60 - 30 Mar 2015, H.Merijn Brand * No merged cell support in Spreadsheet::XLSX 0.59 - 26 Mar 2015, H.Merijn Brand * Minimal support (+ docs) for merged cells * Make parser errors report at one level up * Don't select non-existing columns in xlscat 0.58 - 11 Feb 2015, H.Merijn Brand * Remove perl recommendation from META as it breaks cpan clients * Move sort instruction to correct place in xlscat's help 0.57 - 08 Feb 2015, H.Merijn Brand * Moved project to github * Add --sort to xlscat * Clip before conversion * Removed an unneeded localizing of $/ (related to p5 RT#123218) 0.56 - 05 Jan 2015, H.Merijn Brand * printf does not play nice with encoding (related to RT#98436) * default output UTF-8 if whole line is UTF-8 0.55 - 01 Jan 2015, H.Merijn Brand * Mention Spreadsheet::CSV in documentation * Add ssdiff to examples * Amend xlscat -n to also number in HTML * Updated copyright to 2015 0.54 - 30 Jan 2014, H.Merijn Brand * Optional features required versions now builtin 0.53 - 29 Jan 2014, H.Merijn Brand * Updated copyright to 2014 * Prefer Data::Peek over Data::Dumper * Support (and prefer) Spreadsheet::ParseXLSX for .xlsx 0.52 - 05 Dec 2013, H.Merijn Brand * Store CSV parse error - if any - in $ss->[0]{error} 0.51 - 30 Oct 2013, H.Merijn Brand * Link xlsgrep during install 0.50 - 24 Oct 2013, H.Merijn Brand * Added xlsgrep to examples * Allow -C B,D for xlscat * More prominent reference to xlscat in docs 0.49 - 11 May 2013, H.Merijn Brand * /dev/null cannot be used for tests on Windows 0.48 - 14 Mar 2013, H.Merijn Brand * Improve documentation consistency (RT#80409) * Updated copyright to 2013 * Force old(er) tar format (ustar) - assumes GNU tar on release box * Fix yml/json optional_features * Install utilities from example by default * Several minor changes (for maint) 0.47 - 30 Jun 2012, H.Merijn Brand * Note that empty sheets are skipped when clip is true (RT#75277) * Allow undef as valid value for the options (Max Maischein) * Don't generate warnings when stripping whitespace and only generating one of cells or rc. (Max Maschein) * Fix test warning under perl-5.17.x 0.46 - 14 Feb 2012, H.Merijn Brand * Updated copyright to 2012 * Support passing attributes to the underlying parser * Do not strip fields in sheets with no cells at all (RT#74976) 0.45 - 07 Sep 2011, H.Merijn Brand * NAME / DISTNAME in Makefile.PL 0.44 - 07 Sep 2011, H.Merijn Brand * More cross-checks for META data 0.43 - 02 Aug 2011, H.Merijn Brand * Changed name in META.yml (RT#69574) 0.42 - 01 Jun 2011, H.Merijn Brand * Add --html output option to xlscat * Force CSV parser when in-sep is given * Prefer Data::Peek over Data::Dumper if available 0.41 - 06 Oct 2010, H.Merijn Brand * Spell-check * Fixed requiring optional modules (RT#61928 - Roderick Schupp) 0.40 - 31 Mar 2010, H.Merijn Brand * Default option for clip fixed (RT#56151 - Alan James) 0.39 - 16 Mar 2010, H.Merijn Brand * Doc fix (RT#54507, Patrick Cronin) * Upped Copyright notices to 2010 * Drop YAML version to 1.0 0.38 - 15 Dec 2009, H.Merijn Brand * Add row () and cellrow () * Updated META.yml to meet most recent specs (optional_features = map) 0.37 - 09 Nov 2009, H.Merijn Brand * IO streams improvements * MANIFEST fix 0.36 - 06 Nov 2009, H.Merijn Brand * Add strip option * Spreadsheet::XLSX 0.12 still does not support attributes * Require Text::CSV_XS-0.69 for CSV for auto-detection of \r * New attribute "parser" to force format * Allow CSV streams * Allow SC streams * Allow XLS streams 0.35 - 03 Jun 2009, H.Merijn Brand * Add Test::NoWarnings, which is not run in AUTOMATED_TESTING * Switched to Test::More using tests_done () * Text::CSV_XS requires 0.43 or up, as we use ->eof () still prefer a really new release, like 0.65, which is Test::NoWarnings safe * Spreadsheet::XLSX 0.10 still does not support attributes * Added -n to xlscat * XLSX tests skip on feature, not on version 0.34 - 27 Jan 2009, H.Merijn Brand * Spreadsheet::XLSX 0.09 still does not support attributes still think it is better to follow closely. 0.09 is much better than 0.08 0.33 - 23 Jan 2009, H.Merijn Brand * A few Perl::Critic inspired changes * Modified tests to prevent rounding errors (we were not checking for that) * Added examples/ss-dups-tk.pl 0.32 - 06 Jan 2009, H.Merijn Brand * Add basic support for M$ Excel 2007 using Spreadsheet::XLSX * Test suite reports the parsers it found 0.31 - 04 Jan 2009, H.Merijn Brand * Upped Copyright notices to 2009 * Detection of percentage type * Even more reliable detection of Date types 0.30 - 22 Dec 2008, H.Merijn Brand * Wrong e-mail in META.yml * CSV files from a Mac, with \r as eol, would not parse 0.29 - 19 Oct 2008, H.Merijn Brand * Make Read safer for files that do not match extension, like HTML in foo.xls * YAML declared 1.4 (META.yml) instead of 1.1 (YAML) * Bring Makefile.PL in sync with META.yml * Recommend Text-CSV-0.56 0.28 - 04 Sep 2008, H.Merijn Brand * More tests on date formats * Declare Spreadsheet::ParseExcel::FmtDefault in META.yml * Add 'size' from Excel font size * Update docs about Excel quirks and CPAN links * Reference to public git repo * Some typo's 0.27 - 31 Aug 2008, H.Merijn Brand * Fixed META.yml (the specs are inconsistent) * Added --dtfmt to xlscat 0.26 - 29 Aug 2008, H.Merijn Brand * Added examples/xls2csv * Upped copyright to 2008 in examples * Don't ask to install examples under automated testing * die => croak * Added tgzdist target * Added encoding options to examples/xlscat * Added date-type checks for SS:PE > 0.32 0.25 - 02 Jan 2008, H.Merijn Brand * Spreadsheet-Read now under git * Upped copyrights to 2008 * Added all prereq's to Makefile.PL, even core mods * Tested under perl-5.10.0 * Text::CSV as of 1.00 is OK 0.24 - 05 Oct 2007, H.Merijn Brand * -? and --help in utils moved to Getopt::Long * Adjusted copyright notice in utils * removed prototypes in utils * next is illegal in do {} while (); (Johan Vromans) only happens with old Text::CSV_XS 0.23 - 21 Jun 2007, H.Merijn Brand * Use IO::Scalar instead of File::Temp when installed Thanks to David Cantrell for making a OpenBSD test box available! * use binmode () when opening files * Also use 3-arg open in test files * die if test files cannot be opene'ed 0.22 - 18 Jun 2007, H.Merijn Brand * 0.21 should already support Text::CSV_PP 1.05 Tested Text::CSV_PP 1.05 on bleadperl. * Better detection of (not) installed modules * Module requires perl 5.6.x 0.21 - 18 Jun 2007, H.Merijn Brand * Text::CSV_XS uses keep_meta_info instead of get_flags * Removed always_quote from xlscat's CSV output 0.20 - 31 May 2007, H.Merijn Brand * perlcritic OK * CSV parsing now uses getline (), and auto-detects eol Assumes first line does not contain embedded eol. This implies that parsing CSV with embedded eol sequences is now safe. * As I now also maintain Text::CSV_XS, I changed the references * Changed TODO's from Text::CSV to Text::CSV_PP (::CSV is dated 1997) 0.19 - 04 May 2007, H.Merijn Brand * Could not retreive '0' fields from OpenOffice (Jim Kelly) 0.18 - 27 Apr 2007, H.Merijn Brand * use strict in Makefile.PL * Added test_cover make target * Added "ods" for OpenOffice conversions * Added color tests for ods (but SR::RS doesn't support that yet) * Switched from \d to 0-9 in regexp * Added more test files and tests (increase coverage) 0.17 - 04 Jul 2006, H.Merijn Brand * xlscat new option: --ansii to (try to) use the ansi colors for fields * Fixed a color attribute off-by-one error * Added test cases (not yet complete) * Added bold and underline 0.16 - 04 Jul 2006, H.Merijn Brand * xlscat new option: --in-sep-char to force-define input sep-char for CSV * More debug lines * Parser name info in $ref->[0] * SquirrelCalc now reports Spreadsheet::Read and its version for parser info * Most of the attributes for Excel now implemented. Tested, but no test case 0.15 - 21 Jun 2006, H.Merijn Brand * Small doc change from AnnoCPAN * Sheets with undefined labels might cause havoc * Clip now skips empty xls sheets (TODO: sxc) * xlscat clips by default * xlscat new options -d and --noclip * xlscat usage () from -?/--help to STDOUT from fault to STDERR 0.14 - 20 Jan 2006, H.Merijn Brand * maxrow and maxcol were swapped in csv sheets * promoted internal debug flag to option * small doc changes 0.13 - 04 Nov 2005, H.Merijn Brand * Control attrib 'cells' was misinterpreted * New option: clip, default is true if {cell} is selected, false otherwise Removes trailing lines and columns in each sheet that have no visible data * new test t/11_call.t for checking options. Not complete yet * Added test_cover target to Makefile.PL 0.12 - 31 Oct 2005, H.Merijn Brand * Added ss2tk to examples 0.11 - 26 Oct 2005, H.Merijn Brand * Allow ods (OpenOffice 2.0) for sxc * include real ods test files and new test * Check if sc.version is undef, not 0 0.10 - 19 Sep 2005, H.Merijn Brand * More test coverage * cr2cell () returns "" for illegal col/row values * cell2cr () returns (0, 0) for illegal cell values * rows () tests even better for valid reference pointer * Renamed the test files 0.09 - 18 Sep 2005, H.Merijn Brand * Added Test::Pod * Added Test::Pod::Coverage * Spreadsheet::ReadSXC 0.20 now required (too many tests fail on 0.12) * Small changes to the docs * More secure handling of false values * Mention a bug in Spreadsheet::ParseExcel 0.08 - 22 Aug 2005, H.Merijn Brand * Slightly changed the Synopsis 0.07 - 06 Jul 2005, H.Merijn Brand * Added function rows () * Added function parses () * Made all modules optional * Prepared for Spreadsheet::Perl * Doc updates 0.06 - 22 Jun 2005, H.Merijn Brand * Repaired error in label names in metadata for SXC 0.05 - 17 Jun 2005, H.Merijn Brand * Spreadsheet::ReadSXC >= 0.20 supports sheet order * Spreadsheet::ReadSXC has new data structure (we still support the old) * Added "version" to the meta data for parser version * More tests 0.04 - 14 Jun 2005, H.Merijn Brand * Changed TODO * Added options "rc", and "cell" * Added CSV * Added CSV options "sep", and "quote" * Support xls from content * Added basic support for SquirrelCalc format * Updated pod * xlscat -R option for row selection was a one-off * xlscat now supports selecting fields with -F 0.03 - 19 May 2005, H.Merijn Brand * Expanded xlscat to support -i for index * Optionally install xlscat 0.02 - 19 May 2005, H.Merijn Brand * Typoes in the doc * Small change in organization so it actually installs 0.01 - 12 May 2005, H.Merijn Brand * Initial CPAN version. A lot can still change Spreadsheet-Read-0.84/Makefile.PL0000644000031300001440000001235013773601633017246 0ustar00merijnusers00000000000000use strict; require 5.008001; use ExtUtils::MakeMaker; use File::Copy; if ($ENV{PERLBREW_HOME} and $ENV{PERLBREW_HOME} eq "/home/njh/.perlbrew") { warn "Your smokers have been blocked because of consistent failures that\n"; warn " are all caused by the smoking setup and not by module errors. If\n"; warn " you have fixed that all, please inform the authors, so this block\n"; warn " can be lifted again.\n"; exit 0; } sub link_or_copy { my ($source, $dest) = @_; link ($source, $dest) or copy ($source, $dest); } # link_or_copy my @exe; unless (exists $ENV{AUTOMATED_TESTING} and $ENV{AUTOMATED_TESTING} == 1) { -f "scripts/xls2csv" or link_or_copy "scripts/xlsx2csv", "scripts/xls2csv"; -f "scripts/xlsgrep" or link_or_copy "scripts/xlscat", "scripts/xlsgrep"; for ( [ "xlscat", "Convert Spreadsheet to plain text or CSV" ], [ "xlsgrep", "Grep pattern from Spreadsheet" ], [ "ss2tk", "Show a Spreadsheet in Perl/Tk" ], [ "ssdiff", "Show diff between two spreadsheets" ], [ "xls2csv", "Wrapper around xlscat for easy XLS => CSV" ], [ "xlsx2csv", "Wrapper around xlscat for easy XLSX => CSV" ], ) { prompt ("Do you want to install $_->[0]\t$_->[1] ?", "y") =~ m/[Yy]/ and push @exe, "scripts/$_->[0]"; } } my %wm = ( NAME => "Spreadsheet::Read", DISTNAME => "Spreadsheet-Read", ABSTRACT => "Read the data from a spreadsheet", AUTHOR => "H.Merijn Brand ", VERSION_FROM => "Read.pm", EXE_FILES => [ @exe ], PREREQ_FATAL => 0, PREREQ_PM => { # Core modules "Exporter" => 0, "Encode" => 0, "Carp" => 0, "Data::Dumper" => 0, "File::Temp" => 0.22, "IO::Scalar" => 0, # Optional "List::Util" => 0, # For testing "Test::More" => 0.88, "Test::NoWarnings" => 0, # for ss2tk # "Tk" => 804.032, # "Tk::NoteBook" => 4.009, # "Tk::TableMatrix::Spreadsheet" => 1.2, }, macro => { TARFLAGS => "--format=ustar -c -v -f", }, ); $ExtUtils::MakeMaker::VERSION > 6.30 and $wm{LICENSE} = "perl"; if ($ENV{EXTENDED_TESTING}) { # for CpanCover and masochists # Backend parsers, all optional # Versions also need to be declared inside Read.pm ! $wm{PREREQ_PM}{"Text::CSV_PP"} = "1.97"; $wm{PREREQ_PM}{"Text::CSV_XS"} = "1.36"; $wm{PREREQ_PM}{"Spreadsheet::ReadSXC"} = "0.26"; $wm{PREREQ_PM}{"Spreadsheet::ParseODS"} = "0.26"; $wm{PREREQ_PM}{"Spreadsheet::ParseExcel"} = "0.65"; $wm{PREREQ_PM}{"Spreadsheet::ParseXLSX"} = "0.27"; $wm{PREREQ_PM}{"Spreadsheet::XLSX"} = "0.15"; $wm{PREREQ_PM}{"Spreadsheet::Perl"} = "0"; } my $rv = WriteMakefile (%wm); # perlcriticrc uses Config::Tiny, which does not support nesting if (-f ".perlcriticrc" && -s "$ENV{HOME}/.perlcriticrc") { open my $fh, ">", ".perlcriticrc"; print $fh do { local (@ARGV, $/) = ("$ENV{HOME}/.perlcriticrc"); <> }; print $fh join "\n" => "", "[-Bangs::ProhibitDebuggingModules]", "[-BuiltinFunctions::ProhibitBooleanGrep]", "[-BuiltinFunctions::ProhibitStringyEval]", # Guarded "[-Compatibility::PodMinimumVersion]", # Lvalgrind.log ); my @pc = -f ".perlcriticrc" ? ("\tperlcritic -1 Read.pm") : (); $] >= 5.010 && -d "xt" && ($ENV{AUTOMATED_TESTING} || 0) != 1 and push @pc, '', 'test::', ' -@env TEST_FILES="xt/*.t" make -e test_dynamic'; join "\n" => 'cover test_cover:', ' ccache -C', ' cover -test', '', 'leakcheck:', " $valgrind", ' -@tail -5 valgrind.log', '', 'leaktest:', q{ sandbox/leaktest $(FULLPERLRUN) "test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES)}, '', 'spellcheck:', ' pod-spell-check --aspell --ispell', '', 'checkmeta: spellcheck', ' perl sandbox/genMETA.pl -c', '', 'fixmeta: distmeta', ' perl sandbox/genMETA.pl', ' ls -l */META.yml', '', 'tgzdist: doc checkmeta fixmeta $(DISTVNAME).tar.gz distcheck', ' -@mv -f $(DISTVNAME).tar.gz $(DISTVNAME).tgz', ' -@cpants_lint.pl $(DISTVNAME).tgz', ' -@rm -f Debian_CPANTS.txt', '', 'doc docs: doc/Spreadsheet-Read.md doc/Spreadsheet-Read.html doc/Spreadsheet-Read.man', ' -@rm -f pod2html.tmp', 'doc/Spreadsheet-Read.md: Read.pm', ' pod2markdown < $? > $@', 'doc/Spreadsheet-Read.html: Read.pm', ' pod2html < $? 2>&1 | grep -v "^Cannot find" > $@', 'doc/Spreadsheet-Read.3: Read.pm', ' pod2man < $? > $@', 'doc/Spreadsheet-Read.man: doc/Spreadsheet-Read.3', ' nroff -mandoc < $? > $@', @pc, ''; } # postamble 1; Spreadsheet-Read-0.84/examples/0000755000031300001440000000000014016160366017103 5ustar00merijnusers00000000000000Spreadsheet-Read-0.84/examples/ss-dups-tk.pl0000755000031300001440000001670113773573521021474 0ustar00merijnusers00000000000000#!/pro/bin/perl # ss-dup-tk.pl: Find dups in spreadsheet # (m)'18 [28-03-2018] Copyright H.M.Brand 2005-2021 use strict; use warnings; sub usage { my $err = shift and select STDERR; print "usage: $0 [-t] [-S ] [-R ] [-C columns] [-F ]\n", "\t-t Only check on true values\n", "\t-S sheets Check sheet(s). Default = 1, 1,3-5,all\n", "\t-R rows Check row(s). Default = all, 6,19-66\n", "\t-C columns Check column(s). Default = all, 2,5-9\n", "\t-F fields Check field(s). Default = all, A1,A2,B15,C23\n"; exit $err; } # usage use Spreadsheet::Read; use Getopt::Long qw(:config bundling nopermute noignorecase); my $opt_v = 0; my $opt_t = 0; # Only check on true values my @opt_S; # Sheets to print my @opt_R; # Rows to print my @opt_C; # Columns to print my @opt_F; GetOptions ( "help|?" => sub { usage (0); }, "S|sheets=s" => \@opt_S, "R|rows=s" => \@opt_R, "C|columns=s" => \@opt_C, "F|fields=s" => \@opt_F, "t|true" => \$opt_t, "v|verbose:1" => \$opt_v, ) or usage (1); @opt_S or @opt_S = (1); use Tk; use Tk::ROText; my $file = shift || (sort { -M $b <=> -M $a } glob "*.xls")[0]; my ($mw, $is, $ss, $dt) = (MainWindow->new, "1.0"); sub ReadFile { $file or return; $dt->delete ("1.0", "end"); unless ($ss = ReadData ($file)) { $dt->insert ("end", "Cannot read $file as spreadsheet\n"); return; } my @ss = map { qq{"$ss->[$_]{label}"} } 1 .. $ss->[0]{sheets}; my @finfo = ( "File: $file", ( map { "Sheet $_: '$ss->[$_]{label}'\t($ss->[$_]{maxcol} x $ss->[$_]{maxrow})" } 1 .. $ss->[0]{sheets} ), "=============================================================="); $dt->insert ("end", join "\n", @finfo, ""); $is = (@finfo + 1).".0"; return $ss; } # ReadFile my $tf = $mw->Frame ()->pack (qw( -side top -anchor nw -expand 1 -fill both )); $tf->Entry ( -textvariable => \$file, -width => 40, -vcmd => \&ReadFile, )->pack (qw(-side left -expand 1 -fill both)); my %ftyp; for ([ xls => [ "Excel Files", [qw( .xls .XLS )] ] ], [ xlsx => [ "Excel Files", [qw( .xlsx .XLSX )] ] ], [ sxc => [ "OpenOffice Files", [qw( .sxc .SXC )] ] ], [ ods => [ "OpenOffice Files", [qw( .ods .ODS )] ] ], [ csv => [ "CSV Files", [qw( .csv .CSV )] ] ], ) { my ($ft, $r) = @$_; Spreadsheet::Read::parses ($ft) or next; push @{$ftyp{$r->[0]}}, @{$r->[1]}; push @{$ftyp{"All spreadsheet types"}}, @{$r->[1]}; } $tf->Button ( -text => "Select file", -command => sub { $ss = undef; $file = $mw->getOpenFile ( -filetypes => [ ( map { [ $_, $ftyp{$_} ] } sort keys %ftyp ), [ "All files", "*" ], ], ); ReadFile (); }, )->pack (qw(-side left -expand 1 -fill both)); $tf->Button ( -text => "Detect", -command => \&Detect, )->pack (qw(-side left -expand 1 -fill both)); $tf->Button ( -text => "Show", -command => \&Show, )->pack (qw(-side left -expand 1 -fill both)); $tf->Button ( -text => "Exit", -command => \&exit, )->pack (qw(-side left -expand 1 -fill both)); my $mf = $mw->Frame ()->pack (qw( -side top -anchor nw -expand 1 -fill both )); my $sw = $mf->Scrolled ("ROText", -scrollbars => "osoe", -height => 40, -width => 85, -foreground => "Black", -background => "White", -highlightthickness => 0, -setgrid => 1)->pack (qw(-expand 1 -fill both)); $dt = $sw->Subwidget ("scrolled"); #$sw->Subwidget ("xscrollbar")->packForget; $dt->configure ( -wrap => "none", -font => "mono 12", ); my $bf = $mw->Frame ()->pack (qw( -side top -anchor nw -expand 1 -fill both )); $bf->Checkbutton ( -variable => \$opt_t, -text => "True values only", )->pack (qw(-side left -expand 1 -fill both)); { my $opt_S = @opt_S ? join ",", @opt_S : 1; $bf->Label ( -text => "Sheet(s)", )->pack (qw(-side left -expand 1 -fill both)); $bf->Entry ( -textvariable => \$opt_S, -width => 10, -validate => "focusout", -vcmd => sub { @opt_S = grep m/\S/, split m/\s*,\s*/ => $opt_S; 1; }, )->pack (qw(-side left -expand 1 -fill both)); } { my $opt_R = join ",", @opt_R; $bf->Label ( -text => "Rows(s)", )->pack (qw(-side left -expand 1 -fill both)); $bf->Entry ( -textvariable => \$opt_R, -width => 10, -validate => "focusout", -vcmd => sub { @opt_R = grep m/\S/, split m/\s*,\s*/ => $opt_R; 1; }, )->pack (qw(-side left -expand 1 -fill both)); } { my $opt_C = join ",", @opt_C; $bf->Label ( -text => "Columns(s)", )->pack (qw(-side left -expand 1 -fill both)); $bf->Entry ( -textvariable => \$opt_C, -width => 10, -validate => "focusout", -vcmd => sub { @opt_C = grep m/\S/, split m/\s*,\s*/ => $opt_C; 1; }, )->pack (qw(-side left -expand 1 -fill both)); } sub ranges (@) { my @g; foreach my $arg (@_) { for (split m/,/, $arg) { if (m/^(\w+)\.\.(\w+)$/) { my ($s, $e) = ($1, $2); $s =~ m/^[1-9]\d*$/ or ($s, $e) = (qq("$s"), qq("$e")); eval "push \@g, $s .. $e"; } else { push @g, $_; } } } $opt_v and print STDERR "( @g )\n"; @g; } # ranges sub Detect { $ss or ReadFile (); $dt->delete ($is, "end"); $dt->insert ("end", join "\n", "", "Shts: @opt_S", "Rows: @opt_R", "Cols: @opt_C", "--------------------------------------------------------------", ""); my %done; my @S = $opt_S[0] eq "all" ? (1 .. $ss->[0]{sheets}) : ranges (@opt_S); my @R = ranges (@opt_R); my @C = ranges (@opt_C); my %f = map { uc $_ => 1 } ("@opt_F" =~ m/(\b[A-Z]\d+\b)/ig); foreach my $s (@S) { my $xls = $ss->[$s] or die "Cannot read sheet $s\n"; my @r = @R ? @R : (1 .. $xls->{maxrow}); my @c = @C ? @C : (1 .. $xls->{maxcol}); foreach my $r (@r) { foreach my $c (@c) { defined $xls->{cell}[$c][$r] or next; my $v = uc $xls->{cell}[$c][$r]; my $cell = cr2cell ($c, $r); @S > 1 and $cell = $xls->{label} . "[$cell]"; $opt_t && !$v and next; @opt_F && !exists $f{$cell} and next; if (exists $done{$v}) { $dt->insert ("end", sprintf "Cell %-5s is dup of %-5s '%s'\n", $cell, $done{$v}, $v); next; } $done{$v} = $cell; } } } } # Detect sub Show { $ss or ReadFile (); $dt->delete ($is, "end"); $dt->insert ("end", join "\n", "", "Shts: @opt_S", "Rows: @opt_R", "Cols: @opt_C"); my @S = $opt_S[0] eq "all" ? (1 .. $ss->[0]{sheets}) : ranges (@opt_S); my @R = ranges (@opt_R); my @C = ranges (@opt_C); my %f = map { uc $_ => 1 } ("@opt_F" =~ m/(\b[A-Z]\d+\b)/ig); foreach my $s (@S) { my $xls = $ss->[$s] or die "Cannot read sheet $s\n"; $dt->insert ("end", "\n--------------------------------------------------------------". "\nSheet $s: '$xls->{label}'\t($xls->{maxcol} x $xls->{maxrow})\n"); my @r = @R ? @R : (1 .. $xls->{maxrow}); my @c = @C ? @C : (1 .. $xls->{maxcol}); $dt->insert ("end", " |"); for (@c) { (my $ch = cr2cell ($_, 1)) =~ s/1$//; $dt->insert ("end", sprintf "%11s |", $ch); } $dt->insert ("end", "\n-----+"); $dt->insert ("end", "------------+") for @c; foreach my $r (@r) { $dt->insert ("end", sprintf "\n%4d |", $r); foreach my $c (@c) { my $cell = cr2cell ($c, $r); my $v = defined $xls->{cell}[$c][$r] ? $xls->{$cell} : "--"; length ($v) < 12 and substr $v, 0, 0, " " x (12 - length $v); $dt->insert ("end", substr ($v, 0, 12). "|"); } } } } # Show MainLoop; Spreadsheet-Read-0.84/cpanfile0000644000031300001440000000362514016160367017000 0ustar00merijnusers00000000000000requires "Carp"; requires "Data::Dumper"; requires "Data::Peek"; requires "Encode"; requires "Exporter"; requires "File::Temp" => "0.22"; requires "List::Util"; recommends "Data::Peek" => "0.50"; recommends "File::Temp" => "0.2311"; recommends "IO::Scalar"; on "configure" => sub { requires "ExtUtils::MakeMaker"; }; on "test" => sub { requires "Test::Harness"; requires "Test::More" => "0.88"; requires "Test::NoWarnings"; recommends "Test::More" => "1.302183"; }; feature "opt_csv", "Provides parsing of CSV streams" => sub { requires "Text::CSV_XS" => "0.71"; recommends "Text::CSV" => "2.00"; recommends "Text::CSV_PP" => "2.00"; recommends "Text::CSV_XS" => "1.45"; }; feature "opt_ods", "Provides parsing of OpenOffice spreadsheets" => sub { requires "Spreadsheet::ParseODS" => "0.26"; recommends "Spreadsheet::ParseODS" => "0.33"; }; feature "opt_sxc", "Provides parsing of OpenOffice spreadsheets old style" => sub { requires "Spreadsheet::ReadSXC" => "0.26"; recommends "Spreadsheet::ReadSXC" => "0.33"; }; feature "opt_tools", "Spreadsheet tools" => sub { recommends "Tk" => "804.036"; recommends "Tk::NoteBook"; recommends "Tk::TableMatrix::Spreadsheet"; }; feature "opt_xls", "Provides parsing of Microsoft Excel files" => sub { requires "Spreadsheet::ParseExcel" => "0.34"; requires "Spreadsheet::ParseExcel::FmtDefault"; recommends "Spreadsheet::ParseExcel" => "0.65"; }; feature "opt_xlsx", "Provides parsing of Microsoft Excel 2007 files" => sub { requires "Spreadsheet::ParseExcel::FmtDefault"; requires "Spreadsheet::ParseXLSX" => "0.24"; recommends "Spreadsheet::ParseXLSX" => "0.27"; }; Spreadsheet-Read-0.84/CONTRIBUTING.md0000644000031300001440000000245313531672470017527 0ustar00merijnusers00000000000000# General I am always open to improvements and suggestions. Use [issues](https://github.com/Tux/Spreadsheet-Read/issues) # Style I will never accept pull request that do not strictly conform to my style, however you might hate it. You can read the reasoning behind my [preferences](http://tux.nl/style.html). I really do not care about mixed spaces and tabs in (leading) whitespace Perl::Tidy will help getting the code in shape, but as all software, it is not perfect. You can find my preferences for these in [.perltidy](https://github.com/Tux/Release-Checklist/blob/master/.perltidyrc) and [.perlcritic](https://github.com/Tux/Release-Checklist/blob/master/.perlcriticrc). # Mail Please, please, please, do *NOT* use HTML mail. [Plain text](https://useplaintext.email) [without](http://www.goldmark.org/jeff/stupid-disclaimers/) [disclaimers](https://www.economist.com/business/2011/04/07/spare-us-the-e-mail-yada-yada) will do fine! # Requirements The minimum version required to use this module is stated in [Makefile.PL](./Makefile.PL). That does however not guarantee that it will work for all underlying parsers, as they might require newer perl versions. # New parsers I am all open to support new parsers. The closer the API is to that of Spreadsheet::ParseExcel, the easier it will be to support it. Spreadsheet-Read-0.84/README0000644000031300001440000000431713773573545016172 0ustar00merijnusers00000000000000=head1 NAME Spreadsheet::Read - Meta-Wrapper for reading spreadsheet data =head1 SYNOPSIS use Spreadsheet::Read; my $ref = ReadData ("file.xls"); =head1 DESCRIPTION Spreadsheet::Read offers a uniformed wrapper to Spreadsheet::ParseExcel and Spreadheet::ReadSXC to give the end-user a single point of view to various types of spreadsheets and deal with these in a transparent way. For more thorough documentation please refer to the perl documentation in the module in pod format, or $ man Spreadsheet::Read after installation. =head1 INSTALLATION $ perl Makefile.PL $ make $ make test $ make install If the C warns you in the xls tests, read the message and apply the generated patch. Spreadsheet::ParseExcel has a small bug in the parsing of the default format regarding UTF-8. This module requires perl-5.8.1 or newer. It might still work under perl-5.8.0 or perl-5.6.x, but only if Encode is also available. The code might need some minor changes. Recent changes can be (re)viewed in the public GIT repository at https://github.com/Tux/Spreadsheet-Read Feel free to clone your own copy: $ git clone https://github.com/Tux/Spreadsheet-Read Spreadsheet-Read or get it as a tgz: $ wget --output-document=Spreadsheet-Read-git.tgz \ 'https://github.com/Tux/Spreadsheet-Read/archive/master.tar.gz' =head1 TOOLS Installing this module will optionally (default is yes) also install some useful tools that use Spreadsheet::Read. At least two are know to cause a possible name clash: * xls2csv also exists as https://metacpan.org/release/KEN/xls2csv-1.06 Mine existed before that script, and this version dates from 2005 * ssdiff also exists in the gnumeric package with similar functionality =head1 TODO * Make tests for scripts/xlscat * Support Parsers native module options * Check if Tk is installed before asking if ss2tk is wanted * Test diagnostics output * Make clip skip empty sheets * Support Spreadsheet::Perl * Support Data::XLSX::Parser =head1 AUTHOR H.Merijn Brand =head1 COPYRIGHT AND LICENSE Copyright (C) 2005-2021 H.Merijn Brand This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Spreadsheet-Read-0.84/META.yml0000644000031300001440000000322614016160367016542 0ustar00merijnusers00000000000000--- abstract: Meta-Wrapper for reading spreadsheet data author: - H.Merijn Brand configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: Author, CPAN::Meta::Converter version 2.150010 license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Spreadsheet-Read optional_features: opt_csv: description: Provides parsing of CSV streams requires: Text::CSV_XS: '0.71' opt_ods: description: Provides parsing of OpenOffice spreadsheets requires: Spreadsheet::ParseODS: '0.26' opt_sxc: description: Provides parsing of OpenOffice spreadsheets old style requires: Spreadsheet::ReadSXC: '0.26' opt_tools: description: Spreadsheet tools opt_xls: description: Provides parsing of Microsoft Excel files requires: Spreadsheet::ParseExcel: '0.34' Spreadsheet::ParseExcel::FmtDefault: 0 opt_xlsx: description: Provides parsing of Microsoft Excel 2007 files requires: Spreadsheet::ParseExcel::FmtDefault: 0 Spreadsheet::ParseXLSX: '0.24' provides: Spreadsheet::Read: file: Read.pm version: '0.84' recommends: Data::Peek: '0.50' File::Temp: '0.2311' IO::Scalar: 0 Test::More: '1.302183' requires: Carp: 0 Data::Dumper: 0 Data::Peek: 0 Encode: 0 Exporter: 0 File::Temp: '0.22' List::Util: 0 Test::Harness: 0 Test::More: '0.88' Test::NoWarnings: 0 perl: '5.008001' resources: bugtracker: https://github.com/Tux/Spreadsheet-Read/issues license: http://dev.perl.org/licenses/ repository: https://github.com/Tux/Spreadsheet-Read version: '0.84' Spreadsheet-Read-0.84/META.json0000644000031300001440000001032614016160367016711 0ustar00merijnusers00000000000000{ "provides" : { "Spreadsheet::Read" : { "file" : "Read.pm", "version" : "0.84" } }, "meta-spec" : { "version" : 2, "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec" }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ], "bugtracker" : { "web" : "https://github.com/Tux/Spreadsheet-Read/issues" }, "repository" : { "type" : "git", "web" : "https://github.com/Tux/Spreadsheet-Read", "url" : "https://github.com/Tux/Spreadsheet-Read" } }, "name" : "Spreadsheet-Read", "abstract" : "Meta-Wrapper for reading spreadsheet data", "dynamic_config" : 1, "author" : [ "H.Merijn Brand " ], "generated_by" : "Author", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "test" : { "requires" : { "Test::Harness" : "0", "Test::NoWarnings" : "0", "Test::More" : "0.88" }, "recommends" : { "Test::More" : "1.302183" } }, "runtime" : { "requires" : { "Data::Dumper" : "0", "Carp" : "0", "List::Util" : "0", "Encode" : "0", "File::Temp" : "0.22", "Data::Peek" : "0", "Exporter" : "0", "perl" : "5.008001" }, "recommends" : { "Data::Peek" : "0.50", "File::Temp" : "0.2311", "IO::Scalar" : "0" } } }, "optional_features" : { "opt_ods" : { "prereqs" : { "runtime" : { "requires" : { "Spreadsheet::ParseODS" : "0.26" }, "recommends" : { "Spreadsheet::ParseODS" : "0.33" } } }, "description" : "Provides parsing of OpenOffice spreadsheets" }, "opt_tools" : { "description" : "Spreadsheet tools", "prereqs" : { "runtime" : { "recommends" : { "Tk::TableMatrix::Spreadsheet" : "0", "Tk::NoteBook" : "0", "Tk" : "804.036" } } } }, "opt_xlsx" : { "prereqs" : { "runtime" : { "requires" : { "Spreadsheet::ParseXLSX" : "0.24", "Spreadsheet::ParseExcel::FmtDefault" : "0" }, "recommends" : { "Spreadsheet::ParseXLSX" : "0.27" } } }, "description" : "Provides parsing of Microsoft Excel 2007 files" }, "opt_xls" : { "description" : "Provides parsing of Microsoft Excel files", "prereqs" : { "runtime" : { "requires" : { "Spreadsheet::ParseExcel::FmtDefault" : "0", "Spreadsheet::ParseExcel" : "0.34" }, "recommends" : { "Spreadsheet::ParseExcel" : "0.65" } } } }, "opt_sxc" : { "description" : "Provides parsing of OpenOffice spreadsheets old style", "prereqs" : { "runtime" : { "requires" : { "Spreadsheet::ReadSXC" : "0.26" }, "recommends" : { "Spreadsheet::ReadSXC" : "0.33" } } } }, "opt_csv" : { "prereqs" : { "runtime" : { "requires" : { "Text::CSV_XS" : "0.71" }, "recommends" : { "Text::CSV_PP" : "2.00", "Text::CSV" : "2.00", "Text::CSV_XS" : "1.45" } } }, "description" : "Provides parsing of CSV streams" } }, "version" : "0.84", "license" : [ "perl_5" ] }