From 93ccde2d0e7e30b42a8d09ef7cc9040bc58d0776 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Fri, 1 Feb 2008 15:41:32 +0000 Subject: [PATCH] Get the Hyperlink record code so that it doesn't break any existing tests, and add in (no usermodel support yet though) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@617523 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/HyperlinkRecord.java | 93 +++++++++++------- .../apache/poi/hssf/record/RecordFactory.java | 3 +- .../poi/hssf/record/RecordInputStream.java | 2 +- .../apache/poi/hssf/data/WithHyperlink.xls | Bin 0 -> 31232 bytes .../poi/hssf/record/TestHyperlinkRecord.java | 47 +++++++++ .../poi/hssf/usermodel/TestHSSFCell.java | 6 ++ 6 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/data/WithHyperlink.xls diff --git a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java index 76f9f531d..36a26f415 100644 --- a/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java +++ b/src/java/org/apache/poi/hssf/record/HyperlinkRecord.java @@ -65,11 +65,13 @@ public class HyperlinkRecord extends Record implements CellValueRecordInterface private short field_3_xf_index; private short field_4_unknown; private byte[] field_5_unknown; - private int field_6_url_len; - private int field_7_label_len; - private String field_8_label; - private byte[] field_9_unknown; - private String field_10_url; + private int field_6_label_opts; + private int field_7_url_len; + private int field_8_label_len; + private String field_9_label; + private byte[] field_10_unknown; + private int field_11_url_opts; + private String field_12_url; /** Blank Constructor */ public HyperlinkRecord() @@ -186,33 +188,51 @@ public class HyperlinkRecord extends Record implements CellValueRecordInterface */ protected void fillFields(RecordInputStream in) { +// System.err.println(in.currentSid); +// System.err.println(in.currentLength); +// for(int i=0; i<300; i++) { +// System.err.println(in.readByte()); +// } +// if(1==1) +// throw new IllegalArgumentException(""); + field_1_row = in.readUShort(); field_2_column = in.readShort(); field_3_xf_index = in.readShort(); field_4_unknown = in.readShort(); - // Next up is 20 bytes we don't get - field_5_unknown = new byte[20]; + // Next up is 16 bytes we don't get + field_5_unknown = new byte[16]; try { in.read(field_5_unknown); } catch(IOException e) { throw new IllegalStateException(e); } + // Some sort of opts + field_6_label_opts = in.readInt(); + // Now for lengths, in characters - field_6_url_len = in.readInt(); - field_7_label_len = in.readInt(); + field_7_url_len = in.readInt(); + field_8_label_len = in.readInt(); // Now we have the label, as little endian unicode, // with a trailing \0 - field_8_label = in.readUnicodeLEString(field_7_label_len); + field_9_label = in.readUnicodeLEString(field_8_label_len); // Next up is some more data we can't make sense of - field_9_unknown = new byte[20]; + field_10_unknown = new byte[16]; try { - in.read(field_9_unknown); + in.read(field_10_unknown); } catch(IOException e) { throw new IllegalStateException(e); } + // Might need to nudge the length by one byte + // This is an empirical hack! + field_11_url_opts = in.readInt(); + if(field_11_url_opts == 44) { + field_7_url_len--; + } + // Finally it's the URL - field_10_url = in.readUnicodeLEString(field_6_url_len); + field_12_url = in.readUnicodeLEString(field_7_url_len); } /* (non-Javadoc) @@ -247,19 +267,23 @@ public class HyperlinkRecord extends Record implements CellValueRecordInterface offset++; } - LittleEndian.putInt(data, offset, field_6_url_len); + LittleEndian.putInt(data, offset, field_6_label_opts); offset += 4; - LittleEndian.putInt(data, offset, field_7_label_len); + LittleEndian.putInt(data, offset, field_7_url_len); offset += 4; - StringUtil.putUnicodeLE(field_8_label, data, offset); - offset += field_8_label.length()*2; + LittleEndian.putInt(data, offset, field_8_label_len); + offset += 4; + StringUtil.putUnicodeLE(field_9_label, data, offset); + offset += field_9_label.length()*2; - for(int i=0; iI*+F*sXnN#6Cka4m_k3-2bWbuCWvBW3%C$l~A!X7)SX zedlpCBMmlTC2CqaeeOMdy8HC&bl*AM_nv<{^WyWbWPd;=w~VZGEs#bjVRQ}G48qxo zigCgB*8+inBog5=;l@!7dO0}23zfFc0*KZa6VF9a+ClmW^Civddk2G2NZnwugjtw-g24QD}*F$A?B9o@!0 z(V*~Yl|;&)aJ9Ff<*ZhM+aB&jaGS_OKH5p!fIYz1>!y%J<9=(%5KnxT@W2+ynM@m~ zn|9&P2|4yr9d%NhkclaNa^t#lghca@KkGmqKPl zlp}wm?D6K$>JELMM`5hfnl7z-IFD_-$xwbGNwk z;=;mGy~)+(*K2(4-7bA&m&>Q$aJO8@;M7=#d$bhHGZxhG)9@!jr!W;Q4}Yrge=hjW zNN$9*77u-qvDRD38i41h%UYG-`=Rh1@HM2v{%H~Cw}M^-t#uasfrt8J?JQ5FZ@YZ0 z&Q7Nc(hzipb0sndSz^bs#*P&;uan4P9Yq!6B&1$PF~mrMlIB?W4@o#PDHr_=8rgA| zWA^;nvkRN&F5R4G+-#mZGierdKD4tzLihvgU9AsBGC43QKz$ob`Gt|`;GUD3gK5KI z<}#(GSj(Wvy>fuu}eQpf;{226kQR%!^y3E?& z)Q-tmK}E}#`KvV@zTpP-CoD;1@396LXZEECJf$y5;HiD70%!Hv1g1U`__m(pz#(X9 zsp)tEdf%2pcb?8dvKQ#;|0dI)YzK&reTWEft-N0AqrSgdf~onZn1*|3aBvW)hgyza zqxTmSQ{alMu7yhMh)Nnc%z(2z|%!K{akNZIXIXc%5e6F8L z+5%K^?i}dQdJO%5Hlnt+emZ>kFoA(e`a!_*pajq_0JIXs1!1#&l9*)?OHH#|p}RFY z2u+^LOH=5u4clEVe-Tsu$csjUQp}W7HDQ#JUP?k-jb7Jm0HXhSS)(@FS^#rNXW>=u zkgVC1p=luUQiDetk6Lz&8LDXJCCsCc3?2nUeO|!=`6Ietq#+ksDh=eoY4D1{h|kw0 zG+~HW(gRSSHhNgY%G)-Gd5dgD>R5Z*P*58*xs6l5ip3kR)74sig{Px?SEpWt^wniC zR_?X?ye?mdyK`q3WanvH1b6z~o!u@ZR^#b(>3)#io$ZjKetva;EJ-#xi$pVMAkc-0 zWQYzt^~haRv$YZTym+u?UHU0nkY*1A_8u|tK%l>mevDdR;F1A@zl!R9beWpVGss1) zL?;kt*WnrAeX=%)4xPTg7yLaO57$E*${t-R?zfZsK<`IhY8MM7C*4}m z8B|*g*}A==d{6x(SC+TCkNH_v23(>SlbyqebRGQXas4uAsRj+#9|7)H@h{?<4!m$i z2jcwBv%Ci!KQ5Hz*?XMx3zt`=$3s($UtrFE5D4*i_t4*dDC?{4#U9)ja{PlC?I#ef z;l3)^9;{x1Lp+JExsxzP{NHmu7%BkRCg>u4@F2ZE(xY#3zQ{wAPlR(^;gC0E{sa2F zT~R{iH{=uYAe_hVk+;9ce1c#0msB2Ss$U$Wnm1S;gp2W9C7=1_vw=P0*xV`a0T&lB{!h5v}4^oUL))BFZ{ zFdA8V7$L7GabEn3!hXShK=^BD$+W3dQMq?lhrZk8>vDTK?{O667dmuTXN#v5dh8y@ z#->#Z${m%<(ko`wG^}X)PUA}5+u_C|OXJ4n^>r(-GAt;l_If*91qC%tHF{%x-G(L| zX%rN!Tp;l7fOgd-miznJd4=vx^zK3L1SLs8j#GdL*_05%OF8tqx=(Q;!e_ z)K+(ke_483#ZK40Wk^CL=JmNd{rQc~cGoJ8Z)`IaFS<5GxN zV8~ceUo{PKaGeT!+ND1{0(!Wh*@hRCMAGyVrdjDiK*V~h-nuI_D3a<26{ zG50sSJKH?X#*7+mrfyu**jUrZyemAduC>lxE@K`En?0{*CW&`aA5m=&pViYUjM~!9e z`a7-?#u%;Fr@+ffq7Kf5WsAng&+smjzj=pN*6P^{YlLDf076e1Ig{K`RQxFZ9dO z*U)#_1Otmp+SatKFfCB?6RYXVBVQhAeQV8q*7oE)>s4W9sHIvCwfx$WCu}ybT>@LJ z!e;YO0M`)~ne8^3uJv&Y(uE(@d!Dz(z(T^2c}LULz*V(l>|&*iaIsROjR=8l#Ui)J zv6V%difk5X?6JZ=B6e!R{>?NNMACYHK-!Udrm?9>(sanJ3qBTI(!3p{;SJ=SK2Ue}dUT^o zX3d%vtc?cL#w5|-Gf)FWSF(o6aR*z}epc zK*y$fY}l&?zG&jf2W>m{$@=KlF=4pd{89p*k)^d*snfg;U}NQH8E_!A=~^& zKa`kv0tRjLqs$mLc-KITGKAH2!j8>bN~6x+H?%E6?H*;vX-q>sH&nuoJ#2?=sJ_fL zgK;!EN_NVxE1qO+J_WZ31f`b zgdJNQs|efbIOdmABMs8ZXJ&Dz+)_YmEts8heJDwN74id zJGL~Bg!x~^jvb0F>_@`%QYDC^*^gvQVNk?nyw;p~c*9HLR3gqiCagJe9Jb_DQ^J~) zu;xVn1t!9vVEUam`20W89AbXt8@`h%>hD1#B{}>+PuTA^L7~vCM?HOPDo}7JB&<2n zD^IOGZd?Nx7KAVpRj?5f)|`YjC(7#s64soAH7DAO9j;SjMf}zuHfhLYVp^nFJE@Jv z32RQmnj;p@iBpNAzjoz@j?Upf4jQ}QaeyPXy^6T^lMcVa-vBI$_PB@p39r+GN=O`qrFKT8XQhT?6uL7@yCS zr>^)sA)o!@bB}zOi%)T}#f?8#z%NB0OM_)d^C(taq%0I z|B~PT;BR^qA&+7JUKWj0h>_p_;Bfx_2jhf`UIW)~{@9vs*j7s?j@u z>`TH?j>5Wl74ADIdiEcLqa1}f&U73Io=(|^55M^0$&-|$u+HfqwQL+1&mj#X$$`(| zNW4(t}DO{uQI)%3=yi?)5 z3LjMXkiyR@d|csQDEy|t=KA2Cf*yi*511v?(c^OPc^HHY>vt0oGLb`u^}9((Z<6*n z%0+l%`$U0HDEx)Q+A4(~2R5heK>Sur7mRbD%aDw<-LJ!dE5M z?gciN(t%RuVjMDVSNIHVR7vDWV~*%K%ARXMo=DkL zyAITf>{%K{HsYJ=*nwP)^s~7JYiic5+p;An8EX~RB{`67KG~CKVtsduyVa@R>vMLt zy2uKh%P)YKh+51S3K*ZqN}sNAiPF&L%|nU~W!2p|0nGX02BEk&3^ zn0g5QGlI`jB;|en?;xRX)mtjitvw#+fqvIBK@9J7Z59}oE% zW-bTX1K)`NUVy&McoF?s@RiXO!Ba$t##n_^t2hd$;2&TrC;B>tcSxc&}}uUZ`Kj#d^qUbsL> zkZx{<6`yqoNdXdKuMzpk??8wY&=U|Btq&h9o`(bWGcv+I4me6z2M5C+9{UXYT?eKfgW2h#9&HkdBez0-q}mz7ya(5eMHF;QL~9KIpV} z0i((X&G;^0R6dk-l6GiRJ|5#aaq#ho&WnSO$N9oI_;~a$kAshOLPH#UtSL6f!N>Z; z9S0w4mECdhv98%42On#ozBu?;Cp{AfA8V?kaqzMJIvoceYqdAx;NunHJ2CjoT1FS+ zkF;-NT(LU~P;VO&_ri;{{)ZML%X`0k@9F#;`xAeU_5b|OUakQx*+k2Qn)@~A{G5nO zY6S4J;e7zCuEd)`_}P)44S1anZ6%%wz6Xre9~}VjGi5J;pBY{SaNfo<0xK(ayoOJ< zPJmLEE*74NOqiFSQRLTvLYKv%%M!`}BWJ`PGU3EFd3-y&`13(sB0i^a0>GG^4&d@Z z^NDCx>YkHextkm7YMN{7>(;K`5R|_f^z8uo?j)j0`hGAyBVEQEekXwI>-yeoBIB`K zU)5=}LcAr#i|KzG?YQn__$z$jPnPi{z;(#|<3_pb&HqN_Yos%t^Vje+Y(dZFGMK;J l$qL2vT&)L(iFk@GUsbo9e+?4P-1%a><#X#M+<2*h{{sZ(71jU% literal 0 HcmV?d00001 diff --git a/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java b/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java index 587548b48..983b91601 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java @@ -56,6 +56,37 @@ public class TestHyperlinkRecord extends TestCase { 0, 110, 0, 103, 0, 115, 0, 46, 0, 99, 0, 111, 0, 109, 0, 0, 0 }; + + private byte[] data2 = new byte[] { + -72, 1, -126, 0, + // Row, col, xf, ?? + 2, 0, 2, 0, 4, 0, 4, 0, + + // ?? + -48, -55, -22, 121, -7, -70, -50, 17, + -116, -126, 0, -86, 0, 75, -87, 11, + 2, 0, 0, 0, + + // URL and Label lengths + 23, 0, 0, 0, + 15, 0, 0, 0, + + // Label + 83, 0, 116, 0, 97, 0, 99, 0, 105, 0, + 101, 0, 64, 0, 65, 0, 66, 0, 67, 0, + 46, 0, 99, 0, 111, 0, 109, 0, 0, 0, + + // ?? + -32, -55, -22, 121, -7, -70, -50, 17, + -116, -126, 0, -86, 0, 75, -87, 11, + 44, 0, 0, 0, + + // URL + 109, 0, 97, 0, 105, 0, 108, 0, 116, 0, + 111, 0, 58, 0, 83, 0, 116, 0, 97, 0, + 99, 0, 105, 0, 101, 0, 64, 0, 65, 0, + 66, 0, 67, 0, 46, 0, 99, 0, 111, 0, + 109, 0, 0, 0 }; public void testRecordParsing() throws Exception { RecordInputStream inp = new RecordInputStream( @@ -81,4 +112,20 @@ public class TestHyperlinkRecord extends TestCase { assertEquals(data[i], d[i]); } } + + public void testSecondRecord() throws Exception { + RecordInputStream inp = new RecordInputStream( + new ByteArrayInputStream(data2) + ); + inp.nextRecord(); + + HyperlinkRecord r = new HyperlinkRecord(inp); + + assertEquals(2, r.getRow()); + assertEquals(2, r.getColumn()); + assertEquals(4, r.getXFIndex()); + + assertEquals("Stacie@ABC.com", r.getLabel()); + assertEquals("mailto:Stacie@ABC.com", r.getUrlString()); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java index ee3cace26..482ae7c6c 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java @@ -310,6 +310,12 @@ extends TestCase { in.close(); } + public void testWithHyperlinks() throws Exception { + String dir = System.getProperty("HSSF.testdata.path"); + File f = new File(dir, "WithHyperlink.xls"); + HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(f)); + } + /*tests the toString() method of HSSFCell*/ public void testToString() throws Exception { HSSFWorkbook wb = new HSSFWorkbook();