From 3081e25a4d753577dabe0cab0e96d387fad68ebb Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 10 Nov 2020 10:33:29 +0800 Subject: [PATCH] fix sax --- CHANGELOG.md | 3 +- .../java/cn/hutool/core/text/StrBuilder.java | 6 +-- .../poi/excel/cell/FormulaCellValue.java | 38 ++++++++++++++- .../cn/hutool/poi/excel/sax/CellDataType.java | 6 +-- .../cn/hutool/poi/excel/sax/ElementName.java | 25 +++++++++- .../poi/excel/sax/Excel03SaxReader.java | 18 ++----- .../poi/excel/sax/Excel07SaxReader.java | 45 ++++++++++++++---- .../cn/hutool/poi/excel/sax/ExcelSaxUtil.java | 35 ++++++++++++-- .../poi/excel/test/ExcelSaxReadTest.java | 38 +++++++++++++-- .../src/test/resources/data_for_sax_test.xls | Bin 0 -> 31232 bytes .../src/test/resources/data_for_sax_test.xlsx | Bin 0 -> 10000 bytes 11 files changed, 172 insertions(+), 42 deletions(-) create mode 100644 hutool-poi/src/test/resources/data_for_sax_test.xls create mode 100644 hutool-poi/src/test/resources/data_for_sax_test.xlsx diff --git a/CHANGELOG.md b/CHANGELOG.md index a1dfb24f3..f60d2e604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.0 (2020-11-08) +# 5.5.0 (2020-11-09) ### 新特性 * 【core 】 NumberUtil.parseInt等支持123,2.00这类数字(issue#I23ORQ@Gitee) @@ -20,6 +20,7 @@ * 【core 】 修复ClassUtil.getTypeArgument方法在判断泛型时导致的问题(issue#1207@Github) * 【core 】 修复Ipv4Util分隔符问题(issue#I24A9I@Gitee) * 【core 】 修复Ipv4Util.longToIp的问题 +* 【poi 】 修复Excel07SaxReader读取公式的错误的问题(issue#I23VFL@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrBuilder.java b/hutool-core/src/main/java/cn/hutool/core/text/StrBuilder.java index 91535be4f..dae62696b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/StrBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/StrBuilder.java @@ -33,7 +33,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable { /** * 创建字符串构建器 * - * @return {@link StrBuilder} + * @return this */ public static StrBuilder create() { return new StrBuilder(); @@ -43,7 +43,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable { * 创建字符串构建器 * * @param initialCapacity 初始容量 - * @return {@link StrBuilder} + * @return this */ public static StrBuilder create(int initialCapacity) { return new StrBuilder(initialCapacity); @@ -53,7 +53,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable { * 创建字符串构建器 * * @param strs 初始字符串 - * @return {@link StrBuilder} + * @return this * @since 4.0.1 */ public static StrBuilder create(CharSequence... strs) { diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java index 4f6729f2b..28844b054 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java @@ -2,17 +2,39 @@ package cn.hutool.poi.excel.cell; /** * 公式类型的值 - * + * * @author looly * @since 4.0.11 */ public class FormulaCellValue implements CellValue { - /** 公式 */ + /** + * 公式 + */ String formula; + /** + * 结果,使用ExcelWriter时可以不用 + */ + Object result; + /** + * 构造 + * + * @param formula 公式 + */ public FormulaCellValue(String formula) { + this(formula, null); + } + + /** + * 构造 + * + * @param formula 公式 + * @param result 结果 + */ + public FormulaCellValue(String formula, Object result) { this.formula = formula; + this.result = result; } @Override @@ -20,4 +42,16 @@ public class FormulaCellValue implements CellValue { return this.formula; } + /** + * 获取结果 + * @return 结果 + */ + public Object getResult() { + return this.result; + } + + @Override + public String toString() { + return getResult().toString(); + } } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/CellDataType.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/CellDataType.java index 44baadb39..1d5143960 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/CellDataType.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/CellDataType.java @@ -11,15 +11,15 @@ public enum CellDataType { BOOL("b"), /** 类型错误 */ ERROR("e"), - /** 计算结果类型 */ - FORMULA("str"), + /** 计算结果类型,此类型使用f标签辅助判断,而非属性 */ + FORMULA("formula"), /** 富文本类型 */ INLINESTR("inlineStr"), /** 共享字符串索引类型 */ SSTINDEX("s"), /** 数字类型 */ NUMBER(""), - /** 日期类型 */ + /** 日期类型,此类型使用值判断,而非属性 */ DATE("m/d/yy"), /** 空类型 */ NULL(""); diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ElementName.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ElementName.java index 08614fc8e..e1328cfda 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ElementName.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ElementName.java @@ -12,9 +12,17 @@ public enum ElementName { */ row, /** - * 单元格标签名,表示一个单元格 + * Cell单元格标签名,表示一个单元格 */ - c; + c, + /** + * Value单元格值的标签,表示单元格内的值 + */ + v, + /** + * Formula公式,表示一个存放公式的单元格 + */ + f; /** * 给定标签名是否匹配当前标签 @@ -25,4 +33,17 @@ public enum ElementName { public boolean match(String elementName){ return this.name().equals(elementName); } + + /** + * 解析支持的节点名枚举 + * @param elementName 节点名 + * @return 节点名枚举 + */ + public static ElementName of(String elementName){ + try { + return valueOf(elementName); + } catch (Exception ignore){ + } + return null; + } } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index b51b449ae..67d31b67f 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -275,10 +275,10 @@ public class Excel03SaxReader implements HSSFListener, ExcelSaxReader rowCellList = new ArrayList<>(); @@ -189,10 +194,20 @@ public class Excel07SaxReader extends DefaultHandler implements ExcelSaxReader rows = new ArrayList<>(); + ExcelUtil.readBySax("data_for_sax_test.xls", -1, (i, i1, list) -> { + if(list.size() > 1){ + rows.add(list.get(1)); + } else{ + rows.add(""); + } + }); + Assert.assertEquals(50L, rows.get(3)); + } + + @Test + public void formulaRead07Test() { + List rows = new ArrayList<>(); + ExcelUtil.readBySax("data_for_sax_test.xlsx", 0, (i, i1, list) -> + rows.add(list.get(1))); + + final FormulaCellValue value = (FormulaCellValue) rows.get(3); + Assert.assertEquals(50L, value.getResult()); + } + + @Test public void dateReadTest() { - ExcelUtil.readBySax("d:/test/date_test.xls", 0, (i, i1, list) -> - Console.log(StrUtil.join(", ", list))); + List rows = new ArrayList<>(); + ExcelUtil.readBySax("data_for_sax_test.xls", 0, (i, i1, list) -> + rows.add(StrUtil.toString(list.get(0)))); + + Assert.assertEquals("2020-10-09 00:00:00", rows.get(1)); + // 非日期格式不做转换 + Assert.assertEquals("112233", rows.get(2)); + Assert.assertEquals("1000", rows.get(3)); } @Test diff --git a/hutool-poi/src/test/resources/data_for_sax_test.xls b/hutool-poi/src/test/resources/data_for_sax_test.xls new file mode 100644 index 0000000000000000000000000000000000000000..ebebc51bc0b1676a907911e2862d27cc5934857c GIT binary patch literal 31232 zcmeG_2UrwIv%Sj#izq=jBnYeoL5Y$TbP>$JfnYpAR9sXFVmL>gwuL(=%MTtbc#w zUej747rGHO@?EG!G-z-Z-1~~tdIa)?LQIN(yTCnwRN;S-2DG@)kQ(abr_gfEQo<%0 zTtaH$cMszx=sT9Cl|?+yW!3?o@6!wE3Fu5ia9c>vWX zCX{5YsjC5X-A&;gqpn>^Ya&b&rjeipwmwjrK)E4oe+uts>S{$@b>PY(ho~~QC`cz_ zNNxi@mt>=eB@d4TlW}AW8A~P;l+BUF z0-R&0DjAtMO5nGl-c0ydcS8v;*}Cg9!dajzMZQSiLkV1q5zZ!U80izzLJ8bM3EYnn z&LVt9zJzpR#3w{c30&SbEI7tQofr^eRbXZ9Xl?E43pbHY)U5@_9L7&$THdg5!RRPD zf(6k8bCwi#cBPkxlm*8cRBR!OAxDKm^ClgM8zIp=px%*3v5)5YHY6M5kpirotf+*4 zG|z(LOgg|H6s4Ez$fFnP$df6-CyoRLdpa`^LQ1}&s0<7U@cB}vUc>=xSISh3E8!~z z$dxn&TloP7B^yyCJNQQ0H{3^du;5sNzD?=5l(J+{c%X4J2@3L|(SRh9u>~SLIUHF^ z62v`-ILyYWmyfG!)MyBij*+|x5F&Y^`xy`{IND?{PNuF@y(~EG$Uf4Rxml@t0h$HJ zjO-^ygopvYlmz0`edwzg-U(p@mxL2MgyXDD!QYBARB(|d{yjZlSr(z`nJq^Lhjk2` z^|Jbxz;`QwXDNZNQ37A91inoPe1{UaGI>@g!QZX~u8h7i{Jl!({CCT9q=B!Ns9$^( zH5aTcD7YphnfePXhD7k|Bn)mX#rRsXaOk5VIxVDd9wF&4^vl8J`lGfOUt%XaDS2SE zCE_cAi`uu97=E3Mgt<#1j|L3Ll>Bn_(tufk39ciivs_<)rS?i~!V$H*t^^(%d))H4 zCE*;R(E;Wao=BJK z91s{o!#G1=BA~_}Id~gDq2Oq!7yv(oYe-VWX$sh#%v{A;m&$b_sWNb?0BHsDg&N$# zLX)`STm=gO9az(_6$>B=yEz4LN!qLeC`hvkphB8eK)tyIa4u~Y2hHXdz(#2n2ONHy zRRG7OW);AJsaXYZ#A;Rn9Lkzi0LQFm6~Mu)(E{D&`U8$~YRb)&VaaRzRfDp-{enwM+q= zmFY_Zmg2ByBO|7K0XDZ`kV21GAC86>mu7eB_SmHAiIs1xEWT4zE))9zsl+R+C3@t%#9kF9qarNf_ zgrz!Z!gA5^p9nQyF<;(Xj4pt$?oXQDb@)c*7PQp7s^XcsHx0C3CmVXYWAP+4D#ysmZ)24 zXTXfcM`)j>5ovsy@7y#ZjZgF7#HLO2kWlQ~Se?eFd3+=)T~jJ0()cv**EAxs)4aUN zbfsifx}g`_u~1m1U^4sm?Nb=4=rFMzBMhsEK|EB^VTxlwH^6Mxw83v~0sqDeEMuF1 z>$U}9xe-@lOL)WyqW`p{xjc9Rk<0B35ePH{7RN%^0-mHOVqzn+;5n!!M-W?G`$nja z_c#l}SZa&@66B-L%*Ty^j};>y95EaCs0(7h{#nV)r!_MlcLqM~8TsHq+rURd5c}fA z3uZnB%zQi;_;h6CBO0G6y=e+!g>TB3`4}?u@nqoR%*Y3a@P_(u1+jPPKQQz8ftimN z10Od=J~%2j@X->)K6rJDnU4|j@nEnbMSHUZK1`SrKAf`PqO*^g`Lto?!(?yPjC|{+}?9Gmm58d9%f@^AOnE9A6^I@_#2Sz@0dn*eTK3dJp$CQ~5lfAhx z@}b*XS#U|!OJ+W1%zT*a&7F}C-QLQA&)zR$=F=AWcs0r1c)*7VQ)+K+?n|~RX&-ZD zK1}vz!^nqjZ*J~y_hc~F$AXy;lfBt9@}b+Cn|o<#DKj5SWHqtg=i9cSg5dG zM&)wRzOX4ofyFWtvdGIQaZgvrZ6G)#P%6AfuSLU32Go{LpoQfcjYXi*e1`v#C1EYQ z0Mdl#c)&V!s3L1qV4XUY&KlhqV%F&EXke`c&n&@cddK^YP?#*$On^V;;1+{YCY`?q zt-)EaXqPs>2B?-p9MU;ZB~w|QsB?g%-OsGys3XL3OxFY~o*b4Yh>BRlV2lL?Qn*^M zk_1UNE?PM&mzyYCfNcb1F$Z@Kxcor{;|5Y(WAtuNHAbm16FnFrsii5dOrDlZY8hLX zID-;cC&t!|85j}R-*0R#cZ!@8ZGfLNpDqjfD<};@Rq(u`j4Zf=)u1$pvWQY*SwtzZ zETR<3;)1d~%({?cH)6iPaZD~37uS@gs0)kj3H+q_Vha*iwxRV~fqtRe$1dtOKtx5Z z1F*HB1Bi3!G(b+V1?j?w0J3~vUJxVJ3tvtaV~|CfFCIQn7D>CH{U88693uO1OIHKS zu#hFCt_A`HMudcFgfCx#HANe8PuBoU8#zo3p{4{=){Z>Tj@a2wKjw11Wec&|f*oNF zz2^wQn<2I%ba_a6jwjMtw)AsTreM)Bt*v>)o zN%{g#7(P;ZIAO@sYbT*cU)B)vBDE7$F9mv?rSx#Rkf&!Wp+{f75W?73QNAuxdN^6g z)9WCiM_;Bu9ZwKu`Fy4HaO#k!=Om#=Uyi`(x3xEz>G?_N;SxliUMC4X`m%$Ni935U z(bFPb(Y~I=s~Om_xAZH;lLF=nxOD=%kREvnVAtXHiOQ&Z5*3 z?hvws#vvQ{=)>Otn5ssRcp@MXaQt=#br%Au(QqVp3Yh?|gD|+8N)jPgia|fH>qSOT zhmJF$GgYDoifE9Cu>!&5PHVWvWDSj{XmTS^8$ve0LG4YnJS?{u)H?|NPO`WV3GsZ! zCSOS}P!f)e)EtS=w1XzxSX3vl97CxE`iMBd6e`Y+@2?vzpDl#7B$wO)r#$kH;Tk~{ z7bSQukqT_Gf*aFv1udu5Vm1j2Qsdw;Lpu6gA z@$bj%z2~R*%~}&)FzeC8F~R$~F3C=^%-($Mvk&{C=hXJ;-_mu;r}V#VT%VQW^RP6q zs!r|T9`hkxU)FtEW%D4rsF?5dX(ndUV`(UDorO%AxVc?kw52B*klZ*^eiM zh9lnbpBPk>r4361jR;}YEUT}A%EHGdKu=!Krg#z~I!O?p?Ba~qjHQ?3PP?|8|0=U& z-qqCp*G?PTPIW2B4s_X+N^0%X##))xnAO*Wp3`V?l$){n)rYNJzwcV~sdo8ep3$0Z z8mAuw@-L39o!a$y+T7C2&4sqyVbdr6YtyWn1JTFAu5R)x?_^fc=b-B^t#ubvhaL;x z6)^g0sou4IJ!?Eh*`yWbOp30uT(!>RzE^O?JEQO_?-9F}ZYdS+KkZt!F7#yDZpXTw zoCNRX!Q=iMwQ-Bf!-$gXErM;=Ev_6m{HgLAR7J6(<7ccenguaj&9?tW= zbkFd{+MrfL9rH9>EfkbHFF5p9iesVKmRo(=o^gz?J@><-r_+r~i+(n^*Y|vK|5WQ6 z*_k^J+~HLoaJbR#mE)b^M{MG{F6uq_NyUc_4|>)+v~R)oVHW-6!iw0 z*rFoz&Lx#xZJc@z`M%>5<0pX?~GgP z_e9Vus32+UzF(eJk&bO9?Tp)gZQJP29^~DZJr&Cr?c85{%RXeUhW)oESMKcas#<7t z_sa2uCuVHlG27{wM#1MG?T=HBvW6G^WxD*qMeUDCsU>%d-i;4ixZCmm_RO8JTjQQq zZOG1@UX<><++qCB)d}wBv#(CDODTzr8$7u1LbBoLz!gy!{>VO)G;~+bC)uyPh+(!> z-%+7Iw)X3h+UJo*{^oO8hXUv7wRY*=$zV_95T_#T@qa~sTk+P;ynoT0oOU~>vkdm` z+5B;O{^h<_`};flcZXN}J$>YZdtX0RuZ>PiTR-#Wq?Ze;qK{Ai`^}m9$I-{W)vgZwV${2< z!ChN@qq`Q}-oM<-^?GuD>8!6Qt?%gR2eC6Z)NCxa4b(pD-Tivz_L!PXU7rCaZT_nK zc;&$@txrQ*&#yZ=ax`n2$)+i1f7Lm>J>JCP<&uXdCgd#*x!pBmN#sE@`-AM;rgmY& zvw{THe;AdkEgY4_ZX5G->#X>Uy)n~twf2534*Hy@<+c27;Da0blZrP7%^YM^7f@p} z_i%6|r``1xiBm17Pw5qPG~t1@nbuPEe4RH@!A{x_O$r)DLtwitk{0DL27YusbF-h+2m^d=F zE^$o2eD2Y0WkySPJS#qvcY}a|)n|A8 zQ9SQ?USJ95gs`=pGIZsoJ|rc^w3dXjW0yg2lW zwZY-uBU)snOzI+tPS>$MvNEnKH|NID>jx%2uFn|u+V`Tn#^t(=Js-BbYjMTm|cWmGKC~n(p;fILw zePcewtr+SxDYD$HTbc3T{bg@Q*CoZSPDz_xFly_g!fC5#mU~?(+~Lmd z_ukK@WsFyrr)Ji(`2L;yu75hWqOHx_OU{{Riszk~QZU7Jv2NMrRaOZyj_w;Nh{o!!HNMU5(gvtwg{587|uFsrvw)kIT6V42@=UO@*nPTr?Y1)}vY(Cnr?StPvPABZJ4=r37R$K8? z?Xm4=TyzHI#<#3}nK3VBckgpwE#?|J3|@3$j+)i|Gu=DAdz5}+?VcUkb)USeR{bWZ zO8KE6**>bbht}1iO{>oMW!8tUyLxr-YTd=#pRPN(@n1o|{k*5m7LD;;Zan*KXjPxi zjxUM}wL4rk>FNGz^`L?Mqbj1#IBM_ra(#Spk>`wgH_Fb0Rg~$hU-9x&?$K`Brz9r_ zRN9`XT`g=I^`T{}lN(l;?cdVj>>|OC8_%C^yW<;c=9hVE=$efF?;P9@B+tG$Gozxd zXR5aV{Y)7WjM+%8XlnY8BQgu~C5_=g+) zm{sjNde4ZtOA@_b{4gdb$UdaKO}M>tr&UQhcKw#+U0FEbQ~EBSO-l#;X|?IM?&ptQ z>GNSq>W0^ASt)01N=E6;xh}3(%kEpR-4@Kb zFs!)vk9(4;v)E2>QbXAa7tm;dVZ9p`BuhYk$tNxC3i_li0ObqHFQKFbO<-+FZv=Vu z%TtnH&qyg%GEt&dH}W*(jX+AH4jx_8rD?<@!h+QCu{~_$)JYW7{yrXGCTn2>w3fEb zfDE!2V2f!m#6x7!TdjIBZ?$T(4KbSvcs{`bToDH01dbcQo)We=Y}mr-Quq4Q=1C7W zFJHI5z7{enj2}(G(Jx8hy*0efr6B3l28SX^Y{BmX3qjT#$Thq&!%?3230gr=-Hup+VR2l!rH6XUDrd0DhAVq`>=!dv^~9 zo@F1f@?P-U39jA2d*2g0mhJ#^g4hE*Bi?Z51CXBZ=LC4(0QUiGZxRS8cj8HJu`^qeqCi?s+XHTH#*#IYd01^qCdP^>{Qb zWZp~7K5b5T&bb1x;D$WOU_wiGgnNWzS$~LwAmXcyJzyM(phQX+Wg`l?GHA zP-#G=0hI<+8c=CKr2&-&nxcV?#0or|=-tFWHuyG&u-&Op!59C+R|L83Au6Zmho`To zFc4^PNh);!20qrMgZ^O%Z2T65=q)#qf0N6`gEV+=By!WRbP2*RArC_e@-Xzp&|%*w zFE#-mEe27F1>PE@H=7Md{o%J8;VrE5#}rc3CE2lGs1(wICp7*`{WZX2g}z-86+-&@ zLl%pCH77j)>4XW;vs|+p!&W{f)GgFVcQaB2)h!21KRA-11ApDvt;s>kA&=$7VG+3A z7s)7*P0WFn8gfK7YRH@Q3LcTDga3?>G2Au~#l^9{EOZI0^$@x2r5UQb|3M9W7oz$p ztCr!4ZFoO({hLprWA(P@aEXK6{%Ti%?SY8L8ZqA=B0lrz0}&f`1jN=5r$fXeW7!b# zGcS1%@z~cEh{$ORSRa0+0s9R7qoR=fM|jA%n54wy#MsHap3`Fl@stc?jK7OcekIEv z3D}zb#y?oe0v4*E(tt_>Dh;SKpwfU!11b%uG@#OeN&_kls5GF`fJy@m8fa|)&%RN9 zBhT4PZ`n%N|2ux#h5P>#5b+~Kxc?7>h`yyE5b?vBcs2-MSBi&-d;7@{ao?W;5nmU} zfQbHp#SqayupT1aAAr6D45Gce9z_e&NE3tnuLUqcInW;=dV!9#1Q3!$_X2{CY_9sS z_XR}}F;zjO0hI<+8c=CKr2&-&R2ooeK&1hd22>hQX+Wic|DPJbT`_K$anFtWZ+y!R z&wAkI8K3FnULW76#JxA}*>V4lr(ba2k9&N0If;7akNbS_JCC^6M}L4ZL=%YkUnyJ;V+W@&C&@z^@}jCy4k(b{B}Q5IaG{ zd_1y)uNLBmiM$}@#kaGX6O4#Db&Ln8 zq8;(Lcoq4H;HMXrXt<>BY=0mE&Sqdch~a~&x5~!DCzVi+@nUe3f8oEtO8BD;O)Z!O zZ~kIXhxgF%vrQA=EjO%tU(iA!@FsT08t+7fj{;k>_1KAPrZSMod<%t!h3hk RlgH=Zs6T$JjOx7b^IyY+j_v>e literal 0 HcmV?d00001 diff --git a/hutool-poi/src/test/resources/data_for_sax_test.xlsx b/hutool-poi/src/test/resources/data_for_sax_test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8fb64fd8b5f1031ac5f20b8f28ac3d6994cd6e07 GIT binary patch literal 10000 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 literal 0 HcmV?d00001