Bug 49312 - HSSFSheet - RuntimeException: Unexpected missing row
Summary: HSSFSheet - RuntimeException: Unexpected missing row
Status: RESOLVED DUPLICATE of bug 47245
Alias: None
Product: POI
Classification: Unclassified
Component: HSSF (show other bugs)
Version: 3.8-dev
Hardware: PC Windows Vista
: P1 normal (vote)
Target Milestone: ---
Assignee: POI Developers List
Depends on: 47245
  Show dependency tree
Reported: 2010-05-19 05:30 UTC by Kamil [Camillo] Soltys
Modified: 2012-10-11 10:25 UTC (History)
3 users (show)

Test File with RuntimeException: Unexpected missing row (5.50 KB, application/vnd.ms-excel)
2010-05-19 05:30 UTC, Kamil [Camillo] Soltys

Note You need to log in before you can comment on or make changes to this bug.
Description Kamil [Camillo] Soltys 2010-05-19 05:30:33 UTC
Created attachment 25455 [details]
Test File with RuntimeException: Unexpected missing row

+++ This bug was initially created as a clone of Bug #47245 +++

I have the same Problem:

java.lang.RuntimeException: Unexpected missing row when some rows already present
	at org.apache.poi.hssf.usermodel.HSSFSheet.setPropertiesFromSheet(HSSFSheet.java:170)
	at org.apache.poi.hssf.usermodel.HSSFSheet.<init>(HSSFSheet.java:117)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:288)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:201)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:317)
	at de.infomotion.excelConverter.ConverterFactory.getConverter(ConverterFactory.java:49)
	at de.infomotion.excelConverter.ConverterFactory.getConverter(ConverterFactory.java:27)
	at de.infomotion.excelConverter.Main.main(Main.java:22)

I trayed to switch back to POI3.5-FINAL, but has same issue.

Opening and Saving in MSExcel corrects the Problem. The resaved (corrected?) file is about 25% smaller like before.

To more specifie the Situation: this XLS-File is generated from BusinessObjects Enterprise 3.1 and i should automaticaly postprocess/clean the generated files.


Many Thanks
Comment 1 Kamil [Camillo] Soltys 2010-05-19 05:34:29 UTC
After resaving in MSExcel of this sample file was the size greater... whatever - the size is not the same like before, but file can be after that with POI processsed.
Comment 2 Nick Burch 2010-05-19 05:44:06 UTC
You should probably open a bug with the people who make your spreadsheet
writing software. It's putting non row records into the middle of the bit where
the row records should live

If you want to produce a workaround, you'll need to use hssf.dev.BiffViewer to
figure out what those records are that are in the wrong place, then produce a
patch to poi to have it handle them coming where they're not supposed to be
Comment 3 Kamil [Camillo] Soltys 2010-05-19 13:42:51 UTC
Thank you for response. 

It ist possible to configure or learn POI to ignore that non-row-records without patching of POI?

Comment 4 Nick Burch 2010-05-19 13:46:52 UTC
Code changes will be needed. If you do come up with a patch, please do share it!
Comment 5 Kamil [Camillo] Soltys 2010-05-20 03:15:25 UTC
I have tonight analysed the File with BiffViewer.
If 'm I right so:
- the count of RowRecords in Sheet is 7 (index 6)
- at end of CellValues are 4 that are pointed at RowRecord 8 (index 7) and throws RuntimeException

Like you said - it is not POI Problem but SAP Businessobject. The Fullclient reporting engine that generates Excel output is bugy. It is not supported by SAP anymore. 
The Webi reporting engine generates clean XLS and cann be opened by POI.

I have fixed it by commenting im HSSFSheet at row 170 this RuntimeException out, so that the missing RowRecord for CellValue will be created.

I think it is NOT clean, but in our Case of postprocessing the Excel output form SAP Businessobjects Fullclient Reports does it.

POI rocks!
Comment 6 mouss4rs 2012-03-07 10:40:30 UTC
mee too.
I have this error:
Exception in thread "main" java.lang.RuntimeException: Unexpected missing row when some rows already present
	at org.apache.poi.hssf.usermodel.HSSFSheet.setPropertiesFromSheet(HSSFSheet.java:168)
	at org.apache.poi.hssf.usermodel.HSSFSheet.<init>(HSSFSheet.java:115)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:299)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:250)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:194)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:329)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:310)
	at Extraction.main(Extraction.java:93)

line cause:
wbd = new HSSFWorkbook(istr);

I have 2 HSSFWorkbook:
wb, wbd.

Here is my code:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.Collator;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import Modele.Agent;

public class Extraction {
	public static void main(String[] args) throws ParseException {
		String fichierExtract = "C:/Donnees/Aide_Manager/extract_25012012.xls";
		String fichierProjection = "C:/Donnees/Aide_Manager/Projection_2012_Eq2.xlsx";
		InputStream is, istr,ist;
		HSSFWorkbook wb, wbd;
		HSSFSheet sheet, sheetd;
		HSSFRow row, rowd;
		HSSFCell cell, celld;
		String onglet;
		String semaine_en_string;
		int n_l_valid = 0; // pour récupérer la ligne de chaque validation
		int valid = 0; // pour récupérer le nombre de validation
		HSSFCell valid_recupere = null;// pour récupérer les valeurs des validations
		java.util.Date datextract;
		DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
		String date_extract;
		Calendar calendar = Calendar.getInstance();
		int validation_ancienne, validation_nouvelle;
		ArrayList<Agent> listAgent = new ArrayList<Agent>();
		String prenom_agent = null; //pour récupérer les Agents
		String ag;
		int va;
		String sub;
		int isub;
		String tab[][] = new String [100][100];
		int tabvalidation[][] = new int [100][100];
		int onglet_conv;
		int semaine = 0;
		try {
			is = new FileInputStream(fichierExtract);
			//POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("extract.xls")); //pour ouvrir les fichiers xls
			wb = new HSSFWorkbook(is);
			sheet = wb.getSheetAt(0);
			row = null;
			cell = null;
			int n = 0;
			//int i = 0;//compte le nombre d'agent
			for (Iterator rowIt = sheet.rowIterator(); rowIt.hasNext();){
				row = (HSSFRow) rowIt.next();
				Agent a = new Agent();
				n++;// pour avoir le numéro de chaque ligne lue
				if(row.getRowNum() == 6 && row.getCell(0) != null){//pour obtenir la date de l'extract et déterminer sa semaine dans l'année.
					date_extract = row.getCell(0).getStringCellValue().substring(3,13);//on récupère la date
					System.out.println("date_extract: "+date_extract);
					//faire une vérification pour savoir:
					//si la date du fichier n'est pas trouvée sur
					istr = new FileInputStream("C:/Donnees/Aide_Manager/date_extract1.xls");
					//ce fichier permettra de récupérer les dates pour savoir si un extract à déjà été utilisé.
					wbd = new HSSFWorkbook(istr);
					sheetd = wbd.getSheetAt(0);
					rowd = null;
					celld = null;
					boolean date_stockee_trouvee = false;
					int dernLigneTrouvee = 0;
					for (Iterator r = sheetd.rowIterator(); r.hasNext();){
						rowd = (HSSFRow) r.next();
						celld = rowd.getCell(0);
						if(celld != null ){
							System.out.println("c'est un nombre: "+celld.getNumericCellValue());
								System.out.println("c'est une chaine: "+celld.getStringCellValue());
								if(celld.getStringCellValue().equals(date_extract)){// si on trouve que la date_extract est = à la date trouvée dans le fichier
									System.out.println("DATE TROUVEE Ds le fichier !");
									System.out.println("CETTE EXTRACT A DEJA ETE UTILISEE !!");
							dernLigneTrouvee = rowd.getCell(0).getRowIndex();
					System.out.println("dernLigneTrouvee: "+dernLigneTrouvee);
					//si la date n'est pas trouvée dans le fichier
					System.out.println("date_stockee_trouvee: "+date_stockee_trouvee);
						//retrouver la dernière ligne du fichier pour y ecrire la date
							System.out.println("retrouver la dernière ligne du fichier: "+dernLigneTrouvee);
							//pour crée la date ds le fichier 
							//et pour la retrouver et eviter de rajouter la validation d'un extract comportant la même date
							celld = rowd.createCell(0);
						    System.out.println("La nouvelle date_extract '"+date_extract+"' a été stocké dans le fichier.");
						    //pour ecrire dans le même fichier
							FileOutputStream fileOutd = new FileOutputStream("C:/Donnees/Aide_Manager/date_extract1.xls");
					// Date actuelle
					datextract = formatter.parse(date_extract);
					semaine = calendar.get(Calendar.WEEK_OF_YEAR);//récupérer la semaine dans l'année pour faire la comparaison avec les onglet du fichier de destination
				if(row.getCell(0) != null && row.getCell(0).getStringCellValue().startsWith("Agent")){//si les lignes de la colonne 0 ne sont pas null
					prenom_agent=row.getCell(0).getStringCellValue();//on récupère notre agent
				    //isub = nom_agent.indexOf(",");
				    sub = prenom_agent.substring(prenom_agent.indexOf(",")+1).trim();//récupérer la chaine après la virgule, après l'espace mais sans l'espace à la fin
				    a.setAgent(sub);//on récupère notre agent dans notre objet
					//System.out.println(a.getAgent()); //on l'affiche
				if(row.getCell(1) != null && row.getCell(1).getStringCellValue().startsWith("Validation")){// si les lignes de la colonne 2 ne sont pas null
						valid++; //Nombre de validation détecter dans le fichier
						n_l_valid = n; // on récupère le numéro de ligne de la Validation
						n_l_valid--;//on décrémente pour récupérer la validation dans le fichier
						//valid_recupere=sheet.getRow(n_l_valid).getCell(4);// on récupére la validation dans le fichier
						//System.out.println("Validation: "+valid_recupere);//on l'affiche
						a.setValidation((int)sheet.getRow(n_l_valid).getCell(4).getNumericCellValue());//on récupère notre agent dans notre objet sous forme d'entier
						System.out.println("validation: "+a.getValidation());//on l'affiche
			}//fin du for
			/*for (Agent agt : listAgent){
					System.out.println("agent: "+agt.getAgent()+"--validation: "+agt.getValidation());
			int k = 0;//pour passer à la colonne suivante
			for (Agent agt : listAgent){
				if(agt.getAgent()!=null){//si l'agent n'est pas null
					ag=agt.getAgent().toUpperCase();//obtenir L'agent
					//System.out.println("k: "+k);
				if(agt.getValidation()!=0){//si la validation n'est pas null
					va=agt.getValidation();//obtenir la validation
					tabvalidation[1][k]=va;//assigner les 2 valeurs trouvées
					k++;//passe à la colonne suivante
			/*for (int d=0; d<tab.length;d++){
			if(tab[0][d] != null || tab[1][d]!=null){//si l'une des cellules n'est pas null
				//afficher l'agent + la validation
				System.out.println("Agent: "+tab[0][d]+" Validation: "+tab[1][d]);
				int nbfeuille=0;
				int ligne_trouvee;
				//version .xls
				/*InputStream ist = new FileInputStream("C:/Users/LZ2059/Desktop/Projection_2012_Eq2.xls"); //pour ouvrir les fichiers xls de 2007
				HSSFWorkbook wb2 = new HSSFWorkbook(ist);
				HSSFSheet sheet2 = wb2.getSheetAt(0);
				nbfeuille= wb2.getNumberOfSheets();//retourne le nombre de feuille renseigné
				HSSFRow row2 = null;
				HSSFCell cell2 = null;
				HSSFCellStyle cellStyle = null;*/
				//version .xlsx
				ist = new FileInputStream(fichierProjection);
				OPCPackage opc=OPCPackage.open(ist);//version .xlsx
			    XSSFWorkbook wb2= new XSSFWorkbook(opc); 
				XSSFSheet sheet2 = wb2.getSheetAt(0);//onglet 0
				nbfeuille= wb2.getNumberOfSheets();//retourne le nombre de feuille renseigné
				XSSFRow row2 = null;
				XSSFCell cell2 = null;
				XSSFCellStyle cellStyle = null;
				XSSFDataFormat fmt = wb2.createDataFormat(); //version .xlsx
				//pour ouvrir un .xlsx
			    FormulaEvaluator evaluator = wb2.getCreationHelper().createFormulaEvaluator();
				String prenom_proj;
				Collator usCollator;
				System.out.println("wb2.getNumberOfNames(): "+nbfeuille);
				// il faut définir la feuille qui sera alimenté:
				//Parcourir les feuilles du document
				//si la semaine correspond au libellé d'une feuille
				for (int g=0; g<nbfeuille; g++){//boucle de parcours des onglets
					sheet2 = wb2.getSheetAt(g);
					onglet=sheet2.getSheetName();// on récupère le nom de la feuille excel en String
					if(onglet.startsWith("S")){//si ca commence par "S"
						//on enleve le "S"
						// on converti le nom de l'onglet en Int
						onglet_conv = Integer.parseInt(semaine_en_string);
						System.out.println("onglet: "+onglet_conv);
						if(onglet_conv == semaine){//si la semaine de l'onglet du doc "extract.xls"
													//correspond à la semaine de l'année trouver dans le fichier "Projection_2012_Eq2.xls"
							System.out.println("onglet de la semaine "+onglet_conv+" TROUVEE !");
							for (Iterator it = sheet2.rowIterator(); it.hasNext();){//boucle de parcours du fichier de ligne en ligne
								row2 = (XSSFRow) it.next();
								if(row2.getCell(0)!= null && row2.getRowNum() <= 19){// si la ligne est différent de null et inférieur ou égale à la 20ème ligne
									if(!row2.getCell(0).getStringCellValue().equals("Noms") && !row2.getCell(0).getStringCellValue().equals("EQUIPE") && !row2.getCell(0).getStringCellValue().equals("")){
										//on récupère le 1er prénom du fichier Projection
										for (int d=0; d<tab.length;d++){
											if(tab[0][d] != null || tab[1][d]!=null){//si l'une des cellules n'est pas null
												//System.out.println("prénom: "+prenom_proj);
												//Get the Collator for US English and set its strength to PRIMARY
												 usCollator = Collator.getInstance(Locale.FRANCE);
												 if( usCollator.compare(prenom_proj, tab[0][d]) == 0 ){//si le prénom trouvé dans le fichier 'Projection_2012_Eq2.xlsx' correspond au prenom de l'extract Hermes
												     //System.out.println("Strings are equivalent");
												     System.out.println("Agent: "+tab[0][d]+" Validation: "+tabvalidation[1][d]);
												     //on récupère la ligne du prénom
												     ligne_trouvee= row2.getCell(0).getRowIndex();
												     ligne_trouvee++;//pour écrire dans la bonne ligne
												     //System.out.println("ligne TROUVEE: "+ligne_trouvee);
												     //on récupère la valeur si présente pour l'additionner
												     cell2 = row2.getCell(8);// colonne(I)
												     //on additionne
												     	//on écrit dans la colonne I la validation du prénom trouvé
												     	//cell2 = row2.getCell(8);// colonne(I)
													 	cell2 = row2.createCell(8);
													    System.out.println("Nouvelle valeur écrite"+validation_nouvelle);
													    //on ré-écrit la formule pour la colonne J
													    cell2 = row2.getCell(9);// colonne(J)
													 	cell2 = row2.createCell(9);
													 	//System.out.println("Formule: I"+ligne_trouvee+"/B"+ligne_trouvee);
													 	//arrondir à 2 chiffre après la virgule
													    cellStyle = wb2.createCellStyle();
													    //cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));//version .xls
													 	//on ré-écrit la formule pour la colonne K
													    cell2 = row2.getCell(10);// colonne(K)
													 	cell2 = row2.createCell(10);
													 	//arrondir à 2 chiffre après la virgule
													    cellStyle = wb2.createCellStyle();
													 	//on ré-écrit la formule pour la colonne L
													    cell2 = row2.getCell(11);// colonne(L)
													 	cell2 = row2.createCell(11);
													 	//System.out.println("Formule: J"+ligne_trouvee+"*7");
													 	//arrondir à 2 chiffre après la virgule
													    cellStyle = wb2.createCellStyle();

													 	ligne_trouvee--;//pour retrouver ma ligne
							//on réécrit la formule du total colonne I en se fixant à la ligne de total des equipe (20)
						    cell2 = row2.createCell(8);
						    String colonneI = "I3:I20";
						    //format EQUIPE de la colonne I
						    cellStyle = wb2.createCellStyle();
						    cellStyle.setDataFormat(fmt.getFormat("#,##0"));//format 1 000 par ex.
						    System.out.println("Total Validation refait");
						    //on réécrit la formule du total colonne J
							//System.out.println("on doit se fixer à la ligne 20: "+row2.getRowNum());
						    cell2 = row2.createCell(9);//colonne J
						    String resultatParH = "SUM(I3:I20)/SUM(B3:B20)";
						    //arrondir à 2 chiffre après la virgule
						    cellStyle = wb2.createCellStyle();
						    //on réécrit la formule du total colonne K
							//System.out.println("on doit se fixer à la ligne 20: "+row2.getRowNum());
						    cell2 = row2.createCell(10);//colonne K
						    String txtransfo = "(SUM(I3:I20)/SUM(C3:C20))/100";//j'ai rajouté /100 pour prendre en compte le % dans l'ecriture du format
						    //arrondir à 2 chiffre après la virgule
						    cellStyle = wb2.createCellStyle();
						    //on réécrit la formule du total colonne L
							//System.out.println("on doit se fixer à la ligne 20: "+row2.getRowNum());
						    cell2 = row2.createCell(11);//colonne L
						    String resultatetp = "J21*7";
						    //arrondir à 2 chiffre après la virgule
						    cellStyle = wb2.createCellStyle();
				//pour ecrire dans le même fichier
				FileOutputStream fileOut = new FileOutputStream("C:/Donnees/Aide_Manager/Projection_2012_Eq2.xlsx");
		} catch (FileNotFoundException e){
		} catch (IOException e) {
		} catch (InvalidFormatException e) {
			// TODO Auto-generated catch block
	/*public void ecrireDansFichier(String monfichierdedestination, String Tableau[][]){
		InputStream inp;
		try {
			inp = new FileInputStream("workbook.xls");//à remplacer par monfichierdedestination

	    Workbook wb;
		try {
			wb = WorkbookFactory.create(inp);
	    Sheet sheet = wb.getSheet("test");//onglet 0
	    Row row = sheet.getRow(3);//en fonction des personnes
	    Cell cell = row.getCell(8);//colonne 8 (I)
	    if (cell == null)
	        cell = row.createCell(8);//ecrire à la colonne 8
	    cell.setCellValue("j'écrit dans la feuille 'test'");

	    // Write the output to a file
	    FileOutputStream fileOut = new FileOutputStream("workbook.xls");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
		} catch (InvalidFormatException e) {
			// TODO Auto-generated catch block
		} catch (IOException e) {
			// TODO Auto-generated catch block
Comment 7 Yegor Kozlov 2012-03-20 11:11:06 UTC
Please attach the input file, without it  we cannot ru your code to reproduce the problem.


(In reply to comment #6)
> mee too.
> I have this error:
> Exception in thread "main" java.lang.RuntimeException: Unexpected missing row
> when some rows already present
>     at
Comment 8 Sime Essert 2012-04-12 14:06:00 UTC
I have added one problematic file on https://issues.apache.org/bugzilla/show_bug.cgi?id=47245
Comment 9 Triqui 2012-10-11 10:25:24 UTC
This looks like an exact duplicate of bug 47245.

(I've added some comments there)

Please, correct me if I'm wrong.

*** This bug has been marked as a duplicate of bug 47245 ***