2019-01-01 13:20:14 +08:00
|
|
|
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
|
2018-09-14 00:44:23 +08:00
|
|
|
// this source code is governed by a BSD-style license that can be found in
|
|
|
|
// the LICENSE file.
|
|
|
|
//
|
|
|
|
// Package excelize providing a set of functions that allow you to write to
|
|
|
|
// and read from XLSX files. Support reads and writes XLSX file generated by
|
|
|
|
// Microsoft Excel™ 2007 and later. Support save file without losing original
|
|
|
|
// charts of XLSX. This library needs Go version 1.8 or later.
|
2018-09-14 00:58:48 +08:00
|
|
|
|
2016-10-31 19:13:22 +08:00
|
|
|
package excelize
|
|
|
|
|
|
|
|
import (
|
2017-07-24 10:26:02 +08:00
|
|
|
"bytes"
|
2016-10-31 19:13:22 +08:00
|
|
|
"encoding/xml"
|
2018-05-05 13:33:19 +08:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2017-07-24 10:26:02 +08:00
|
|
|
"math"
|
2016-11-02 12:58:51 +08:00
|
|
|
"strconv"
|
2016-10-31 19:13:22 +08:00
|
|
|
)
|
|
|
|
|
2017-09-13 22:00:33 +08:00
|
|
|
// GetRows return all the rows in a sheet by given worksheet name (case
|
|
|
|
// sensitive). For example:
|
2016-11-02 12:58:51 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// rows, err := xlsx.GetRows("Sheet1")
|
|
|
|
// for _, row := range rows {
|
2016-11-02 12:58:51 +08:00
|
|
|
// for _, colCell := range row {
|
|
|
|
// fmt.Print(colCell, "\t")
|
|
|
|
// }
|
|
|
|
// fmt.Println()
|
|
|
|
// }
|
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) GetRows(sheet string) ([][]string, error) {
|
2017-10-18 19:07:35 +08:00
|
|
|
name, ok := f.sheetMap[trimSheetName(sheet)]
|
|
|
|
if !ok {
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil, nil
|
2017-10-18 19:07:35 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
xlsx := f.workSheetReader(sheet)
|
2017-03-12 20:38:26 +08:00
|
|
|
if xlsx != nil {
|
|
|
|
output, _ := xml.Marshal(f.Sheet[name])
|
2018-05-07 16:12:51 +08:00
|
|
|
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
2016-10-31 19:13:22 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2018-05-27 11:25:55 +08:00
|
|
|
xml.NewDecoder(bytes.NewReader(f.readXML(name)))
|
2017-06-29 13:28:44 +08:00
|
|
|
d := f.sharedStringsReader()
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
var (
|
|
|
|
inElement string
|
|
|
|
rowData xlsxRow
|
|
|
|
)
|
|
|
|
|
2019-03-23 20:08:06 +08:00
|
|
|
rowCount, colCount, err := f.getTotalRowsCols(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
rows := make([][]string, rowCount)
|
2019-01-01 18:18:42 +08:00
|
|
|
for i := range rows {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
rows[i] = make([]string, colCount+1)
|
2017-02-17 17:41:11 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-01-01 18:18:42 +08:00
|
|
|
var row int
|
2018-05-27 11:25:55 +08:00
|
|
|
decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
|
2017-02-12 19:03:24 +08:00
|
|
|
for {
|
|
|
|
token, _ := decoder.Token()
|
|
|
|
if token == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
switch startElement := token.(type) {
|
|
|
|
case xml.StartElement:
|
|
|
|
inElement = startElement.Name.Local
|
|
|
|
if inElement == "row" {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
rowData = xlsxRow{}
|
|
|
|
_ = decoder.DecodeElement(&rowData, &startElement)
|
|
|
|
cr := rowData.R - 1
|
|
|
|
for _, colCell := range rowData.C {
|
2019-03-23 20:08:06 +08:00
|
|
|
col, _, err := CellNameToCoordinates(colCell.R)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-02-12 19:03:24 +08:00
|
|
|
val, _ := colCell.getValueFrom(f, d)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
rows[cr][col-1] = val
|
2019-01-01 18:18:42 +08:00
|
|
|
if val != "" {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
row = rowData.R
|
2019-01-01 18:18:42 +08:00
|
|
|
}
|
2017-02-12 19:03:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
2016-11-02 12:58:51 +08:00
|
|
|
}
|
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return rows[:row], nil
|
2016-10-31 19:13:22 +08:00
|
|
|
}
|
|
|
|
|
2018-05-05 13:33:19 +08:00
|
|
|
// Rows defines an iterator to a sheet
|
|
|
|
type Rows struct {
|
|
|
|
decoder *xml.Decoder
|
|
|
|
token xml.Token
|
|
|
|
err error
|
|
|
|
f *File
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next will return true if find the next row element.
|
|
|
|
func (rows *Rows) Next() bool {
|
|
|
|
for {
|
|
|
|
rows.token, rows.err = rows.decoder.Token()
|
|
|
|
if rows.err == io.EOF {
|
|
|
|
rows.err = nil
|
|
|
|
}
|
|
|
|
if rows.token == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
switch startElement := rows.token.(type) {
|
|
|
|
case xml.StartElement:
|
|
|
|
inElement := startElement.Name.Local
|
|
|
|
if inElement == "row" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error will return the error when the find next row element
|
|
|
|
func (rows *Rows) Error() error {
|
|
|
|
return rows.err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Columns return the current row's column values
|
2019-03-23 20:08:06 +08:00
|
|
|
func (rows *Rows) Columns() ([]string, error) {
|
2018-05-05 13:33:19 +08:00
|
|
|
if rows.token == nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return []string{}, nil
|
2018-05-05 13:33:19 +08:00
|
|
|
}
|
|
|
|
startElement := rows.token.(xml.StartElement)
|
|
|
|
r := xlsxRow{}
|
2018-05-27 11:25:55 +08:00
|
|
|
_ = rows.decoder.DecodeElement(&r, &startElement)
|
2018-05-05 13:33:19 +08:00
|
|
|
d := rows.f.sharedStringsReader()
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
columns := make([]string, len(r.C))
|
2018-05-05 13:33:19 +08:00
|
|
|
for _, colCell := range r.C {
|
2019-03-23 20:08:06 +08:00
|
|
|
col, _, err := CellNameToCoordinates(colCell.R)
|
|
|
|
if err != nil {
|
|
|
|
return columns, err
|
|
|
|
}
|
2018-05-05 13:33:19 +08:00
|
|
|
val, _ := colCell.getValueFrom(rows.f, d)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
columns[col-1] = val
|
2018-05-05 13:33:19 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return columns, nil
|
2018-05-05 13:33:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// ErrSheetNotExist defines an error of sheet is not exist
|
|
|
|
type ErrSheetNotExist struct {
|
|
|
|
SheetName string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err ErrSheetNotExist) Error() string {
|
|
|
|
return fmt.Sprintf("Sheet %s is not exist", string(err.SheetName))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rows return a rows iterator. For example:
|
|
|
|
//
|
2018-08-06 10:21:24 +08:00
|
|
|
// rows, err := xlsx.Rows("Sheet1")
|
2018-05-05 13:33:19 +08:00
|
|
|
// for rows.Next() {
|
2019-03-23 20:08:06 +08:00
|
|
|
// row, err := rows.Columns()
|
|
|
|
// for _, colCell := range row {
|
2018-05-05 13:33:19 +08:00
|
|
|
// fmt.Print(colCell, "\t")
|
|
|
|
// }
|
|
|
|
// fmt.Println()
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
func (f *File) Rows(sheet string) (*Rows, error) {
|
|
|
|
xlsx := f.workSheetReader(sheet)
|
|
|
|
name, ok := f.sheetMap[trimSheetName(sheet)]
|
|
|
|
if !ok {
|
|
|
|
return nil, ErrSheetNotExist{sheet}
|
|
|
|
}
|
|
|
|
if xlsx != nil {
|
2018-05-07 16:14:35 +08:00
|
|
|
output, _ := xml.Marshal(f.Sheet[name])
|
2018-05-07 16:12:51 +08:00
|
|
|
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
2018-05-05 13:33:19 +08:00
|
|
|
}
|
|
|
|
return &Rows{
|
|
|
|
f: f,
|
2018-05-07 16:12:51 +08:00
|
|
|
decoder: xml.NewDecoder(bytes.NewReader(f.readXML(name))),
|
2018-05-05 13:33:19 +08:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2017-02-17 17:41:11 +08:00
|
|
|
// getTotalRowsCols provides a function to get total columns and rows in a
|
2017-09-13 22:00:33 +08:00
|
|
|
// worksheet.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) getTotalRowsCols(name string) (int, int, error) {
|
2018-05-07 16:12:51 +08:00
|
|
|
decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
|
2017-02-17 17:41:11 +08:00
|
|
|
var inElement string
|
|
|
|
var r xlsxRow
|
|
|
|
var tr, tc int
|
|
|
|
for {
|
|
|
|
token, _ := decoder.Token()
|
|
|
|
if token == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
switch startElement := token.(type) {
|
|
|
|
case xml.StartElement:
|
|
|
|
inElement = startElement.Name.Local
|
|
|
|
if inElement == "row" {
|
|
|
|
r = xlsxRow{}
|
2018-05-27 11:25:55 +08:00
|
|
|
_ = decoder.DecodeElement(&r, &startElement)
|
2017-02-17 17:41:11 +08:00
|
|
|
tr = r.R
|
|
|
|
for _, colCell := range r.C {
|
2019-03-23 20:08:06 +08:00
|
|
|
col, _, err := CellNameToCoordinates(colCell.R)
|
|
|
|
if err != nil {
|
|
|
|
return tr, tc, err
|
|
|
|
}
|
2017-02-17 17:41:11 +08:00
|
|
|
if col > tc {
|
|
|
|
tc = col
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return tr, tc, nil
|
2017-02-17 17:41:11 +08:00
|
|
|
}
|
|
|
|
|
2018-04-02 10:59:15 +08:00
|
|
|
// SetRowHeight provides a function to set the height of a single row. For
|
|
|
|
// example, set the height of the first row in Sheet1:
|
2017-02-02 10:59:31 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := xlsx.SetRowHeight("Sheet1", 1, 50)
|
2017-02-02 10:59:31 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetRowHeight(sheet string, row int, height float64) error {
|
2019-03-06 21:40:45 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return newInvalidRowNumberError(row)
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
xlsx := f.workSheetReader(sheet)
|
|
|
|
|
|
|
|
prepareSheetXML(xlsx, 0, row)
|
|
|
|
|
2018-04-02 10:59:15 +08:00
|
|
|
rowIdx := row - 1
|
|
|
|
xlsx.SheetData.Row[rowIdx].Ht = height
|
|
|
|
xlsx.SheetData.Row[rowIdx].CustomHeight = true
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2017-02-02 10:59:31 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// getRowHeight provides a function to get row height in pixels by given sheet
|
2017-06-29 11:14:33 +08:00
|
|
|
// name and row index.
|
|
|
|
func (f *File) getRowHeight(sheet string, row int) int {
|
|
|
|
xlsx := f.workSheetReader(sheet)
|
|
|
|
for _, v := range xlsx.SheetData.Row {
|
|
|
|
if v.R == row+1 && v.Ht != 0 {
|
|
|
|
return int(convertRowHeightToPixels(v.Ht))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Optimisation for when the row heights haven't changed.
|
|
|
|
return int(defaultRowHeightPixels)
|
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// GetRowHeight provides a function to get row height by given worksheet name
|
2018-04-02 10:59:15 +08:00
|
|
|
// and row index. For example, get the height of the first row in Sheet1:
|
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// height, err := xlsx.GetRowHeight("Sheet1", 1)
|
2018-04-02 10:59:15 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return defaultRowHeightPixels, newInvalidRowNumberError(row)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
|
2017-06-29 11:14:33 +08:00
|
|
|
xlsx := f.workSheetReader(sheet)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row > len(xlsx.SheetData.Row) {
|
2019-03-23 20:08:06 +08:00
|
|
|
return defaultRowHeightPixels, nil // it will be better to use 0, but we take care with BC
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
2017-06-29 11:14:33 +08:00
|
|
|
for _, v := range xlsx.SheetData.Row {
|
2018-04-02 10:59:15 +08:00
|
|
|
if v.R == row && v.Ht != 0 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return v.Ht, nil
|
2017-06-29 11:14:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Optimisation for when the row heights haven't changed.
|
2019-03-23 20:08:06 +08:00
|
|
|
return defaultRowHeightPixels, nil
|
2017-06-29 11:14:33 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// sharedStringsReader provides a function to get the pointer to the structure
|
2017-06-29 13:28:44 +08:00
|
|
|
// after deserialization of xl/sharedStrings.xml.
|
|
|
|
func (f *File) sharedStringsReader() *xlsxSST {
|
|
|
|
if f.SharedStrings == nil {
|
|
|
|
var sharedStrings xlsxSST
|
2018-03-02 10:19:40 +08:00
|
|
|
ss := f.readXML("xl/sharedStrings.xml")
|
2018-05-07 16:12:51 +08:00
|
|
|
if len(ss) == 0 {
|
2018-03-02 10:19:40 +08:00
|
|
|
ss = f.readXML("xl/SharedStrings.xml")
|
|
|
|
}
|
2018-10-18 10:23:08 +08:00
|
|
|
_ = xml.Unmarshal(namespaceStrictToTransitional(ss), &sharedStrings)
|
2017-06-29 13:28:44 +08:00
|
|
|
f.SharedStrings = &sharedStrings
|
|
|
|
}
|
|
|
|
return f.SharedStrings
|
2016-10-31 19:13:22 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// getValueFrom return a value from a column/row cell, this function is
|
|
|
|
// inteded to be used with for range on rows an argument with the xlsx opened
|
|
|
|
// file.
|
2017-02-12 19:03:24 +08:00
|
|
|
func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
|
2016-11-02 12:58:51 +08:00
|
|
|
switch xlsx.T {
|
|
|
|
case "s":
|
|
|
|
xlsxSI := 0
|
|
|
|
xlsxSI, _ = strconv.Atoi(xlsx.V)
|
2017-02-07 14:03:03 +08:00
|
|
|
if len(d.SI[xlsxSI].R) > 0 {
|
|
|
|
value := ""
|
|
|
|
for _, v := range d.SI[xlsxSI].R {
|
|
|
|
value += v.T
|
|
|
|
}
|
|
|
|
return value, nil
|
|
|
|
}
|
2017-05-05 14:40:28 +08:00
|
|
|
return f.formattedValue(xlsx.S, d.SI[xlsxSI].T), nil
|
2016-11-02 12:58:51 +08:00
|
|
|
case "str":
|
2017-05-05 14:40:28 +08:00
|
|
|
return f.formattedValue(xlsx.S, xlsx.V), nil
|
2018-04-09 19:44:08 +08:00
|
|
|
case "inlineStr":
|
|
|
|
return f.formattedValue(xlsx.S, xlsx.IS.T), nil
|
2016-11-02 12:58:51 +08:00
|
|
|
default:
|
2017-05-05 14:40:28 +08:00
|
|
|
return f.formattedValue(xlsx.S, xlsx.V), nil
|
2016-11-02 12:58:51 +08:00
|
|
|
}
|
2016-10-31 19:13:22 +08:00
|
|
|
}
|
2017-06-08 11:11:11 +08:00
|
|
|
|
2019-03-07 15:13:32 +08:00
|
|
|
// SetRowVisible provides a function to set visible of a single row by given
|
2019-03-06 21:40:45 +08:00
|
|
|
// worksheet name and Excel row number. For example, hide row 2 in Sheet1:
|
2017-06-08 11:11:11 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := xlsx.SetRowVisible("Sheet1", 2, false)
|
2017-06-08 11:11:11 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetRowVisible(sheet string, row int, visible bool) error {
|
2019-03-06 21:40:45 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return newInvalidRowNumberError(row)
|
2017-06-14 15:01:49 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
xlsx := f.workSheetReader(sheet)
|
|
|
|
prepareSheetXML(xlsx, 0, row)
|
|
|
|
xlsx.SheetData.Row[row-1].Hidden = !visible
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2017-06-08 11:11:11 +08:00
|
|
|
}
|
|
|
|
|
2019-03-07 15:13:32 +08:00
|
|
|
// GetRowVisible provides a function to get visible of a single row by given
|
|
|
|
// worksheet name and Excel row number. For example, get visible state of row
|
|
|
|
// 2 in Sheet1:
|
2017-06-08 11:11:11 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// visible, err := xlsx.GetRowVisible("Sheet1", 2)
|
2017-06-08 11:11:11 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) GetRowVisible(sheet string, row int) (bool, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, newInvalidRowNumberError(row)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
|
2017-06-08 11:11:11 +08:00
|
|
|
xlsx := f.workSheetReader(sheet)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row > len(xlsx.SheetData.Row) {
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, nil
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return !xlsx.SheetData.Row[row-1].Hidden, nil
|
2017-06-08 11:11:11 +08:00
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
|
2018-05-11 10:14:18 +08:00
|
|
|
// SetRowOutlineLevel provides a function to set outline level number of a
|
2019-03-20 15:13:41 +08:00
|
|
|
// single row by given worksheet name and Excel row number. For example,
|
|
|
|
// outline row 2 in Sheet1 to level 1:
|
2018-05-08 02:32:20 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := xlsx.SetRowOutlineLevel("Sheet1", 2, 1)
|
2018-05-08 02:32:20 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error {
|
2019-03-06 21:40:45 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return newInvalidRowNumberError(row)
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
xlsx := f.workSheetReader(sheet)
|
|
|
|
prepareSheetXML(xlsx, 0, row)
|
2019-03-06 21:40:45 +08:00
|
|
|
xlsx.SheetData.Row[row-1].OutlineLevel = level
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2018-05-08 02:32:20 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// GetRowOutlineLevel provides a function to get outline level number of a
|
2019-03-20 15:13:41 +08:00
|
|
|
// single row by given worksheet name and Excel row number. For example, get
|
|
|
|
// outline number of row 2 in Sheet1:
|
2018-05-08 02:32:20 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// level, err := xlsx.GetRowOutlineLevel("Sheet1", 2)
|
2018-05-08 02:32:20 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) GetRowOutlineLevel(sheet string, row int) (uint8, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return 0, newInvalidRowNumberError(row)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2018-05-08 02:32:20 +08:00
|
|
|
xlsx := f.workSheetReader(sheet)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row > len(xlsx.SheetData.Row) {
|
2019-03-23 20:08:06 +08:00
|
|
|
return 0, nil
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return xlsx.SheetData.Row[row-1].OutlineLevel, nil
|
2018-05-08 02:32:20 +08:00
|
|
|
}
|
|
|
|
|
2019-03-07 16:03:31 +08:00
|
|
|
// RemoveRow provides a function to remove single row by given worksheet name
|
2019-03-06 21:40:45 +08:00
|
|
|
// and Excel row number. For example, remove row 3 in Sheet1:
|
2017-07-24 10:26:02 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := xlsx.RemoveRow("Sheet1", 3)
|
2017-07-24 10:26:02 +08:00
|
|
|
//
|
2019-02-22 22:17:38 +08:00
|
|
|
// Use this method with caution, which will affect changes in references such
|
|
|
|
// as formulas, charts, and so on. If there is any referenced value of the
|
|
|
|
// worksheet, it will cause a file error when you open it. The excelize only
|
|
|
|
// partially updates these references currently.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) RemoveRow(sheet string, row int) error {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return newInvalidRowNumberError(row)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
|
2019-03-06 21:40:45 +08:00
|
|
|
xlsx := f.workSheetReader(sheet)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row > len(xlsx.SheetData.Row) {
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
2019-03-21 18:44:30 +08:00
|
|
|
for rowIdx := range xlsx.SheetData.Row {
|
|
|
|
if xlsx.SheetData.Row[rowIdx].R == row {
|
|
|
|
xlsx.SheetData.Row = append(xlsx.SheetData.Row[:rowIdx],
|
|
|
|
xlsx.SheetData.Row[rowIdx+1:]...)[:len(xlsx.SheetData.Row)-1]
|
2019-03-23 20:08:06 +08:00
|
|
|
return f.adjustHelper(sheet, rows, row, -1)
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
2019-03-07 15:13:32 +08:00
|
|
|
// InsertRow provides a function to insert a new row after given Excel row
|
|
|
|
// number starting from 1. For example, create a new row before row 3 in
|
|
|
|
// Sheet1:
|
2017-07-24 10:26:02 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := elsx.InsertRow("Sheet1", 3)
|
2017-07-24 10:26:02 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) InsertRow(sheet string, row int) error {
|
2019-03-06 21:40:45 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return newInvalidRowNumberError(row)
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return f.adjustHelper(sheet, rows, row, 1)
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
2019-03-06 21:40:45 +08:00
|
|
|
// DuplicateRow inserts a copy of specified row (by it Excel row number) below
|
2018-12-26 13:33:40 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := xlsx.DuplicateRow("Sheet1", 2)
|
2018-12-26 13:33:40 +08:00
|
|
|
//
|
2019-02-22 22:17:38 +08:00
|
|
|
// Use this method with caution, which will affect changes in references such
|
|
|
|
// as formulas, charts, and so on. If there is any referenced value of the
|
|
|
|
// worksheet, it will cause a file error when you open it. The excelize only
|
|
|
|
// partially updates these references currently.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) DuplicateRow(sheet string, row int) error {
|
|
|
|
return f.DuplicateRowTo(sheet, row, row+1)
|
2018-12-27 22:28:28 +08:00
|
|
|
}
|
|
|
|
|
2019-03-06 21:40:45 +08:00
|
|
|
// DuplicateRowTo inserts a copy of specified row by it Excel number
|
|
|
|
// to specified row position moving down exists rows after target position
|
2018-12-27 22:28:28 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
// err := xlsx.DuplicateRowTo("Sheet1", 2, 7)
|
2018-12-27 22:28:28 +08:00
|
|
|
//
|
2019-02-22 22:17:38 +08:00
|
|
|
// Use this method with caution, which will affect changes in references such
|
|
|
|
// as formulas, charts, and so on. If there is any referenced value of the
|
|
|
|
// worksheet, it will cause a file error when you open it. The excelize only
|
|
|
|
// partially updates these references currently.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if row < 1 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return newInvalidRowNumberError(row)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
xlsx := f.workSheetReader(sheet)
|
|
|
|
if row > len(xlsx.SheetData.Row) || row2 < 1 || row == row2 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2018-12-26 13:33:40 +08:00
|
|
|
}
|
|
|
|
|
2018-12-27 22:28:28 +08:00
|
|
|
var ok bool
|
|
|
|
var rowCopy xlsxRow
|
|
|
|
|
2019-03-06 21:40:45 +08:00
|
|
|
for i, r := range xlsx.SheetData.Row {
|
2018-12-26 13:33:40 +08:00
|
|
|
if r.R == row {
|
2019-03-06 21:40:45 +08:00
|
|
|
rowCopy = xlsx.SheetData.Row[i]
|
2018-12-27 22:28:28 +08:00
|
|
|
ok = true
|
2018-12-26 13:33:40 +08:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2018-12-27 22:28:28 +08:00
|
|
|
if !ok {
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2018-12-27 22:28:28 +08:00
|
|
|
}
|
2018-12-26 13:33:40 +08:00
|
|
|
|
2019-03-23 20:08:06 +08:00
|
|
|
if err := f.adjustHelper(sheet, rows, row2, 1); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-12-27 22:28:28 +08:00
|
|
|
|
|
|
|
idx2 := -1
|
2019-03-06 21:40:45 +08:00
|
|
|
for i, r := range xlsx.SheetData.Row {
|
2018-12-27 22:28:28 +08:00
|
|
|
if r.R == row2 {
|
|
|
|
idx2 = i
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
if idx2 == -1 && len(xlsx.SheetData.Row) >= row2 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2018-12-26 13:33:40 +08:00
|
|
|
}
|
2018-12-27 22:28:28 +08:00
|
|
|
|
|
|
|
rowCopy.C = append(make([]xlsxC, 0, len(rowCopy.C)), rowCopy.C...)
|
|
|
|
f.ajustSingleRowDimensions(&rowCopy, row2)
|
|
|
|
|
2018-12-26 13:33:40 +08:00
|
|
|
if idx2 != -1 {
|
2019-03-06 21:40:45 +08:00
|
|
|
xlsx.SheetData.Row[idx2] = rowCopy
|
2018-12-26 13:33:40 +08:00
|
|
|
} else {
|
2019-03-06 21:40:45 +08:00
|
|
|
xlsx.SheetData.Row = append(xlsx.SheetData.Row, rowCopy)
|
2018-12-26 13:33:40 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2018-12-26 13:33:40 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// checkRow provides a function to check and fill each column element for all
|
|
|
|
// rows and make that is continuous in a worksheet of XML. For example:
|
2017-07-24 10:26:02 +08:00
|
|
|
//
|
|
|
|
// <row r="15" spans="1:22" x14ac:dyDescent="0.2">
|
|
|
|
// <c r="A15" s="2" />
|
|
|
|
// <c r="B15" s="2" />
|
|
|
|
// <c r="F15" s="1" />
|
|
|
|
// <c r="G15" s="1" />
|
|
|
|
// </row>
|
|
|
|
//
|
|
|
|
// in this case, we should to change it to
|
|
|
|
//
|
|
|
|
// <row r="15" spans="1:22" x14ac:dyDescent="0.2">
|
|
|
|
// <c r="A15" s="2" />
|
|
|
|
// <c r="B15" s="2" />
|
|
|
|
// <c r="C15" s="2" />
|
|
|
|
// <c r="D15" s="2" />
|
|
|
|
// <c r="E15" s="2" />
|
|
|
|
// <c r="F15" s="1" />
|
|
|
|
// <c r="G15" s="1" />
|
|
|
|
// </row>
|
|
|
|
//
|
|
|
|
// Noteice: this method could be very slow for large spreadsheets (more than
|
|
|
|
// 3000 rows one sheet).
|
2019-03-23 20:08:06 +08:00
|
|
|
func checkRow(xlsx *xlsxWorksheet) error {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
for rowIdx := range xlsx.SheetData.Row {
|
|
|
|
rowData := &xlsx.SheetData.Row[rowIdx]
|
2017-07-24 10:26:02 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
colCount := len(rowData.C)
|
|
|
|
if colCount == 0 {
|
|
|
|
continue
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
lastCol, _, err := CellNameToCoordinates(rowData.C[colCount-1].R)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
if colCount < lastCol {
|
|
|
|
oldList := rowData.C
|
|
|
|
newlist := make([]xlsxC, 0, lastCol)
|
|
|
|
|
|
|
|
rowData.C = xlsx.SheetData.Row[rowIdx].C[:0]
|
|
|
|
|
|
|
|
for colIdx := 0; colIdx < lastCol; colIdx++ {
|
2019-03-23 20:08:06 +08:00
|
|
|
cellName, err := CoordinatesToCellName(colIdx+1, rowIdx+1)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
newlist = append(newlist, xlsxC{R: cellName})
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
rowData.C = newlist
|
|
|
|
|
|
|
|
for colIdx := range oldList {
|
|
|
|
colData := &oldList[colIdx]
|
2019-03-23 20:08:06 +08:00
|
|
|
colNum, _, err := CellNameToCoordinates(colData.R)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
xlsx.SheetData.Row[rowIdx].C[colNum-1] = *colData
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// convertRowHeightToPixels provides a function to convert the height of a
|
|
|
|
// cell from user's units to pixels. If the height hasn't been set by the user
|
|
|
|
// we use the default value. If the row is hidden it has a value of zero.
|
2017-07-24 10:26:02 +08:00
|
|
|
func convertRowHeightToPixels(height float64) float64 {
|
|
|
|
var pixels float64
|
|
|
|
if height == 0 {
|
|
|
|
return pixels
|
|
|
|
}
|
|
|
|
pixels = math.Ceil(4.0 / 3.0 * height)
|
|
|
|
return pixels
|
|
|
|
}
|