Bug 37101

Summary: Save sheets with comments cannot be reopened (in Excel or HSSF)
Product: POI Reporter: Bill Seddon <bill.seddon>
Component: HSSFAssignee: POI Developers List <dev>
Severity: major    
Priority: P2    
Version: 3.0-dev   
Target Milestone: ---   
Hardware: All   
OS: Linux   

Description Bill Seddon 2005-10-16 14:14:28 UTC
If you open an .xls containing cell comments and save it using 
HSSFWorkbook.write() the resulting document will not open successfully using 
either Excel or Poi.  The problem is manifested in the serialize() method of 
class TextObjectRecord.  The serialize() method only outputs a string if there 
is one to export.  Even though one is read in (and the field length and format 
properties indicate there is a string) the serialize() method sees an empty 
string.  However the cause of the problem is not in serialize() but in the 
class constructor.

The class has a variable, 'str', that is initialised *and* is set by the 
virtual method fillFields().  The problem arises because fillFields is called 
in the constructor.  Java seems to run the constructor code (and super()) THEN 
initialise class variables.  The effect is that no matter what value the str 
variable is assigned when fillFields() is called by the constructor, the value 
it has when the constructor is complete is the value it is assigned when the 
variable is initialised in the class (ie and empty string).

The solution is to assign a default value to variable 'str' in the constructor 
before calling super() rather than initialize it.

Here are a couple of very short classes that show the same effect.  In these 
examples, MethodToOverride() is the equivalent of fillFields().  It is called 
form the parent constructor just as fillFields() is called by the Record() 
constructor (which is the ultimate parent of TextObjectRecord.

In this example, the end value of the class variable is BBB not the XXX set 
MethodToOverride().  This shows that Java initialises class variable after 
completing the constructor.

public abstract class ABaseClass
	public ABaseClass()
	protected abstract void MethodToOverride();

public class DerivedClass extends ABaseClass
	public String SomeDerivedString = "BBB";

	public DerivedClass() 

	protected void MethodToOverride()
		System.out.println( "Overridden method before'" + 
SomeDerivedString + "'");
		SomeDerivedString = "XXX";
		SomeDerivedInt = 99;
		System.out.println( "Overridden method after '" + 
SomeDerivedString + "'");

	public static void main(String [] args)
		DerivedClass d = new DerivedClass();
		System.out.println( d.SomeDerivedString );
Comment 1 Bill Seddon 2005-10-16 14:20:08 UTC
OK, you can't as I suggest initialise str before calling super(in) because 
that not legal syntax.  So the following line should be called after the call 
to super(in).

if (str == null) str = new HSSFRichTextString( "" );


str = new HSSFRichTextString( "" );

should appear in the default constructor.
Comment 2 Trejkaz (pen name) 2007-02-19 16:28:04 UTC
Is this a dupe of Bug 36947?
Comment 3 Yegor Kozlov 2008-05-17 05:54:54 UTC
Could you please try poi-3.1-beta1 and report if the problem still persists? 

Comment 4 Nick Burch 2011-02-25 17:00:15 UTC
I believe this was fixed some time ago, please re-open if the problem still occurs with poi 3.8 beta 1