From 6ecdb90abdabc19a299399ced7db544d8049bd47 Mon Sep 17 00:00:00 2001 From: zl Date: Fri, 25 Oct 2019 15:07:37 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E8=BE=93=E5=87=BA=E6=97=B6=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E5=8D=95=E5=85=83=E6=A0=BC=E5=A2=9E=E5=8A=A0=E8=A1=8C?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/write/merge/LoopMergeStrategy.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java index 85694a81..b0878047 100644 --- a/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java +++ b/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java @@ -13,24 +13,39 @@ import com.alibaba.excel.metadata.Head; */ public class LoopMergeStrategy extends AbstractMergeStrategy { private int eachRow; + private int columnCount; private int columnIndex; public LoopMergeStrategy(int eachRow, int columnIndex) { + this(eachRow, 1, columnIndex); + } + + public LoopMergeStrategy(int eachRow, int columnCount, int columnIndex) { if (eachRow < 1) { throw new IllegalArgumentException("EachRows must be greater than 1"); } + if (columnCount < 1) { + throw new IllegalArgumentException("ColumnCount must be greater than 1"); + } + if (columnCount == 1 && eachRow == 1) { + throw new IllegalArgumentException("ColumnCount or eachRows must be greater than 1"); + } if (columnIndex < 0) { throw new IllegalArgumentException("ColumnIndex must be greater than 0"); } this.eachRow = eachRow; + this.columnCount = columnCount; this.columnIndex = columnIndex; } @Override protected void merge(Sheet sheet, Cell cell, Head head, int relativeRowIndex) { if (head.getColumnIndex() == columnIndex && relativeRowIndex % eachRow == 0) { - CellRangeAddress cellRangeAddress = new CellRangeAddress(cell.getRowIndex(), - cell.getRowIndex() + eachRow - 1, cell.getColumnIndex(), cell.getColumnIndex()); + CellRangeAddress cellRangeAddress = new CellRangeAddress( + cell.getRowIndex(), + cell.getRowIndex() + eachRow - 1, + cell.getColumnIndex(), + cell.getColumnIndex() + columnCount - 1); sheet.addMergedRegion(cellRangeAddress); } } From 00581c77ee8d996a8bcf20a7f622d339125e1ef2 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 28 Oct 2019 18:48:04 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- img/readme/quickstart/fill/complexFill.png | Bin 5119 -> 0 bytes .../quickstart/fill/complexFillTemplate.png | Bin 1938 -> 0 bytes .../quickstart/fill/complexFillWithTable.png | Bin 4917 -> 0 bytes .../fill/complexFillWithTableTemplate.png | Bin 1621 -> 0 bytes img/readme/quickstart/fill/horizontalFill.png | Bin 4608 -> 0 bytes .../quickstart/fill/horizontalFillTemplate.png | Bin 1553 -> 0 bytes img/readme/quickstart/fill/listFill.png | Bin 1690 -> 0 bytes img/readme/quickstart/fill/listFillTemplate.png | Bin 811 -> 0 bytes img/readme/quickstart/fill/simpleFill.png | Bin 1680 -> 0 bytes .../quickstart/fill/simpleFillTemplate.png | Bin 1841 -> 0 bytes img/readme/quickstart/read/demo.png | Bin 2746 -> 0 bytes .../quickstart/write/complexHeadWrite.png | Bin 4379 -> 0 bytes img/readme/quickstart/write/converterWrite.png | Bin 5563 -> 0 bytes .../quickstart/write/customHandlerWrite.png | Bin 4344 -> 0 bytes .../quickstart/write/dynamicHeadWrite.png | Bin 4649 -> 0 bytes img/readme/quickstart/write/imageWrite.png | Bin 9060 -> 0 bytes img/readme/quickstart/write/indexWrite.png | Bin 5075 -> 0 bytes .../write/longestMatchColumnWidthWrite.png | Bin 6702 -> 0 bytes img/readme/quickstart/write/mergeWrite.png | Bin 4045 -> 0 bytes img/readme/quickstart/write/repeatedWrite.png | Bin 5576 -> 0 bytes img/readme/quickstart/write/simpleWrite.png | Bin 3528 -> 0 bytes img/readme/quickstart/write/styleWrite.png | Bin 4610 -> 0 bytes img/readme/quickstart/write/tableWrite.png | Bin 6807 -> 0 bytes img/readme/quickstart/write/templateWrite.png | Bin 6844 -> 0 bytes .../quickstart/write/widthAndHeightWrite.png | Bin 4805 -> 0 bytes img/readme/wechat.png | Bin 67852 -> 0 bytes .../excel/analysis/ExcelAnalyserImpl.java | 3 --- update.md | 3 +++ 28 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 img/readme/quickstart/fill/complexFill.png delete mode 100644 img/readme/quickstart/fill/complexFillTemplate.png delete mode 100644 img/readme/quickstart/fill/complexFillWithTable.png delete mode 100644 img/readme/quickstart/fill/complexFillWithTableTemplate.png delete mode 100644 img/readme/quickstart/fill/horizontalFill.png delete mode 100644 img/readme/quickstart/fill/horizontalFillTemplate.png delete mode 100644 img/readme/quickstart/fill/listFill.png delete mode 100644 img/readme/quickstart/fill/listFillTemplate.png delete mode 100644 img/readme/quickstart/fill/simpleFill.png delete mode 100644 img/readme/quickstart/fill/simpleFillTemplate.png delete mode 100644 img/readme/quickstart/read/demo.png delete mode 100644 img/readme/quickstart/write/complexHeadWrite.png delete mode 100644 img/readme/quickstart/write/converterWrite.png delete mode 100644 img/readme/quickstart/write/customHandlerWrite.png delete mode 100644 img/readme/quickstart/write/dynamicHeadWrite.png delete mode 100644 img/readme/quickstart/write/imageWrite.png delete mode 100644 img/readme/quickstart/write/indexWrite.png delete mode 100644 img/readme/quickstart/write/longestMatchColumnWidthWrite.png delete mode 100644 img/readme/quickstart/write/mergeWrite.png delete mode 100644 img/readme/quickstart/write/repeatedWrite.png delete mode 100644 img/readme/quickstart/write/simpleWrite.png delete mode 100644 img/readme/quickstart/write/styleWrite.png delete mode 100644 img/readme/quickstart/write/tableWrite.png delete mode 100644 img/readme/quickstart/write/templateWrite.png delete mode 100644 img/readme/quickstart/write/widthAndHeightWrite.png delete mode 100644 img/readme/wechat.png diff --git a/img/readme/quickstart/fill/complexFill.png b/img/readme/quickstart/fill/complexFill.png deleted file mode 100644 index d37bb0f9be8c8907f226d5111ab9b7313411e240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5119 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 b%*ZR6B}ogslCpSkrPB`f7h diff --git a/img/readme/quickstart/fill/complexFillTemplate.png b/img/readme/quickstart/fill/complexFillTemplate.png deleted file mode 100644 index 14e26b95176f0516826fb5670cf972fc8c6d9102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1938 zcmV;D2W|L?P)MuYxVX4?cXxN4!or<*oxJ7 z<=5BO$H&LQ!otjqw&R&>$1~ZEXR;m7WILY8c07~qcqXzl zhXIx|f^26!vK`MoB0JYGz;Z^A?W{+(HdVh=(4+#$ZT*>*d|9_j5A->CLsb*_3dTmbsotTfNo!=KEC9^4MU z?ZkEpLH2>&*i_H98U%x#8b&HI%+Q0`8F+333auSUR}EQ0(ADk_e5Lf+{H5)vhy312 z-9wge;Lp)eoRHH>X6Rl@ry!933e4GjCf{OvkN7glp=EYzq+yL87(uqP9zni^CDL$) z9~eQlvmTM1DN>N_Bq7`J-6OKIMhdc>M1*d#-!B$*y)W%8CqCITmmLIQD2O&> zTxg8Z|NmKwjL;ODZVC=`PV9r2xH*~I%FVKK2}TLqQRX~$z===a<|mLE?x?}UjM$DG^SJ|OM-~M5My(1$Vh6UP z0}w}gYjbvF_{iXZE1Mvb3co8b`w-irX;*YGLTr?sA^hL~zpaMtC}TUyja1u-U|vB= zxArP%s`%Eg9Yk_Fq+q9FpnU*e&wlM>VTq$=huF?ecDUnAQ*}FK9jH zj7iZBQ0nkaYx)@G)pxd**+H?g0ma^UDmDMob~dt8uWU$!tnD~E|2%h63t5YN#CF>M z->FwNf=XrMrXkmRzjjvHAvHVnhefI@+q=CpXl@$>qA)>khH0mha}K@a(*FN{*fL%Q z8zfd}m&`ie7c3+tkstX4BCI9Wj^v#FZxp}{4+czRETTN(H}>yIPfTvp)#(ggPN-Fz34Dy6zg-BPVnwWTlKnZ~Jt*GXYnxmjLDP5~cofM{ z8H@hB53W0HPvpWClbkCWkBmp5Oq6jzrwPf{H^%&VMb1@w)Qm@=Oq6lZXY0d#*XV$p zD_8o+cofP+8OLJrR#>I$6qe1}$4qt~;B6 z&QZ%24ABWBF`bkeIu~0upr-?+mJMkBDqq>MjeP_tv}|u2os@H0lth^F-qUmd)J1+} zHniFF*?>tp0LlWC@?vqHZR`X2ReS(#pA9%g$H&;b%ETT|0U}IVGo~tH{oB+S8#OlvSE{ z5mcw6MyH?U)W_Lu=y_wKF3Yh|zvtR=^v&rwohdz~j~AYm?+JW(-LdS$=~(vRbPW6W Y2kuj%@nx5kApigX07*qoM6N<$f}~B-(EtDd diff --git a/img/readme/quickstart/fill/complexFillWithTable.png b/img/readme/quickstart/fill/complexFillWithTable.png deleted file mode 100644 index c107520113287c13bdffb801826fecd563c21be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4917 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 J_V47;NC1cPavWqeHeVMY1 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 diff --git a/img/readme/quickstart/fill/horizontalFillTemplate.png b/img/readme/quickstart/fill/horizontalFillTemplate.png deleted file mode 100644 index 462b86ebb56544c8d5cece22dffedd80aa55be18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1553 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 diff --git a/img/readme/quickstart/fill/listFillTemplate.png b/img/readme/quickstart/fill/listFillTemplate.png deleted file mode 100644 index 010c8c1665a547af3f340b0dc620230ab6a63a18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 811 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 diff --git a/img/readme/quickstart/read/demo.png b/img/readme/quickstart/read/demo.png deleted file mode 100644 index 8bd14139d10fd49f9bc24ad512f2fc49e6bda23e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2746 zcmV;r3PtsaP)1?AGC=gAkKia-K+u^I}ZVvY&;(-u=b+} zx6z=sVZoR%`V2vW{9vR{n+}+z?=b#8PSV1x>L5>>q%cS8`WzN-Qkd2IWvMKfr7z6U z+n7(AUqYDkB@;sy{r>J+=m#*1#mle-vn)$L2=mv8$53`sn6FG`3Zna8svSR4`~b|d zHa`gWRk3*9q=s34Cxp3poJ50(JU3wJ3G-$=tiQJfV=LhUh`D77qtDh8fgc8D=>-!P zm9O(se9znpJd}}OmH{wJz+ACaJ{b5U&aDh4cfADB@yL+*0n9_88n6URrpn>v3wuZl zQyP5)?_qv0QslX5uq^!xgs+pS5a!}VQsz_s#iORl&oif9m;F$tropoGPi%f}adp-= zpew&1>q)pDjPxVPO;N%GxHV;qSsw#%??nMFUwkHSm~lTU1g*=-6lF3jC- zwOWF^}2EpE&mfKWz;TSg) zT?%tNv|-w~YWt6-8)k#peupkTe+V$)r>i3lieVDIEP_n*P?&=bnAEU605XkX5v)Bx z5NpFkzx}?eqdZ?x7Z|v8QcUz%nQ0dTc-os*zM}2OO!#wkq)26sw6pv&(G$YN77c7% zmzX%1j*hX)`~avK5ynK13KKQ)DY~=F@f+rziA*79M|6u+=D0l}785-lOc+=?@z&OT z3vxZpktcRX5Qz8yYC1$XCVG6BWDmf;lYb1CaFoeRz_dF?go%2xCr3>5BvT{AZQtpz zB|M-A9l5EIt7Al%xY~AFFwtYeq^99X-T@N_aF~brMaS5gNpRdSCVHyOdl0x^@W@4)@a>gLZZ_ z@n8~a*LT<^2}~k8E;(T080xvJ%-f%~I|98NCbhEPIs<2PmEdxa;8uH)9UA+ETBvDe zs?y#!n4HqCFl`%D0ZMyPnAC3f2jfEe5D;5snC%g=H0bmO*?iID(%=i zoj4qtnJ<+@X~)rIN;~#W3Nz@QxpYURNAqVzRclL08_T6-Kf%z6&=zw?Iy9( zPUf^QN$>_FUDIw7D(&dUDedQfn#+`SsM6_`b~>@rPO7x$sTyUX+w=;iD($MY=b4!b zQQsPv~#79duC>+w7c(_IsHKmFhiAg zGD(&8@9_ZgP}-5Ls!ki|OEL_e5~wI)=}?Ha*6iw9_~OIP9P7 z`gR_aji{!c_EmpoB(rN(od#V_yOOlOk_~%YnT;-|eI9t)$Ej|8ry=dr5IpVE)P1KS z?b8s_WA@5vho>E+9SAPAm>}&S?J-v-!~|)NDdwXO2&8?-5>Jr!-RfnP=`l2oc_S*V zH=-V&gun|^<7qb~?fkibw7Z&JPs1Lbc98aIK00MiJB?#b+KV%3FS2Lzwo1^5O5{x1 zNk)wtZ6j*2ZA4AQGapxZd{284F)tY!QL~6yRT(_(MZA7I4PdgXVDMbUXzLkP~E~U`_|G_T42qKJycDvb4#y4H0@Q@Rxc+Tonjj@c+4snHC5 zBWf1W(O^!P_BJq0dk1qarycOfX@@gRK=GY9ZQ9|G(+)~N-FOO^#-?3s*uCpB`|)gG+MD(co)t_W3C!`Fc3i+5Gwcy=M74pbFzvv_%p5fA z5z4SFVE%hfdr$CHV2+#i3z!PS{wgrXUZ@$R#yFdHJkqqEM?NYIdu#ic_SSE9(~kRg zUeQ4XN7Ekf;mqVRC(QHbX<&YSm9h|~O?u4lDyQ~^FwK^^6loGBVFrX*xy;RA?%PV3 zMlkEPayPeuDO)+unN~3C!b7`NKk`pM!ZhmV4-l%Z&MsL1cK`qY07*qoM6N<$f}1>I AVE_OC diff --git a/img/readme/quickstart/write/complexHeadWrite.png b/img/readme/quickstart/write/complexHeadWrite.png deleted file mode 100644 index 995ffc3ce37ae2ff14cdee4f058518924f523824..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4379 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 diff --git a/img/readme/quickstart/write/converterWrite.png b/img/readme/quickstart/write/converterWrite.png deleted file mode 100644 index 5c9f28983f9198475cdcae48098750ce06ae4e39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5563 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 diff --git a/img/readme/quickstart/write/customHandlerWrite.png b/img/readme/quickstart/write/customHandlerWrite.png deleted file mode 100644 index 41916c3fb1da3a4f9991d84e26cddfe6629c0219..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4344 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 diff --git a/img/readme/quickstart/write/dynamicHeadWrite.png b/img/readme/quickstart/write/dynamicHeadWrite.png deleted file mode 100644 index 3b25ad72b894131a3fadf7707bf7eb6a1cd0d52e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4649 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 diff --git a/img/readme/quickstart/write/imageWrite.png b/img/readme/quickstart/write/imageWrite.png deleted file mode 100644 index c6a0c67a91dc5a7022a8cd04ff727258f34794d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9060 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 diff --git a/img/readme/quickstart/write/indexWrite.png b/img/readme/quickstart/write/indexWrite.png deleted file mode 100644 index 8dbec177459e85b61bada41ffedbc8b43f425323..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5075 zcma)AX&_YX+aHD*%UC1Fo}z4NMj||98H6EZZ(noN8Mc@NV+4W;ClHuyHXC6~=JVMECZA0< zh9CIFfeARt0w@>CB|!o~UteEsZSCOTV0U*no|OCO(WA!3MzS#i4#MM;lks>M4@Sy` z1f*Pu$>uYeWHJFpBCwgvj*bpKn@J!Lm}KMr{{Gh1*8BJGbGh6*ckcA|_7VtWIFp1= zUJo%w7!%+`LR(u~Q&SUx48suMso~*a*kr@9*=!hbc2mXFcEh>b7dXnz_3t*n`YjnM_4`xEfw`1tS9R`6Uc<_zKe*aFfB(MvzMkl1 zVfbzn#?1P#fr7jKhzInC5-~0}{c-&gTb>_Ljky^)sX9Lw{$kkPC)9;{5OuT$_%>qt z#;&(<=kvkNBt2GOWmFF}_xPbZ<(bj$K&|JK9Hic4zwf)f;Y$}ne6H@-j8vh@zV_W% z74Sv!UH+SD1^;dSik+a;A3)ui9Wg^mH?4YTWj0~Sc8hl7o3EJ_}eF`Ds|M%LG1*I$|Ae5YzsSUz2uvL3H4U@fIhO(2$%-g_6pg0zotsLB{g@007brDdF5 zUDgs3n`(|?7`SSXyP*A|wCL)pICCRvkadp-b)B-|>513|MGR$W`xWWr^1;fc>c}VsWQSd6O8r4Ef#j9%a)v1FBC&EWtd}TdG+v}-Dd6!B ztKAcKPtTCN`VSy(7Dzi6c~E|0S>Q``#sXvhMA%zPFEdH!Bl(7m>Z@sHLQI63&f?R3 zmR%tMM(#M`H(J|qk&d2&sve=m3tKzdSQiw#?ueCt_cEy{C3rrtc&g8vC&_{_N}VNrIS`mTNv`{iG?FBg_8bg#@#-VJC8XDkDJe%4*ER<0BFx|BU<-EoAp2KYn#!S}v!uz1kq&!2^Xr>tQr?Zh> z-3@K-njLcadcCJ&y`&n?Qcxai(sWFXYz(Z1%GvFrWHEKVc+9Luh?PBk(f%6oC&lYZXjiUGw)xeFhguR7Vo8#voxgPsl`A9Ptz@3p5d{sT^iIb&SI&IDJb6|c zwW<_9%%=!yPg{i}`K$IR77a=mUof0(27Id^(TZ9h+34*cZ~F6RntkZhv*~@dUaKeG zZ8+Oxf@&uP9%;EO9PR33sQ*nGUL-Vi(#{OE`Bjum`mGtEc)h7E3WyB*++MFsn z5fmrV>?Ks!+V`yjA-)iyVf_sxbuR8%Q@Z|V>c`uXef1iE?_Foy3rRy1BNu>CHhE)o zRs9aeDkG0SyLLXh++proWNWkg!>YAZ{U3>~6We-lSG>i#Fs+K=aFxt(f!$nE-Cy9Z zQcW@J+unnoQqG|`vE#I=ld-QudQLzwF0{{6R2?6d5+?c@qFsvi+O>1HJorX=X6!i4 zUeVu<7A@opEg3gGgs)yJD;YBGf9`#kxZM9~*U?SsGY2Y`^bLo6YVtFP)jMbn;H~Y; z-cAZi!A9H5(&buyPG_&Zaz)*E^0eae{3{QOQ-3>|N9Vms_!4&Z={FNu2CC~Jk=r#a z*3>?&~ntRC49_$zv+npuUwi@q{;m*r;nZ@e8jP*VEWYn6XGCzOm96!B6GC%vw^;TzW z@t!khGZ#MSQA_bt5*QnosPTvw+z^AQ=g}*@V7i&e^B0pZF3`(WNalu`CaIy@B{6y{ z=HQ$qXPinU`3ip~(8yeDU8QE-ITo{@DqQTutR|JhhQ-CZloVBCOrP$AXA zARz6zz;D$sUf1K^>6HfCd~oDa?%+UJmcoGdkAY2v>-_RC|12oxh`lm5NiBU>rNIJ` z48_y~*d>j;Z-Bl#Hgf3$^eo0#7S$^O%cy{57?zwaWAVMpPNJQ=HS*|Tk_=Xh4e&C? zceOgT0_>Taqz~?bF#(!R`AIqFvGovf7}5x91;b;utTWMIrsnQ@2uCKIY3ee&M|FFo zD9UNihVrbn{3L(y&5SSx`&NXtBJQ$uru@Oz$%}Kd&c9A

#GJHk`?RS=uczJQ%J| zP_fXToQ!YIq7N3JW~EVL8`Fyr$(^_|LW%DVzQ9%;<1Yq$8AN8dQLtr?mlFy^XWo|R zoS8Z7lqOQn(Yg7BGypx`nxzo6!d^i**VMSkse?V<=f-oysYA?UQb(BQ~n6BwsTlqo@eMxI_H)w-6E@;k~$L{MHSf` zPAoxn6#;Hu<&NjY=$+mt(T+JIKcI$K^fb#X5yTfg?$*U>{h=y_)je~(iimM8R0G1( z6(U?T3I_+QwZX-D`P>xNuD1?pBGIy8zJ`GOG>8yOmRzZ>s;ux7MWyY|x9pY&%^VVf zu!mjCb_9qN?JIOw#^i|GY#J~6p5_`a1=JWnIi@U&+LNb?J$$CrI3U@{)Dqy|0uP|= z(2fjUx2|7(xC&&~a(AV)TlOXMD|Ur8fb9<@4-fPV+3T<1L)ge{++a+e>(#i29ID9i z`6K!om{*eWletO8<%T(Ii5e#D>Q)6dk}o)+D9pqtGF5R@jCQE}~~1eF-T$n7h`;p~w0^ zA~Z{m$eLKiqXV{ry4Jki?M=CFg=N8slqgZ>I(lYr(k?;_#rw4^_Yc1OjW|WXRo2At z1>~m)Shw~pUw!jW=&T5efW(}mCD`uQAo}v?Mq-JSUHeLNt$Bv9o>;xJ;2L$n*2v+>{oE-o_%$Dgo1K@awna9u8!a9VaENQIl+3fPe zlvxSX*!3(7x8R$0xA#uoV_8&yo2DvpVBgGqG#fpZ0`V?G@rC9hjKh>cx=}b1evf)) zt-DU9r~+xA4Dze~c*)g_=hG#O5t%uN8mkKjDI#6Fuz0%BHVpTTsPpPskoalh0+fg4 zaRH(#-G~M`)v*6>y>ghYGwB3?m^MhOwWC7fKta?uSZNW&dkFbKd|@yS_=e-jJ_*2J zxL;|}tp*u)yIn1KrZzkx-%EyD^n23t1C;j{6oq6&QW}11_|c7`FeV$YMNYv)oEbgS zAmdUCKWWwG34dFK{xXu`EoXw^#$tIzAt{tp6g@N8ReiGEJK<#bsar&tZZkm4dT?(( zLj;)LtwX|Md0MKhAA3|ut#GN%Pdd-R0uxPnaFlx!j#oCEdxGK=b1);Etxcc*`tELa z*s~N$o<(69P-{@uiyC|4a{BX&vuhQe-W@_WbFc~(5Fb}u;#ssVI4@TQsDu1wYd*M| z@=Q?y9pbFGE!q*r>Yc*JdH_+AT5H+-;q9JIVQ?;7ohXA$8AZF(q&tO%I|$wcNqY6m zTj()MfH>kdA<)XIJGEibXjTe^Qh|gq&F4b`F#N!7$saT-^pyuLT+rKsQUS?F-1H{cujce%O}_5v^_a#%C(%HO)BXce%&MECELiYb(@NX7}u=#=i#`u6ps zRBU**^#8vVvN2r=C!kIxCqD1X!uySMX{P7G-4Z9uK}ZUGbzFkE->6ydHm2M?nHKCE%}dH2CRsHYA$X!TJm`wIfPG~H-g zwCgzj#_t0nj`PrYNck^mR+L-p(vJ?|dlY6|$Z1E@q-)RtUBX}*H2N`|a^pYJ4KF)* z#f(UZ)wyVpkro}5zx0vfr&N1NL$QIqv(e`IOiq z8Qp2X3A8*x0p2Xz?KcYADZ@CzY}0@+#%=f73RqKmwFc{_3^xiA`iN}#c{#7On>QttTBbvKqRtPi zW)0?b>iK1ujSF!VD(h|r@y8OzAbVhk){azd5yu*@c>1x^B^PrffbjG0)rt90dr{zFWzJax5lpXx8b~0z zjYzqseU2*&{?%5ik&gy~&#$VouICm@OQSeVW NgsYP$p6dY8{tHioFaQ7m diff --git a/img/readme/quickstart/write/longestMatchColumnWidthWrite.png b/img/readme/quickstart/write/longestMatchColumnWidthWrite.png deleted file mode 100644 index c8a06049062bb982f35903212ff1834a918ab3a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6702 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 diff --git a/img/readme/quickstart/write/mergeWrite.png b/img/readme/quickstart/write/mergeWrite.png deleted file mode 100644 index b631e59bd0e04b221c39593bb5570d7d1c399b40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4045 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 diff --git a/img/readme/quickstart/write/repeatedWrite.png b/img/readme/quickstart/write/repeatedWrite.png deleted file mode 100644 index fb204a4bbafb476425d72363985f791b46db020d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5576 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 diff --git a/img/readme/quickstart/write/simpleWrite.png b/img/readme/quickstart/write/simpleWrite.png deleted file mode 100644 index e5924b196bccb240a109aa574aef47d350917132..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3528 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 z

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 diff --git a/img/readme/wechat.png b/img/readme/wechat.png deleted file mode 100644 index b8057604d16ad255000c635210c80a825754e8fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67852 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 Date: Mon, 28 Oct 2019 19:25:29 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9map=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java | 3 ++- .../excel/analysis/v07/handlers/DefaultCellHandler.java | 3 ++- .../alibaba/excel/read/listener/ModelBuildEventListener.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index 21977a4d..a489ccec 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -3,6 +3,7 @@ package com.alibaba.excel.analysis.v03; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -77,7 +78,7 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { public XlsSaxAnalyser(AnalysisContext context, POIFSFileSystem poifsFileSystem) { this.analysisContext = context; - this.records = new TreeMap(); + this.records = new LinkedHashMap(); this.poifsFileSystem = poifsFileSystem; analysisContext.readWorkbookHolder().setPoifsFileSystem(poifsFileSystem); } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java index 0d44a95b..002999d6 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java @@ -9,6 +9,7 @@ import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TYPE_TAG; import java.math.BigDecimal; import java.util.Deque; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; import java.util.TreeMap; @@ -37,7 +38,7 @@ public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder private final AnalysisContext analysisContext; private Deque currentTagDeque = new LinkedList(); private int curCol; - private Map curRowContent = new TreeMap(); + private Map curRowContent = new LinkedHashMap(); private CellData currentCellData; private StringBuilder dataStringBuilder; private StringBuilder formulaStringBuilder; diff --git a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java index a368024f..1cfe1823 100644 --- a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java +++ b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java @@ -2,6 +2,7 @@ package com.alibaba.excel.read.listener; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -44,7 +45,7 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener AnalysisContext context) { int index = 0; if (context.readWorkbookHolder().getDefaultReturnMap()) { - Map map = new HashMap(cellDataMap.size() * 4 / 3 + 1); + Map map = new LinkedHashMap(cellDataMap.size() * 4 / 3 + 1); for (Map.Entry entry : cellDataMap.entrySet()) { Integer key = entry.getKey(); CellData cellData = entry.getValue(); From 6e6896d4a7add91f70349212e09f8a94a52949ae Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 28 Oct 2019 19:26:03 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9map=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- update.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.md b/update.md index f389bbff..edc64f49 100644 --- a/update.md +++ b/update.md @@ -1,5 +1,5 @@ # 2.1.0-bea5 - +* 修改map返回为LinkedHashMap # 2.1.0-beta4 * 修改最长匹配策略会空指针的bug [Issue #747](https://github.com/alibaba/easyexcel/issues/747) From 2205ade4bebf6d06c638377429d3c097249ed8a6 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 1 Nov 2019 19:53:06 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E8=BF=94=E5=9B=9E=E5=AF=B9=E8=B1=A1=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=B3=9B=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 ++-- .../java/com/alibaba/excel/ExcelReader.java | 21 +------- .../java/com/alibaba/excel/ExcelWriter.java | 20 ++++++- .../excel/analysis/ExcelAnalyserImpl.java | 8 +++ .../excel/analysis/v03/XlsSaxAnalyser.java | 2 +- .../v03/handlers/BofRecordHandler.java | 2 +- .../v07/handlers/DefaultCellHandler.java | 3 +- .../alibaba/excel/context/WriteContext.java | 5 +- .../excel/context/WriteContextImpl.java | 33 +++++++++--- .../converters/DefaultConverterLoader.java | 2 + .../converters/url/UrlImageConverter.java | 52 +++++++++++++++++++ .../read/builder/ExcelReaderSheetBuilder.java | 4 +- .../metadata/holder/AbstractReadHolder.java | 3 ++ .../alibaba/excel/util/ConverterUtils.java | 11 +++- .../com/alibaba/excel/util/DateUtils.java | 3 ++ .../com/alibaba/excel/write/ExcelBuilder.java | 5 +- .../alibaba/excel/write/ExcelBuilderImpl.java | 24 +++++---- .../write/builder/ExcelWriterBuilder.java | 8 +++ .../excel/write/metadata/WriteWorkbook.java | 12 +++++ .../metadata/holder/WriteWorkbookHolder.java | 22 +++++++- .../easyexcel/test/demo/fill/FillTest.java | 11 ++++ .../easyexcel/test/demo/read/DemoDAO.java | 15 ++++++ .../test/demo/read/DemoDataListener.java | 34 ++++++++++++ .../easyexcel/test/demo/read/ReadTest.java | 10 ++-- .../easyexcel/test/demo/web/UploadDAO.java | 20 +++++++ .../test/demo/web/UploadDataListener.java | 38 +++++++++++++- .../easyexcel/test/demo/web/WebTest.java | 43 +++++++++++++-- .../easyexcel/test/demo/write/ImageData.java | 7 +++ .../easyexcel/test/demo/write/WriteTest.java | 5 +- .../easyexcel/test/temp/read/HDListener.java | 42 +++++++++++++++ .../test/temp/read/HeadReadData.java | 18 +++++++ .../test/temp/read/HeadReadTest.java | 25 +++++++++ update.md | 9 +++- 33 files changed, 459 insertions(+), 67 deletions(-) create mode 100644 src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDAO.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDAO.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java diff --git a/README.md b/README.md index fd5c5a2f..1251ebd2 100644 --- a/README.md +++ b/README.md @@ -62,16 +62,19 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java) ```java /** - * 文件下载 + * 文件下载(失败了会返回一个有部分数据的Excel) *

1. 创建excel对应的实体对象 参照{@link DownloadData} *

2. 设置返回的 参数 *

3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大 */ @GetMapping("download") public void download(HttpServletResponse response) throws IOException { + // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); - response.setHeader("Content-disposition", "attachment;filename=demo.xlsx"); + // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 + String fileName = URLEncoder.encode("测试", "UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data()); } @@ -84,7 +87,7 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja @PostMapping("upload") @ResponseBody public String upload(MultipartFile file) throws IOException { - EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener()).sheet().doRead(); + EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead(); return "success"; } ``` diff --git a/src/main/java/com/alibaba/excel/ExcelReader.java b/src/main/java/com/alibaba/excel/ExcelReader.java index 0887e325..07a373b7 100644 --- a/src/main/java/com/alibaba/excel/ExcelReader.java +++ b/src/main/java/com/alibaba/excel/ExcelReader.java @@ -14,7 +14,6 @@ import com.alibaba.excel.analysis.ExcelReadExecutor; import com.alibaba.excel.cache.MapCache; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.parameter.AnalysisParam; import com.alibaba.excel.read.listener.ReadListener; @@ -35,8 +34,6 @@ public class ExcelReader { */ private ExcelAnalyser excelAnalyser; - private boolean finished = false; - /** * Create new reader * @@ -160,7 +157,6 @@ public class ExcelReader { * Parse all sheet content by default */ public void readAll() { - checkFinished(); excelAnalyser.analysis(null, Boolean.TRUE); } @@ -181,7 +177,6 @@ public class ExcelReader { * @return */ public ExcelReader read(List readSheetList) { - checkFinished(); excelAnalyser.analysis(readSheetList, Boolean.FALSE); return this; } @@ -231,7 +226,6 @@ public class ExcelReader { * @return */ public AnalysisContext analysisContext() { - checkFinished(); return excelAnalyser.analysisContext(); } @@ -241,7 +235,6 @@ public class ExcelReader { * @return */ public ExcelReadExecutor excelExecutor() { - checkFinished(); return excelAnalyser.excelExecutor(); } @@ -281,10 +274,6 @@ public class ExcelReader { * Complete the entire read file.Release the cache and close stream. */ public void finish() { - if (finished) { - return; - } - finished = true; excelAnalyser.finish(); } @@ -294,19 +283,11 @@ public class ExcelReader { */ @Override protected void finalize() { - if (finished) { - return; - } try { - excelAnalyser.finish(); + finish(); } catch (Throwable e) { LOGGER.warn("Destroy object failed", e); } } - private void checkFinished() { - if (finished) { - throw new ExcelAnalysisException("Can not use a finished reader."); - } - } } diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 65a99fe5..a0b4795b 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -5,6 +5,9 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; @@ -31,6 +34,8 @@ import com.alibaba.excel.write.metadata.fill.FillConfig; * @author jipengfei */ public class ExcelWriter { + private static final Logger LOGGER = LoggerFactory.getLogger(ExcelWriter.class); + private ExcelBuilder excelBuilder; /** @@ -320,7 +325,20 @@ public class ExcelWriter { * Close IO */ public void finish() { - excelBuilder.finish(); + excelBuilder.finish(false); + } + + /** + * Prevents calls to {@link #finish} from freeing the cache + * + */ + @Override + protected void finalize() { + try { + finish(); + } catch (Throwable e) { + LOGGER.warn("Destroy object failed", e); + } } /** diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java index 4002b843..f3ef9505 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java @@ -34,6 +34,10 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { private AnalysisContext analysisContext; private ExcelReadExecutor excelReadExecutor; + /** + * Prevent multiple shutdowns + */ + private boolean finished = false; public ExcelAnalyserImpl(ReadWorkbook readWorkbook) { try { @@ -121,6 +125,10 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { @Override public void finish() { + if (finished) { + return; + } + finished = true; if (analysisContext == null || analysisContext.readWorkbookHolder() == null) { return; } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index a489ccec..76a869ae 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -121,7 +121,7 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { private void init() { lastRowNumber = 0; lastColumnNumber = 0; - records = new TreeMap(); + records = new LinkedHashMap(); buildXlsRecordHandlers(); } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java index 3a862942..083edbc7 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java @@ -73,7 +73,7 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { readSheet = SheetUtils.match(readSheet, readSheetList, readAll, context.readWorkbookHolder().getGlobalConfiguration()); if (readSheet != null) { - if (readSheet.getSheetNo() != 0) { + if (readSheet.getSheetNo() != 0 && context.readSheetHolder() != null) { // Prompt for the end of the previous form read context.readSheetHolder().notifyAfterAllAnalysed(context); } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java index 002999d6..e0b9c413 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java @@ -12,7 +12,6 @@ import java.util.Deque; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; -import java.util.TreeMap; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.xssf.model.StylesTable; @@ -55,7 +54,7 @@ public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder @Override public void clearResult() { - curRowContent = new TreeMap(); + curRowContent = new LinkedHashMap(); } @Override diff --git a/src/main/java/com/alibaba/excel/context/WriteContext.java b/src/main/java/com/alibaba/excel/context/WriteContext.java index c6e85c94..0a59e1d0 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContext.java +++ b/src/main/java/com/alibaba/excel/context/WriteContext.java @@ -66,9 +66,10 @@ public interface WriteContext { /** * close + * + * @param onException */ - void finish(); - + void finish(boolean onException); /** * Current sheet diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index ec49ea3e..3f2b51a4 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -65,6 +65,10 @@ public class WriteContextImpl implements WriteContext { * Configuration of currently operated cell */ private WriteHolder currentWriteHolder; + /** + * Prevent multiple shutdowns + */ + private boolean finished = false; public WriteContextImpl(WriteWorkbook writeWorkbook) { if (writeWorkbook == null) { @@ -249,23 +253,36 @@ public class WriteContextImpl implements WriteContext { } @Override - public void finish() { + public void finish(boolean onException) { + if (finished) { + return; + } + finished = true; WriteHandlerUtils.afterWorkbookDispose(this); if (writeWorkbookHolder == null) { return; } Throwable throwable = null; - boolean isOutputStreamEncrypt = false; - try { - isOutputStreamEncrypt = doOutputStreamEncrypt07(); - } catch (Throwable t) { - throwable = t; + // Determine if you need to write excel + boolean writeExcel = !onException; + if (writeWorkbookHolder.getWriteExcelOnException()) { + writeExcel = Boolean.TRUE; + } + // No data is written if an exception is thrown + if (writeExcel) { + try { + isOutputStreamEncrypt = doOutputStreamEncrypt07(); + } catch (Throwable t) { + throwable = t; + } } if (!isOutputStreamEncrypt) { try { - writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream()); + if (writeExcel) { + writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream()); + } writeWorkbookHolder.getWorkbook().close(); } catch (Throwable t) { throwable = t; @@ -289,7 +306,7 @@ public class WriteContextImpl implements WriteContext { throwable = t; } - if (!isOutputStreamEncrypt) { + if (writeExcel && !isOutputStreamEncrypt) { try { doFileEncrypt07(); } catch (Throwable t) { diff --git a/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java b/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java index e53c1f85..77e8b592 100644 --- a/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java +++ b/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java @@ -37,6 +37,7 @@ import com.alibaba.excel.converters.string.StringBooleanConverter; import com.alibaba.excel.converters.string.StringErrorConverter; import com.alibaba.excel.converters.string.StringNumberConverter; import com.alibaba.excel.converters.string.StringStringConverter; +import com.alibaba.excel.converters.url.UrlImageConverter; /** * Load default handler @@ -71,6 +72,7 @@ public class DefaultConverterLoader { putWriteConverter(new InputStreamImageConverter()); putWriteConverter(new ByteArrayImageConverter()); putWriteConverter(new BoxingByteArrayImageConverter()); + putWriteConverter(new UrlImageConverter()); return defaultWriteConverter; } diff --git a/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java b/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java new file mode 100644 index 00000000..b622d66d --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java @@ -0,0 +1,52 @@ +package com.alibaba.excel.converters.url; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.IoUtils; + +/** + * Url and image converter + * + * @since 2.1.1 + * @author Jiaju Zhuang + */ +public class UrlImageConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return URL.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.IMAGE; + } + + @Override + public URL convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + throw new UnsupportedOperationException("Cannot convert images to url."); + } + + @Override + public CellData convertToExcelData(URL value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws IOException { + InputStream inputStream = null; + try { + inputStream = value.openStream(); + byte[] bytes = IoUtils.toByteArray(inputStream); + return new CellData(bytes); + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + } + +} diff --git a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderSheetBuilder.java b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderSheetBuilder.java index af3b05e1..d494e233 100644 --- a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderSheetBuilder.java +++ b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderSheetBuilder.java @@ -166,7 +166,7 @@ public class ExcelReaderSheetBuilder { * * @return */ - public List doReadSync() { + public List doReadSync() { if (excelReader == null) { throw new ExcelAnalysisException("Must use 'EasyExcelFactory.read().sheet()' to call this method"); } @@ -174,7 +174,7 @@ public class ExcelReaderSheetBuilder { registerReadListener(syncReadListener); excelReader.read(build()); excelReader.finish(); - return syncReadListener.getList(); + return (List)syncReadListener.getList(); } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java index 157f90ee..786d4386 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java @@ -208,6 +208,9 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH List headNameList = headData.getHeadNameList(); String headName = headNameList.get(headNameList.size() - 1); for (Map.Entry stringEntry : dataMap.entrySet()) { + if (stringEntry == null) { + continue; + } String headString = stringEntry.getValue(); Integer stringKey = stringEntry.getKey(); if (StringUtils.isEmpty(headString)) { diff --git a/src/main/java/com/alibaba/excel/util/ConverterUtils.java b/src/main/java/com/alibaba/excel/util/ConverterUtils.java index b6244c23..200440ec 100644 --- a/src/main/java/com/alibaba/excel/util/ConverterUtils.java +++ b/src/main/java/com/alibaba/excel/util/ConverterUtils.java @@ -33,10 +33,17 @@ public class ConverterUtils { */ public static Map convertToStringMap(Map cellDataMap, ReadHolder readHolder) { Map stringMap = new HashMap(cellDataMap.size() * 4 / 3 + 1); + int index = 0; for (Map.Entry entry : cellDataMap.entrySet()) { + Integer key = entry.getKey(); CellData cellData = entry.getValue(); + while (index < key) { + stringMap.put(index, null); + index++; + } + index++; if (cellData.getType() == CellDataTypeEnum.EMPTY) { - stringMap.put(entry.getKey(), null); + stringMap.put(key, null); continue; } Converter converter = @@ -46,7 +53,7 @@ public class ConverterUtils { "Converter not found, convert " + cellData.getType() + " to String"); } try { - stringMap.put(entry.getKey(), + stringMap.put(key, (String)(converter.convertToJavaData(cellData, null, readHolder.globalConfiguration()))); } catch (Exception e) { throw new ExcelDataConvertException("Convert data " + cellData + " to String error ", e); diff --git a/src/main/java/com/alibaba/excel/util/DateUtils.java b/src/main/java/com/alibaba/excel/util/DateUtils.java index 1ea05c0f..0df5cf46 100644 --- a/src/main/java/com/alibaba/excel/util/DateUtils.java +++ b/src/main/java/com/alibaba/excel/util/DateUtils.java @@ -12,6 +12,7 @@ import com.alibaba.excel.exception.ExcelDataConvertException; * @author Jiaju Zhuang **/ public class DateUtils { + public static final String DATE_FORMAT_10 = "yyyy-MM-dd"; public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss"; public static final String DATE_FORMAT_17 = "yyyyMMdd HH:mm:ss"; public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss"; @@ -65,6 +66,8 @@ public class DateUtils { return DATE_FORMAT_17; case 14: return DATE_FORMAT_14; + case 10: + return DATE_FORMAT_10; default: throw new ExcelDataConvertException("can not find date format for:" + dateString); } diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java index 8a7d57da..4ef3b42a 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java @@ -71,11 +71,14 @@ public interface ExcelBuilder { /** * Close io + * + * @param onException */ - void finish(); + void finish(boolean onException); /** * add password + * * @param data * @param writeSheet * @param writeTable diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index fc017fdd..9658f553 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -31,10 +31,10 @@ public class ExcelBuilderImpl implements ExcelBuilder { FileUtils.createPoiFilesDirectory(); context = new WriteContextImpl(writeWorkbook); } catch (RuntimeException e) { - finish(); + finishOnException(); throw e; } catch (Throwable e) { - finish(); + finishOnException(); throw new ExcelGenerateException(e); } } @@ -57,10 +57,10 @@ public class ExcelBuilderImpl implements ExcelBuilder { } excelWriteAddExecutor.add(data); } catch (RuntimeException e) { - finish(); + finishOnException(); throw e; } catch (Throwable e) { - finish(); + finishOnException(); throw new ExcelGenerateException(e); } } @@ -80,18 +80,22 @@ public class ExcelBuilderImpl implements ExcelBuilder { } excelWriteFillExecutor.fill(data, fillConfig); } catch (RuntimeException e) { - finish(); + finishOnException(); throw e; } catch (Throwable e) { - finish(); + finishOnException(); throw new ExcelGenerateException(e); } } + private void finishOnException() { + finish(true); + } + @Override - public void finish() { + public void finish(boolean onException) { if (context != null) { - context.finish(); + context.finish(onException); } } @@ -108,10 +112,10 @@ public class ExcelBuilderImpl implements ExcelBuilder { } excelWriteAddExecutor.add(data); } catch (RuntimeException e) { - finish(); + finishOnException(); throw e; } catch (Throwable e) { - finish(); + finishOnException(); throw new ExcelGenerateException(e); } } diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java index 8af1e62c..f0d37ede 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java @@ -146,6 +146,14 @@ public class ExcelWriterBuilder { return this; } + /** + * Excel is also written in the event of an exception being thrown.The default false. + */ + public ExcelWriterBuilder writeExcelOnException(Boolean writeExcelOnException) { + writeWorkbook.setWriteExcelOnException(writeExcelOnException); + return this; + } + /** * The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a * field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed. diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java b/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java index 738299af..c28e0412 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java @@ -63,6 +63,10 @@ public class WriteWorkbook extends WriteBasicParameter { * Comment and RichTextString are only supported in memory mode. */ private Boolean inMemory; + /** + * Excel is also written in the event of an exception being thrown.The default false. + */ + private Boolean writeExcelOnException; /** * The default is all excel objects.Default is true. *

@@ -169,4 +173,12 @@ public class WriteWorkbook extends WriteBasicParameter { public void setInMemory(Boolean inMemory) { this.inMemory = inMemory; } + + public Boolean getWriteExcelOnException() { + return writeExcelOnException; + } + + public void setWriteExcelOnException(Boolean writeExcelOnException) { + this.writeExcelOnException = writeExcelOnException; + } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java index 4de6ade6..c8f7555f 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java @@ -103,6 +103,10 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { * Comment and RichTextString are only supported in memory mode. */ private Boolean inMemory; + /** + * Excel is also written in the event of an exception being thrown.The default false. + */ + private Boolean writeExcelOnException; public WriteWorkbookHolder(WriteWorkbook writeWorkbook) { super(writeWorkbook, null, writeWorkbook.getConvertAllFiled()); @@ -128,7 +132,10 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { throw new ExcelGenerateException("Copy template failure.", e); } if (writeWorkbook.getExcelType() == null) { - if (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) { + boolean isXls = (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) + || (writeWorkbook.getTemplateFile() != null + && writeWorkbook.getTemplateFile().getName().endsWith(ExcelTypeEnum.XLS.getValue())); + if (isXls) { this.excelType = ExcelTypeEnum.XLS; } else { this.excelType = ExcelTypeEnum.XLSX; @@ -148,6 +155,11 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { } else { this.inMemory = writeWorkbook.getInMemory(); } + if (writeWorkbook.getWriteExcelOnException() == null) { + this.writeExcelOnException = Boolean.FALSE; + } else { + this.writeExcelOnException = writeWorkbook.getWriteExcelOnException(); + } } private void copyTemplate() throws IOException { @@ -281,6 +293,14 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.inMemory = inMemory; } + public Boolean getWriteExcelOnException() { + return writeExcelOnException; + } + + public void setWriteExcelOnException(Boolean writeExcelOnException) { + this.writeExcelOnException = writeExcelOnException; + } + @Override public HolderEnum holderType() { return HolderEnum.WORKBOOK; diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java index 0159cbc7..32a01852 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java @@ -19,12 +19,15 @@ import com.alibaba.excel.write.metadata.fill.FillConfig; /** * 写的填充写法 * + * @since 2.1.1 * @author Jiaju Zhuang */ @Ignore public class FillTest { /** * 最简单的填充 + * + * @since 2.1.1 */ @Test public void simpleFill() { @@ -51,6 +54,8 @@ public class FillTest { /** * 填充列表 + * + * @since 2.1.1 */ @Test public void listFill() { @@ -76,6 +81,8 @@ public class FillTest { /** * 复杂的填充 + * + * @since 2.1.1 */ @Test public void complexFill() { @@ -105,6 +112,8 @@ public class FillTest { * 数据量大的复杂填充 *

* 这里的解决方案是 确保模板list为最后一行,然后再拼接table.还有03版没救,只能刚正面加内存。 + * + * @since 2.1.1 */ @Test public void complexFillWithTable() { @@ -145,6 +154,8 @@ public class FillTest { /** * 横向的填充 + * + * @since 2.1.1 */ @Test public void horizontalFill() { diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDAO.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDAO.java new file mode 100644 index 00000000..8ca6b026 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDAO.java @@ -0,0 +1,15 @@ +package com.alibaba.easyexcel.test.demo.read; + +import java.util.List; + +/** + * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。 + * + * @author Jiaju Zhuang + **/ +public class DemoDAO { + + public void save(List list) { + // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入 + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java index 434af3b6..f26ff4be 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java @@ -23,19 +23,52 @@ public class DemoDataListener extends AnalysisEventListener { */ private static final int BATCH_COUNT = 5; List list = new ArrayList(); + /** + * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 + */ + private DemoDAO demoDAO; + + public DemoDataListener() { + // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数 + demoDAO = new DemoDAO(); + } + + /** + * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 + * + * @param demoDAO + */ + public DemoDataListener(DemoDAO demoDAO) { + this.demoDAO = demoDAO; + } + /** + * 这个每一条数据解析都会来调用 + * + * @param data + * one row value. Is is same as {@link AnalysisContext#readRowHolder()} + * @param context + */ @Override public void invoke(DemoData data, AnalysisContext context) { LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); list.add(data); + // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (list.size() >= BATCH_COUNT) { saveData(); + // 存储完成清理 list list.clear(); } } + /** + * 所有数据解析完成了 都会来调用 + * + * @param context + */ @Override public void doAfterAllAnalysed(AnalysisContext context) { + // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); LOGGER.info("所有数据解析完成!"); } @@ -45,6 +78,7 @@ public class DemoDataListener extends AnalysisEventListener { */ private void saveData() { LOGGER.info("{}条数据,开始存储数据库!", list.size()); + demoDAO.save(list); LOGGER.info("存储数据库成功!"); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java index 9ebafa4f..0dc22aa7 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java @@ -202,17 +202,15 @@ public class ReadTest { public void synchronousRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish - List list = EasyExcel.read(fileName).head(DemoData.class).sheet().doReadSync(); - for (Object obj : list) { - DemoData data = (DemoData)obj; + List list = EasyExcel.read(fileName).head(DemoData.class).sheet().doReadSync(); + for (DemoData data : list) { LOGGER.info("读取到数据:{}", JSON.toJSONString(data)); } // 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finish - list = EasyExcel.read(fileName).sheet().doReadSync(); - for (Object obj : list) { + List> listMap = EasyExcel.read(fileName).sheet().doReadSync(); + for (Map data : listMap) { // 返回每条数据的键值对 表示所在的列 和所在列的值 - Map data = (Map)obj; LOGGER.info("读取到数据:{}", JSON.toJSONString(data)); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDAO.java b/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDAO.java new file mode 100644 index 00000000..eac96625 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDAO.java @@ -0,0 +1,20 @@ +package com.alibaba.easyexcel.test.demo.web; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.alibaba.easyexcel.test.demo.read.DemoData; + +/** + * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。 + * + * @author Jiaju Zhuang + **/ +@Repository +public class UploadDAO { + + public void save(List list) { + // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入 + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDataListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDataListener.java index 7475ced3..e61a5d65 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/web/UploadDataListener.java @@ -15,26 +15,61 @@ import com.alibaba.fastjson.JSON; * * @author Jiaju Zhuang */ +// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 public class UploadDataListener extends AnalysisEventListener { - private static final Logger LOGGER = LoggerFactory.getLogger(UploadDataListener.class); + private static final Logger LOGGER = + LoggerFactory.getLogger(com.alibaba.easyexcel.test.demo.read.DemoDataListener.class); /** * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 5; List list = new ArrayList(); + /** + * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 + */ + private UploadDAO uploadDAO; + + public UploadDataListener() { + // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数 + uploadDAO = new UploadDAO(); + } + + /** + * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 + * + * @param uploadDAO + */ + public UploadDataListener(UploadDAO uploadDAO) { + this.uploadDAO = uploadDAO; + } + /** + * 这个每一条数据解析都会来调用 + * + * @param data + * one row value. Is is same as {@link AnalysisContext#readRowHolder()} + * @param context + */ @Override public void invoke(UploadData data, AnalysisContext context) { LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); list.add(data); + // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (list.size() >= BATCH_COUNT) { saveData(); + // 存储完成清理 list list.clear(); } } + /** + * 所有数据解析完成了 都会来调用 + * + * @param context + */ @Override public void doAfterAllAnalysed(AnalysisContext context) { + // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); LOGGER.info("所有数据解析完成!"); } @@ -44,6 +79,7 @@ public class UploadDataListener extends AnalysisEventListener { */ private void saveData() { LOGGER.info("{}条数据,开始存储数据库!", list.size()); + uploadDAO.save(list); LOGGER.info("存储数据库成功!"); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java index cc525629..98f400a4 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java @@ -2,14 +2,15 @@ package com.alibaba.easyexcel.test.demo.web; import java.io.IOException; import java.net.URLEncoder; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; /** * web读写案例 @@ -25,8 +27,12 @@ import com.alibaba.excel.EasyExcel; **/ @Controller public class WebTest { + + @Autowired + private UploadDAO uploadDAO; + /** - * 文件下载 + * 文件下载(失败了会返回一个有部分数据的Excel) *

* 1. 创建excel对应的实体对象 参照{@link DownloadData} *

@@ -45,6 +51,35 @@ public class WebTest { EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data()); } + /** + * 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel) + * + * @since 2.1.1 + */ + @GetMapping("downloadFailedUsingJson") + public void downloadFailedUsingJson(HttpServletResponse response) throws IOException { + // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman + try { + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 + String fileName = URLEncoder.encode("测试", "UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + // 这里需要设置不关闭流 + EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板") + .doWrite(data()); + } catch (Exception e) { + // 重置response + response.reset(); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + Map map = new HashMap(); + map.put("status", "failure"); + map.put("message", "下载文件失败" + e.getMessage()); + response.getWriter().println(JSON.toJSONString(map)); + } + } + /** * 文件上传 *

@@ -57,7 +92,7 @@ public class WebTest { @PostMapping("upload") @ResponseBody public String upload(MultipartFile file) throws IOException { - EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener()).sheet().doRead(); + EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead(); return "success"; } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java index 951026cf..3fcb9484 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java @@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.demo.write; import java.io.File; import java.io.InputStream; +import java.net.URL; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; @@ -27,4 +28,10 @@ public class ImageData { @ExcelProperty(converter = StringImageConverter.class) private String string; private byte[] byteArray; + /** + * 根据url导出 + * + * @since 2.1.1 + */ + private URL url; } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java index f9a69db7..3e27bd38 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java @@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.demo.write; import java.io.File; import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; @@ -215,12 +216,14 @@ public class WriteTest { ImageData imageData = new ImageData(); list.add(imageData); String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg"; - // 放入四种类型的图片 实际使用只要选一种即可 + // 放入五种类型的图片 实际使用只要选一种即可 imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath))); imageData.setFile(new File(imagePath)); imageData.setString(imagePath); inputStream = FileUtils.openInputStream(new File(imagePath)); imageData.setInputStream(inputStream); + imageData.setUrl(new URL( + "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg")); EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list); } finally { if (inputStream != null) { diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java new file mode 100644 index 00000000..196b2da9 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java @@ -0,0 +1,42 @@ +package com.alibaba.easyexcel.test.temp.read; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.fastjson.JSON; + +/** + * 模板的读取类 + * + * @author Jiaju Zhuang + */ +public class HDListener extends AnalysisEventListener { + private static final Logger LOGGER = LoggerFactory.getLogger(HDListener.class); + /** + * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 + */ + private static final int BATCH_COUNT = 5; + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + LOGGER.info("HEAD:{}", JSON.toJSONString(headMap)); + + } + + @Override + public void invoke(HeadReadData data, AnalysisContext context) { + LOGGER.info("index:{}", context.readRowHolder().getRowIndex()); + LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + LOGGER.info("所有数据解析完成!"); + } + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java new file mode 100644 index 00000000..38ee661f --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java @@ -0,0 +1,18 @@ +package com.alibaba.easyexcel.test.temp.read; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + * 临时测试 + * + * @author Jiaju Zhuang + **/ +@Data +public class HeadReadData { + @ExcelProperty("头1") + private String h1; + @ExcelProperty({"头", "头2"}) + private String h2; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java new file mode 100644 index 00000000..f356524a --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java @@ -0,0 +1,25 @@ +package com.alibaba.easyexcel.test.temp.read; + +import java.io.File; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.EasyExcel; + +/** + * 临时测试 + * + * @author Jiaju Zhuang + **/ +public class HeadReadTest { + private static final Logger LOGGER = LoggerFactory.getLogger(HeadReadTest.class); + + @Test + public void test() throws Exception { + File file = new File("D:\\test\\headt1.xlsx"); + EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet().doRead(); + } + +} diff --git a/update.md b/update.md index edc64f49..4055d43d 100644 --- a/update.md +++ b/update.md @@ -1,5 +1,12 @@ -# 2.1.0-bea5 +# 2.1.1 +* 发布正式版 * 修改map返回为LinkedHashMap +* 修改同步读取返回对象支持泛型 +* 修复03版不能直接读取第二个sheet的bug [Issue #772](https://github.com/alibaba/easyexcel/issues/772) +* 新增支持图片导出用URL [Issue #774](https://github.com/alibaba/easyexcel/issues/774) +* 加入多次关闭判断,防止多次关闭异常 +* 加入根据模板自动识别导出的excel类型 +* 修改默认失败后,不再往文件流写入数据。通过参数`writeExcelOnException` 参数设置异常了也要写入前面的数据。 # 2.1.0-beta4 * 修改最长匹配策略会空指针的bug [Issue #747](https://github.com/alibaba/easyexcel/issues/747) From cba3a9cea9b3e02f6c0fcfed52e6f41eeb369e09 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 4 Nov 2019 18:28:41 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E8=A7=A3=E6=9E=90class?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../excel/analysis/v03/XlsSaxAnalyser.java | 2 + .../v03/handlers/IndexRecordHandler.java | 42 +++++ .../v07/handlers/CountRowCellHandler.java | 4 +- .../excel/event/AnalysisEventListener.java | 2 +- .../exception/ExcelDataConvertException.java | 35 ++-- .../com/alibaba/excel/metadata/CellData.java | 7 +- .../metadata/property/ExcelHeadProperty.java | 46 +----- .../listener/ModelBuildEventListener.java | 3 +- .../metadata/holder/AbstractReadHolder.java | 3 +- .../read/metadata/holder/ReadSheetHolder.java | 28 +++- .../com/alibaba/excel/util/ClassUtils.java | 150 ++++++++++++++++++ .../alibaba/excel/util/ConverterUtils.java | 19 ++- .../com/alibaba/excel/util/DateUtils.java | 2 +- .../executor/AbstractExcelWriteExecutor.java | 16 +- .../write/executor/ExcelWriteAddExecutor.java | 18 +-- .../executor/ExcelWriteFillExecutor.java | 38 ++++- .../write/metadata/fill/AnalysisCell.java | 9 ++ .../test/demo/read/DemoExceptionListener.java | 4 +- .../test/demo/read/DemoHeadDataListener.java | 4 +- .../easyexcel/test/temp/FillTempTest.java | 110 +++++++++++++ .../easyexcel/test/temp/poi/PoiTest.java | 4 +- .../easyexcel/test/temp/read/HDListener.java | 1 + .../test/temp/read/HeadReadData.java | 2 + .../test/temp/read/HeadReadTest.java | 7 +- update.md | 5 + 26 files changed, 450 insertions(+), 113 deletions(-) create mode 100644 src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java create mode 100644 src/main/java/com/alibaba/excel/util/ClassUtils.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java diff --git a/pom.xml b/pom.xml index a6183490..7dad24da 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.alibaba easyexcel - 2.1.0-beta4 + 2.1.1 jar easyexcel diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index 76a869ae..e0c150cd 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -27,6 +27,7 @@ import com.alibaba.excel.analysis.ExcelReadExecutor; import com.alibaba.excel.analysis.v03.handlers.BlankOrErrorRecordHandler; import com.alibaba.excel.analysis.v03.handlers.BofRecordHandler; import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler; +import com.alibaba.excel.analysis.v03.handlers.IndexRecordHandler; import com.alibaba.excel.analysis.v03.handlers.LabelRecordHandler; import com.alibaba.excel.analysis.v03.handlers.MissingCellDummyRecordHandler; import com.alibaba.excel.analysis.v03.handlers.NoteRecordHandler; @@ -211,6 +212,7 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { recordHandlers.add(new RkRecordHandler()); recordHandlers.add(new SstRecordHandler()); recordHandlers.add(new MissingCellDummyRecordHandler()); + recordHandlers.add(new IndexRecordHandler(analysisContext)); Collections.sort(recordHandlers); } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java new file mode 100644 index 00000000..6837ebd6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java @@ -0,0 +1,42 @@ +package com.alibaba.excel.analysis.v03.handlers; + +import org.apache.poi.hssf.record.IndexRecord; +import org.apache.poi.hssf.record.Record; + +import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler; +import com.alibaba.excel.context.AnalysisContext; + +/** + * Record handler + * + * @author Jiaju Zhuang + */ +public class IndexRecordHandler extends AbstractXlsRecordHandler { + + private AnalysisContext context; + + public IndexRecordHandler(AnalysisContext context) { + this.context = context; + } + + @Override + public boolean support(Record record) { + return record instanceof IndexRecord; + } + + @Override + public void init() {} + + @Override + public void processRecord(Record record) { + if (context.readSheetHolder() == null) { + return; + } + context.readSheetHolder().setApproximateTotalRowNumber(((IndexRecord)record).getLastRowAdd1()); + } + + @Override + public int getOrder() { + return 1; + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java index ea63409b..b94483f4 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java @@ -10,7 +10,7 @@ import com.alibaba.excel.context.AnalysisContext; /** * Cell Handler - * + * * @author jipengfei */ public class CountRowCellHandler implements XlsxCellHandler { @@ -31,7 +31,7 @@ public class CountRowCellHandler implements XlsxCellHandler { String d = attributes.getValue(DIMENSION_REF); String totalStr = d.substring(d.indexOf(":") + 1, d.length()); String c = totalStr.toUpperCase().replaceAll("[A-Z]", ""); - analysisContext.readSheetHolder().setTotal(Integer.parseInt(c)); + analysisContext.readSheetHolder().setApproximateTotalRowNumber(Integer.parseInt(c)); } @Override diff --git a/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java b/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java index 89bca753..176bd798 100644 --- a/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java +++ b/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java @@ -16,7 +16,7 @@ public abstract class AnalysisEventListener implements ReadListener { @Override public void invokeHead(Map headMap, AnalysisContext context) { - invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context.currentReadHolder()), context); + invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context); } /** diff --git a/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java b/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java index 2ffdde5f..5198c20f 100644 --- a/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java +++ b/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java @@ -1,5 +1,6 @@ package com.alibaba.excel.exception; +import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.write.builder.ExcelWriterBuilder; @@ -17,6 +18,10 @@ public class ExcelDataConvertException extends RuntimeException { * NotNull. */ private Integer columnIndex; + /** + * NotNull. + */ + private CellData cellData; /** * Nullable.Only when the header is configured and when the class header is used is not null. * @@ -24,34 +29,24 @@ public class ExcelDataConvertException extends RuntimeException { */ private ExcelContentProperty excelContentProperty; - public ExcelDataConvertException(String message) { - super(message); - } - - public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, ExcelContentProperty excelContentProperty, - String message) { + public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, CellData cellData, + ExcelContentProperty excelContentProperty, String message) { super(message); this.rowIndex = rowIndex; this.columnIndex = columnIndex; + this.cellData = cellData; this.excelContentProperty = excelContentProperty; } - public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, ExcelContentProperty excelContentProperty, - String message, Throwable cause) { + public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, CellData cellData, + ExcelContentProperty excelContentProperty, String message, Throwable cause) { super(message, cause); this.rowIndex = rowIndex; this.columnIndex = columnIndex; + this.cellData = cellData; this.excelContentProperty = excelContentProperty; } - public ExcelDataConvertException(String message, Throwable cause) { - super(message, cause); - } - - public ExcelDataConvertException(Throwable cause) { - super(cause); - } - public Integer getRowIndex() { return rowIndex; } @@ -75,4 +70,12 @@ public class ExcelDataConvertException extends RuntimeException { public void setExcelContentProperty(ExcelContentProperty excelContentProperty) { this.excelContentProperty = excelContentProperty; } + + public CellData getCellData() { + return cellData; + } + + public void setCellData(CellData cellData) { + this.cellData = cellData; + } } diff --git a/src/main/java/com/alibaba/excel/metadata/CellData.java b/src/main/java/com/alibaba/excel/metadata/CellData.java index a6b7af58..7cd5496e 100644 --- a/src/main/java/com/alibaba/excel/metadata/CellData.java +++ b/src/main/java/com/alibaba/excel/metadata/CellData.java @@ -229,18 +229,21 @@ public class CellData { @Override public String toString() { if (type == null) { - return "empty"; + return StringUtils.EMPTY; } switch (type) { case NUMBER: return numberValue.toString(); case BOOLEAN: return booleanValue.toString(); + case DIRECT_STRING: case STRING: case ERROR: return stringValue; + case IMAGE: + return "image[" + imageValue.length + "]"; default: - return "empty"; + return StringUtils.EMPTY; } } diff --git a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java index 9d6a5442..782f635a 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java @@ -24,6 +24,7 @@ import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Holder; +import com.alibaba.excel.util.ClassUtils; import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; @@ -119,51 +120,10 @@ public class ExcelHeadProperty { if (headClazz == null) { return; } - List fieldList = new ArrayList(); - Class tempClass = headClazz; - // When the parent class is null, it indicates that the parent class (Object class) has reached the top - // level. - while (tempClass != null) { - Collections.addAll(fieldList, tempClass.getDeclaredFields()); - // Get the parent class and give it to yourself - tempClass = tempClass.getSuperclass(); - } - - ExcelIgnoreUnannotated excelIgnoreUnannotated = - (ExcelIgnoreUnannotated)headClazz.getAnnotation(ExcelIgnoreUnannotated.class); - // Screening of field + // Declared fields List defaultFieldList = new ArrayList(); Map customFiledMap = new TreeMap(); - for (Field field : fieldList) { - ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class); - if (excelIgnore != null) { - ignoreMap.put(field.getName(), field); - continue; - } - ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); - boolean noExcelProperty = excelProperty == null - && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null); - if (noExcelProperty) { - ignoreMap.put(field.getName(), field); - continue; - } - boolean isStaticFinalOrTransient = - (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) - || Modifier.isTransient(field.getModifiers()); - if (excelProperty == null && isStaticFinalOrTransient) { - ignoreMap.put(field.getName(), field); - continue; - } - if (excelProperty == null || excelProperty.index() < 0) { - defaultFieldList.add(field); - continue; - } - if (customFiledMap.containsKey(excelProperty.index())) { - throw new ExcelGenerateException("The index of '" + customFiledMap.get(excelProperty.index()).getName() - + "' and '" + field.getName() + "' must be inconsistent"); - } - customFiledMap.put(excelProperty.index(), field); - } + ClassUtils.declaredFields(headClazz, defaultFieldList, customFiledMap, ignoreMap, convertAllFiled); int index = 0; for (Field field : defaultFieldList) { diff --git a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java index 1cfe1823..f5594db0 100644 --- a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java +++ b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java @@ -93,7 +93,8 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener try { resultModel = excelReadHeadProperty.getHeadClazz().newInstance(); } catch (Exception e) { - throw new ExcelDataConvertException( + throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0, + new CellData(CellDataTypeEnum.EMPTY), null, "Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e); } Map headMap = excelReadHeadProperty.getHeadMap(); diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java index 786d4386..02b2ef5f 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java @@ -190,8 +190,7 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) { return; } - Map dataMap = - ConverterUtils.convertToStringMap(cellDataMap, analysisContext.currentReadHolder()); + Map dataMap = ConverterUtils.convertToStringMap(cellDataMap, analysisContext); ExcelReadHeadProperty excelHeadPropertyData = analysisContext.readSheetHolder().excelReadHeadProperty(); Map headMapData = excelHeadPropertyData.getHeadMap(); Map contentPropertyMapData = excelHeadPropertyData.getContentPropertyMap(); diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java index 64d1d6cb..84dd4c4a 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java @@ -26,10 +26,9 @@ public class ReadSheetHolder extends AbstractReadHolder { */ private String sheetName; /** - * get total row , Data may be inaccurate + * Gets the total number of rows , data may be inaccurate */ - @Deprecated - private Integer total; + private Integer approximateTotalRowNumber; public ReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { super(readSheet, readWorkbookHolder, readWorkbookHolder.getReadWorkbook().getConvertAllFiled()); @@ -71,12 +70,29 @@ public class ReadSheetHolder extends AbstractReadHolder { this.sheetName = sheetName; } + /** + * + * Approximate total number of rows + * + * @return + * @see #getApproximateTotalRowNumber() + */ + @Deprecated public Integer getTotal() { - return total; + return approximateTotalRowNumber; + } + + /** + * Approximate total number of rows + * + * @return + */ + public Integer getApproximateTotalRowNumber() { + return approximateTotalRowNumber; } - public void setTotal(Integer total) { - this.total = total; + public void setApproximateTotalRowNumber(Integer approximateTotalRowNumber) { + this.approximateTotalRowNumber = approximateTotalRowNumber; } @Override diff --git a/src/main/java/com/alibaba/excel/util/ClassUtils.java b/src/main/java/com/alibaba/excel/util/ClassUtils.java new file mode 100644 index 00000000..64bc29d7 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/ClassUtils.java @@ -0,0 +1,150 @@ +package com.alibaba.excel.util; + +import java.lang.ref.SoftReference; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.exception.ExcelCommonException; +import com.alibaba.excel.metadata.BaseRowModel; + +/** + * Class utils + * + * @author Jiaju Zhuang + **/ +public class ClassUtils { + private static final Map> FIELD_CACHE = + new ConcurrentHashMap>(); + + public static void declaredFields(Class clazz, List defaultFieldList, Map customFiledMap, + Map ignoreMap, Boolean convertAllFiled) { + FieldCache fieldCache = getFieldCache(clazz, convertAllFiled); + if (fieldCache != null) { + defaultFieldList.addAll(fieldCache.getDefaultFieldList()); + customFiledMap.putAll(fieldCache.getCustomFiledMap()); + ignoreMap.putAll(fieldCache.getIgnoreMap()); + } + } + + public static void declaredFields(Class clazz, List fieldList, Boolean convertAllFiled) { + FieldCache fieldCache = getFieldCache(clazz, convertAllFiled); + if (fieldCache != null) { + fieldList.addAll(fieldCache.getAllFieldList()); + } + } + + private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) { + if (clazz == null) { + return null; + } + SoftReference fieldCacheSoftReference = FIELD_CACHE.get(clazz); + if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) { + return fieldCacheSoftReference.get(); + } + synchronized (clazz) { + fieldCacheSoftReference = FIELD_CACHE.get(clazz); + if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) { + return fieldCacheSoftReference.get(); + } + declaredFields(clazz, convertAllFiled); + } + return FIELD_CACHE.get(clazz).get(); + } + + private static void declaredFields(Class clazz, Boolean convertAllFiled) { + List tempFieldList = new ArrayList(); + Class tempClass = clazz; + // When the parent class is null, it indicates that the parent class (Object class) has reached the top + // level. + while (tempClass != null && tempClass != BaseRowModel.class) { + Collections.addAll(tempFieldList, tempClass.getDeclaredFields()); + // Get the parent class and give it to yourself + tempClass = tempClass.getSuperclass(); + } + // Screening of field + List defaultFieldList = new ArrayList(); + Map customFiledMap = new TreeMap(); + List allFieldList = new ArrayList(); + Map ignoreMap = new HashMap(16); + + ExcelIgnoreUnannotated excelIgnoreUnannotated = + (ExcelIgnoreUnannotated)clazz.getAnnotation(ExcelIgnoreUnannotated.class); + for (Field field : tempFieldList) { + ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class); + if (excelIgnore != null) { + ignoreMap.put(field.getName(), field); + continue; + } + ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); + boolean noExcelProperty = excelProperty == null + && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null); + if (noExcelProperty) { + ignoreMap.put(field.getName(), field); + continue; + } + boolean isStaticFinalOrTransient = + (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) + || Modifier.isTransient(field.getModifiers()); + if (excelProperty == null && isStaticFinalOrTransient) { + ignoreMap.put(field.getName(), field); + continue; + } + if (excelProperty == null || excelProperty.index() < 0) { + defaultFieldList.add(field); + allFieldList.add(field); + continue; + } + if (customFiledMap.containsKey(excelProperty.index())) { + throw new ExcelCommonException("The index of '" + customFiledMap.get(excelProperty.index()).getName() + + "' and '" + field.getName() + "' must be inconsistent"); + } + customFiledMap.put(excelProperty.index(), field); + allFieldList.add(field); + } + + FIELD_CACHE.put(clazz, + new SoftReference(new FieldCache(defaultFieldList, customFiledMap, allFieldList, ignoreMap))); + } + + private static class FieldCache { + private List defaultFieldList; + private Map customFiledMap; + private List allFieldList; + private Map ignoreMap; + + public FieldCache(List defaultFieldList, Map customFiledMap, List allFieldList, + Map ignoreMap) { + this.defaultFieldList = defaultFieldList; + this.customFiledMap = customFiledMap; + this.allFieldList = allFieldList; + this.ignoreMap = ignoreMap; + } + + public List getDefaultFieldList() { + return defaultFieldList; + } + + public Map getCustomFiledMap() { + return customFiledMap; + } + + public List getAllFieldList() { + return allFieldList; + } + + public Map getIgnoreMap() { + return ignoreMap; + } + + } +} diff --git a/src/main/java/com/alibaba/excel/util/ConverterUtils.java b/src/main/java/com/alibaba/excel/util/ConverterUtils.java index 200440ec..43b12c53 100644 --- a/src/main/java/com/alibaba/excel/util/ConverterUtils.java +++ b/src/main/java/com/alibaba/excel/util/ConverterUtils.java @@ -6,6 +6,7 @@ import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; +import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; import com.alibaba.excel.enums.CellDataTypeEnum; @@ -28,11 +29,12 @@ public class ConverterUtils { * Convert it into a String map * * @param cellDataMap - * @param readHolder + * @param context * @return */ - public static Map convertToStringMap(Map cellDataMap, ReadHolder readHolder) { + public static Map convertToStringMap(Map cellDataMap, AnalysisContext context) { Map stringMap = new HashMap(cellDataMap.size() * 4 / 3 + 1); + ReadHolder currentReadHolder = context.currentReadHolder(); int index = 0; for (Map.Entry entry : cellDataMap.entrySet()) { Integer key = entry.getKey(); @@ -47,16 +49,17 @@ public class ConverterUtils { continue; } Converter converter = - readHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType())); + currentReadHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType())); if (converter == null) { - throw new ExcelDataConvertException( + throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null, "Converter not found, convert " + cellData.getType() + " to String"); } try { stringMap.put(key, - (String)(converter.convertToJavaData(cellData, null, readHolder.globalConfiguration()))); + (String)(converter.convertToJavaData(cellData, null, currentReadHolder.globalConfiguration()))); } catch (Exception e) { - throw new ExcelDataConvertException("Convert data " + cellData + " to String error ", e); + throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null, + "Convert data " + cellData + " to String error ", e); } } return stringMap; @@ -123,13 +126,13 @@ public class ConverterUtils { converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType())); } if (converter == null) { - throw new ExcelDataConvertException(rowIndex, columnIndex, contentProperty, + throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty, "Converter not found, convert " + cellData.getType() + " to " + clazz.getName()); } try { return converter.convertToJavaData(cellData, contentProperty, globalConfiguration); } catch (Exception e) { - throw new ExcelDataConvertException(rowIndex, columnIndex, contentProperty, + throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty, "Convert data " + cellData + " to " + clazz + " error ", e); } } diff --git a/src/main/java/com/alibaba/excel/util/DateUtils.java b/src/main/java/com/alibaba/excel/util/DateUtils.java index 0df5cf46..a581a955 100644 --- a/src/main/java/com/alibaba/excel/util/DateUtils.java +++ b/src/main/java/com/alibaba/excel/util/DateUtils.java @@ -69,7 +69,7 @@ public class DateUtils { case 10: return DATE_FORMAT_10; default: - throw new ExcelDataConvertException("can not find date format for:" + dateString); + throw new IllegalArgumentException("can not find date format for:" + dateString); } } diff --git a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java index a1746299..1f09d47e 100644 --- a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java @@ -59,8 +59,9 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { case EMPTY: return cellData; default: - throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType() - + "at row:" + cell.getRow().getRowNum()); + throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), cellData, + excelContentProperty, "Not supported data:" + value + " return type:" + cell.getCellType() + + "at row:" + cell.getRow().getRowNum()); } } @@ -102,7 +103,8 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz)); } if (converter == null) { - throw new ExcelDataConvertException( + throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), + new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, "Can not find 'Converter' support class " + clazz.getSimpleName() + "."); } CellData cellData; @@ -110,11 +112,13 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { cellData = converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration()); } catch (Exception e) { - throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), - e); + throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), + new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, + "Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), e); } if (cellData == null || cellData.getType() == null) { - throw new ExcelDataConvertException( + throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), + new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, "Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum()); } return cellData; diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java index 0fa0cae2..5b0d8ae8 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java @@ -2,7 +2,6 @@ package com.alibaba.excel.write.executor; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -13,10 +12,10 @@ import org.apache.poi.ss.usermodel.Row; import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.enums.HeadKindEnum; -import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.ClassUtils; import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WriteHandlerUtils; @@ -158,13 +157,11 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { continue; } Object value = beanMap.get(filedName); - if (value == null) { - continue; - } WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE); Cell cell = WorkBookUtil.createCell(row, cellIndex++); WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE); - CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null); + CellData cellData = + converterAndSet(currentWriteHolder, value == null ? null : value.getClass(), cell, value, null); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); } } @@ -173,13 +170,8 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { if (!fieldList.isEmpty()) { return; } - Class tempClass = clazz; - while (tempClass != null) { - if (tempClass != BaseRowModel.class) { - Collections.addAll(fieldList, tempClass.getDeclaredFields()); - } - tempClass = tempClass.getSuperclass(); - } + ClassUtils.declaredFields(clazz, fieldList, + writeContext.writeWorkbookHolder().getWriteWorkbook().getConvertAllFiled()); } } diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java index d7cb6307..c7b227f4 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -3,9 +3,11 @@ package com.alibaba.excel.write.executor; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -57,6 +59,10 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { */ private Map> collectionFieldStyleCache = new HashMap>(8); + /** + * Row height cache for collection + */ + private Map collectionRowHeightCache = new HashMap(8); /** * Last index cache for collection fields */ @@ -121,7 +127,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { if (collectionLastIndexMap == null) { number--; } - sheet.shiftRows(maxRowIndex + 1, lastRowIndex, number); + sheet.shiftRows(maxRowIndex + 1, lastRowIndex, number, true, false); for (AnalysisCell analysisCell : templateAnalysisCache.get(writeContext.writeSheetHolder().getSheetNo())) { if (analysisCell.getRowIndex() > maxRowIndex) { analysisCell.setRowIndex(analysisCell.getRowIndex() + number); @@ -245,7 +251,10 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } else { row = sheet.createRow(lastRowIndex); } + checkRowHeight(analysisCell, fillConfig, isOriginalCell, row, sheetNo); WriteHandlerUtils.afterRowCreate(writeContext, row, null, Boolean.FALSE); + } else { + checkRowHeight(analysisCell, fillConfig, isOriginalCell, row, sheetNo); } } Cell cell = row.getCell(lastColumnIndex); @@ -271,6 +280,21 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { return cell; } + private void checkRowHeight(AnalysisCell analysisCell, FillConfig fillConfig, boolean isOriginalCell, Row row, + Integer sheetNo) { + if (!analysisCell.getFirstColumn() || !WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection())) { + return; + } + if (isOriginalCell) { + collectionRowHeightCache.put(sheetNo, row.getHeight()); + return; + } + Short rowHeight = collectionRowHeightCache.get(sheetNo); + if (rowHeight != null) { + row.setHeight(rowHeight); + } + } + private List readTemplateData(Map> analysisCache) { Integer sheetNo = writeContext.writeSheetHolder().getSheetNo(); List analysisCellList = analysisCache.get(sheetNo); @@ -280,6 +304,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { Sheet sheet = writeContext.writeSheetHolder().getCachedSheet(); analysisCellList = new ArrayList(); List collectionAnalysisCellList = new ArrayList(); + Set firstColumnCache = new HashSet(); for (int i = 0; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { @@ -290,7 +315,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { if (cell == null) { continue; } - String preparedData = prepareData(cell, analysisCellList, collectionAnalysisCellList, i, j); + String preparedData = + prepareData(cell, analysisCellList, collectionAnalysisCellList, i, j, firstColumnCache); // Prevent empty data from not being replaced if (preparedData != null) { cell.setCellValue(preparedData); @@ -310,10 +336,11 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { * @param collectionAnalysisCellList * @param rowIndex * @param columnIndex + * @param firstColumnCache * @return Returns the data that the cell needs to replace */ private String prepareData(Cell cell, List analysisCellList, - List collectionAnalysisCellList, int rowIndex, int columnIndex) { + List collectionAnalysisCellList, int rowIndex, int columnIndex, Set firstColumnCache) { if (!CellType.STRING.equals(cell.getCellTypeEnum())) { return null; } @@ -386,6 +413,10 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) { analysisCellList.add(analysisCell); } else { + if (!firstColumnCache.contains(rowIndex)) { + analysisCell.setFirstColumn(Boolean.TRUE); + firstColumnCache.add(rowIndex); + } collectionAnalysisCellList.add(analysisCell); } return preparedData.toString(); @@ -403,6 +434,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { List prepareDataList = new ArrayList(); analysisCell.setPrepareDataList(prepareDataList); analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COMMON); + analysisCell.setFirstColumn(Boolean.FALSE); return analysisCell; } diff --git a/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java b/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java index 791e2643..47a25947 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java +++ b/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java @@ -16,6 +16,7 @@ public class AnalysisCell { private List prepareDataList; private Boolean onlyOneVariable; private WriteTemplateAnalysisCellTypeEnum cellType; + private Boolean firstColumn; public int getColumnIndex() { return columnIndex; @@ -65,6 +66,14 @@ public class AnalysisCell { this.cellType = cellType; } + public Boolean getFirstColumn() { + return firstColumn; + } + + public void setFirstColumn(Boolean firstColumn) { + this.firstColumn = firstColumn; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExceptionListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExceptionListener.java index 0f00719d..e4f9571a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExceptionListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExceptionListener.java @@ -39,8 +39,8 @@ public class DemoExceptionListener extends AnalysisEventListener { LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage()); if (exception instanceof ExcelDataConvertException) { ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception; - LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(), - excelDataConvertException.getColumnIndex()); + LOGGER.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(), + excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData()); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java new file mode 100644 index 00000000..6c82082d --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java @@ -0,0 +1,110 @@ +package com.alibaba.easyexcel.test.temp; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Ignore; +import org.junit.Test; + +import com.alibaba.easyexcel.test.demo.fill.FillData; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; +import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy; + +/** + * 写的填充写法 + * + * @since 2.1.1 + * @author Jiaju Zhuang + */ +@Ignore +public class FillTempTest { + + /** + * 复杂的填充 + * + * @since 2.1.1 + */ + @Test + public void complexFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // {} 代表普通变量 {.} 代表是list的变量 + String templateFileName = "D:\\test\\complex.xlsx"; + + String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。 + // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用 + // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存 + // 如果数据量大 list不是最后一行 参照下一个 + FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); + excelWriter.fill(data(), fillConfig, writeSheet); + excelWriter.fill(data(), fillConfig, writeSheet); + Map map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + map.put("total", 1000); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + } + + /** + * 数据量大的复杂填充 + *

+ * 这里的解决方案是 确保模板list为最后一行,然后再拼接table.还有03版没救,只能刚正面加内存。 + * + * @since 2.1.1 + */ + @Test + public void complexFillWithTable() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // {} 代表普通变量 {.} 代表是list的变量 + // 这里模板 删除了list以后的数据,也就是统计的这一行 + String templateFileName = "D:\\test\\complex.xlsx"; + + String fileName = TestFileUtil.getPath() + "complexFillWithTable" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + // 直接写入数据 + excelWriter.fill(data(), writeSheet); + excelWriter.fill(data(), writeSheet); + + // 写入list之前的数据 + Map map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // list 后面还有个统计 想办法手动写入 + // 这里偷懒直接用list 也可以用对象 + List> totalListList = new ArrayList>(); + List totalList = new ArrayList(); + totalListList.add(totalList); + totalList.add(null); + totalList.add(null); + totalList.add(null); + // 第四列 + totalList.add("统计:1000"); + // 这里是write 别和fill 搞错了 + excelWriter.write(totalListList, writeSheet); + excelWriter.finish(); + // 总体上写法比较复杂 但是也没有想到好的版本 异步的去写入excel 不支持行的删除和移动,也不支持备注这种的写入,所以也排除了可以 + // 新建一个 然后一点点复制过来的方案,最后导致list需要新增行的时候,后面的列的数据没法后移,后续会继续想想解决方案 + } + + private List data() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + FillData fillData = new FillData(); + list.add(fillData); + fillData.setName("张三"); + fillData.setNumber(5.2); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java index 367ee583..f7778338 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java @@ -79,11 +79,11 @@ public class PoiTest { @Test public void lastRowNum255() throws IOException, InvalidFormatException { - String file = TestFileUtil.getPath() + "fill" + File.separator + "complex.xlsx"; + String file = "D:\\test\\complex.xlsx"; XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new File(file)); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook); Sheet xssfSheet = xssfWorkbook.getSheetAt(0); - xssfSheet.shiftRows(2, 4, 10); + xssfSheet.shiftRows(1, 4, 10, true, true); FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx"); sxssfWorkbook.write(fileout); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java index 196b2da9..e52dc51a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java @@ -25,6 +25,7 @@ public class HDListener extends AnalysisEventListener { @Override public void invokeHeadMap(Map headMap, AnalysisContext context) { LOGGER.info("HEAD:{}", JSON.toJSONString(headMap)); + LOGGER.info("total:{}", context.readSheetHolder().getTotal()); } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java index 38ee661f..538e2663 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java @@ -3,6 +3,7 @@ package com.alibaba.easyexcel.test.temp.read; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; +import lombok.experimental.Accessors; /** * 临时测试 @@ -10,6 +11,7 @@ import lombok.Data; * @author Jiaju Zhuang **/ @Data +@Accessors(chain = true) public class HeadReadData { @ExcelProperty("头1") private String h1; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java index f356524a..5127f72f 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java @@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.temp.read; import java.io.File; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,13 +14,15 @@ import com.alibaba.excel.EasyExcel; * * @author Jiaju Zhuang **/ +@Ignore public class HeadReadTest { private static final Logger LOGGER = LoggerFactory.getLogger(HeadReadTest.class); @Test public void test() throws Exception { - File file = new File("D:\\test\\headt1.xlsx"); - EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet().doRead(); + File file = new File("D:\\test\\headt1.xls"); + EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet(0).doRead(); + } } diff --git a/update.md b/update.md index 4055d43d..9bd246e5 100644 --- a/update.md +++ b/update.md @@ -7,6 +7,11 @@ * 加入多次关闭判断,防止多次关闭异常 * 加入根据模板自动识别导出的excel类型 * 修改默认失败后,不再往文件流写入数据。通过参数`writeExcelOnException` 参数设置异常了也要写入前面的数据。 +* 循环合并策略支持一次性合并多列 +* `ExcelDataConvertException`返回新增具体报错的数据 +* 加入解析class缓存 +* 修复填充的时候行高不复制的Bug [Issue #780](https://github.com/alibaba/easyexcel/issues/780) +* 修复03版无法获取大概总行数的bug # 2.1.0-beta4 * 修改最长匹配策略会空指针的bug [Issue #747](https://github.com/alibaba/easyexcel/issues/747) From d7af9b42eac762ec19a03ec11ea56ad836e5dc97 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 4 Nov 2019 18:53:08 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E8=A7=A3=E6=9E=90class?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/write/executor/ExcelWriteFillExecutor.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java index c7b227f4..800b7c07 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -350,6 +350,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } StringBuilder preparedData = new StringBuilder(); AnalysisCell analysisCell = null; + int startIndex = 0; int length = value.length(); int lastPrepareDataIndex = 0; @@ -403,6 +404,13 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } lastPrepareDataIndex = suffixIndex + 1; } + return dealAnalysisCell(analysisCell, value, rowIndex, lastPrepareDataIndex, length, analysisCellList, + collectionAnalysisCellList, firstColumnCache, preparedData); + } + + private String dealAnalysisCell(AnalysisCell analysisCell, String value, int rowIndex, int lastPrepareDataIndex, + int length, List analysisCellList, List collectionAnalysisCellList, + Set firstColumnCache, StringBuilder preparedData) { if (analysisCell != null) { if (lastPrepareDataIndex == length) { analysisCell.getPrepareDataList().add(StringUtils.EMPTY);