mirror of
https://github.com/unidoc/unioffice.git
synced 2025-04-25 13:48:53 +08:00
Get all cells in a row with empty ones (#377)
* Get all cells in a row with empty ones * sheet.MaxColumnIdx() changed * goimports for all
This commit is contained in:
parent
5f9c94bf84
commit
72ad869a28
36
_examples/spreadsheet/cells-with-empty/main.go
Normal file
36
_examples/spreadsheet/cells-with-empty/main.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2017 FoxyUtils ehf. All rights reserved.
|
||||
package main
|
||||
|
||||
// This example demonstrates outputing all cells in a row of an excel spreadsheet, including empty cells.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/unidoc/unioffice/spreadsheet"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ss, err := spreadsheet.Open("test.xlsx")
|
||||
if err != nil {
|
||||
log.Fatalf("error opening document: %s", err)
|
||||
}
|
||||
|
||||
s := ss.Sheets()[0]
|
||||
|
||||
maxColumnIdx := s.MaxColumnIdx()
|
||||
for _, row := range s.Rows() {
|
||||
for _, cell := range row.CellsWithEmpty(maxColumnIdx) {
|
||||
fmt.Println(cell.Reference(), ":", cell.GetFormattedValue())
|
||||
}
|
||||
}
|
||||
fmt.Print("\n\n\n")
|
||||
|
||||
s.Cell("F4").SetString("Hello world")
|
||||
maxColumnIdx = s.MaxColumnIdx()
|
||||
for _, row := range s.Rows() {
|
||||
for _, cell := range row.CellsWithEmpty(maxColumnIdx) {
|
||||
fmt.Println(cell.Reference(), ":", cell.GetFormattedValue())
|
||||
}
|
||||
}
|
||||
}
|
BIN
_examples/spreadsheet/cells-with-empty/test.xlsx
Normal file
BIN
_examples/spreadsheet/cells-with-empty/test.xlsx
Normal file
Binary file not shown.
@ -10,9 +10,9 @@ import (
|
||||
|
||||
"github.com/unidoc/unioffice/common"
|
||||
"github.com/unidoc/unioffice/document"
|
||||
"github.com/unidoc/unioffice/schema/soo/ofc/docPropsVTypes"
|
||||
"github.com/unidoc/unioffice/testhelper"
|
||||
"github.com/unidoc/unioffice/zippkg"
|
||||
"github.com/unidoc/unioffice/schema/soo/ofc/docPropsVTypes"
|
||||
)
|
||||
|
||||
func TestMarshalCustomProperties(t *testing.T) {
|
||||
|
@ -395,7 +395,6 @@ func (p *Presentation) Save(w io.Writer) error {
|
||||
r.Properties().SetSolidFill(color.Red)
|
||||
}
|
||||
|
||||
|
||||
dt := unioffice.DocTypePresentation
|
||||
|
||||
z := zip.NewWriter(w)
|
||||
|
@ -8,6 +8,7 @@
|
||||
// commercial license can be purchased via https://unidoc.io website.
|
||||
|
||||
package custom_properties
|
||||
|
||||
import "github.com/unidoc/unioffice"
|
||||
|
||||
// init registers constructor functions for dynamically creating elements based off the XML namespace and name
|
||||
|
@ -27,7 +27,7 @@ const iso8601Format = "2006-01-02T15:04:05Z07:00"
|
||||
// Cell is a single cell within a sheet.
|
||||
type Cell struct {
|
||||
w *Workbook
|
||||
s *sml.Worksheet
|
||||
sheet *Sheet
|
||||
r *sml.CT_Row
|
||||
x *sml.CT_Cell
|
||||
}
|
||||
@ -110,8 +110,8 @@ func (c Cell) SetFormulaShared(formula string, rows, cols uint32) error {
|
||||
}
|
||||
|
||||
sid := uint32(0)
|
||||
for _, r := range c.s.SheetData.Row {
|
||||
for _, c := range r.C {
|
||||
for _, r := range c.sheet.Rows() {
|
||||
for _, c := range r.x.C {
|
||||
if c.F != nil && c.F.SiAttr != nil && *c.F.SiAttr >= sid {
|
||||
sid = *c.F.SiAttr
|
||||
}
|
||||
@ -122,7 +122,7 @@ func (c Cell) SetFormulaShared(formula string, rows, cols uint32) error {
|
||||
ref := fmt.Sprintf("%s%d:%s%d", cref.Column, cref.RowIdx, reference.IndexToColumn(cref.ColumnIdx+cols), cref.RowIdx+rows)
|
||||
c.x.F.RefAttr = unioffice.String(ref)
|
||||
c.x.F.SiAttr = unioffice.Uint32(sid)
|
||||
sheet := Sheet{c.w, nil, c.s}
|
||||
sheet := Sheet{c.w, c.sheet.cts, c.sheet.x}
|
||||
for row := cref.RowIdx; row <= cref.RowIdx+rows; row++ {
|
||||
for col := cref.ColumnIdx; col <= cref.ColumnIdx+cols; col++ {
|
||||
if row == cref.RowIdx && col == cref.ColumnIdx {
|
||||
@ -200,11 +200,16 @@ func (c Cell) getLabelPrefix() string {
|
||||
sid := *c.x.SAttr
|
||||
cs := c.w.StyleSheet.GetCellStyle(sid)
|
||||
switch cs.xf.Alignment.HorizontalAttr {
|
||||
case sml.ST_HorizontalAlignmentLeft: return "'"
|
||||
case sml.ST_HorizontalAlignmentRight: return "\""
|
||||
case sml.ST_HorizontalAlignmentCenter: return "^"
|
||||
case sml.ST_HorizontalAlignmentFill: return "\\"
|
||||
default: return ""
|
||||
case sml.ST_HorizontalAlignmentLeft:
|
||||
return "'"
|
||||
case sml.ST_HorizontalAlignmentRight:
|
||||
return "\""
|
||||
case sml.ST_HorizontalAlignmentCenter:
|
||||
return "^"
|
||||
case sml.ST_HorizontalAlignmentFill:
|
||||
return "\\"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,22 +509,23 @@ func (c Cell) GetRawValue() (string, error) {
|
||||
|
||||
// SetHyperlink sets a hyperlink on a cell.
|
||||
func (c Cell) SetHyperlink(hl common.Hyperlink) {
|
||||
if c.s.Hyperlinks == nil {
|
||||
c.s.Hyperlinks = sml.NewCT_Hyperlinks()
|
||||
ws := c.sheet.x
|
||||
if ws.Hyperlinks == nil {
|
||||
ws.Hyperlinks = sml.NewCT_Hyperlinks()
|
||||
}
|
||||
rel := common.Relationship(hl)
|
||||
|
||||
hle := sml.NewCT_Hyperlink()
|
||||
hle.RefAttr = c.Reference()
|
||||
hle.IdAttr = unioffice.String(rel.ID())
|
||||
c.s.Hyperlinks.Hyperlink = append(c.s.Hyperlinks.Hyperlink, hle)
|
||||
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, hle)
|
||||
}
|
||||
|
||||
// AddHyperlink creates and sets a hyperlink on a cell.
|
||||
func (c Cell) AddHyperlink(url string) {
|
||||
// store the relationships so we don't need to do a lookup here?
|
||||
for i, ws := range c.w.xws {
|
||||
if ws == c.s {
|
||||
if ws == c.sheet.x {
|
||||
// add a hyperlink relationship in the worksheet relationships file
|
||||
c.SetHyperlink(c.w.xwsRels[i].AddHyperlink(url))
|
||||
return
|
||||
|
@ -9,10 +9,10 @@ package spreadsheet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/unidoc/unioffice/spreadsheet/formula"
|
||||
"github.com/unidoc/unioffice/spreadsheet/reference"
|
||||
@ -220,7 +220,7 @@ func (e *evalContext) LastRow(col string) int {
|
||||
max := 1
|
||||
for _, r := range sheet.x.SheetData.Row {
|
||||
if r.RAttr != nil {
|
||||
row := Row{sheet.w, sheet.x, r}
|
||||
row := Row{sheet.w, sheet, r}
|
||||
l := len(row.Cells())
|
||||
if l > colIdx {
|
||||
max = int(row.RowNumber())
|
||||
|
@ -904,7 +904,7 @@ func feb29Between(date1, date2 time.Time) bool {
|
||||
date2S := date2.Unix()
|
||||
year1 := date1.Year()
|
||||
mar1year1 := makeDateS(year1, time.March, 1)
|
||||
if (isLeapYear(year1) && date1S < mar1year1 && date2S >= mar1year1) {
|
||||
if isLeapYear(year1) && date1S < mar1year1 && date2S >= mar1year1 {
|
||||
return true
|
||||
}
|
||||
var year2 = date2.Year()
|
||||
|
@ -8,10 +8,10 @@
|
||||
package formula
|
||||
|
||||
import (
|
||||
"time"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -11,9 +11,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/unidoc/unioffice/internal/mergesort"
|
||||
"github.com/unidoc/unioffice/internal/wildcard"
|
||||
"github.com/unidoc/unioffice/spreadsheet/reference"
|
||||
"github.com/unidoc/unioffice/internal/mergesort"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -9,6 +9,7 @@ package formula
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/unidoc/unioffice/spreadsheet/update"
|
||||
)
|
||||
|
||||
|
@ -366,7 +366,6 @@ func TestCountIfs(t *testing.T) {
|
||||
sheet.Cell("B9").SetNumber(2)
|
||||
sheet.Cell("B10").SetNumber(1)
|
||||
|
||||
|
||||
ctx := sheet.FormulaContext()
|
||||
|
||||
runTests(t, ctx, td)
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
|
||||
type MergedCell struct {
|
||||
wb *Workbook
|
||||
ws *sml.Worksheet
|
||||
sheet *Sheet
|
||||
x *sml.CT_MergeCell
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ func (s MergedCell) Cell() Cell {
|
||||
ref := s.Reference()
|
||||
if idx := strings.Index(s.Reference(), ":"); idx != -1 {
|
||||
ref = ref[0:idx]
|
||||
return Sheet{w: s.wb, x: s.ws}.Cell(ref)
|
||||
return s.sheet.Cell(ref)
|
||||
}
|
||||
// couldn't find it, log an error?
|
||||
return Cell{}
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/unidoc/unioffice"
|
||||
"github.com/unidoc/unioffice/zippkg"
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
// Row is a row within a spreadsheet.
|
||||
type Row struct {
|
||||
w *Workbook
|
||||
s *sml.Worksheet
|
||||
sheet *Sheet
|
||||
x *sml.CT_Row
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ func (r Row) AddCell() Cell {
|
||||
nextCellID = unioffice.Stringf("%s%d", reference.IndexToColumn(nextIdx), r.RowNumber())
|
||||
}
|
||||
c.RAttr = nextCellID
|
||||
return Cell{r.w, r.s, r.x, c}
|
||||
return Cell{r.w, r.sheet, r.x, c}
|
||||
}
|
||||
|
||||
// Cells returns a slice of cells. The cells can be manipulated, but appending
|
||||
@ -116,7 +116,18 @@ func (r Row) Cells() []Cell {
|
||||
}
|
||||
}
|
||||
lastIndex = currentIndex
|
||||
ret = append(ret, Cell{r.w, r.s, r.x, c})
|
||||
ret = append(ret, Cell{r.w, r.sheet, r.x, c})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// CellsWithEmpty returns a slice of cells including empty ones from the first column to the last one used in the sheet.
|
||||
// The cells can be manipulated, but appending to the slice will have no effect.
|
||||
func (r Row) CellsWithEmpty(lastColIdx uint32) []Cell {
|
||||
ret := []Cell{}
|
||||
for columnIdx := uint32(0); columnIdx <= lastColIdx; columnIdx++ {
|
||||
c := r.Cell(reference.IndexToColumn(columnIdx))
|
||||
ret = append(ret, c)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -147,7 +158,7 @@ func (r Row) AddNamedCell(col string) Cell {
|
||||
r.x.C = append(r.x.C[:indexToInsert], append([]*sml.CT_Cell{c}, r.x.C[indexToInsert:]...)...)
|
||||
}
|
||||
|
||||
return Cell{r.w, r.s, r.x, c}
|
||||
return Cell{r.w, r.sheet, r.x, c}
|
||||
}
|
||||
|
||||
// Cell retrieves or adds a new cell to a row. Col is the column (e.g. 'A', 'B')
|
||||
@ -155,7 +166,7 @@ func (r Row) Cell(col string) Cell {
|
||||
name := fmt.Sprintf("%s%d", col, r.RowNumber())
|
||||
for _, c := range r.x.C {
|
||||
if c.RAttr != nil && *c.RAttr == name {
|
||||
return Cell{r.w, r.s, r.x, c}
|
||||
return Cell{r.w, r.sheet, r.x, c}
|
||||
}
|
||||
}
|
||||
return r.AddNamedCell(col)
|
||||
|
@ -31,6 +31,22 @@ type Sheet struct {
|
||||
x *sml.Worksheet
|
||||
}
|
||||
|
||||
// MaxColumnIdx returns the max used column of the sheet.
|
||||
func (s Sheet) MaxColumnIdx() uint32 {
|
||||
maxColumnIdx := uint32(0)
|
||||
for _, r := range s.Rows() {
|
||||
cells := r.x.C
|
||||
if len(cells) > 0 {
|
||||
lastCell := cells[len(cells)-1]
|
||||
ref, _ := reference.ParseCellReference(*lastCell.RAttr)
|
||||
if maxColumnIdx < ref.ColumnIdx {
|
||||
maxColumnIdx = ref.ColumnIdx
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxColumnIdx
|
||||
}
|
||||
|
||||
func (s Sheet) IsValid() bool {
|
||||
return s.x != nil
|
||||
}
|
||||
@ -42,11 +58,11 @@ func (s Sheet) X() *sml.Worksheet {
|
||||
|
||||
// Row will return a row with a given row number, creating a new row if
|
||||
// necessary.
|
||||
func (s Sheet) Row(rowNum uint32) Row {
|
||||
func (s *Sheet) Row(rowNum uint32) Row {
|
||||
// see if the row exists
|
||||
for _, r := range s.x.SheetData.Row {
|
||||
if r.RAttr != nil && *r.RAttr == rowNum {
|
||||
return Row{s.w, s.x, r}
|
||||
return Row{s.w, s, r}
|
||||
}
|
||||
}
|
||||
// create a new row
|
||||
@ -54,7 +70,7 @@ func (s Sheet) Row(rowNum uint32) Row {
|
||||
}
|
||||
|
||||
// Cell creates or returns a cell given a cell reference of the form 'A10'
|
||||
func (s Sheet) Cell(cellRef string) Cell {
|
||||
func (s *Sheet) Cell(cellRef string) Cell {
|
||||
cref, err := reference.ParseCellReference(cellRef)
|
||||
if err != nil {
|
||||
unioffice.Log("error parsing cell reference: %s", err)
|
||||
@ -66,7 +82,7 @@ func (s Sheet) Cell(cellRef string) Cell {
|
||||
// AddNumberedRow adds a row with a given row number. If you reuse a row number
|
||||
// the resulting file will fail validation and fail to open in Office programs. Use
|
||||
// Row instead which creates a new row or returns an existing row.
|
||||
func (s Sheet) AddNumberedRow(rowNum uint32) Row {
|
||||
func (s *Sheet) AddNumberedRow(rowNum uint32) Row {
|
||||
r := sml.NewCT_Row()
|
||||
r.RAttr = unioffice.Uint32(rowNum)
|
||||
s.x.SheetData.Row = append(s.x.SheetData.Row, r)
|
||||
@ -84,22 +100,22 @@ func (s Sheet) AddNumberedRow(rowNum uint32) Row {
|
||||
return *l < *r
|
||||
})
|
||||
|
||||
return Row{s.w, s.x, r}
|
||||
return Row{s.w, s, r}
|
||||
}
|
||||
|
||||
// addNumberedRowFast is a fast path that can be used when adding consecutive
|
||||
// rows and not skipping any.
|
||||
func (s Sheet) addNumberedRowFast(rowNum uint32) Row {
|
||||
func (s *Sheet) addNumberedRowFast(rowNum uint32) Row {
|
||||
r := sml.NewCT_Row()
|
||||
r.RAttr = unioffice.Uint32(rowNum)
|
||||
s.x.SheetData.Row = append(s.x.SheetData.Row, r)
|
||||
return Row{s.w, s.x, r}
|
||||
return Row{s.w, s, r}
|
||||
}
|
||||
|
||||
// AddRow adds a new row to a sheet. You can mix this with numbered rows,
|
||||
// however it will get confusing. You should prefer to use either automatically
|
||||
// numbered rows with AddRow or manually numbered rows with Row/AddNumberedRow
|
||||
func (s Sheet) AddRow() Row {
|
||||
func (s *Sheet) AddRow() Row {
|
||||
maxRowID := uint32(0)
|
||||
|
||||
numRows := uint32(len(s.x.SheetData.Row))
|
||||
@ -120,7 +136,7 @@ func (s Sheet) AddRow() Row {
|
||||
|
||||
// InsertRow inserts a new row into a spreadsheet at a particular row number. This
|
||||
// row will now be the row number specified, and any rows after it will be renumbed.
|
||||
func (s Sheet) InsertRow(rowNum int) Row {
|
||||
func (s *Sheet) InsertRow(rowNum int) Row {
|
||||
rIdx := uint32(rowNum)
|
||||
|
||||
// Renumber every row after the row we're inserting
|
||||
@ -166,7 +182,7 @@ func (s Sheet) Name() string {
|
||||
}
|
||||
|
||||
// SetName sets the sheet name.
|
||||
func (s Sheet) SetName(name string) {
|
||||
func (s *Sheet) SetName(name string) {
|
||||
s.cts.NameAttr = name
|
||||
}
|
||||
|
||||
@ -182,7 +198,7 @@ func (s Sheet) Validate() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := s.cts.Validate(); err != nil {
|
||||
if err := s.x.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.x.Validate()
|
||||
@ -249,21 +265,21 @@ func (s Sheet) validateMergedCells() error {
|
||||
// ValidateWithPath validates the sheet passing path informaton for a better
|
||||
// error message
|
||||
func (s Sheet) ValidateWithPath(path string) error {
|
||||
return s.cts.ValidateWithPath(path)
|
||||
return s.x.ValidateWithPath(path)
|
||||
}
|
||||
|
||||
// Rows returns all of the rows in a sheet.
|
||||
func (s Sheet) Rows() []Row {
|
||||
func (s *Sheet) Rows() []Row {
|
||||
ret := []Row{}
|
||||
for _, r := range s.x.SheetData.Row {
|
||||
ret = append(ret, Row{s.w, s.x, r})
|
||||
ret = append(ret, Row{s.w, s, r})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetDrawing sets the worksheet drawing. A worksheet can have a reference to a
|
||||
// single drawing, but the drawing can have many charts.
|
||||
func (s Sheet) SetDrawing(d Drawing) {
|
||||
func (s *Sheet) SetDrawing(d Drawing) {
|
||||
var rel common.Relationships
|
||||
for i, wks := range s.w.xws {
|
||||
if wks == s.x {
|
||||
@ -288,7 +304,7 @@ func (s Sheet) SetDrawing(d Drawing) {
|
||||
// AddHyperlink adds a hyperlink to a sheet. Adding the hyperlink to the sheet
|
||||
// and setting it on a cell is more efficient than setting hyperlinks directly
|
||||
// on a cell.
|
||||
func (s Sheet) AddHyperlink(url string) common.Hyperlink {
|
||||
func (s *Sheet) AddHyperlink(url string) common.Hyperlink {
|
||||
// store the relationships so we don't need to do a lookup here?
|
||||
for i, ws := range s.w.xws {
|
||||
if ws == s.x {
|
||||
@ -318,7 +334,7 @@ func (s Sheet) RangeReference(n string) string {
|
||||
const autoFilterName = "_xlnm._FilterDatabase"
|
||||
|
||||
// ClearAutoFilter removes the autofilters from the sheet.
|
||||
func (s Sheet) ClearAutoFilter() {
|
||||
func (s *Sheet) ClearAutoFilter() {
|
||||
s.x.AutoFilter = nil
|
||||
sn := "'" + s.Name() + "'!"
|
||||
// see if we have a defined auto filter name for the sheet
|
||||
@ -336,7 +352,7 @@ func (s Sheet) ClearAutoFilter() {
|
||||
// filters that are common for a header row. The RangeRef should be of the form
|
||||
// "A1:C5" and cover the entire range of cells to be filtered, not just the
|
||||
// header. SetAutoFilter replaces any existing auto filter on the sheet.
|
||||
func (s Sheet) SetAutoFilter(rangeRef string) {
|
||||
func (s *Sheet) SetAutoFilter(rangeRef string) {
|
||||
// this should have no $ in it
|
||||
rangeRef = strings.Replace(rangeRef, "$", "", -1)
|
||||
|
||||
@ -369,7 +385,7 @@ func (s Sheet) SetAutoFilter(rangeRef string) {
|
||||
}
|
||||
|
||||
// AddMergedCells merges cells within a sheet.
|
||||
func (s Sheet) AddMergedCells(fromRef, toRef string) MergedCell {
|
||||
func (s *Sheet) AddMergedCells(fromRef, toRef string) MergedCell {
|
||||
// TODO: we might need to actually create the merged cells if they don't
|
||||
// exist, but it appears to work fine on both Excel and LibreOffice just
|
||||
// creating the merged region
|
||||
@ -383,24 +399,24 @@ func (s Sheet) AddMergedCells(fromRef, toRef string) MergedCell {
|
||||
|
||||
s.x.MergeCells.MergeCell = append(s.x.MergeCells.MergeCell, merge)
|
||||
s.x.MergeCells.CountAttr = unioffice.Uint32(uint32(len(s.x.MergeCells.MergeCell)))
|
||||
return MergedCell{s.w, s.x, merge}
|
||||
return MergedCell{s.w, s, merge}
|
||||
}
|
||||
|
||||
// MergedCells returns the merged cell regions within the sheet.
|
||||
func (s Sheet) MergedCells() []MergedCell {
|
||||
func (s *Sheet) MergedCells() []MergedCell {
|
||||
if s.x.MergeCells == nil {
|
||||
return nil
|
||||
}
|
||||
ret := []MergedCell{}
|
||||
for _, c := range s.x.MergeCells.MergeCell {
|
||||
ret = append(ret, MergedCell{s.w, s.x, c})
|
||||
ret = append(ret, MergedCell{s.w, s, c})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// RemoveMergedCell removes merging from a cell range within a sheet. The cells
|
||||
// that made up the merged cell remain, but are no lon merged.
|
||||
func (s Sheet) RemoveMergedCell(mc MergedCell) {
|
||||
func (s *Sheet) RemoveMergedCell(mc MergedCell) {
|
||||
for i, c := range s.x.MergeCells.MergeCell {
|
||||
if c == mc.X() {
|
||||
copy(s.x.MergeCells.MergeCell[i:], s.x.MergeCells.MergeCell[i+1:])
|
||||
@ -443,7 +459,7 @@ func (s Sheet) Extents() string {
|
||||
}
|
||||
|
||||
// AddConditionalFormatting adds conditional formatting to the sheet.
|
||||
func (s Sheet) AddConditionalFormatting(cellRanges []string) ConditionalFormatting {
|
||||
func (s *Sheet) AddConditionalFormatting(cellRanges []string) ConditionalFormatting {
|
||||
cfmt := sml.NewCT_ConditionalFormatting()
|
||||
s.x.ConditionalFormatting = append(s.x.ConditionalFormatting, cfmt)
|
||||
|
||||
@ -460,7 +476,7 @@ func (s Sheet) AddConditionalFormatting(cellRanges []string) ConditionalFormatti
|
||||
// can span multiple column indices, this method will return the column that
|
||||
// applies to a column index if it exists or create a new column that only
|
||||
// applies to the index passed in otherwise.
|
||||
func (s Sheet) Column(idx uint32) Column {
|
||||
func (s *Sheet) Column(idx uint32) Column {
|
||||
// scan for any existing column that covers this index
|
||||
for _, colSet := range s.x.Cols {
|
||||
for _, col := range colSet.Col {
|
||||
@ -487,7 +503,7 @@ func (s Sheet) Column(idx uint32) Column {
|
||||
}
|
||||
|
||||
// Comments returns the comments for a sheet.
|
||||
func (s Sheet) Comments() Comments {
|
||||
func (s *Sheet) Comments() Comments {
|
||||
for i, wks := range s.w.xws {
|
||||
if wks == s.x {
|
||||
if s.w.comments[i] == nil {
|
||||
@ -518,7 +534,7 @@ func (s Sheet) Comments() Comments {
|
||||
// the cells on the top,left,right,bottom and four corners. This function
|
||||
// breaks apart a single border into its components and applies it to cells as
|
||||
// needed to give the effect of a border applying to multiple cells.
|
||||
func (s Sheet) SetBorder(cellRange string, border Border) error {
|
||||
func (s *Sheet) SetBorder(cellRange string, border Border) error {
|
||||
from, to, err := reference.ParseRangeReference(cellRange)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -605,7 +621,7 @@ func (s Sheet) SetBorder(cellRange string, border Border) error {
|
||||
}
|
||||
|
||||
// AddDataValidation adds a data validation rule to a sheet.
|
||||
func (s Sheet) AddDataValidation() DataValidation {
|
||||
func (s *Sheet) AddDataValidation() DataValidation {
|
||||
if s.x.DataValidations == nil {
|
||||
s.x.DataValidations = sml.NewCT_DataValidations()
|
||||
}
|
||||
@ -860,8 +876,8 @@ func (s *Sheet) Sort(column string, firstRow uint32, order SortOrder) {
|
||||
cmp := Comparer{Order: order}
|
||||
sort.Slice(sheetData, func(i, j int) bool {
|
||||
return cmp.LessRows(column,
|
||||
Row{s.w, s.x, sheetData[i]},
|
||||
Row{s.w, s.x, sheetData[j]})
|
||||
Row{s.w, s, sheetData[i]},
|
||||
Row{s.w, s, sheetData[j]})
|
||||
})
|
||||
|
||||
// since we probably moved some rows, we need to go and fix up their row
|
||||
|
@ -369,3 +369,16 @@ func TestRemoveColumn(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCellsWithEmpty(t *testing.T) {
|
||||
wb := spreadsheet.New()
|
||||
sheet := wb.AddSheet()
|
||||
sheet.Cell("A1").SetNumber(1)
|
||||
sheet.Cell("F2").SetNumber(1)
|
||||
rows := sheet.Rows()
|
||||
exp := 6
|
||||
got := len(rows[0].CellsWithEmpty(sheet.MaxColumnIdx()))
|
||||
if got != exp {
|
||||
t.Errorf("expected %d cells in row, got %d", exp, got)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ package update
|
||||
|
||||
// UpdateAction is the type for update types constants.
|
||||
type UpdateAction byte
|
||||
|
||||
const (
|
||||
// UpdateActionRemoveColumn means updating references after removing a column.
|
||||
UpdateActionRemoveColumn UpdateAction = iota
|
||||
|
@ -237,7 +237,8 @@ func (wb *Workbook) CopySheet(ind int, copiedSheetName string) (Sheet, error) {
|
||||
wb.comments = append(wb.comments, &copiedComments)
|
||||
}
|
||||
|
||||
return Sheet{wb, &copiedSheet, &copiedWs}, nil
|
||||
sheet := Sheet{wb, &copiedSheet, &copiedWs}
|
||||
return sheet, nil
|
||||
}
|
||||
|
||||
// CopySheetByName copies the existing sheet with the name `name` and puts its copy with the name `copiedSheetName`.
|
||||
@ -438,7 +439,8 @@ func (wb *Workbook) Sheets() []Sheet {
|
||||
ret := []Sheet{}
|
||||
for i, wks := range wb.xws {
|
||||
r := wb.x.Sheets.Sheet[i]
|
||||
ret = append(ret, Sheet{wb, r, wks})
|
||||
sheet := Sheet{wb, r, wks}
|
||||
ret = append(ret, sheet)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user