From 436aaa80c9891f38635d759cab708e55bd3155b2 Mon Sep 17 00:00:00 2001 From: aulickiDnv <104196418+aulickiDnv@users.noreply.github.com> Date: Sat, 28 Sep 2024 12:24:12 +0200 Subject: [PATCH] Yield empty self-closing row tags as empty row during query. (#673) --- samples/xlsx/TestEmptySelfClosingRow.xlsx | Bin 0 -> 9205 bytes .../OpenXml/ExcelOpenXmlSheetReader.cs | 4 +++ tests/MiniExcelTests/MiniExcelOpenXmlTests.cs | 25 ++++++++++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 samples/xlsx/TestEmptySelfClosingRow.xlsx diff --git a/samples/xlsx/TestEmptySelfClosingRow.xlsx b/samples/xlsx/TestEmptySelfClosingRow.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a309ea83e245ea39698fb6efeea4efc5a167fe71 GIT binary patch literal 9205 zcmeHNWmr^e+Z_Y}2?^5wjIq#2~Ukp>xH012g2V5Cbrq`Nx=LApByq`MsWM$h}c zdOYX*uJ8YQ_FUJV+UuTq_Fn6`*K^++C=ZW-13&~I0{{R@z{`6c+*)t|KmY;&@Cbl> zPglah-r3yV*-*{h(Hx}D>Skw4k%@4RJ{@omcKkovfAJY8is`rSV8@iYh`q*$u2nbL z%KX514|SGR7w;5a@0B?7H^__h!wZ)IQTiEdmoTB=2qndc=Ioz`tA zj-yO_c-%Kht?@%eqS#6g)=0-~QG4muZW>2Ci2-3Tdu0|ZDsC$z=BOG*8}M~iW0#iq zbEfK+#d>qJ06rvWX?3S>+f-yz5s4!WGO(B=y65P;7WqSrqHxFbjXr)zL~gfapy%JP z$-4!963&oI6JSwS)85_B17ImN9<{O85!B{a1cLX6-^f3 zVpWB(vGFMvMU8+8Ie-PAt-4WNA>QbB@aP*!xDZ<>G4b|be8A9U`nbdLm3wmlGYB!b ziu-jf>nl8ADJ5u<6gj)1y?_69(8z8@f0RE3Byi2~ocl^fLDlE%WyVb@PQLt%Q^5M( z#AT`iM#`qV**8=G;O-6{0Q{369~rcm--8Kq38ptxm>> z6*|oO-Z@D}?8`hNF^0e&P`Z6y#%7sk_HHUby2Nx@@VQ1m5l3~az z#M6cc0Pc8dGz4K2&#iqN8W18IY_cyZTHz1!#c_^nyf6R6?B`%wP zjl0;$yjx0^2CX}6X51H2)W;BOZmfeG@flJkcYvk$5(Uw)SWAvNt%kPP41>y2jAq!u zNrM+&Co%1wCicDG z_AR3}qg$uuFM(DvQ=KVo&wDfOMdOGIBLXN75u%lg z&Pz(S_mUvjd1mOUXE%z+lDsChib5tj%czqoAPTT81Cdber#z$Oi#uiD4eR@Gft*0ZTU=NS7DX@AxSK``uf6M*0_rR zIH)wpB=Hetyl-~t;b-k(bx|TrwFAsUs0@!|E*ue@lwf;^u_;guGu*B-1QN~Ju0kN# zmsaHDbJi!$$=$dR(~D=H-;lB}t!`J5x}aEc9b%XEa6hdvSZ%(x@$T~>UK86^NKYR$ zByiI1 zMg+||F2mHv0!v&(0Ax6r3jfGmziRQ{c?=F_C}C0lySJj~e(TQfhAQCJFTqRL6(uL8 zcP2)>rW*>Nj3n=h^S6LZ`WUYGE{MwT%pjK_E`Vt4z#?nuN;vfwN)pi<>Al*97bO#i z>Rv+4z9t+cJbvJ8W2!*?tIINIcDsx~mp-{x4&Fy1f#}1)-kPit$1m{pTvnbW5!nQ~ zXgy>K@^yVD_~Cbg=|VedH#!pYQ$y(=7-)|7?3cKjbHEOf)cp0YMdPew@PV-*EFpod zDYVbp`Y%5VA3@RrG_FZr8id(A>=q_%@e*=;MpO8)qMJ_{k5K4l{TTo6_<;(f)L4OW zBNsMH6TmL~zh-HWrMbB?i0#J{$M@+v1@hBo#$7Da;EYQnsJ;16QFuK|`~v1OW$aF# zPxu`0;pBHAV$lwErKJd(F0Hr~;%fVyj3)W!F8E`!cf^e{qg)@|j@RdPA=%576ut4? zZyP(>I=84Rx8JsTEgEIyDYk=|l)}MgJvB+B z58QuH-{@~#D2I}uQ$A|cLAEM-^!n^Zhv!ywY!y4@i+#PdK*v`^EKq^jbTv?}s`mw| zDd~Hr-B-zrFU4ve9-zHn6w6H&Q5}8Gw_}IfAY*ZpG&JX9gb^M_z1?&d#=cDoDvLV; zDCh4sKt^w)V^fWqnT-9YneF5IH7l66z{g;h!_*#1e)OPfasi?^Y-K)IDH65&UJ56& zY#Fv(w&2Ej^q6o!njD&Ikp12hxf=@_|N3>FXaL>8{HA>^Wjl0%Ev5Yo8}eUQBUdRz?Dy*`}`0&>^j}u zrKssX^kv6vLfM96)^9^%P?TI1PMYl^ZyOHvc!h5|jP2dvlPvo}pfXjhp|HAT#DIza zG}0_T!6>A0dvHa~g4sP(FZuY`x`?yp1XrFH$WHs&xdx9fLQdu>W8Y_dVHTCQqm@r3 zx5$kZTMaVbJoUJ}5ZN#asTW+T-SoEPmKHS<#(S^-g@g4ZQa+&;^AgJ{94GA|FOl^g zvPxH)xB#ZiYn3cs^q5UJTa|B$S`lv8Jd|l_Kp9<>kWu7xu6y(my_rPqKCL6f-$(Of zNRkm^DBssIrB4Rnim)Z4xG3{QNeas+$*vi2&#Tc7TLJg@?@-=aMG6bH zc~Iz^c8VK64pI+UmM0q>=NGTq6Bl{pD%5r1zXR;LFJ#$>d$t(|W{Vq9vX|_})BS9p ze(TgYZ{(z<>XlnL(x5tY(wts-UJ6jNUA>O*9>$ow#Q{WoWFHL=+aEiqX%H6qXq~=0 zy4pCkHBpFYaALT$Jb$z?)W!t-vNYF*fk-Ji0(%{J!NOrRF8=-FKn$M42)VpXZnUO* zQZY0^#9N`{cA))v4*@by0t^$+pz$`ORhW z%t~nLh|T+YwcDY!^^SRp@pU7hU&@dskq=-M}6DCLst|=Q+NY|dG0zg$!&2=`611$X}~_G zbR%;$;_`=G`LILB=z-nTJXBKfqYP@@B}%z)gbRF7l%@%YPa(sD+!hQa#t9gm=?OrlLG-{lo;uKlz?P=vp${2bldv;^L1I`ol=!+<%7+b{) zJKqTB_bdptqIxcJQg3=6hmAw}`x6om)*wn)8jSF>4l*7J5Y97bOvTMzc*Pv|H3`?k z{-yqS(>v@PL6?n~K!;8!Qfy-oULQIdTmP4VGqE}m0#%qLr{wnx*?GTksDQnbq zLiAA%WvFg7qVHiT?bJQ(tJ-M4>}1)VF$OYJ;XR$OaA#Lkl=oHvX9Z7uUX@jup~_r{ zaq+uKJ4Y`{0!_TL7~%OSN#6Q=(B^uKFvvM2t}(t;5W*0z4;59J08YN$5)!`(&kS=% z)TC<2&Dx*j7~VhTkPzjS;7jUzaGv^Np)${!kYAB2jDHM>%WpH=eF{}PCMq<+=GHPF zEv`Xt8g7`B+err&S9TFr?%OCJ6IEw&`X!k)F?2q!JkfYJ%g>5jC4->5T9Zay6zw*b zNWQD2S)4+lu_LE``L#3X7RJ7PU$@g`95=E1ng#xB7!1BrhOTc@`VgC_E+ku|{h3}w zLuy{Nu7aD&z69mSjUB`{HE1$$LzSAxkDwma2bxUH_Iq#&%v7O;-sdCc03;RXL>~{8 zJ>vI)YT-)}G$6*MXhWqB;_@_>dG#Iw63KNGT+*~z*mFF7*4LWz-Mrdf<*ITXI3v%%MZ z%wh6jlv{I$#K()?k3o7;MO`%mxBuvkwx@cNPrNo5bJx2wK?0Cr`<8dmZqt9-x|60F z-=iPL)2b?ZynV7LWPwQ9W(Px7Y?VC)Q?|ZCxI<6l?jBWv`@Ef>TtAD8XZL+@&_h&e z?avNVa>NbTqSX=DIvG4k2?W(&VzN(Kda2#bt0p2E0eYFqfttIt3xtVSI;qisD;F6R zxsFTiy<&IT=i+E{AU1N=3TdVnDmma!ZxTeuYmIL6Pr>Tf%8N74a1)_#&edK&?#S+C zWT_H+nC&;{LMBDKLtRp^%+%?nB|(cHv`G5uS>8E^lG9c*7<*`~PK&QAfIzD|4Zs(Q zwhkJ|$L86x6d|dJGHA~}W7nTI%$y1&%j6>^rO@x7(zR0UG<$#Z(g`=wC;~n+u$0%^ z#RIjKX^$k|(2P6Jra1pF=aj+^ZbMBW_>~BBDe1+uo!_`p+~~q2f8eY2WXC5NQCTx< zXT*^r(mUnP%38GVFv4an+I;4=-;y2@;zEno-v}L#LDq(DD^L>}so|<-U#`?$E7rf( zuH8foG!WTjv!9x!L_ICHKwo%p!R|S5G;`Z!-SX}T^DN+?dWXWvv*w^_aHMO~sJO9` zJ*6x&b%p=dz4DS>cQNKAJ39UtMZK97yF7kBg<=VQzd1kZ+Tr!o)|Ff5+DNl2g;mTz z@$1JuBw@mFZa(K5ZdKdc;71RuKF+^5qWP8}Z45LBREbj9;!03r9ZOfpa^si91qE&N<$*rZKGI9A5@6su_mwGwN?@&LBkj0)W)7x6CkICmo2i47`5(Oz`hS+Puv7Q{+5DsbQ?@kj^Wr6kmIW^CiEYb@l|4Vg zgIE#In@M0VoG&HY&)JE!o4UPsx1duU1n2g(v?DFdqKx>aqZQf4)+D1ev*2H$nNy+^ zN{;E|50l+XnyTf^an`FLGw|GLdxlOaPe)wmj62)2#n&Td-yRI4>Bx0l@SryFxJGvs z_YOrjlJ3PJ4i*ogKNL%7Y!6nFqeaTOIaXu?VoSgy+M*@k;TTRMFZzq1UayC83GD07 zZgcHd>-L%Q4L7DEmF+ZS5}%o7Uom+5czf(=ey$e&7K@-3FL%CIcS=E(&-~!Be1Ts( zf{ZL4RgF{pF@NG0vx;m^r2{@{a@wb=dDmgX*=t2-BGNpAeO`l*XeXW(TTgQ#)UVig z0wz#c5%aHwmB%7FagHz&Zo){2384H*LSskAKR8JG4+sA*0;WL3lsnnc0uE%p1u=r- z9%72CCOtsUAdO0>g4-N!u#rrbEZ5}l7Pc=ef5`U|^eru|l~3g)GFM3_*s{65%NY`i zptp~@QWN2ud@fr}#Y}A4EkW&RKATcIEbC@8dY*&lH z%NFg3!#;;iKDo1b2#n4LiMR5gUh!+g1?u@9h;q;j>RdZmuAIEZFyy&uYtuOz;9hUE zv?^7l{rIeUP!S!qW@mI9S&od@`a!O4_owM#ooX%{%E#o7s@^w+%SSg6`rFIU={zca z+0`j9=eV^aKp_SFx+bUr@RzGFwmjdM7A)DTPCG|rRf^DW19WsStoA%dzf>zx$QB9C zGhIzHUM6*%Bwb<$4NMs(K8E%hT+$KLzF2AWsM;re-`TT7?As}zoNTS1hv{>ObBO zMPw_Ej;Lgpct!wgfZzNiaN+ib?D{%F!Rk?&xlJ*7$_z zt4|Qg^RKkNK06cy^Ut1@#+-j)OyAZTj-(X8uY@8{B2}Lo)eP}? zwgin`GY-#eDU6emvF0%;NyrHr{&PA1 zClmmXL-_&zUyA#`$N9bN`!kX?+JFAUUy8uLNBO-<_A|;GSjP`Gl;3M+zX$kziSjdm z6yA>jKNl>&L;q|7e*ysjGC~00FP89k_@C4Fukb8bJ@P;Be c if (!XmlReaderHelper.ReadFirstContent(reader)) + { + //Fill in case of self closed empty row tag eg. + yield return GetCell(useHeaderRow, maxColumnIndex, headRows, startColumnIndex); continue; + } // startcell pass rows if (rowIndex < startRowIndex) diff --git a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs index 6afa983..1afc692 100644 --- a/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs +++ b/tests/MiniExcelTests/MiniExcelOpenXmlTests.cs @@ -180,7 +180,7 @@ namespace MiniExcelLibs.Tests Assert.Equal(2d, rows[1]["B"]); Assert.Equal(null!, rows[2]["A"]); } - + [Fact()] public void CenterEmptyRowsQueryTest() { @@ -201,7 +201,7 @@ namespace MiniExcelLibs.Tests Assert.Equal(null, rows[2].A); Assert.Equal(2, rows[2].B); - Assert.Equal(null, rows[2].C); + Assert.Equal(null, rows[2].C); Assert.Equal(4, rows[2].D); Assert.Equal(null, rows[3].A); @@ -252,6 +252,27 @@ namespace MiniExcelLibs.Tests } } + [Fact] + public void TestEmptyRowsQuerySelfClosingTag() + { + var path = @"../../../../../samples/xlsx/TestEmptySelfClosingRow.xlsx"; + using (var stream = File.OpenRead(path)) + { + var rows = stream.Query().ToList(); + + Assert.Equal(null, rows[0].A); + Assert.Equal(1, rows[1].A); + Assert.Equal(null, rows[2].A); + Assert.Equal(2, rows[3].A); + Assert.Equal(null, rows[4].A); + Assert.Equal(null, rows[5].A); + Assert.Equal(null, rows[6].A); + Assert.Equal(null, rows[7].A); + Assert.Equal(null, rows[8].A); + Assert.Equal(1, rows[9].A); + } + } + [Fact()] public void TestDynamicQueryBasic_WithoutHead() {