Browse Source

Populate the VMerge and HMerge properties of the cell based on the xlsxWorksheet.MergeCells.

Geoffrey J. Teale 10 years ago
parent
commit
e07ef57987
4 changed files with 103 additions and 0 deletions
  1. 6 0
      lib.go
  2. 61 0
      lib_test.go
  3. 24 0
      xmlWorksheet.go
  4. 12 0
      xmlWorksheet_test.go

+ 6 - 0
lib.go

@@ -504,6 +504,10 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File, sheet *Sheet) ([]*R
 
 		insertColIndex = minCol
 		for _, rawcell := range rawrow.C {
+			h, v, err := Worksheet.MergeCells.getExtent(rawcell.R)
+			if err != nil {
+				panic(err.Error())
+			}
 			x, _, _ := getCoordsFromCellIDString(rawcell.R)
 
 			// Some spreadsheets will omit blank cells
@@ -515,6 +519,8 @@ func readRowsFromSheet(Worksheet *xlsxWorksheet, file *File, sheet *Sheet) ([]*R
 			}
 			cellX := insertColIndex
 			cell := row.Cells[cellX]
+			cell.HMerge = h
+			cell.VMerge = v
 			fillCellData(rawcell, reftable, sharedFormulas, cell)
 			if file.styles != nil {
 				cell.style = file.styles.getStyle(rawcell.S)

+ 61 - 0
lib_test.go

@@ -342,6 +342,67 @@ func (l *LibSuite) TestReadRowsFromSheet(c *C) {
 	c.Assert(pane.YSplit, Equals, 1.0)
 }
 
+func (l *LibSuite) TestReadRowsFromSheetWithMergeCells(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="3" uniqueCount="3">
+  <si>
+    <t>Value A</t>
+  </si>
+  <si>
+    <t>Value B</t>
+  </si>
+  <si>
+    <t>Value C</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:mx="http://schemas.microsoft.com/office/mac/excel/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
+  <sheetViews>
+    <sheetView workbookViewId="0"/>
+  </sheetViews>
+  <sheetFormatPr customHeight="1" defaultColWidth="17.29" defaultRowHeight="15.0"/>
+  <cols>
+    <col customWidth="1" min="1" max="6" width="14.43"/>
+  </cols>
+  <sheetData>
+    <row r="1" ht="15.75" customHeight="1">
+      <c r="A1" s="1" t="s">
+        <v>0</v>
+      </c>
+    </row>
+    <row r="2" ht="15.75" customHeight="1">
+      <c r="A2" s="1" t="s">
+        <v>1</v>
+      </c>
+      <c r="B2" s="1" t="s">
+        <v>2</v>
+      </c>
+    </row>
+  </sheetData>
+  <mergeCells count="1">
+    <mergeCell ref="A1:B1"/>
+  </mergeCells>
+  <drawing r:id="rId1"/>
+</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)
+	sheet := new(Sheet)
+	rows, _, _, _ := readRowsFromSheet(worksheet, file, sheet)
+	row := rows[0] //
+	cell1 := row.Cells[0]
+	c.Assert(cell1.HMerge, Equals, 1)
+	c.Assert(cell1.VMerge, Equals, 0)
+}
+
 // An invalid value in the "r" attribute in a <row> was causing a panic
 // in readRowsFromSheet. This test is a copy of TestReadRowsFromSheet,
 // with the important difference of the value 1048576 below in <row r="1048576", which is

+ 24 - 0
xmlWorksheet.go

@@ -2,6 +2,7 @@ package xlsx
 
 import (
 	"encoding/xml"
+	"strings"
 )
 
 // xlsxWorksheet directly maps the worksheet element in the namespace
@@ -241,6 +242,29 @@ type xlsxMergeCells struct {
 	Cells   []xlsxMergeCell `xml:"mergeCell,omitempty"`
 }
 
+// Return the cartesian extent of a merged cell range from its origin
+// cell (the closest merged cell to the to left of the sheet.
+func (mc *xlsxMergeCells) getExtent(cellRef string) (int, int, error) {
+	if mc == nil {
+		return 0, 0, nil
+	}
+	for _, cell := range mc.Cells {
+		if strings.HasPrefix(cell.Ref, cellRef) {
+			parts := strings.Split(cell.Ref, ":")
+			startx, starty, err := getCoordsFromCellIDString(parts[0])
+			if err != nil {
+				return -1, -1, err
+			}
+			endx, endy, err := getCoordsFromCellIDString(parts[1])
+			if err != nil {
+				return -2, -2, err
+			}
+			return endx - startx, endy - starty, nil
+		}
+	}
+	return 0, 0, nil
+}
+
 // xlsxC directly maps the c element in the namespace
 // http://schemas.openxmlformats.org/sprceadsheetml/2006/main -
 // currently I have not checked it for completeness - it does as much

+ 12 - 0
xmlWorksheet_test.go

@@ -184,3 +184,15 @@ func (w *WorksheetSuite) TestUnmarshallWorksheetWithMergeCells(c *C) {
 	mergeCell := worksheet.MergeCells.Cells[0]
 	c.Assert(mergeCell.Ref, Equals, "A1:B1")
 }
+
+// MergeCells.getExtents returns the horizontal and vertical extent of
+// a merge that begins at a given reference.
+func (w *WorksheetSuite) TestMergeCellsGetExtent(c *C) {
+	mc := xlsxMergeCells{Count: 1}
+	mc.Cells = make([]xlsxMergeCell, 1)
+	mc.Cells[0] = xlsxMergeCell{Ref: "A1:B5"}
+	h, v, err := mc.getExtent("A1")
+	c.Assert(err, IsNil)
+	c.Assert(h, Equals, 1)
+	c.Assert(v, Equals, 4)
+}