Vaadin Spreadsheet: setRowHeight not possible for row index higher than 199

Hello,

I am trying to generate a spreadsheet with potentially multiple sheets each containing 200+ rows (using Java with Vaadin Spreadsheets - 2.1.0).

The approach I am currently using is to set the row height for each row to the desired value, using the method “setRowHeight”. A simplification of the code I’m executing is attached below:

    	final Spreadsheet spreadSheet = new Spreadsheet();
    	spreadSheet.setSheetName(0, "Sheet 1");
    	
    	spreadSheet.createCell(0, 0, "Header");
    	for (int i=1; i<201; i++) {
    		spreadSheet.createCell(i, 0, Integer.toString(i));
    		spreadSheet.setRowHeight(i, (i % 2 == 0) ? 20 : 30);
    	}
    	
    	try {
			spreadSheet.write("C:\\SomeDirectory\\testFile.xlsx");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("File not found exception");
			e.printStackTrace();			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("I/O Exception");
			e.printStackTrace();
		}

The logic works well for any number of rows under 200. However, as soon as I attempt to set the rowHeight for the 200th row (or further), I get an out-of-bounds exception. The stack is as follows:

SEVERE: 
java.lang.ArrayIndexOutOfBoundsException: Index 200 out of bounds for length 200
	at com.vaadin.addon.spreadsheet.Spreadsheet.setRowHeight(Spreadsheet.java:3130)
	at com.example.myHelloWorld.MyUI.testButtonClick(MyUI.java:61)
	at com.example.myHelloWorld.MyUI.lambda$0(MyUI.java:47)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012)
	at java.base/com.zeroturnaround.jrebelbase.facade.Forward.b(SourceFile:287)
	at java.base/com.zeroturnaround.jrebelbase.facade.Forward.a(SourceFile:279)
	at java.base/com.zeroturnaround.jrebelbase.facade.Forward.methodInvoke(SourceFile:260)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:499)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:273)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:237)
	at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1014)
	at com.vaadin.ui.Button.fireClick(Button.java:384)
	at com.vaadin.ui.Button$1.click(Button.java:57)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012)
	at java.base/com.zeroturnaround.jrebelbase.facade.Forward.b(SourceFile:287)
	at java.base/com.zeroturnaround.jrebelbase.facade.Forward.a(SourceFile:279)
	at java.base/com.zeroturnaround.jrebelbase.facade.Forward.methodInvoke(SourceFile:260)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:445)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:410)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1602)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:448)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at jdk.internal.reflect.GeneratedMethodAccessor46.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:830)

After a bit of debugging, I found the problem to be with the array-field “rowH”, located within the SpreadsheetState (Spreadsheet.getState()). This array is initialized by default for the first sheet with 200 entries (default row count), but is never resized, even in the case that a 201st or higher row is added.

The only way I was able to workaround this was limitation of “200” was by re-creating the first/default sheet within the spreadsheet (i.e. createNewSheet(“Sheet 1”, someRowCount, someColumnCount) and deleteSheet(0)) with the number of rows that would be assigned to it. This however requires knowledge of the number of rows in advance, and this is not always given.

Is there a cleaner way to achieve setting row heights for individual rows i.e. without having to know the rowCount in advance?

Thanks in advance and Best Regards!