You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BaseTestBugzillaIssues.java 58KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ss.usermodel;
  16. import static org.junit.Assert.assertEquals;
  17. import static org.junit.Assert.assertNotNull;
  18. import static org.junit.Assert.assertNull;
  19. import static org.junit.Assert.assertTrue;
  20. import static org.junit.Assert.fail;
  21. import java.awt.font.FontRenderContext;
  22. import java.awt.font.TextAttribute;
  23. import java.awt.font.TextLayout;
  24. import java.io.FileInputStream;
  25. import java.io.IOException;
  26. import java.text.AttributedString;
  27. import java.util.HashMap;
  28. import java.util.Map;
  29. import java.awt.geom.Rectangle2D;
  30. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  31. import org.apache.poi.hssf.util.PaneInformation;
  32. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  33. import org.apache.poi.ss.ITestDataProvider;
  34. import org.apache.poi.ss.SpreadsheetVersion;
  35. import org.apache.poi.ss.util.CellRangeAddress;
  36. import org.apache.poi.ss.util.SheetUtil;
  37. import org.apache.poi.util.POILogFactory;
  38. import org.apache.poi.util.POILogger;
  39. import org.junit.Assume;
  40. import org.junit.Ignore;
  41. import org.junit.Test;
  42. /**
  43. * A base class for bugzilla issues that can be described in terms of common ss interfaces.
  44. *
  45. * @author Yegor Kozlov
  46. */
  47. public abstract class BaseTestBugzillaIssues {
  48. private static final POILogger logger = POILogFactory.getLogger(BaseTestBugzillaIssues.class);
  49. private final ITestDataProvider _testDataProvider;
  50. protected BaseTestBugzillaIssues(ITestDataProvider testDataProvider) {
  51. _testDataProvider = testDataProvider;
  52. }
  53. /**
  54. * Unlike org.junit.Assert.assertEquals(double expected, double actual, double delta),
  55. * where delta is an absolute error value, this function's factor is a relative error,
  56. * so it's easier to express "actual is within 5% of expected".
  57. */
  58. public static void assertAlmostEquals(double expected, double actual, float factor) {
  59. double diff = Math.abs(expected - actual);
  60. double fuzz = expected * factor;
  61. if (diff > fuzz)
  62. fail(actual + " not within " + fuzz + " of " + expected);
  63. }
  64. /**
  65. * Test writing a hyperlink
  66. * Open resulting sheet in Excel and check that A1 contains a hyperlink
  67. *
  68. * Also tests bug 15353 (problems with hyperlinks to Google)
  69. */
  70. @Test
  71. public final void bug23094() throws IOException {
  72. Workbook wb1 = _testDataProvider.createWorkbook();
  73. Sheet s = wb1.createSheet();
  74. Row r = s.createRow(0);
  75. r.createCell(0).setCellFormula("HYPERLINK(\"http://jakarta.apache.org\",\"Jakarta\")");
  76. r.createCell(1).setCellFormula("HYPERLINK(\"http://google.com\",\"Google\")");
  77. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  78. wb1.close();
  79. r = wb2.getSheetAt(0).getRow(0);
  80. Cell cell_0 = r.getCell(0);
  81. assertEquals("HYPERLINK(\"http://jakarta.apache.org\",\"Jakarta\")", cell_0.getCellFormula());
  82. Cell cell_1 = r.getCell(1);
  83. assertEquals("HYPERLINK(\"http://google.com\",\"Google\")", cell_1.getCellFormula());
  84. wb2.close();
  85. }
  86. /**
  87. * test writing a file with large number of unique strings,
  88. * open resulting file in Excel to check results!
  89. * @param num the number of strings to generate
  90. */
  91. public final void bug15375(int num) throws IOException {
  92. Workbook wb1 = _testDataProvider.createWorkbook();
  93. Sheet sheet = wb1.createSheet();
  94. CreationHelper factory = wb1.getCreationHelper();
  95. for (int i = 0; i < num; i++) {
  96. String tmp1 = "Test1" + i;
  97. String tmp2 = "Test2" + i;
  98. String tmp3 = "Test3" + i;
  99. Row row = sheet.createRow(i);
  100. Cell cell = row.createCell(0);
  101. cell.setCellValue(factory.createRichTextString(tmp1));
  102. cell = row.createCell(1);
  103. cell.setCellValue(factory.createRichTextString(tmp2));
  104. cell = row.createCell(2);
  105. cell.setCellValue(factory.createRichTextString(tmp3));
  106. }
  107. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  108. wb1.close();
  109. sheet = wb2.getSheetAt(0);
  110. for (int i = 0; i < num; i++) {
  111. String tmp1 = "Test1" + i;
  112. String tmp2 = "Test2" + i;
  113. String tmp3 = "Test3" + i;
  114. Row row = sheet.getRow(i);
  115. assertEquals(tmp1, row.getCell(0).getStringCellValue());
  116. assertEquals(tmp2, row.getCell(1).getStringCellValue());
  117. assertEquals(tmp3, row.getCell(2).getStringCellValue());
  118. }
  119. wb2.close();
  120. }
  121. /**
  122. * Merged regions were being removed from the parent in cloned sheets
  123. */
  124. @Test
  125. public void bug22720() throws IOException {
  126. Workbook wb = _testDataProvider.createWorkbook();
  127. wb.createSheet("TEST");
  128. Sheet template = wb.getSheetAt(0);
  129. template.addMergedRegion(new CellRangeAddress(0, 1, 0, 2));
  130. template.addMergedRegion(new CellRangeAddress(2, 3, 0, 2));
  131. Sheet clone = wb.cloneSheet(0);
  132. int originalMerged = template.getNumMergedRegions();
  133. assertEquals("2 merged regions", 2, originalMerged);
  134. //remove merged regions from clone
  135. for (int i=template.getNumMergedRegions()-1; i>=0; i--) {
  136. clone.removeMergedRegion(i);
  137. }
  138. assertEquals("Original Sheet's Merged Regions were removed", originalMerged, template.getNumMergedRegions());
  139. //check if template's merged regions are OK
  140. if (template.getNumMergedRegions()>0) {
  141. // fetch the first merged region...EXCEPTION OCCURS HERE
  142. template.getMergedRegion(0);
  143. }
  144. //make sure we dont exception
  145. wb.close();
  146. }
  147. @Test
  148. public final void bug28031() throws IOException {
  149. Workbook wb1 = _testDataProvider.createWorkbook();
  150. Sheet sheet = wb1.createSheet();
  151. wb1.setSheetName(0, "Sheet1");
  152. Row row = sheet.createRow(0);
  153. Cell cell = row.createCell(0);
  154. String formulaText =
  155. "IF(ROUND(A2*B2*C2,2)>ROUND(B2*D2,2),ROUND(A2*B2*C2,2),ROUND(B2*D2,2))";
  156. cell.setCellFormula(formulaText);
  157. assertEquals(formulaText, cell.getCellFormula());
  158. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  159. wb1.close();
  160. cell = wb2.getSheetAt(0).getRow(0).getCell(0);
  161. assertEquals("IF(ROUND(A2*B2*C2,2)>ROUND(B2*D2,2),ROUND(A2*B2*C2,2),ROUND(B2*D2,2))", cell.getCellFormula());
  162. wb2.close();
  163. }
  164. /**
  165. * Bug 21334: "File error: data may have been lost" with a file
  166. * that contains macros and this formula:
  167. * {=SUM(IF(FREQUENCY(IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),""),IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),""))>0,1))}
  168. */
  169. @Test
  170. public final void bug21334() throws IOException {
  171. Workbook wb1 = _testDataProvider.createWorkbook();
  172. Sheet sh = wb1.createSheet();
  173. Cell cell = sh.createRow(0).createCell(0);
  174. String formula = "SUM(IF(FREQUENCY(IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),\"\"),IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),\"\"))>0,1))";
  175. cell.setCellFormula(formula);
  176. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  177. wb1.close();
  178. Cell cell_sv = wb2.getSheetAt(0).getRow(0).getCell(0);
  179. assertEquals(formula, cell_sv.getCellFormula());
  180. wb2.close();
  181. }
  182. /** another test for the number of unique strings issue
  183. *test opening the resulting file in Excel*/
  184. @Test
  185. public final void bug22568() throws IOException {
  186. Workbook wb1 = _testDataProvider.createWorkbook();
  187. Sheet sheet = wb1.createSheet("ExcelTest") ;
  188. int col_cnt = 3;
  189. int rw_cnt = 2000;
  190. Row rw ;
  191. rw = sheet.createRow(0) ;
  192. //Header row
  193. for(int j=0; j<col_cnt; j++){
  194. Cell cell = rw.createCell(j) ;
  195. cell.setCellValue("Col " + (j+1));
  196. }
  197. for(int i=1; i<rw_cnt; i++){
  198. rw = sheet.createRow(i) ;
  199. for(int j=0; j<col_cnt; j++){
  200. Cell cell = rw.createCell(j) ;
  201. cell.setCellValue("Row:" + (i+1) + ",Column:" + (j+1));
  202. }
  203. }
  204. sheet.setDefaultColumnWidth(18) ;
  205. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  206. wb1.close();
  207. sheet = wb2.getSheetAt(0);
  208. rw = sheet.getRow(0);
  209. //Header row
  210. for(int j=0; j<col_cnt; j++){
  211. Cell cell = rw.getCell(j) ;
  212. assertEquals("Col " + (j+1), cell.getStringCellValue());
  213. }
  214. for(int i=1; i<rw_cnt; i++){
  215. rw = sheet.getRow(i) ;
  216. for(int j=0; j<col_cnt; j++){
  217. Cell cell = rw.getCell(j) ;
  218. assertEquals("Row:" + (i+1) + ",Column:" + (j+1), cell.getStringCellValue());
  219. }
  220. }
  221. wb2.close();
  222. }
  223. /**
  224. * Bug 42448: Can't parse SUMPRODUCT(A!C7:A!C67, B8:B68) / B69
  225. */
  226. @Test
  227. public final void bug42448() throws IOException {
  228. Workbook wb = _testDataProvider.createWorkbook();
  229. Cell cell = wb.createSheet().createRow(0).createCell(0);
  230. cell.setCellFormula("SUMPRODUCT(A!C7:A!C67, B8:B68) / B69");
  231. assertTrue("no errors parsing formula", true);
  232. wb.close();
  233. }
  234. @Test
  235. public void bug18800() throws IOException {
  236. Workbook wb1 = _testDataProvider.createWorkbook();
  237. wb1.createSheet("TEST");
  238. Sheet sheet = wb1.cloneSheet(0);
  239. wb1.setSheetName(1,"CLONE");
  240. sheet.createRow(0).createCell(0).setCellValue("Test");
  241. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  242. wb1.close();
  243. sheet = wb2.getSheet("CLONE");
  244. Row row = sheet.getRow(0);
  245. Cell cell = row.getCell(0);
  246. assertEquals("Test", cell.getRichStringCellValue().getString());
  247. wb2.close();
  248. }
  249. private static void addNewSheetWithCellsA1toD4(Workbook book, int sheet) {
  250. Sheet sht = book .createSheet("s" + sheet);
  251. for (int r=0; r < 4; r++) {
  252. Row row = sht.createRow (r);
  253. for (int c=0; c < 4; c++) {
  254. Cell cel = row.createCell(c);
  255. cel.setCellValue(sheet*100 + r*10 + c);
  256. }
  257. }
  258. }
  259. @Test
  260. public void bug43093() throws IOException {
  261. Workbook xlw = _testDataProvider.createWorkbook();
  262. addNewSheetWithCellsA1toD4(xlw, 1);
  263. addNewSheetWithCellsA1toD4(xlw, 2);
  264. addNewSheetWithCellsA1toD4(xlw, 3);
  265. addNewSheetWithCellsA1toD4(xlw, 4);
  266. Sheet s2 = xlw.getSheet("s2");
  267. Row s2r3 = s2.getRow(3);
  268. Cell s2E4 = s2r3.createCell(4);
  269. s2E4.setCellFormula("SUM(s3!B2:C3)");
  270. FormulaEvaluator eva = xlw.getCreationHelper().createFormulaEvaluator();
  271. double d = eva.evaluate(s2E4).getNumberValue();
  272. assertEquals(d, (311+312+321+322), 0.0000001);
  273. xlw.close();
  274. }
  275. @Test
  276. public void bug46729_testMaxFunctionArguments() throws IOException {
  277. String[] func = {"COUNT", "AVERAGE", "MAX", "MIN", "OR", "SUBTOTAL", "SKEW"};
  278. SpreadsheetVersion ssVersion = _testDataProvider.getSpreadsheetVersion();
  279. Workbook wb = _testDataProvider.createWorkbook();
  280. Cell cell = wb.createSheet().createRow(0).createCell(0);
  281. String fmla;
  282. for (String name : func) {
  283. fmla = createFunction(name, 5);
  284. cell.setCellFormula(fmla);
  285. fmla = createFunction(name, ssVersion.getMaxFunctionArgs());
  286. cell.setCellFormula(fmla);
  287. try {
  288. fmla = createFunction(name, ssVersion.getMaxFunctionArgs() + 1);
  289. cell.setCellFormula(fmla);
  290. fail("Expected FormulaParseException");
  291. } catch (RuntimeException e){
  292. assertTrue(e.getMessage().startsWith("Too many arguments to function '"+name+"'"));
  293. }
  294. }
  295. wb.close();
  296. }
  297. private static String createFunction(String name, int maxArgs){
  298. StringBuilder fmla = new StringBuilder();
  299. fmla.append(name);
  300. fmla.append("(");
  301. for(int i=0; i < maxArgs; i++){
  302. if(i > 0) fmla.append(',');
  303. fmla.append("A1");
  304. }
  305. fmla.append(")");
  306. return fmla.toString();
  307. }
  308. @Test
  309. public final void bug50681_testAutoSize() throws IOException {
  310. Workbook wb = _testDataProvider.createWorkbook();
  311. BaseTestSheetAutosizeColumn.fixFonts(wb);
  312. Sheet sheet = wb.createSheet("Sheet1");
  313. _testDataProvider.trackAllColumnsForAutosizing(sheet);
  314. Row row = sheet.createRow(0);
  315. Cell cell0 = row.createCell(0);
  316. String longValue = "www.hostname.com, www.hostname.com, " +
  317. "www.hostname.com, www.hostname.com, www.hostname.com, " +
  318. "www.hostname.com, www.hostname.com, www.hostname.com, " +
  319. "www.hostname.com, www.hostname.com, www.hostname.com, " +
  320. "www.hostname.com, www.hostname.com, www.hostname.com, " +
  321. "www.hostname.com, www.hostname.com, www.hostname.com, www.hostname.com";
  322. cell0.setCellValue(longValue);
  323. // autoSize will fail if required fonts are not installed, skip this test then
  324. Font font = wb.getFontAt(cell0.getCellStyle().getFontIndex());
  325. Assume.assumeTrue("Cannot verify autoSizeColumn() because the necessary Fonts are not installed on this machine: " + font,
  326. SheetUtil.canComputeColumnWidth(font));
  327. assertEquals("Expecting no indentation in this test",
  328. 0, cell0.getCellStyle().getIndention());
  329. assertEquals("Expecting no rotation in this test",
  330. 0, cell0.getCellStyle().getRotation());
  331. // check computing size up to a large size
  332. // StringBuilder b = new StringBuilder();
  333. // for(int i = 0;i < longValue.length()*5;i++) {
  334. // b.append("w");
  335. // assertTrue("Had zero length starting at length " + i, computeCellWidthFixed(font, b.toString()) > 0);
  336. // }
  337. double widthManual = computeCellWidthManually(cell0, font);
  338. double widthBeforeCell = SheetUtil.getCellWidth(cell0, 8, null, false);
  339. double widthBeforeCol = SheetUtil.getColumnWidth(sheet, 0, false);
  340. String info = widthManual + "/" + widthBeforeCell + "/" + widthBeforeCol + "/" +
  341. SheetUtil.canComputeColumnWidth(font) + "/" + computeCellWidthFixed(font, "1") + "/" + computeCellWidthFixed(font, "w") + "/" +
  342. computeCellWidthFixed(font, "1w") + "/" + computeCellWidthFixed(font, "0000") + "/" + computeCellWidthFixed(font, longValue);
  343. assertTrue("Expected to have cell width > 0 when computing manually, but had " + info, widthManual > 0);
  344. assertTrue("Expected to have cell width > 0 BEFORE auto-size, but had " + info, widthBeforeCell > 0);
  345. assertTrue("Expected to have column width > 0 BEFORE auto-size, but had " + info, widthBeforeCol > 0);
  346. sheet.autoSizeColumn(0);
  347. double width = SheetUtil.getColumnWidth(sheet, 0, false);
  348. assertTrue("Expected to have column width > 0 AFTER auto-size, but had " + width, width > 0);
  349. width = SheetUtil.getCellWidth(cell0, 8, null, false);
  350. assertTrue("Expected to have cell width > 0 AFTER auto-size, but had " + width, width > 0);
  351. assertEquals(255*256, sheet.getColumnWidth(0)); // maximum column width is 255 characters
  352. sheet.setColumnWidth(0, sheet.getColumnWidth(0)); // Bug 50681 reports exception at this point
  353. wb.close();
  354. }
  355. @Test
  356. public final void bug51622_testAutoSizeShouldRecognizeLeadingSpaces() throws IOException {
  357. Workbook wb = _testDataProvider.createWorkbook();
  358. BaseTestSheetAutosizeColumn.fixFonts(wb);
  359. Sheet sheet = wb.createSheet();
  360. _testDataProvider.trackAllColumnsForAutosizing(sheet);
  361. Row row = sheet.createRow(0);
  362. Cell cell0 = row.createCell(0);
  363. Cell cell1 = row.createCell(1);
  364. Cell cell2 = row.createCell(2);
  365. cell0.setCellValue("Test Column AutoSize");
  366. cell1.setCellValue(" Test Column AutoSize");
  367. cell2.setCellValue("Test Column AutoSize ");
  368. sheet.autoSizeColumn(0);
  369. sheet.autoSizeColumn(1);
  370. sheet.autoSizeColumn(2);
  371. int noWhitespaceColWidth = sheet.getColumnWidth(0);
  372. int leadingWhitespaceColWidth = sheet.getColumnWidth(1);
  373. int trailingWhitespaceColWidth = sheet.getColumnWidth(2);
  374. // Based on the amount of text and whitespace used, and the default font
  375. // assume that the cell with whitespace should be at least 20% wider than
  376. // the cell without whitespace. This number is arbitrary, but should be large
  377. // enough to guarantee that the whitespace cell isn't wider due to chance.
  378. // Experimentally, I calculated the ratio as 1.2478181, though this ratio may change
  379. // if the default font or margins change.
  380. final double expectedRatioThreshold = 1.2f;
  381. double leadingWhitespaceRatio = ((double) leadingWhitespaceColWidth)/noWhitespaceColWidth;
  382. double trailingWhitespaceRatio = ((double) leadingWhitespaceColWidth)/noWhitespaceColWidth;
  383. assertGreaterThan("leading whitespace is longer than no whitespace", leadingWhitespaceRatio, expectedRatioThreshold);
  384. assertGreaterThan("trailing whitespace is longer than no whitespace", trailingWhitespaceRatio, expectedRatioThreshold);
  385. assertEquals("cells with equal leading and trailing whitespace have equal width",
  386. leadingWhitespaceColWidth, trailingWhitespaceColWidth);
  387. wb.close();
  388. }
  389. /**
  390. * Test if a > b. Fails if false.
  391. */
  392. private void assertGreaterThan(String message, double a, double b) {
  393. if (a <= b) {
  394. String msg = "Expected: " + a + " > " + b;
  395. fail(message + ": " + msg);
  396. }
  397. }
  398. // FIXME: this function is a self-fulfilling prophecy: this test will always pass as long
  399. // as the code-under-test and the testcase code are written the same way (have the same bugs).
  400. private double computeCellWidthManually(Cell cell0, Font font) {
  401. final FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
  402. RichTextString rt = cell0.getRichStringCellValue();
  403. String[] lines = rt.getString().split("\\n");
  404. assertEquals(1, lines.length);
  405. String txt = lines[0] + "0";
  406. AttributedString str = new AttributedString(txt);
  407. copyAttributes(font, str, 0, txt.length());
  408. // TODO: support rich text fragments
  409. /*if (rt.numFormattingRuns() > 0) {
  410. }*/
  411. TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext);
  412. double frameWidth = getFrameWidth(layout);
  413. return ((frameWidth / 1) / 8);
  414. }
  415. private double getFrameWidth(TextLayout layout) {
  416. Rectangle2D bounds = layout.getBounds();
  417. return bounds.getX() + bounds.getWidth();
  418. }
  419. private double computeCellWidthFixed(Font font, String txt) {
  420. final FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
  421. AttributedString str = new AttributedString(txt);
  422. copyAttributes(font, str, 0, txt.length());
  423. TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext);
  424. return getFrameWidth(layout);
  425. }
  426. private static void copyAttributes(Font font, AttributedString str, int startIdx, int endIdx) {
  427. str.addAttribute(TextAttribute.FAMILY, font.getFontName(), startIdx, endIdx);
  428. str.addAttribute(TextAttribute.SIZE, (float)font.getFontHeightInPoints());
  429. if (font.getBoldweight() == Font.BOLDWEIGHT_BOLD) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx);
  430. if (font.getItalic() ) str.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, startIdx, endIdx);
  431. if (font.getUnderline() == Font.U_SINGLE ) str.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, startIdx, endIdx);
  432. }
  433. /**
  434. * CreateFreezePane column/row order check
  435. */
  436. @Test
  437. public void bug49381() throws IOException {
  438. Workbook wb = _testDataProvider.createWorkbook();
  439. int colSplit = 1;
  440. int rowSplit = 2;
  441. int leftmostColumn = 3;
  442. int topRow = 4;
  443. Sheet s = wb.createSheet();
  444. // Populate
  445. for(int rn=0; rn<= topRow; rn++) {
  446. Row r = s.createRow(rn);
  447. for(int cn=0; cn<leftmostColumn; cn++) {
  448. Cell c = r.createCell(cn, Cell.CELL_TYPE_NUMERIC);
  449. c.setCellValue(100*rn + cn);
  450. }
  451. }
  452. // Create the Freeze Pane
  453. s.createFreezePane(colSplit, rowSplit, leftmostColumn, topRow);
  454. PaneInformation paneInfo = s.getPaneInformation();
  455. // Check it
  456. assertEquals(colSplit, paneInfo.getVerticalSplitPosition());
  457. assertEquals(rowSplit, paneInfo.getHorizontalSplitPosition());
  458. assertEquals(leftmostColumn, paneInfo.getVerticalSplitLeftColumn());
  459. assertEquals(topRow, paneInfo.getHorizontalSplitTopRow());
  460. // Now a row only freezepane
  461. s.createFreezePane(0, 3);
  462. paneInfo = s.getPaneInformation();
  463. assertEquals(0, paneInfo.getVerticalSplitPosition());
  464. assertEquals(3, paneInfo.getHorizontalSplitPosition());
  465. assertEquals(0, paneInfo.getVerticalSplitLeftColumn());
  466. assertEquals(3, paneInfo.getHorizontalSplitTopRow());
  467. // Now a column only freezepane
  468. s.createFreezePane(4, 0);
  469. paneInfo = s.getPaneInformation();
  470. assertEquals(4, paneInfo.getVerticalSplitPosition());
  471. assertEquals(0, paneInfo.getHorizontalSplitPosition());
  472. assertEquals(4 , paneInfo.getVerticalSplitLeftColumn());
  473. assertEquals(0, paneInfo.getHorizontalSplitTopRow());
  474. wb.close();
  475. }
  476. /**
  477. * Test hyperlinks
  478. * open resulting file in excel, and check that there is a link to Google
  479. */
  480. @Test
  481. public void bug15353() throws IOException {
  482. String hyperlinkF = "HYPERLINK(\"http://google.com\",\"Google\")";
  483. Workbook wb1 = _testDataProvider.createWorkbook();
  484. Sheet sheet = wb1.createSheet("My sheet");
  485. Row row = sheet.createRow(0);
  486. Cell cell = row.createCell(0);
  487. cell.setCellFormula(hyperlinkF);
  488. assertEquals(hyperlinkF, cell.getCellFormula());
  489. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  490. wb1.close();
  491. sheet = wb2.getSheet("My Sheet");
  492. row = sheet.getRow(0);
  493. cell = row.getCell(0);
  494. assertEquals(hyperlinkF, cell.getCellFormula());
  495. wb2.close();
  496. }
  497. /**
  498. * HLookup and VLookup with optional arguments
  499. */
  500. @Test
  501. public void bug51024() throws IOException {
  502. Workbook wb = _testDataProvider.createWorkbook();
  503. Sheet s = wb.createSheet();
  504. Row r1 = s.createRow(0);
  505. Row r2 = s.createRow(1);
  506. r1.createCell(0).setCellValue("v A1");
  507. r2.createCell(0).setCellValue("v A2");
  508. r1.createCell(1).setCellValue("v B1");
  509. Cell c = r1.createCell(4);
  510. FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
  511. c.setCellFormula("VLOOKUP(\"v A1\", A1:B2, 1)");
  512. assertEquals("v A1", eval.evaluate(c).getStringValue());
  513. c.setCellFormula("VLOOKUP(\"v A1\", A1:B2, 1, 1)");
  514. assertEquals("v A1", eval.evaluate(c).getStringValue());
  515. c.setCellFormula("VLOOKUP(\"v A1\", A1:B2, 1, )");
  516. assertEquals("v A1", eval.evaluate(c).getStringValue());
  517. c.setCellFormula("HLOOKUP(\"v A1\", A1:B2, 1)");
  518. assertEquals("v A1", eval.evaluate(c).getStringValue());
  519. c.setCellFormula("HLOOKUP(\"v A1\", A1:B2, 1, 1)");
  520. assertEquals("v A1", eval.evaluate(c).getStringValue());
  521. c.setCellFormula("HLOOKUP(\"v A1\", A1:B2, 1, )");
  522. assertEquals("v A1", eval.evaluate(c).getStringValue());
  523. wb.close();
  524. }
  525. @Test
  526. public void stackoverflow23114397() throws IOException {
  527. Workbook wb = _testDataProvider.createWorkbook();
  528. DataFormat format = wb.getCreationHelper().createDataFormat();
  529. // How close the sizing should be, given that not all
  530. // systems will have quite the same fonts on them
  531. float fontAccuracy = 0.22f;
  532. // x%
  533. CellStyle iPercent = wb.createCellStyle();
  534. iPercent.setDataFormat(format.getFormat("0%"));
  535. // x.x%
  536. CellStyle d1Percent = wb.createCellStyle();
  537. d1Percent.setDataFormat(format.getFormat("0.0%"));
  538. // x.xx%
  539. CellStyle d2Percent = wb.createCellStyle();
  540. d2Percent.setDataFormat(format.getFormat("0.00%"));
  541. Sheet s = wb.createSheet();
  542. _testDataProvider.trackAllColumnsForAutosizing(s);
  543. Row r1 = s.createRow(0);
  544. for (int i=0; i<3; i++) {
  545. r1.createCell(i, Cell.CELL_TYPE_NUMERIC).setCellValue(0);
  546. }
  547. for (int i=3; i<6; i++) {
  548. r1.createCell(i, Cell.CELL_TYPE_NUMERIC).setCellValue(1);
  549. }
  550. for (int i=6; i<9; i++) {
  551. r1.createCell(i, Cell.CELL_TYPE_NUMERIC).setCellValue(0.12345);
  552. }
  553. for (int i=9; i<12; i++) {
  554. r1.createCell(i, Cell.CELL_TYPE_NUMERIC).setCellValue(1.2345);
  555. }
  556. for (int i=0; i<12; i+=3) {
  557. r1.getCell(i).setCellStyle(iPercent);
  558. r1.getCell(i+1).setCellStyle(d1Percent);
  559. r1.getCell(i+2).setCellStyle(d2Percent);
  560. }
  561. for (int i=0; i<12; i++) {
  562. s.autoSizeColumn(i);
  563. }
  564. // Check the 0(.00)% ones
  565. assertAlmostEquals(980, s.getColumnWidth(0), fontAccuracy);
  566. assertAlmostEquals(1400, s.getColumnWidth(1), fontAccuracy);
  567. assertAlmostEquals(1700, s.getColumnWidth(2), fontAccuracy);
  568. // Check the 100(.00)% ones
  569. assertAlmostEquals(1500, s.getColumnWidth(3), fontAccuracy);
  570. assertAlmostEquals(1950, s.getColumnWidth(4), fontAccuracy);
  571. assertAlmostEquals(2225, s.getColumnWidth(5), fontAccuracy);
  572. // Check the 12(.34)% ones
  573. assertAlmostEquals(1225, s.getColumnWidth(6), fontAccuracy);
  574. assertAlmostEquals(1650, s.getColumnWidth(7), fontAccuracy);
  575. assertAlmostEquals(1950, s.getColumnWidth(8), fontAccuracy);
  576. // Check the 123(.45)% ones
  577. assertAlmostEquals(1500, s.getColumnWidth(9), fontAccuracy);
  578. assertAlmostEquals(1950, s.getColumnWidth(10), fontAccuracy);
  579. assertAlmostEquals(2225, s.getColumnWidth(11), fontAccuracy);
  580. wb.close();
  581. }
  582. /**
  583. * =ISNUMBER(SEARCH("AM",A1)) evaluation
  584. */
  585. @Test
  586. public void stackoverflow26437323() throws IOException {
  587. Workbook wb = _testDataProvider.createWorkbook();
  588. Sheet s = wb.createSheet();
  589. Row r1 = s.createRow(0);
  590. Row r2 = s.createRow(1);
  591. // A1 is a number
  592. r1.createCell(0).setCellValue(1.1);
  593. // B1 is a string, with the wanted text in it
  594. r1.createCell(1).setCellValue("This is text with AM in it");
  595. // C1 is a string, with different text
  596. r1.createCell(2).setCellValue("This some other text");
  597. // D1 is a blank cell
  598. r1.createCell(3, Cell.CELL_TYPE_BLANK);
  599. // E1 is null
  600. // A2 will hold our test formulas
  601. Cell cf = r2.createCell(0, Cell.CELL_TYPE_FORMULA);
  602. // First up, check that TRUE and ISLOGICAL both behave
  603. cf.setCellFormula("TRUE()");
  604. cf = evaluateCell(wb, cf);
  605. assertEquals(true, cf.getBooleanCellValue());
  606. cf.setCellFormula("ISLOGICAL(TRUE())");
  607. cf = evaluateCell(wb, cf);
  608. assertEquals(true, cf.getBooleanCellValue());
  609. cf.setCellFormula("ISLOGICAL(4)");
  610. cf = evaluateCell(wb, cf);
  611. assertEquals(false, cf.getBooleanCellValue());
  612. // Now, check ISNUMBER / ISTEXT / ISNONTEXT
  613. cf.setCellFormula("ISNUMBER(A1)");
  614. cf = evaluateCell(wb, cf);
  615. assertEquals(true, cf.getBooleanCellValue());
  616. cf.setCellFormula("ISNUMBER(B1)");
  617. cf = evaluateCell(wb, cf);
  618. assertEquals(false, cf.getBooleanCellValue());
  619. cf.setCellFormula("ISNUMBER(C1)");
  620. cf = evaluateCell(wb, cf);
  621. assertEquals(false, cf.getBooleanCellValue());
  622. cf.setCellFormula("ISNUMBER(D1)");
  623. cf = evaluateCell(wb, cf);
  624. assertEquals(false, cf.getBooleanCellValue());
  625. cf.setCellFormula("ISNUMBER(E1)");
  626. cf = evaluateCell(wb, cf);
  627. assertEquals(false, cf.getBooleanCellValue());
  628. cf.setCellFormula("ISTEXT(A1)");
  629. cf = evaluateCell(wb, cf);
  630. assertEquals(false, cf.getBooleanCellValue());
  631. cf.setCellFormula("ISTEXT(B1)");
  632. cf = evaluateCell(wb, cf);
  633. assertEquals(true, cf.getBooleanCellValue());
  634. cf.setCellFormula("ISTEXT(C1)");
  635. cf = evaluateCell(wb, cf);
  636. assertEquals(true, cf.getBooleanCellValue());
  637. cf.setCellFormula("ISTEXT(D1)");
  638. cf = evaluateCell(wb, cf);
  639. assertEquals(false, cf.getBooleanCellValue());
  640. cf.setCellFormula("ISTEXT(E1)");
  641. cf = evaluateCell(wb, cf);
  642. assertEquals(false, cf.getBooleanCellValue());
  643. cf.setCellFormula("ISNONTEXT(A1)");
  644. cf = evaluateCell(wb, cf);
  645. assertEquals(true, cf.getBooleanCellValue());
  646. cf.setCellFormula("ISNONTEXT(B1)");
  647. cf = evaluateCell(wb, cf);
  648. assertEquals(false, cf.getBooleanCellValue());
  649. cf.setCellFormula("ISNONTEXT(C1)");
  650. cf = evaluateCell(wb, cf);
  651. assertEquals(false, cf.getBooleanCellValue());
  652. cf.setCellFormula("ISNONTEXT(D1)");
  653. cf = evaluateCell(wb, cf);
  654. assertEquals(true, cf.getBooleanCellValue());
  655. cf.setCellFormula("ISNONTEXT(E1)");
  656. cf = evaluateCell(wb, cf);
  657. assertEquals(true, cf.getBooleanCellValue()); // Blank and Null the same
  658. // Next up, SEARCH on its own
  659. cf.setCellFormula("SEARCH(\"am\", A1)");
  660. cf = evaluateCell(wb, cf);
  661. assertEquals(FormulaError.VALUE.getCode(), cf.getErrorCellValue());
  662. cf.setCellFormula("SEARCH(\"am\", B1)");
  663. cf = evaluateCell(wb, cf);
  664. assertEquals(19, (int)cf.getNumericCellValue());
  665. cf.setCellFormula("SEARCH(\"am\", C1)");
  666. cf = evaluateCell(wb, cf);
  667. assertEquals(FormulaError.VALUE.getCode(), cf.getErrorCellValue());
  668. cf.setCellFormula("SEARCH(\"am\", D1)");
  669. cf = evaluateCell(wb, cf);
  670. assertEquals(FormulaError.VALUE.getCode(), cf.getErrorCellValue());
  671. // Finally, bring it all together
  672. cf.setCellFormula("ISNUMBER(SEARCH(\"am\", A1))");
  673. cf = evaluateCell(wb, cf);
  674. assertEquals(false, cf.getBooleanCellValue());
  675. cf.setCellFormula("ISNUMBER(SEARCH(\"am\", B1))");
  676. cf = evaluateCell(wb, cf);
  677. assertEquals(true, cf.getBooleanCellValue());
  678. cf.setCellFormula("ISNUMBER(SEARCH(\"am\", C1))");
  679. cf = evaluateCell(wb, cf);
  680. assertEquals(false, cf.getBooleanCellValue());
  681. cf.setCellFormula("ISNUMBER(SEARCH(\"am\", D1))");
  682. cf = evaluateCell(wb, cf);
  683. assertEquals(false, cf.getBooleanCellValue());
  684. cf.setCellFormula("ISNUMBER(SEARCH(\"am\", E1))");
  685. cf = evaluateCell(wb, cf);
  686. assertEquals(false, cf.getBooleanCellValue());
  687. wb.close();
  688. }
  689. private Cell evaluateCell(Workbook wb, Cell c) {
  690. Sheet s = c.getSheet();
  691. wb.getCreationHelper().createFormulaEvaluator().evaluateFormulaCell(c);
  692. return s.getRow(c.getRowIndex()).getCell(c.getColumnIndex());
  693. }
  694. /**
  695. * Should be able to write then read formulas with references
  696. * to cells in other files, eg '[refs/airport.xls]Sheet1'!$A$2
  697. * or 'http://192.168.1.2/[blank.xls]Sheet1'!$A$1 .
  698. * Additionally, if a reference to that file is provided, it should
  699. * be possible to evaluate them too
  700. * TODO Fix this to evaluate for XSSF
  701. * TODO Fix this to work at all for HSSF
  702. */
  703. @Ignore("Fix this to evaluate for XSSF, Fix this to work at all for HSSF")
  704. @Test
  705. public void bug46670() throws IOException {
  706. Workbook wb1 = _testDataProvider.createWorkbook();
  707. Sheet s = wb1.createSheet();
  708. Row r1 = s.createRow(0);
  709. // References to try
  710. String ext = _testDataProvider.getStandardFileNameExtension();
  711. String refLocal = "'[test."+ext+"]Sheet1'!$A$2";
  712. String refHttp = "'[http://example.com/test."+ext+"]Sheet1'!$A$2";
  713. String otherCellText = "In Another Workbook";
  714. // Create the references
  715. Cell c1 = r1.createCell(0, Cell.CELL_TYPE_FORMULA);
  716. c1.setCellFormula(refLocal);
  717. Cell c2 = r1.createCell(1, Cell.CELL_TYPE_FORMULA);
  718. c2.setCellFormula(refHttp);
  719. // Check they were set correctly
  720. assertEquals(refLocal, c1.getCellFormula());
  721. assertEquals(refHttp, c2.getCellFormula());
  722. // Reload, and ensure they were serialised and read correctly
  723. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  724. wb1.close();
  725. s = wb2.getSheetAt(0);
  726. r1 = s.getRow(0);
  727. c1 = r1.getCell(0);
  728. c2 = r1.getCell(1);
  729. assertEquals(refLocal, c1.getCellFormula());
  730. assertEquals(refHttp, c2.getCellFormula());
  731. // Try to evaluate, without giving a way to get at the other file
  732. try {
  733. evaluateCell(wb2, c1);
  734. fail("Shouldn't be able to evaluate without the other file");
  735. } catch (Exception e) {
  736. // expected here
  737. }
  738. try {
  739. evaluateCell(wb2, c2);
  740. fail("Shouldn't be able to evaluate without the other file");
  741. } catch (Exception e) {
  742. // expected here
  743. }
  744. // Set up references to the other file
  745. Workbook wb3 = _testDataProvider.createWorkbook();
  746. wb3.createSheet().createRow(1).createCell(0).setCellValue(otherCellText);
  747. Map<String,FormulaEvaluator> evaluators = new HashMap<String, FormulaEvaluator>();
  748. evaluators.put(refLocal, wb3.getCreationHelper().createFormulaEvaluator());
  749. evaluators.put(refHttp, wb3.getCreationHelper().createFormulaEvaluator());
  750. FormulaEvaluator evaluator = wb2.getCreationHelper().createFormulaEvaluator();
  751. evaluator.setupReferencedWorkbooks(evaluators);
  752. // Try to evaluate, with the other file
  753. evaluator.evaluateFormulaCell(c1);
  754. evaluator.evaluateFormulaCell(c2);
  755. assertEquals(otherCellText, c1.getStringCellValue());
  756. assertEquals(otherCellText, c2.getStringCellValue());
  757. wb3.close();
  758. wb2.close();
  759. }
  760. @Test
  761. public void test56574OverwriteExistingRow() throws IOException {
  762. Workbook wb = _testDataProvider.createWorkbook();
  763. Sheet sheet = wb.createSheet();
  764. { // create the Formula-Cell
  765. Row row = sheet.createRow(0);
  766. Cell cell = row.createCell(0);
  767. cell.setCellFormula("A2");
  768. }
  769. { // check that it is there now
  770. Row row = sheet.getRow(0);
  771. /* CTCell[] cArray = ((XSSFRow)row).getCTRow().getCArray();
  772. assertEquals(1, cArray.length);*/
  773. Cell cell = row.getCell(0);
  774. assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
  775. }
  776. { // overwrite the row
  777. Row row = sheet.createRow(0);
  778. assertNotNull(row);
  779. }
  780. { // creating a row in place of another should remove the existing data,
  781. // check that the cell is gone now
  782. Row row = sheet.getRow(0);
  783. /*CTCell[] cArray = ((XSSFRow)row).getCTRow().getCArray();
  784. assertEquals(0, cArray.length);*/
  785. Cell cell = row.getCell(0);
  786. assertNull(cell);
  787. }
  788. // the calculation chain in XSSF is empty in a newly created workbook, so we cannot check if it is correctly updated
  789. /*assertNull(((XSSFWorkbook)wb).getCalculationChain());
  790. assertNotNull(((XSSFWorkbook)wb).getCalculationChain().getCTCalcChain());
  791. assertNotNull(((XSSFWorkbook)wb).getCalculationChain().getCTCalcChain().getCArray());
  792. assertEquals(0, ((XSSFWorkbook)wb).getCalculationChain().getCTCalcChain().getCArray().length);*/
  793. wb.close();
  794. }
  795. /**
  796. * With HSSF, if you create a font, don't change it, and
  797. * create a 2nd, you really do get two fonts that you
  798. * can alter as and when you want.
  799. * With XSSF, that wasn't the case, but this verfies
  800. * that it now is again
  801. */
  802. @Test
  803. public void bug48718() throws IOException {
  804. Workbook wb = _testDataProvider.createWorkbook();
  805. int startingFonts = wb instanceof HSSFWorkbook ? 4 : 1;
  806. assertEquals(startingFonts, wb.getNumberOfFonts());
  807. // Get a font, and slightly change it
  808. Font a = wb.createFont();
  809. assertEquals(startingFonts+1, wb.getNumberOfFonts());
  810. a.setFontHeightInPoints((short)23);
  811. assertEquals(startingFonts+1, wb.getNumberOfFonts());
  812. // Get two more, unchanged
  813. /*Font b =*/ wb.createFont();
  814. assertEquals(startingFonts+2, wb.getNumberOfFonts());
  815. /*Font c =*/ wb.createFont();
  816. assertEquals(startingFonts+3, wb.getNumberOfFonts());
  817. wb.close();
  818. }
  819. @Test
  820. public void bug57430() throws IOException {
  821. Workbook wb = _testDataProvider.createWorkbook();
  822. wb.createSheet("Sheet1");
  823. Name name1 = wb.createName();
  824. name1.setNameName("FMLA");
  825. name1.setRefersToFormula("Sheet1!$B$3");
  826. wb.close();
  827. }
  828. @Test
  829. public void bug56981() throws IOException {
  830. Workbook wb = _testDataProvider.createWorkbook();
  831. CellStyle vertTop = wb.createCellStyle();
  832. vertTop.setVerticalAlignment(CellStyle.VERTICAL_TOP);
  833. CellStyle vertBottom = wb.createCellStyle();
  834. vertBottom.setVerticalAlignment(CellStyle.VERTICAL_BOTTOM);
  835. Sheet sheet = wb.createSheet("Sheet 1");
  836. Row row = sheet.createRow(0);
  837. Cell top = row.createCell(0);
  838. Cell bottom = row.createCell(1);
  839. top.setCellValue("Top");
  840. top.setCellStyle(vertTop); // comment this out to get all bottom-aligned
  841. // cells
  842. bottom.setCellValue("Bottom");
  843. bottom.setCellStyle(vertBottom);
  844. row.setHeightInPoints(85.75f); // make it obvious
  845. /*FileOutputStream out = new FileOutputStream("c:\\temp\\56981.xlsx");
  846. try {
  847. wb.write(out);
  848. } finally {
  849. out.close();
  850. }*/
  851. wb.close();
  852. }
  853. @Test
  854. public void test57973() throws IOException {
  855. Workbook wb = _testDataProvider.createWorkbook();
  856. CreationHelper factory = wb.getCreationHelper();
  857. Sheet sheet = wb.createSheet();
  858. Drawing drawing = sheet.createDrawingPatriarch();
  859. ClientAnchor anchor = factory.createClientAnchor();
  860. Cell cell0 = sheet.createRow(0).createCell(0);
  861. cell0.setCellValue("Cell0");
  862. Comment comment0 = drawing.createCellComment(anchor);
  863. RichTextString str0 = factory.createRichTextString("Hello, World1!");
  864. comment0.setString(str0);
  865. comment0.setAuthor("Apache POI");
  866. cell0.setCellComment(comment0);
  867. anchor = factory.createClientAnchor();
  868. anchor.setCol1(1);
  869. anchor.setCol2(1);
  870. anchor.setRow1(1);
  871. anchor.setRow2(1);
  872. Cell cell1 = sheet.createRow(3).createCell(5);
  873. cell1.setCellValue("F4");
  874. Comment comment1 = drawing.createCellComment(anchor);
  875. RichTextString str1 = factory.createRichTextString("Hello, World2!");
  876. comment1.setString(str1);
  877. comment1.setAuthor("Apache POI");
  878. cell1.setCellComment(comment1);
  879. Cell cell2 = sheet.createRow(2).createCell(2);
  880. cell2.setCellValue("C3");
  881. anchor = factory.createClientAnchor();
  882. anchor.setCol1(2);
  883. anchor.setCol2(2);
  884. anchor.setRow1(2);
  885. anchor.setRow2(2);
  886. Comment comment2 = drawing.createCellComment(anchor);
  887. RichTextString str2 = factory.createRichTextString("XSSF can set cell comments");
  888. //apply custom font to the text in the comment
  889. Font font = wb.createFont();
  890. font.setFontName("Arial");
  891. font.setFontHeightInPoints((short)14);
  892. font.setBoldweight(Font.BOLDWEIGHT_BOLD);
  893. font.setColor(IndexedColors.RED.getIndex());
  894. str2.applyFont(font);
  895. comment2.setString(str2);
  896. comment2.setAuthor("Apache POI");
  897. comment2.setColumn(2);
  898. comment2.setRow(2);
  899. wb.close();
  900. }
  901. /**
  902. * Ensures that XSSF and HSSF agree with each other,
  903. * and with the docs on when fetching the wrong
  904. * kind of value from a Formula cell
  905. */
  906. @Test
  907. public void bug47815() throws IOException {
  908. Workbook wb = _testDataProvider.createWorkbook();
  909. Sheet s = wb.createSheet();
  910. Row r = s.createRow(0);
  911. // Setup
  912. Cell cn = r.createCell(0, Cell.CELL_TYPE_NUMERIC);
  913. cn.setCellValue(1.2);
  914. Cell cs = r.createCell(1, Cell.CELL_TYPE_STRING);
  915. cs.setCellValue("Testing");
  916. Cell cfn = r.createCell(2, Cell.CELL_TYPE_FORMULA);
  917. cfn.setCellFormula("A1");
  918. Cell cfs = r.createCell(3, Cell.CELL_TYPE_FORMULA);
  919. cfs.setCellFormula("B1");
  920. FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
  921. assertEquals(Cell.CELL_TYPE_NUMERIC, fe.evaluate(cfn).getCellType());
  922. assertEquals(Cell.CELL_TYPE_STRING, fe.evaluate(cfs).getCellType());
  923. fe.evaluateFormulaCell(cfn);
  924. fe.evaluateFormulaCell(cfs);
  925. // Now test
  926. assertEquals(Cell.CELL_TYPE_NUMERIC, cn.getCellType());
  927. assertEquals(Cell.CELL_TYPE_STRING, cs.getCellType());
  928. assertEquals(Cell.CELL_TYPE_FORMULA, cfn.getCellType());
  929. assertEquals(Cell.CELL_TYPE_NUMERIC, cfn.getCachedFormulaResultType());
  930. assertEquals(Cell.CELL_TYPE_FORMULA, cfs.getCellType());
  931. assertEquals(Cell.CELL_TYPE_STRING, cfs.getCachedFormulaResultType());
  932. // Different ways of retrieving
  933. assertEquals(1.2, cn.getNumericCellValue(), 0);
  934. try {
  935. cn.getRichStringCellValue();
  936. fail();
  937. } catch(IllegalStateException e) {
  938. // expected here
  939. }
  940. assertEquals("Testing", cs.getStringCellValue());
  941. try {
  942. cs.getNumericCellValue();
  943. fail();
  944. } catch(IllegalStateException e) {
  945. // expected here
  946. }
  947. assertEquals(1.2, cfn.getNumericCellValue(), 0);
  948. try {
  949. cfn.getRichStringCellValue();
  950. fail();
  951. } catch(IllegalStateException e) {
  952. // expected here
  953. }
  954. assertEquals("Testing", cfs.getStringCellValue());
  955. try {
  956. cfs.getNumericCellValue();
  957. fail();
  958. } catch(IllegalStateException e) {
  959. // expected here
  960. }
  961. wb.close();
  962. }
  963. @Test
  964. public void test58113() throws IOException {
  965. Workbook wb = _testDataProvider.createWorkbook();
  966. Sheet sheet = wb.createSheet( "Test" );
  967. Row row = sheet.createRow(0);
  968. Cell cell = row.createCell(0);
  969. // verify that null-values can be set, this was possible up to 3.11, but broken in 3.12
  970. cell.setCellValue((String)null);
  971. String value = cell.getStringCellValue();
  972. assertTrue("HSSF will currently return empty string, XSSF/SXSSF will return null, but had: " + value,
  973. value == null || value.length() == 0);
  974. cell = row.createCell(1);
  975. // also verify that setting formulas to null works
  976. cell.setCellType(Cell.CELL_TYPE_FORMULA);
  977. cell.setCellValue((String)null);
  978. wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
  979. value = cell.getStringCellValue();
  980. assertTrue("HSSF will currently return empty string, XSSF/SXSSF will return null, but had: " + value,
  981. value == null || value.length() == 0);
  982. // set some value
  983. cell.setCellType(Cell.CELL_TYPE_STRING);
  984. cell.setCellValue("somevalue");
  985. value = cell.getStringCellValue();
  986. assertTrue("can set value afterwards: " + value,
  987. value.equals("somevalue"));
  988. // verify that the null-value is actually set even if there was some value in the cell before
  989. cell.setCellValue((String)null);
  990. value = cell.getStringCellValue();
  991. assertTrue("HSSF will currently return empty string, XSSF/SXSSF will return null, but had: " + value,
  992. value == null || value.length() == 0);
  993. wb.close();
  994. }
  995. /**
  996. * Formulas with Nested Ifs, or If with text functions like
  997. * Mid in it, can give #VALUE in Excel
  998. */
  999. @Test
  1000. public void bug55747() throws IOException {
  1001. Workbook wb1 = _testDataProvider.createWorkbook();
  1002. FormulaEvaluator ev = wb1.getCreationHelper().createFormulaEvaluator();
  1003. Sheet s = wb1.createSheet();
  1004. Row row = s.createRow(0);
  1005. row.createCell(0).setCellValue("abc");
  1006. row.createCell(1).setCellValue("");
  1007. row.createCell(2).setCellValue(3);
  1008. Cell cell = row.createCell(5);
  1009. cell.setCellFormula("IF(A1<>\"\",MID(A1,1,2),\" \")");
  1010. ev.evaluateAll();
  1011. assertEquals("ab", cell.getStringCellValue());
  1012. cell = row.createCell(6);
  1013. cell.setCellFormula("IF(B1<>\"\",MID(A1,1,2),\"empty\")");
  1014. ev.evaluateAll();
  1015. assertEquals("empty", cell.getStringCellValue());
  1016. cell = row.createCell(7);
  1017. cell.setCellFormula("IF(A1<>\"\",IF(C1<>\"\",MID(A1,1,2),\"c1\"),\"c2\")");
  1018. ev.evaluateAll();
  1019. assertEquals("ab", cell.getStringCellValue());
  1020. // Write it back out, and re-read
  1021. Workbook wb2 = _testDataProvider.writeOutAndReadBack(wb1);
  1022. wb1.close();
  1023. ev = wb2.getCreationHelper().createFormulaEvaluator();
  1024. s = wb2.getSheetAt(0);
  1025. row = s.getRow(0);
  1026. // Check read ok, and re-evaluate fine
  1027. cell = row.getCell(5);
  1028. assertEquals("ab", cell.getStringCellValue());
  1029. ev.evaluateFormulaCell(cell);
  1030. assertEquals("ab", cell.getStringCellValue());
  1031. cell = row.getCell(6);
  1032. assertEquals("empty", cell.getStringCellValue());
  1033. ev.evaluateFormulaCell(cell);
  1034. assertEquals("empty", cell.getStringCellValue());
  1035. cell = row.getCell(7);
  1036. assertEquals("ab", cell.getStringCellValue());
  1037. ev.evaluateFormulaCell(cell);
  1038. assertEquals("ab", cell.getStringCellValue());
  1039. wb2.close();
  1040. }
  1041. @Test
  1042. public void bug58260() throws IOException {
  1043. //Create workbook and worksheet
  1044. Workbook wb = _testDataProvider.createWorkbook();
  1045. //Sheet worksheet = wb.createSheet("sample");
  1046. //Loop through and add all values from array list
  1047. // use a fixed seed to always produce the same file which makes comparing stuff easier
  1048. //Random rnd = new Random(4352345);
  1049. int maxStyles = (wb instanceof HSSFWorkbook) ? 4009 : 64000;
  1050. for(int i = 0;i < maxStyles;i++) {
  1051. //Create new row
  1052. //Row row = worksheet.createRow(i);
  1053. //Create cell style
  1054. CellStyle style = null;
  1055. try {
  1056. style = wb.createCellStyle();
  1057. } catch (IllegalStateException e) {
  1058. fail("Failed for row " + i);
  1059. }
  1060. style.setAlignment(CellStyle.ALIGN_RIGHT);
  1061. if((wb instanceof HSSFWorkbook)) {
  1062. // there are some predefined styles
  1063. assertEquals(i+21, style.getIndex());
  1064. } else {
  1065. // getIndex() returns short, which is not sufficient for > 32767
  1066. // we should really change the API to be "int" for getIndex() but
  1067. // that needs API changes
  1068. assertEquals(i+1, style.getIndex() & 0xffff);
  1069. }
  1070. //Create cell
  1071. //Cell cell = row.createCell(0);
  1072. //Set cell style
  1073. //cell.setCellStyle(style);
  1074. //Set cell value
  1075. //cell.setCellValue("r" + rnd.nextInt());
  1076. }
  1077. // should fail if we try to add more now
  1078. try {
  1079. wb.createCellStyle();
  1080. fail("Should fail after " + maxStyles + " styles, but did not fail");
  1081. } catch (IllegalStateException e) {
  1082. // expected here
  1083. }
  1084. /*//add column width for appearance sake
  1085. worksheet.setColumnWidth(0, 5000);
  1086. // Write the output to a file
  1087. System.out.println("Writing...");
  1088. OutputStream fileOut = new FileOutputStream("C:\\temp\\58260." + _testDataProvider.getStandardFileNameExtension());
  1089. // the resulting file can be compressed nicely, so we need to disable the zip bomb detection here
  1090. double before = ZipSecureFile.getMinInflateRatio();
  1091. try {
  1092. ZipSecureFile.setMinInflateRatio(0.00001);
  1093. wb.write(fileOut);
  1094. } finally {
  1095. fileOut.close();
  1096. ZipSecureFile.setMinInflateRatio(before);
  1097. }*/
  1098. wb.close();
  1099. }
  1100. @Test
  1101. public void test50319() throws IOException {
  1102. Workbook wb = new HSSFWorkbook();
  1103. Sheet sheet = wb.createSheet("Test");
  1104. sheet.createRow(0);
  1105. sheet.groupRow(0, 0);
  1106. sheet.setRowGroupCollapsed(0, true);
  1107. sheet.groupColumn(0, 0);
  1108. sheet.setColumnGroupCollapsed(0, true);
  1109. wb.close();
  1110. }
  1111. @Ignore
  1112. @Test
  1113. public void test58648() throws IOException {
  1114. Workbook wb = _testDataProvider.createWorkbook();
  1115. Cell cell = wb.createSheet().createRow(0).createCell(0);
  1116. cell.setCellFormula("((1 + 1) )");
  1117. // fails with
  1118. // org.apache.poi.ss.formula.FormulaParseException: Parse error near char ... ')'
  1119. // in specified formula '((1 + 1) )'. Expected cell ref or constant literal
  1120. wb.close();
  1121. }
  1122. /**
  1123. * If someone sets a null string as a cell value, treat
  1124. * it as an empty cell, and avoid a NPE on auto-sizing
  1125. */
  1126. @Test
  1127. public void test57034() throws Exception {
  1128. Workbook wb = _testDataProvider.createWorkbook();
  1129. Sheet s = wb.createSheet();
  1130. Cell cell = s.createRow(0).createCell(0);
  1131. cell.setCellValue((String)null);
  1132. assertEquals(Cell.CELL_TYPE_BLANK, cell.getCellType());
  1133. _testDataProvider.trackAllColumnsForAutosizing(s);
  1134. s.autoSizeColumn(0);
  1135. assertEquals(2048, s.getColumnWidth(0));
  1136. s.autoSizeColumn(0, true);
  1137. assertEquals(2048, s.getColumnWidth(0));
  1138. wb.close();
  1139. }
  1140. @Test
  1141. public void test52684() throws IOException {
  1142. Workbook wb = _testDataProvider.createWorkbook();
  1143. Sheet sheet = wb.createSheet("test");
  1144. Row row = sheet.createRow(0);
  1145. Cell cell = row.createCell(0);
  1146. cell.setCellValue(12312345123L);
  1147. DataFormat format = wb.createDataFormat();
  1148. CellStyle style = wb.createCellStyle();
  1149. style.setDataFormat(format.getFormat("000-00000-000"));
  1150. cell.setCellStyle(style);
  1151. assertEquals("000-00000-000",
  1152. cell.getCellStyle().getDataFormatString());
  1153. assertEquals(164, cell.getCellStyle().getDataFormat());
  1154. DataFormatter formatter = new DataFormatter();
  1155. assertEquals("12-312-345-123", formatter.formatCellValue(cell));
  1156. wb.close();
  1157. }
  1158. @Test
  1159. public void test58896() throws IOException {
  1160. final int nrows = 160;
  1161. final int ncols = 139;
  1162. // Create a workbook
  1163. final Workbook wb = _testDataProvider.createWorkbook(nrows+1);
  1164. final Sheet sh = wb.createSheet();
  1165. if (logger.check(POILogger.DEBUG)) {
  1166. logger.log(POILogger.DEBUG, wb.getClass().getName() + " column autosizing timing...");
  1167. }
  1168. final long t0 = time();
  1169. _testDataProvider.trackAllColumnsForAutosizing(sh);
  1170. for (int r=0; r<nrows; r++) {
  1171. final Row row = sh.createRow(r);
  1172. for (int c=0; c<ncols; c++) {
  1173. final Cell cell = row.createCell(c);
  1174. cell.setCellValue("Cell[r="+r+",c="+c+"]");
  1175. }
  1176. }
  1177. final double populateSheetTime = delta(t0);
  1178. final double populateSheetTimePerCell_ns = (1000000 * populateSheetTime / (nrows*ncols));
  1179. if (logger.check(POILogger.DEBUG)) {
  1180. logger.log(POILogger.DEBUG, "Populate sheet time: " + populateSheetTime + " ms (" + populateSheetTimePerCell_ns + " ns/cell)");
  1181. logger.log(POILogger.DEBUG, "Autosizing...");
  1182. }
  1183. final long t1 = time();
  1184. for (int c=0; c<ncols; c++) {
  1185. final long t2 = time();
  1186. sh.autoSizeColumn(c);
  1187. if (logger.check(POILogger.DEBUG)) {
  1188. logger.log(POILogger.DEBUG, "Column " + c + " took " + delta(t2) + " ms");
  1189. }
  1190. }
  1191. final double autoSizeColumnsTime = delta(t1);
  1192. final double autoSizeColumnsTimePerColumn = autoSizeColumnsTime / ncols;
  1193. final double bestFitWidthTimePerCell_ns = 1000000 * autoSizeColumnsTime / (ncols * nrows);
  1194. if (logger.check(POILogger.DEBUG)) {
  1195. logger.log(POILogger.DEBUG, "Auto sizing columns took a total of " + autoSizeColumnsTime + " ms (" + autoSizeColumnsTimePerColumn + " ms per column)");
  1196. logger.log(POILogger.DEBUG, "Best fit width time per cell: " + bestFitWidthTimePerCell_ns + " ns");
  1197. }
  1198. final double totalTime_s = (populateSheetTime + autoSizeColumnsTime) / 1000;
  1199. if (logger.check(POILogger.DEBUG)) {
  1200. logger.log(POILogger.DEBUG, "Total time: " + totalTime_s + " s");
  1201. }
  1202. wb.close();
  1203. //if (bestFitWidthTimePerCell_ns > 50000) {
  1204. // fail("Best fit width time per cell exceeded 50000 ns: " + bestFitWidthTimePerCell_ns + " ns");
  1205. //}
  1206. //if (totalTime_s > 10) {
  1207. // fail("Total time exceeded 10 seconds: " + totalTime_s + " s");
  1208. //}
  1209. }
  1210. protected long time() {
  1211. return System.currentTimeMillis();
  1212. }
  1213. protected double delta(long startTimeMillis) {
  1214. return time() - startTimeMillis;
  1215. }
  1216. @Ignore("bug 59393")
  1217. @Test
  1218. public void bug59393_commentsCanHaveSameAnchor() throws IOException
  1219. {
  1220. Workbook wb = _testDataProvider.createWorkbook();
  1221. Sheet sheet = wb.createSheet();
  1222. CreationHelper helper = wb.getCreationHelper();
  1223. ClientAnchor anchor = helper.createClientAnchor();
  1224. Drawing drawing = sheet.createDrawingPatriarch();
  1225. Row row = sheet.createRow(0);
  1226. Cell cell1 = row.createCell(0);
  1227. Cell cell2 = row.createCell(1);
  1228. Cell cell3 = row.createCell(2);
  1229. Comment comment1 = drawing.createCellComment(anchor);
  1230. RichTextString richTextString1 = helper.createRichTextString("comment1");
  1231. comment1.setString(richTextString1);
  1232. cell1.setCellComment(comment1);
  1233. // fails with IllegalArgumentException("Multiple cell comments in one cell are not allowed, cell: A1")
  1234. // because createCellComment tries to create a cell at A1
  1235. // (from CellAddress(anchor.getRow1(), anchor.getCell1())),
  1236. // but cell A1 already has a comment (comment1).
  1237. // Need to atomically create a comment and attach it to a cell.
  1238. // Current workaround: change anchor between each usage
  1239. // anchor.setCol1(1);
  1240. Comment comment2 = drawing.createCellComment(anchor);
  1241. RichTextString richTextString2 = helper.createRichTextString("comment2");
  1242. comment2.setString(richTextString2);
  1243. cell2.setCellComment(comment2);
  1244. // anchor.setCol1(2);
  1245. Comment comment3 = drawing.createCellComment(anchor);
  1246. RichTextString richTextString3 = helper.createRichTextString("comment3");
  1247. comment3.setString(richTextString3);
  1248. cell3.setCellComment(comment3);
  1249. wb.close();
  1250. }
  1251. @Test
  1252. public void bug57798() throws Exception {
  1253. String fileName = "57798." + _testDataProvider.getStandardFileNameExtension();
  1254. Workbook workbook = _testDataProvider.openSampleWorkbook(fileName);
  1255. Sheet sheet = workbook.getSheet("Sheet1");
  1256. // *******************************
  1257. // First cell of array formula, OK
  1258. int rowId = 0;
  1259. int cellId = 1;
  1260. System.out.println("Reading row " + rowId + ", col " + cellId);
  1261. Row row = sheet.getRow(rowId);
  1262. Cell cell = row.getCell(cellId);
  1263. System.out.println("Formula:" + cell.getCellFormula());
  1264. if (Cell.CELL_TYPE_FORMULA == cell.getCellType()) {
  1265. int formulaResultType = cell.getCachedFormulaResultType();
  1266. System.out.println("Formual Result Type:" + formulaResultType);
  1267. }
  1268. // *******************************
  1269. // Second cell of array formula, NOT OK for xlsx files
  1270. rowId = 1;
  1271. cellId = 1;
  1272. System.out.println("Reading row " + rowId + ", col " + cellId);
  1273. row = sheet.getRow(rowId);
  1274. cell = row.getCell(cellId);
  1275. System.out.println("Formula:" + cell.getCellFormula());
  1276. if (Cell.CELL_TYPE_FORMULA == cell.getCellType()) {
  1277. int formulaResultType = cell.getCachedFormulaResultType();
  1278. System.out.println("Formual Result Type:" + formulaResultType);
  1279. }
  1280. workbook.close();
  1281. }
  1282. }