Browse Source

Fixed #732, support single line with repeated row element in the sheet data

xuri 5 years ago
parent
commit
92c8626f81
4 changed files with 46 additions and 24 deletions
  1. 20 1
      cell_test.go
  2. 3 4
      col.go
  3. 7 1
      excelize.go
  4. 16 18
      rows.go

+ 20 - 1
cell_test.go

@@ -136,8 +136,9 @@ func TestSetCellBool(t *testing.T) {
 func TestGetCellValue(t *testing.T) {
 	// Test get cell value without r attribute of the row.
 	f := NewFile()
+	sheetData := `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>%s</sheetData></worksheet>`
 	delete(f.Sheet, "xl/worksheets/sheet1.xml")
-	f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData><row r="3"><c t="str"><v>A3</v></c></row><row><c t="str"><v>A4</v></c><c t="str"><v>B4</v></c></row><row r="7"><c t="str"><v>A7</v></c><c t="str"><v>B7</v></c></row><row><c t="str"><v>A8</v></c><c t="str"><v>B8</v></c></row></sheetData></worksheet>`)
+	f.XLSX["xl/worksheets/sheet1.xml"] = []byte(fmt.Sprintf(sheetData, `<row r="3"><c t="str"><v>A3</v></c></row><row><c t="str"><v>A4</v></c><c t="str"><v>B4</v></c></row><row r="7"><c t="str"><v>A7</v></c><c t="str"><v>B7</v></c></row><row><c t="str"><v>A8</v></c><c t="str"><v>B8</v></c></row>`))
 	f.checked = nil
 	cells := []string{"A3", "A4", "B4", "A7", "B7"}
 	rows, err := f.GetRows("Sheet1")
@@ -151,6 +152,24 @@ func TestGetCellValue(t *testing.T) {
 	cols, err := f.GetCols("Sheet1")
 	assert.Equal(t, [][]string{{"", "", "A3", "A4", "", "", "A7", "A8"}, {"", "", "", "B4", "", "", "B7", "B8"}}, cols)
 	assert.NoError(t, err)
+	delete(f.Sheet, "xl/worksheets/sheet1.xml")
+	f.XLSX["xl/worksheets/sheet1.xml"] = []byte(fmt.Sprintf(sheetData, `<row r="2"><c r="A2" t="str"><v>A2</v></c></row><row r="2"><c r="B2" t="str"><v>B2</v></c></row>`))
+	f.checked = nil
+	cell, err := f.GetCellValue("Sheet1", "A2")
+	assert.Equal(t, "A2", cell)
+	assert.NoError(t, err)
+	delete(f.Sheet, "xl/worksheets/sheet1.xml")
+	f.XLSX["xl/worksheets/sheet1.xml"] = []byte(fmt.Sprintf(sheetData, `<row r="2"><c r="A2" t="str"><v>A2</v></c></row><row r="2"><c r="B2" t="str"><v>B2</v></c></row>`))
+	f.checked = nil
+	rows, err = f.GetRows("Sheet1")
+	assert.Equal(t, [][]string{nil, {"A2", "B2"}}, rows)
+	assert.NoError(t, err)
+	delete(f.Sheet, "xl/worksheets/sheet1.xml")
+	f.XLSX["xl/worksheets/sheet1.xml"] = []byte(fmt.Sprintf(sheetData, `<row r="1"><c r="A1" t="str"><v>A1</v></c></row><row r="1"><c r="B1" t="str"><v>B1</v></c></row>`))
+	f.checked = nil
+	rows, err = f.GetRows("Sheet1")
+	assert.Equal(t, [][]string{{"A1", "B1"}}, rows)
+	assert.NoError(t, err)
 }
 
 func TestGetCellFormula(t *testing.T) {

+ 3 - 4
col.go

@@ -103,10 +103,9 @@ func (cols *Cols) Rows() ([]string, error) {
 			if inElement == "row" {
 				cellCol = 0
 				cellRow++
-				for _, attr := range startElement.Attr {
-					if attr.Name.Local == "r" {
-						cellRow, _ = strconv.Atoi(attr.Value)
-					}
+				attrR, _ := attrValToInt("r", startElement.Attr)
+				if attrR != 0 {
+					cellRow = attrR
 				}
 			}
 			if inElement == "c" {

+ 7 - 1
excelize.go

@@ -219,11 +219,17 @@ func checkSheet(ws *xlsxWorksheet) {
 			row = r.R
 			continue
 		}
-		row++
+		if r.R != row {
+			row++
+		}
 	}
 	sheetData := xlsxSheetData{Row: make([]xlsxRow, row)}
 	row = 0
 	for _, r := range ws.SheetData.Row {
+		if r.R == row {
+			sheetData.Row[r.R-1].C = append(sheetData.Row[r.R-1].C, r.C...)
+			continue
+		}
 		if r.R != 0 {
 			sheetData.Row[r.R-1] = r
 			row = r.R

+ 16 - 18
rows.go

@@ -79,10 +79,10 @@ func (rows *Rows) Error() error {
 // Columns return the current row's column values.
 func (rows *Rows) Columns() ([]string, error) {
 	var (
-		err          error
-		inElement    string
-		row, cellCol int
-		columns      []string
+		err                 error
+		inElement           string
+		attrR, cellCol, row int
+		columns             []string
 	)
 
 	if rows.stashRow >= rows.curRow {
@@ -99,17 +99,13 @@ func (rows *Rows) Columns() ([]string, error) {
 		case xml.StartElement:
 			inElement = startElement.Name.Local
 			if inElement == "row" {
-				for _, attr := range startElement.Attr {
-					if attr.Name.Local == "r" {
-						row, err = strconv.Atoi(attr.Value)
-						if err != nil {
-							return columns, err
-						}
-						if row > rows.curRow {
-							rows.stashRow = row - 1
-							return columns, err
-						}
-					}
+				row++
+				if attrR, err = attrValToInt("r", startElement.Attr); attrR != 0 {
+					row = attrR
+				}
+				if row > rows.curRow {
+					rows.stashRow = row - 1
+					return columns, err
 				}
 			}
 			if inElement == "c" {
@@ -117,8 +113,7 @@ func (rows *Rows) Columns() ([]string, error) {
 				colCell := xlsxC{}
 				_ = rows.decoder.DecodeElement(&colCell, &startElement)
 				if colCell.R != "" {
-					cellCol, _, err = CellNameToCoordinates(colCell.R)
-					if err != nil {
+					if cellCol, _, err = CellNameToCoordinates(colCell.R); err != nil {
 						return columns, err
 					}
 				}
@@ -128,7 +123,10 @@ func (rows *Rows) Columns() ([]string, error) {
 			}
 		case xml.EndElement:
 			inElement = startElement.Name.Local
-			if inElement == "row" {
+			if row == 0 {
+				row = rows.curRow
+			}
+			if inElement == "row" && row+1 < rows.curRow {
 				return columns, err
 			}
 		}