Browse Source

Merge pull request #79 from shibukawa/fix/not_omit_empty_rows_and_cols

Fix for #78 (it doesn't omit empty rows and cols)
Geoffrey J. Teale 11 years ago
parent
commit
e108f62d99
4 changed files with 113 additions and 9 deletions
  1. 18 0
      file_test.go
  2. 19 7
      lib.go
  3. 76 2
      lib_test.go
  4. BIN
      testdocs/empty_rows.xlsx

+ 18 - 0
file_test.go

@@ -764,3 +764,21 @@ func (l *FileSuite) TestReadWorkbookWithTypes(c *C) {
 	c.Assert(sheet.Rows[7].Cells[0].Formula(), Equals, "10/0")
 	c.Assert(sheet.Rows[7].Cells[0].Value, Equals, "#DIV/0!")
 }
+
+func (s *SliceReaderSuite) TestFileWithEmptyRows(c *C) {
+	f, err := OpenFile("./testdocs/empty_rows.xlsx")
+	c.Assert(err, IsNil)
+	sheet, ok := f.Sheet["EmptyRows"]
+	c.Assert(ok, Equals, true)
+	c.Assert(sheet.Cell(0, 0).String(), Equals, "")
+	c.Assert(sheet.Cell(2, 0).String(), Equals, "A3")
+}
+
+func (s *SliceReaderSuite) TestFileWithEmptyCols(c *C) {
+  f, err := OpenFile("./testdocs/empty_rows.xlsx")
+  c.Assert(err, IsNil)
+  sheet, ok := f.Sheet["EmptyCols"]
+  c.Assert(ok, Equals, true)
+  c.Assert(sheet.Cell(0, 0).String(), Equals, "")
+  c.Assert(sheet.Cell(0, 2).String(), Equals, "C1")
+}

+ 19 - 7
lib.go

@@ -305,6 +305,12 @@ func makeRowFromRaw(rawrow xlsxRow) *Row {
 	return row
 }
 
+func makeEmptyRow() *Row {
+	row := new(Row)
+	row.Cells = make([]*Cell, 0)
+	return row
+}
+
 // fillCellData attempts to extract a valid value, usable in
 // CSV form from the raw cell value.  Note - this is not actually
 // general enough - we should support retaining tabs and newlines.
@@ -367,8 +373,8 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File) ([]*Row, []*Col, in
 	if err != nil {
 		panic(err.Error())
 	}
-	rowCount = (maxRow - minRow) + 1
-	colCount = (maxCol - minCol) + 1
+	rowCount = maxRow + 1
+	colCount = maxCol + 1
 	rows = make([]*Row, rowCount)
 	cols = make([]*Col, colCount)
 	insertRowIndex = minRow
@@ -389,17 +395,23 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File) ([]*Row, []*Col, in
 			cols[i-1] = &Col{
 				Min:    rawcol.Min,
 				Max:    rawcol.Max,
-				Hidden: rawcol.Hidden}
+				Hidden: rawcol.Hidden,
+				Width:  rawcol.Width}
 		}
 	}
 
+	// insert leading empty rows that is in front of minRow
+	for rowIndex := 0; rowIndex < minRow; rowIndex++ {
+		rows[rowIndex] = makeEmptyRow()
+	}
+
 	for rowIndex := 0; rowIndex < len(Worksheet.SheetData.Row); rowIndex++ {
 		rawrow := Worksheet.SheetData.Row[rowIndex]
 		// Some spreadsheets will omit blank rows from the
 		// stored data
 		for rawrow.R > (insertRowIndex + 1) {
 			// Put an empty Row into the array
-			rows[insertRowIndex-minRow] = new(Row)
+			rows[insertRowIndex-minRow] = makeEmptyRow()
 			insertRowIndex++
 		}
 		// range is not empty and only one range exist
@@ -422,7 +434,7 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File) ([]*Row, []*Col, in
 				row.Cells[insertColIndex-minCol] = new(Cell)
 				insertColIndex++
 			}
-			cellX := insertColIndex - minCol
+			cellX := insertColIndex
 			cell := row.Cells[cellX]
 			fillCellData(rawcell, reftable, cell)
 			if file.styles != nil {
@@ -433,8 +445,8 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File) ([]*Row, []*Col, in
 			cell.Hidden = rawrow.Hidden || (len(cols) > cellX && cell.Hidden)
 			insertColIndex++
 		}
-		if len(rows) > insertRowIndex-minRow {
-			rows[insertRowIndex-minRow] = row
+		if len(rows) > insertRowIndex {
+			rows[insertRowIndex] = row
 		}
 		insertRowIndex++
 	}

+ 76 - 2
lib_test.go

@@ -356,9 +356,83 @@ func (l *LibSuite) TestReadRowsFromSheetWithLeadingEmptyRows(c *C) {
 
 	file := new(File)
 	file.referenceTable = MakeSharedStringRefTable(sst)
-	_, _, maxCols, maxRows := readRowsFromSheet(worksheet, file)
-	c.Assert(maxRows, Equals, 2)
+	rows, _, maxCols, maxRows := readRowsFromSheet(worksheet, file)
+	c.Assert(maxRows, Equals, 5)
 	c.Assert(maxCols, Equals, 1)
+
+	c.Assert(len(rows[0].Cells), Equals, 0)
+	c.Assert(len(rows[1].Cells), Equals, 0)
+	c.Assert(len(rows[2].Cells), Equals, 0)
+	c.Assert(len(rows[3].Cells), Equals, 1)
+	c.Assert(rows[3].Cells[0].String(), Equals, "ABC")
+	c.Assert(len(rows[4].Cells), Equals, 1)
+	c.Assert(rows[4].Cells[0].String(), Equals, "DEF")
+}
+
+func (l *LibSuite) TestReadRowsFromSheetWithLeadingEmptyCols(c *C) {
+	var sharedstringsXML = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="2" uniqueCount="2"><si><t>ABC</t></si><si><t>DEF</t></si></sst>`)
+	var sheetxml = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
+  <dimension ref="C1:D2"/>
+  <sheetViews>
+    <sheetView tabSelected="1" workbookViewId="0">
+      <selection activeCell="A2" sqref="A2"/>
+    </sheetView>
+  </sheetViews>
+  <sheetFormatPr baseColWidth="10" defaultRowHeight="15" x14ac:dyDescent="0"/>
+  <cols>
+  	<col min="3" max="3" width="17" customWidth="1"/>
+  	<col min="4" max="4" width="18" customWidth="1"/>
+  </cols>
+  <sheetData>
+    <row r="1" spans="3:4">
+      <c r="C1" t="s"><v>0</v></c>
+      <c r="D1" t="s"><v>1</v></c>
+    </row>
+    <row r="2" spans="3:4">
+      <c r="C2" t="s"><v>0</v></c>
+      <c r="D2" t="s"><v>1</v></c>
+    </row>
+  </sheetData>
+  <pageMargins left="0.75" right="0.75" top="1" bottom="1" header="0.5" footer="0.5"/>
+  <pageSetup paperSize="9" orientation="portrait" horizontalDpi="4294967292" verticalDpi="4294967292"/>
+  <extLst>
+    <ext uri="{64002731-A6B0-56B0-2670-7721B7C09600}" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main">
+      <mx:PLV Mode="0" OnePage="0" WScale="0"/>
+    </ext>
+  </extLst>
+</worksheet>
+`)
+	worksheet := new(xlsxWorksheet)
+	err := xml.NewDecoder(sheetxml).Decode(worksheet)
+	c.Assert(err, IsNil)
+	sst := new(xlsxSST)
+	err = xml.NewDecoder(sharedstringsXML).Decode(sst)
+	c.Assert(err, IsNil)
+
+	file := new(File)
+	file.referenceTable = MakeSharedStringRefTable(sst)
+	rows, cols, maxCols, maxRows := readRowsFromSheet(worksheet, file)
+	c.Assert(maxRows, Equals, 2)
+	c.Assert(maxCols, Equals, 4)
+
+	c.Assert(len(rows[0].Cells), Equals, 4)
+	c.Assert(rows[0].Cells[0].String(), Equals, "")
+	c.Assert(rows[0].Cells[1].String(), Equals, "")
+	c.Assert(rows[0].Cells[2].String(), Equals, "ABC")
+	c.Assert(rows[0].Cells[3].String(), Equals, "DEF")
+	c.Assert(len(rows[1].Cells), Equals, 4)
+	c.Assert(rows[1].Cells[0].String(), Equals, "")
+	c.Assert(rows[1].Cells[1].String(), Equals, "")
+	c.Assert(rows[1].Cells[2].String(), Equals, "ABC")
+	c.Assert(rows[1].Cells[3].String(), Equals, "DEF")
+
+	c.Assert(len(cols), Equals, 4)
+	c.Assert(cols[0].Width, Equals, 0.0)
+	c.Assert(cols[1].Width, Equals, 0.0)
+	c.Assert(cols[2].Width, Equals, 17.0)
+	c.Assert(cols[3].Width, Equals, 18.0)
 }
 
 func (l *LibSuite) TestReadRowsFromSheetWithEmptyCells(c *C) {

BIN
testdocs/empty_rows.xlsx